diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/CREDITS linux.pre11.3/CREDITS --- linux.vanilla/CREDITS Tue Jun 15 16:49:44 1999 +++ linux.pre11.3/CREDITS Tue Jul 20 00:25:06 1999 @@ -324,6 +324,10 @@ S: 75252 Paris Cedex 05 S: France +N: Ulf Carlsson +D: SGI Indy audio (HAL2) drivers +E: ulfc@bun.falkenberg.se + N: Ed Carp E: ecarp@netcom.com D: uucp, elm, pine, pico port @@ -453,6 +457,14 @@ S: Warrendale, Pennsylvania 15086 S: USA +N: Alex deVries +E: puffin@redhat.com +D: Various SGI parts, bits of HAL2 and Newport +S: 18 Bernier Terrace +S: Kanata, Ontario +S: K2L 2V@ +S: CANADA + N: Eddie C. Dost E: ecd@skynet.be D: Linux/Sparc kernel hacker @@ -946,7 +958,7 @@ E: nkbj@image.dk W: http://www.image.dk/~nkbj D: 4.4BSD and NeXTstep filesystem support in the old ufs. -D: Openstep filesystem support in the new ufs. +D: Openstep filesystem and NeXTstep CDROM support in the new ufs. D: Danish HOWTO, Linux+FreeBSD mini-HOWTO. S: Dr. Holsts Vej 34, lejl. 164 S: DK-8230 Åbyhøj @@ -1603,6 +1615,15 @@ S: San Jose, California 95129 S: USA +N: Augusto Cesar Radtke +E: bishop@sekure.org +W: http://bishop.sekure.org +D: {copy,get,put}_user calls updates +D: Miscellaneous hacks +S: R. Otto Marquardt, 226 - Garcia +S: 89020-350 Blumenau - Santa Catarina +S: Brazil + N: Eric S. Raymond E: esr@thyrsus.com W: http://www.tuxedo.org/~esr/ @@ -1638,12 +1659,13 @@ S: France N: Rik van Riel -E: H.H.vanRiel@humbolt.geo.uu.nl -W: http://humbolt.geo.uu.nl/ -D: Maintainer of the mm-patches page (see www.linuxhq.com) -D: Documentation/sysctl/*, kswapd fixes, random kernel hacker -S: Vorenkampsweg 1 -S: NL-9488 TG Zeijerveld +E: riel@nl.linux.org +W: http://www.nl.linux.org/~riel/ +D: Linux-MM site, Documentation/sysctl/*, swap/mm readaround +D: clustering contributor, kswapd fixes, random kernel hacker, +D: nl.linux.org maintainer, minor scheduler additions +S: IJsselstraat 23a +S: 9725 GA Groningen S: The Netherlands N: William E. Roadcap @@ -2253,6 +2275,7 @@ E: lnz@dandelion.com W: http://www.dandelion.com/Linux/ D: BusLogic SCSI driver +D: Mylex DAC960 PCI RAID driver D: Miscellaneous kernel fixes S: 3078 Sulphur Spring Court S: San Jose, California 95148 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/Changes linux.pre11.3/Documentation/Changes --- linux.vanilla/Documentation/Changes Thu May 27 22:11:46 1999 +++ linux.pre11.3/Documentation/Changes Mon Jul 19 23:49:58 1999 @@ -11,18 +11,14 @@ functional and running at least 2.0.x kernels. It is originally based on my "Changes" file for 2.0.x kernels and -therefore owes credit to the same people as that file (Jared Mauch, -Axel Boldt, Alessandro Sigala, and countless other users all over the -'net). Please feel free to submit changes, corrections, gripes, -flames, money, etc. to me (kaboom@gatech.edu). If you do so, you don't +therefore owes credit to the same people as that file (Jared Mauch, Axel +Boldt, Alessandro Sigala, and countless other users all over the 'net). +Please feel free to submit changes, corrections, gripes, flames, money, +etc. to me (chris.ricker@genetics.utah.edu). If you do so, you don't need to bother doing so in the form of a diff, as this is generated by texinfo so a diff is useless anyway (though I can incorporate one by hand if you insist upon sending it that way ;-). - For those of you in Europe, -http://www.datanet.hu/generations/linux/Changes2.html is an -English-language HTML version. - The most current version should always be available from http://cyberbuzz.gatech.edu/kaboom/linux/ as well. @@ -30,11 +26,26 @@ http://www.linux-france.com/article/sys/Changes-2.2/Changes-2.2.1.html pour la traduction français. - Also, don't forget http://www.linuxhq.com/ for all your Linux kernel -needs. + Nihongo-ban ha kochira desu (text & html) +http://www.linux.or.jp/JF/JFdocs/kernel-docs-2.2/Changes +http://www2.palnet.or.jp/~matsuda/Changes-2.2.ja.html + + Visite http://www2.adi.uam.es/~ender/tecnico/cambios22.html para +obtener la traducción al español de este documento. + + Also, don't forget + + http://www.linuxhq.com/ -Last updated: March 16, 1999 -Current Author: Chris Ricker (kaboom@gatech.edu or chris.ricker@m.cc.utah.edu). + http://www.kernelnotes.org/ + + http://www.kernel.org/ + + for all your Linux kernel needs. + +Last updated: July 13, 1999 +Current Author: Chris Ricker (kaboom@gatech.edu or + chris.ricker@genetics.utah.edu). Current Minimal Requirements **************************** @@ -53,16 +64,16 @@ - Procps 1.2.9 ; ps --version - Procinfo 16 ; procinfo -v - Psmisc 17 ; pstree -V -- Net-tools 1.50 ; hostname -V +- Net-tools 1.52 ; hostname -V - Loadlin 1.6a - Sh-utils 1.16 ; basename --v - Autofs 3.1.1 ; automount --version - NFS 2.2beta40 ; showmount --version - Bash 1.14.7 ; bash -version - Ncpfs 2.2.0 ; ncpmount -v -- Pcmcia-cs 3.0.7 ; cardmgr -V -- PPP 2.3.5 ; pppd --version -- Util-linux 2.9i ; chsh -v +- Pcmcia-cs 3.0.13 ; cardmgr -V +- PPP 2.3.8 ; pppd --version +- Util-linux 2.9t ; chsh -v Upgrade notes ************* @@ -86,9 +97,9 @@ compiled under 2.2, for example. As of 2.1.115, support for the deprecated major 4 /dev/ttyp* devices -was removed. If necessary (eg, you get "out of pty" error messages when -you obviously are not out of pty's), create major 3 /dev/tty* and major -2 /dev/pty* devices (see Documentation/devices.txt for more +was removed. If necessary (eg, you get "out of pty" error messages +when you obviously are not out of pty's), create major 3 /dev/tty* and +major 2 /dev/pty* devices (see Documentation/devices.txt for more information). In general, you should make sure that your /dev directory is up-to-date if you are experiencing any problems. @@ -134,8 +145,8 @@ release. If you upgrade to libc-5.4.x, you also have to upgrade your dynamic -linker (ld.so) to at least 1.9.9, or all sorts of weirdness will -happen. Actually, ld.so-1.8.2 and later will work, but 1.9.9 is widely +linker (ld.so) to at least 1.9.9, or all sorts of weirdness will happen. +Actually, ld.so-1.8.2 and later will work, but 1.9.9 is widely available, so if you need to upgrade, use it. If you get a release later than 1.8.5, avoid 1.8.10 as it introduces a few bugs that are fixed in later releases. Please make sure you don't install ld.so-2.x @@ -158,9 +169,9 @@ of your boot scripts calls ldconfig, /etc/ld.so.cache is deleted. Init, however, still references that file; as of 2.1.122, the kernel will consequently not be able to remount the root file system r/o at system -shutdown. To fix this, upgrade to at least the pre6 release of GNU -libc 2.0.7. As a temporary workaround, modify your boot scripts to do -the following before calling ldconfig: +shutdown. To fix this, upgrade to at least the pre6 release of GNU libc +2.0.7. As a temporary workaround, modify your boot scripts to do the +following before calling ldconfig: ln -f /etc/ld.so.cache /etc/ld.so.cache.old @@ -197,6 +208,12 @@ and binutils-development packages (Debian puts bfd.h in binutils-dev, for example). +Bin86 +===== + + To compile the kernel on the IA32 platform, a real-mode assembler and +linker is required. These are found in the bin86 package. + Gnu C ===== @@ -287,19 +304,17 @@ larger swap spaces, you need the new mkswap found in util-linux. You also need to upgrade util-linux to get the latest version of mount. - Partitions on 2048 byte sectored media (certain magneto opticals -most prominently) were broken throughout the whole of 2.1 kernel -series, meaning that you will be unable to use 2.1-partitioned media on -Linux 2.2. This is not a 2.2 bug - 2.2 finally does the right thing! -[If you have to interchange media between Linux 2.1 and 2.2, your best -bet is to not use partitions at all but create the filesystem on the -raw device (e.g. /dev/sda) instead. This is also known as the -superfloppy format.] - - To properly create partitions on 2048 byte sectored media with Linux -2.2, be sure to use no less than fdisk version 2.9i and invoke fdisk -using '-b 2048' as an option. - + Partitions on 2048-bytes-per-sector media (certain magneto-opticals +most prominently) were broken throughout the 2.1 kernel series, meaning +that you will be unable to use 2.1-partitioned media on Linux 2.2. This +is not a 2.2 bug - 2.2 finally does the right thing! [If you have to +interchange media between Linux 2.1 and 2.2, your best bet is to not +use partitions at all but create the filesystem on the raw device (e.g. +/dev/sda) instead. This is also known as the superfloppy format.] + + To properly create partitions on 2048-bytes-per-sector media with +Linux 2.2, be sure to use no less than fdisk version 2.9i and invoke +fdisk using '-b 2048' as an option. RPM === @@ -311,7 +326,7 @@ ====== A new "stable" version of DOSEMU is available for 2.2 kernels. -Upgrade to 0.98.4 or later. +Upgrade to 0.98.6 or later. Loadlin ======= @@ -329,7 +344,7 @@ Parallel Ports ============== - As of 2.1.33, parallel port support can now by handled by the parport + As of 2.1.33, parallel port support can now be handled by the parport driver. Be aware that with Plug-and-Play support turned on, your parallel port may no longer be where you expect it; for example, LPT1 (under DOS) was sometimes /dev/lp1 in Linux, but will probably be @@ -351,7 +366,9 @@ When you build your kernel with Syncookie support (CONFIG_SYN_COOKIES) the syncookie code still defaults to off (unlike the 2.0.30+ behavior). You have to explicitly enable it by issuing the -following command: echo 1 > /proc/sys/net/ipv4/tcp_syncookies +following command: + + echo 1 > /proc/sys/net/ipv4/tcp_syncookies Bash ==== @@ -381,8 +398,8 @@ To mount SMB (Samba / Windows) shares, you'll need to use the smbmount utility included with release 2.0 of Samba. Documentation/filesystems/smbfs.txt has more information about this. -Note that smbmount must have been built against 2.2 headers to work -with 2.2; if all else fails, recompile it and hope it works ;-). In +Note that smbmount must have been built against 2.2 headers to work with +2.2; if all else fails, recompile it and hope it works ;-). In addition, Mike Warfield has a script and some information at http://www.wittsend.com/mhw/smbmount.html that you will probably find useful. @@ -445,6 +462,7 @@ backing up your copy of rvplayer, and then editing it by: dd if=/dev/zero of=rvplayer bs=1 count=1 seek=657586 conv=notrunc + dd if=/dev/zero of=rvplayer bs=1 count=1 seek=665986 conv=notrunc If you're lucky, you'll then have sound.... @@ -519,6 +537,13 @@ ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.binutils-2.9.1.0.15 ftp://metalab.unc.edu/pub/Linux/GCC/release.binutils-2.9.1.0.15 +Bin86 +===== + +The 0.4 release: +ftp://metalab.unc.edu/pub/Linux/GCC/bin86-0.4.tar.gz +ftp://tsx-11.mit.edu/pub/linux/packages/GCC/bin86-0.4.tar.gz + Gnu C ===== @@ -598,9 +623,9 @@ DOSEMU ====== -The 0.98.1 release: -ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/dosemu-0.98.4.tgz -ftp://ftp.dosemu.org/dosemu/dosemu-0.98.4.tgz +The 0.98.6 release: +ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/dosemu-0.98.6.tgz +ftp://ftp.dosemu.org/dosemu/dosemu-0.98.6.tgz Loadlin ======= @@ -620,7 +645,7 @@ ========== The 2.9 release: -ftp://ftp.win.tue.nl/pub/linux/utils/util-linux/util-linux-2.9i.tar.gz +ftp://ftp.win.tue.nl/pub/linux/utils/util-linux/util-linux-2.9t.tar.gz Autofs ====== @@ -635,16 +660,16 @@ ftp://ftp.mathematik.th-darmstadt.de/pub/linux/okir/dontuse/nfs-server-2.2beta40.tar.gz ftp://linux.nrao.edu/mirrors/fb0429.mathematik.th-darmstadt.de/pub/linux/okir/dontuse/nfs-server-2.2beta40.tar.gz -The kernel-level 12/04/98 release: -ftp://ftp.yggdrasil.com/private/hjl/knfsd-981204.tar.gz -ftp://ftp.kernel.org/pub/linux/devel/gcc/knfsd-981204.tar.gz +The kernel-level 1.4.4 release: +ftp://ftp.varesearch.com/pub/support/hjl/knfsd/knfsd-1.4.4.tar.gz +ftp://ftp.kernel.org/pub/linux/devel/gcc/knfsd-1.4.4.tar.gz Net-tools ========= -The 1.50 release: -ftp://ftp.cs-ipv6.lancs.ac.uk/pub/Code/Linux/Net_Tools/net-tools-1.50.tar.gz -http://www.tazenda.demon.co.uk/phil/net-tools/net-tools-1.50.tar.gz +The 1.52 release: +ftp://ftp.cs-ipv6.lancs.ac.uk/pub/Code/Linux/Net_Tools/net-tools-1.52.tar.gz +http://www.tazenda.demon.co.uk/phil/net-tools/net-tools-1.52.tar.gz Ypbind ====== @@ -664,8 +689,8 @@ The 1.14.7 release: ftp://ftp.gnu.org/gnu/bash/bash-1.14.7.tar.gz -The 2.02.1 release: -ftp://ftp.gnu.org/gnu/bash/bash-2.02.1.tar.gz +The 2.03 release: +ftp://ftp.gnu.org/gnu/bash/bash-2.03.tar.gz Ncpfs ===== @@ -676,14 +701,14 @@ SMBfs ===== -The 2.0.0 release of Samba: -ftp://ftp.samba.org/pub/samba/samba-2.0.0.tar.gz +The 2.0.4b release of Samba: +ftp://ftp.samba.org/pub/samba/samba-2.0.4b.tar.gz Pcmcia-cs ========= -The 3.0.7 release: -ftp://hyper.stanford.edu/pub/pcmcia/pcmcia-cs.3.0.7.tar.gz +The 3.0.13 release: +ftp://hyper.stanford.edu/pub/pcmcia/pcmcia-cs.3.0.13.tar.gz Setserial ========= @@ -695,8 +720,8 @@ PPP === -The 2.3.5 release: -ftp://cs.anu.edu.au/pub/software/ppp/ppp-2.3.5.tar.gz +The 2.3.8 release: +ftp://cs.anu.edu.au/pub/software/ppp/ppp-2.3.8.tar.gz IP Chains ========= @@ -714,8 +739,8 @@ DHCP clients ============ -The 2.0b1p18 ISC dhcpclient release: -ftp://ftp.isc.org/isc/dhcp/test/dhcp-2.0b1pl8.tar.gz +The 2.0b1pl27 ISC dhcpclient release: +ftp://ftp.isc.org/isc/dhcp/test/dhcp-2.0b1pl27.tar.gz The 1.3.17-pl2 PhysTech dhcpcd release: ftp://ftp.phystech.com/pub/dhcpcd-1.3.17-pl2.tar.gz @@ -735,15 +760,15 @@ Fbset ===== -The 11/04/98 release: -http://www.cs.kuleuven.ac.be/~geert/bin/fbset-2.0-pre-19981104.tar.gz +The 2.1 release: +http://www.cs.kuleuven.ac.be/~geert/bin/fbset-2.1.tar.gz PCI utils ========= -The 1.09 release: -ftp://atrey.karlin.mff.cuni.cz/pub/linux/pci/pciutils-1.09.tar.gz -ftp://metalab.unc.edu/pub/Linux/hardware/pciutils-1.09.tar.gz +The 2.0 release: +ftp://atrey.karlin.mff.cuni.cz/pub/linux/pci/pciutils-2.0.tar.gz +ftp://metalab.unc.edu/pub/Linux/hardware/pciutils-2.0.tar.gz Tunelp ====== @@ -767,8 +792,9 @@ IP utils ======== -The 03/01/99 release: -ftp://ftp.inr.ac.ru/ip-routing/iproute2-2.1.99-now-ss990301.tar.gz +The June 1999 release: +ftp://ftp.inr.ac.ru/ip-routing/iproute2-2.2.4-now-ss990630.tar.gz +ftp://ftp.inr.ac.ru/ip-routing/iputils-ss990610.tar.gz Patch ===== @@ -791,7 +817,7 @@ your favorite Red Hat mirror site before installing the non-RPM version. Remember, you might need to use the --force option to get the upgrade to install. ftp://contrib.redhat.com/ , -ftp://developer.redhat.com/ , or ftp://updates.redhat.com/ will have +ftp://developer.redhat.com/ , or ftp://updates.redhat.com/ will have almost everything you need, and Red Hat 5.2 ships with most necessary software. @@ -802,5 +828,5 @@ Please send info about any other packages that 2.2 "broke" or about any new features of 2.2 that require extra or new packages for use to Chris -Ricker (kaboom@gatech.edu or chris.ricker@m.cc.utah.edu). +Ricker (kaboom@gatech.edu or chris.ricker@genetics.utah.edu). diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/Configure.help linux.pre11.3/Documentation/Configure.help --- linux.vanilla/Documentation/Configure.help Tue Jun 15 16:49:44 1999 +++ linux.pre11.3/Documentation/Configure.help Tue Jul 20 00:25:42 1999 @@ -1844,6 +1844,11 @@ You will get a boot time penguin logo at no additional cost. Please read Documentation/fb/vesafb.txt. If unsure, say Y. +VGA 16-color graphics console +CONFIG_FB_VGA16 + This is the frame buffer device driver for VGA 16 color graphic + cards. Say Y if you have such a card. + Backward compatibility mode for Xpmac CONFIG_FB_COMPAT_XPMAC If you use the Xpmac X server (common with mklinux), you'll need to @@ -4989,6 +4994,17 @@ module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. +Aironet Arlan 655 & IC2200 DS support +CONFIG_ARLAN + Aironet makes Arlan. www.aironet.com. Uses www.Telxon.com chip, which is + used on several similar cards. Driver is tested on 655 and IC2200 series. + Look for http://www.ylenurme.ee/~elmer/655/ for latest information. + Driver is build as two modules, arlan and arlan-proc. The later is /proc + interface and not needed most of time. + On some computers the card ends up in non-valid state after some time. + Use a ping-reset script to clear it. + + LAPB over Ethernet driver CONFIG_LAPBETHER This is a driver for a pseudo device (typically called /dev/lapb0) @@ -5115,6 +5131,15 @@ module, say M here and read Documentation/modules.txt. If you don't know what to use this for, you don't need it. +Sealevel Systems 4021 support +CONFIG_SEALEVEL_4021 + This is a driver for the Sealevel Systems ACB 56 serial I/O adapter. + + This driver can only be compiled as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + If you want to do that, say M here. The module will be called + sealevel.o. + Frame Relay (DLCI) support CONFIG_DLCI This is support for the frame relay protocol; frame relay is a fast @@ -5734,7 +5759,7 @@ say M here and read Documentation/modules.txt. This is recommended. The module will be called yellowfin.o. -Alteon AceNIC / 3Com 3C985 Gigabit Ethernet support. +Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support CONFIG_ACENIC Say Y here if you have an Alteon AceNIC or 3Com 3C985 PCI Gigabit Ethernet adapter. The driver allows for using the Jumbo Frame @@ -6492,6 +6517,25 @@ The module will be called ibmtr.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +IBM Olympic chipset PCI adapter support +CONFIG_IBMOL + This is support for all non-Lanstreamer IBM PCI Token Ring Cards. + Specifically this is all IBM PCI, PCI Wake On Lan, PCI II, PCI II + Wake On Lan, and PCI 100/16/4 adapters. + + If you have such an adapter, say Y and read the Token-Ring mini-HOWTO, + available via FTP (user:anonymous) from + ftp://metalab.unc/edu/pub/Linux/docs/HOWTO. + + 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 will be called olympic.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + + Also read the linux/Documentation/networking/olympic.txt or check the + Linux Token Ring Project site for the latest information at + http://www.linuxtr.net + SysKonnect adapter support CONFIG_SKTR This is support for all SysKonnect Token Ring cards, specifically @@ -7360,6 +7404,18 @@ Say Y here if you want to try writing to UFS partitions. This is experimental, so you should back up your UFS partitions beforehand. +EFS filesystem support (experimental) +CONFIG_EFS_FS + EFS is the filesystem used for CDROMs and filesystems by SGI's IRIX. + This implementation only offers read-only access. If you don't know + what all this is about, it's safe to say N. For more information + about EFS see it's homepage at http://aeschi.ch.eu.org/efs. + +SGI disklabel support +CONFIG_SGI_DISKLABEL + Say Y to this only if you plan on mounting disks with SGI disklabels. + This is not required to mount EFS-format CDROMs. + BSD disklabel (FreeBSD partition tables) support CONFIG_BSD_DISKLABEL FreeBSD uses its own hard disk partition scheme on your PC. It @@ -8110,6 +8166,16 @@ If you haven't heard about it, it's safe to say N. +Cyclades-Z interrupt mode operation (EXPERIMENTAL) +CONFIG_CYZ_INTR + The Cyclades-Z family of multiport cards allows 2 (two) driver + op modes: polling and interrupt. In polling mode, the driver will + check the status of the Cyclades-Z ports every certain amount of + time (which is called polling cycle and is configurable). In + interrupt mode, it will use an interrupt line (IRQ) in order to check + the status of the Cyclades-Z ports. The default op mode is polling. + If unsure, say N. + Stallion multiport serial support CONFIG_STALDRV Stallion cards give you many serial ports. You would need something @@ -9191,7 +9257,7 @@ after the PnP configuration is finished. To do this, say M here and read Documentation/modules.txt as well as Documentation/sound/README.modules; the module will be called - sound.o. + soundcore.o. I'm told that even without a sound card, you can make your computer say more than an occasional beep, by programming the PC speaker. @@ -9764,6 +9830,11 @@ ISDN subsystem CONFIG_ISDN + CAUTION: the ISDN driver shipped with this kernel distribution + is outdated and might not work without problems. An updated driver + is available for download. Please read http://www.isdn4linux.de + on the WWW for a list of servers. + ISDN ("Integrated Services Digital Networks", called RNIS in France) is a special type of fully digital telephone service; it's mostly used to connect to your Internet service provider (with SLIP or @@ -9830,6 +9901,20 @@ connections. See Documentation/isdn/README.x25 for more information if you are thinking about using this. +ISDN diversion services support +CONFIG_ISDN_DIVERSION + This option allows you to use some supplementary diversion + services in conjunction with the HiSax driver on an EURO/DSS1 + line. Supported options are CD (call deflection), CFU (Call + forward unconditional), CFB (Call forward when busy) and CFNR + (call forward not reachable). + Additionally the actual CFU, CFB and CFNR state may be + interrogated. The use of CFU, CFB, CFNR and interrogation may + be limited to some countries. The keypad protocol is still not + implemented. + CD should work in all countries if this service has been sub- + scribed. + ICN 2B and 4B support CONFIG_ISDN_DRV_ICN This enables support for two kinds of ISDN-cards made by a German @@ -9872,6 +9957,24 @@ called hisax.o. See Documentation/isdn/README.HiSax for more information on using this driver. +HiSax Support for EURO/DSS1 +CONFIG_HISAX_EURO + Enable this if you have a EURO ISDN line. + +Support for german chargeinfo +CONFIG_DE_AOC + If you have german AOC, you can enable this to get the charginfo. + +Disable sending complete +CONFIG_HISAX_NO_SENDCOMPLETE + If you have trouble with some ugly exchanges or you live in + Australia select this option. + +Disable sending low layer compatibility +CONFIG_HISAX_NO_LLC + If you have trouble with some ugly exchanges try to select this + option. + HiSax Support for Teles 16.0/8.0 CONFIG_HISAX_16_0 This enables HiSax support for the Teles ISDN-cards S0-16.0, S0-8 @@ -9890,13 +9993,15 @@ different cards, a different D-channel protocol, or non-standard IRQ/port settings. -HiSax Support for Teles 16.3c -CONFIG_HISAX_TELES3C - This enables HiSax support for the Teles ISDN-cards 16.3c. - - See Documentation/isdn/README.HiSax on how to configure it using the - different cards, a different D-channel protocol, or non-standard - IRQ/port settings. +HiSax Support for Teles PCI +CONFIG_HISAX_TELESPCI + This enables HiSax support for the Teles PCI. + See Documentation/isdn/README.HiSax on how to configure it. + +HiSax Support for Teles S0Box +CONFIG_HISAX_S0BOX + This enables HiSax support for the Teles/Creatix parallel port + S0BOX. See Documentation/isdn/README.HiSax on how to configure it. HiSax Support for AVM A1 (Fritz) CONFIG_HISAX_AVM_A1 @@ -9906,7 +10011,17 @@ different cards, a different D-channel protocol, or non-standard IRQ/port settings. -HiSax Support for Elsa ISA cards +HiSax Support for AVM PnP/PCI (Fritz!PNP/PCI) +CONFIG_HISAX_FRITZPCI + This enables HiSax support for the AVM "Fritz!PnP" and "Fritz!PCI". + See Documentation/isdn/README.HiSax on how to configure it. + +HiSax Support for AVM A1 PCMCIA (Fritz) +CONFIG_HISAX_AVM_A1_PCMCIA + This enables HiSax support for the AVM A1 "Fritz!PCMCIA"). + See Documentation/isdn/README.HiSax on how to configure it. + +HiSax Support for Elsa cards CONFIG_HISAX_ELSA This enables HiSax support for the Elsa Mircolink ISA cards, for the Elsa Quickstep series cards and Elsa PCMCIA. @@ -9949,7 +10064,16 @@ different cards, a different D-channel protocol, or non-standard IRQ/port settings. -HiSax Support for Sedlbauer speed card/win-star +HiSax Support for HFC-S based cards +CONFIG_HISAX_HFCS + This enables HiSax support for the HFC-S 2BDS0 based cards, like + teles 16.3c. + + See Documentation/isdn/README.HiSax on how to configure it using the + different cards, a different D-channel protocol, or non-standard + IRQ/port settings. + +HiSax Support for Sedlbauer cards CONFIG_HISAX_SEDLBAUER This enables HiSax support for the Sedlbauer passive ISDN cards. @@ -9986,51 +10110,46 @@ See Documentation/isdn/README.HiSax on how to configure it using a different D-channel protocol, or non-standard IRQ/port settings. +HiSax Support for Siemens I-Surf card +CONFIG_HISAX_ISURF + This enables HiSax support for the Siemens I-Talk/I-Surf card with + ISAR chip. + See Documentation/isdn/README.HiSax on how to configure it using a + different D-channel protocol, or non-standard IRQ/port settings. + +HiSax Support for HST Saphir card +CONFIG_HISAX_HSTSAPHIR + This enables HiSax support for the HST Saphir card. + + See Documentation/isdn/README.HiSax on how to configure it using a + different D-channel protocol, or non-standard IRQ/port settings. + +HiSax Support for Telekom A4T card +CONFIG_HISAX_BKM_A4T + This enables HiSax support for the Telekom A4T card. + + See Documentation/isdn/README.HiSax on how to configure it using a + different D-channel protocol, or non-standard IRQ/port settings. + +HiSax Support for Scitel Quadro card +CONFIG_HISAX_SCT_QUADRO + This enables HiSax support for the Scitel Quadro card. + + See Documentation/isdn/README.HiSax on how to configure it using a + different D-channel protocol, or non-standard IRQ/port settings. + +HiSax Support for Gazel cards +CONFIG_HISAX_GAZEL + This enables HiSax support for the Gazel cards. + + See Documentation/isdn/README.HiSax on how to configure it using a + different D-channel protocol, or non-standard IRQ/port settings. + HiSax Support for Am7930 (EXPERIMENTAL) CONFIG_HISAX_AMD7930 This enables HiSax support for the AMD7930 chips on some SPARCs. This code is not finished yet. -HiSax Support for EURO/DSS1 -CONFIG_HISAX_EURO - Say Y or N according to the D-channel protocol which your local - telephone service company provides. - - NOTE: If you say Y here and you have only one ISDN card installed, - you cannot say Y to "HiSax Support for German 1TR6", below. And vice - versa. - -Support for German tariff info -CONFIG_DE_AOC - If you want that the HiSax hardware driver sends messages to the - upper level of the isdn code on each AOCD (Advice Of Charge, During - the call -- transmission of the fee information during a call) and - on each AOCE (Advice Of Charge, at the End of the call -- - transmission of fee information at the end of the call), say Y here. - This works only in Germany. - -Support for Australian Microlink service (not for std. EURO) -CONFIG_HISAX_ML - If you are in Australia and connected to the Microlink telephone - network, enable this, because there are little differences in - protocol. - - Please don't enable this in other countries. - -HiSax Support for US/NI-1 (not released yet) -CONFIG_HISAX_NI1 - Say Y or N according to the D-channel protocol which your local - telephone service company provides. - -HiSax Support for German 1TR6 -CONFIG_HISAX_1TR6 - Say Y or N according to the D-channel protocol which your local - telephone service company provides. - - NOTE: If you say Y here and you have only one ISDN card installed, - you cannot say Y to "HiSax Support for EURO/DSS1", above. And vice - versa. - PCBIT-D support CONFIG_ISDN_DRV_PCBIT This enables support for the PCBIT ISDN-card. This card is @@ -10731,6 +10850,11 @@ Choose Y here if you have this FM radio card, and then fill in the port address below. + If you have GemTeks combined (PnP) sound- and radio card you must use + this driver as a module and setup the card with isapnptools. You must + also pass the module a suitable io parameter, 0x248 has been reported + to be used by these cards. + In order to control your radio card, you will need to use programs that are compatible with the Video for Linux API. Information on this API and pointers to "v4l" programs may be found on the WWW at @@ -11452,6 +11576,14 @@ boards from BVM Ltd. Everyone using one of these boards should say Y here. +Compaq SMART2 support +CONFIG_BLK_CPQ_DA + This is the driver for Compaq Smart Array controllers. + Everyone using these boards should say Y here. + See "linux/Documentation/cpqarray.txt" for the current list of + boards supported by this driver, and for further information + on the use of this driver. + # # A couple of things I keep forgetting: # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet, diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/cpqarray.txt linux.pre11.3/Documentation/cpqarray.txt --- linux.vanilla/Documentation/cpqarray.txt Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/Documentation/cpqarray.txt Mon Jul 19 23:50:13 1999 @@ -0,0 +1,107 @@ +This driver is for Compaq's SMART2 Intellegent Disk Array Controllers. + +WARNING: +-------- + +This driver comes with NO WARRANTY. It is not officially supported by +Compaq. Do not call technical support. Use at your own risk. + +Supported Cards: +---------------- + +This driver is known to work with the following cards: + + * SMART (EISA) + * SMART-2/E (EISA) + * SMART-2/P + * SMART-2DH + * SMART-2SL + * SMART-221 + * SMART-3100ES + * SMART-3200 + * Integrated Smart Array Controller + * SA 4200 + * SA 4250ES + +It should also work with some really old Disk array adapters, but I am +unable to test against these cards: + + * IDA + * IDA-2 + * IAES + +Installing: +----------- + +You need to build a new kernel to use this device, even if you want to +use a loadable module. + +Apply the patch to a 2.2.x kernel: + +# cd linux +# patch -p1 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/filesystems/ufs.txt linux.pre11.3/Documentation/filesystems/ufs.txt --- linux.vanilla/Documentation/filesystems/ufs.txt Fri Apr 16 22:10:51 1999 +++ linux.pre11.3/Documentation/filesystems/ufs.txt Tue Jul 20 00:26:16 1999 @@ -30,6 +30,10 @@ used in NextStep supported as read-only + nextstep-cd + used for NextStep CDROMs (block_size == 2048) + supported as read-only + openstep used in OpenStep supported as read-only diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/CREDITS linux.pre11.3/Documentation/isdn/CREDITS --- linux.vanilla/Documentation/isdn/CREDITS Tue Jun 15 16:49:44 1999 +++ linux.pre11.3/Documentation/isdn/CREDITS Tue Jul 20 00:26:16 1999 @@ -24,7 +24,7 @@ Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) For his Sync-PPP-code. -Karsten Keil (isdn4@temic-ech.spacenet.de) +Karsten Keil (keil@isdn4linux.de) For adding 1TR6-support to the Teles-driver. For the HiSax-driver. diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/HiSax.cert linux.pre11.3/Documentation/isdn/HiSax.cert --- linux.vanilla/Documentation/isdn/HiSax.cert Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/Documentation/isdn/HiSax.cert Tue Jul 20 00:26:16 1999 @@ -0,0 +1,76 @@ +-----BEGIN PGP SIGNED MESSAGE----- + +First: + + HiSax is free software; you can redistribute 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. + +However, if you wish to modify the HiSax sources, please note the following: + +HiSax has passed the ITU approval test suite with ELSA Quickstep ISDN cards. +The certification is only valid for the combination of the tested software +version and the tested hardware. Any changes to the HiSax source code may +therefore affect the certification. + +If you change the main files of the HiSax ISDN stack, the certification will +become invalid. Because in most countries it is illegal to connect +unapproved ISDN equipment to the public network, I have to guarantee that +changes in HiSax do not affect the certification. + +In order to make a valid certification apparent to the user, I have built in +some validation checks that are made during the make process. The HiSax main +files are protected by md5 checksums and the md5sum file is pgp signed by +myself: + +KeyID 1024/FF992F6D 1997/01/16 Karsten Keil +Key fingerprint = 92 6B F7 58 EE 86 28 C8 C4 1A E6 DC 39 89 F2 AA + +Only if the checksums are OK, and the signature of the file +"drivers/isdn/hisax/md5sums.asc" match, is the certification valid; a +message confirming this is then displayed during the hisax init process. + +The affected files are: + +drivers/isdn/hisax/isac.c +drivers/isdn/hisax/isdnl1.c +drivers/isdn/hisax/isdnl2.c +drivers/isdn/hisax/isdnl3.c +drivers/isdn/hisax/tei.c +drivers/isdn/hisax/callc.c +drivers/isdn/hisax/l3dss1.c +drivers/isdn/hisax/l3_1tr6.c +drivers/isdn/hisax/cert.c +drivers/isdn/hisax/elsa.c + +Please send any changes, bugfixes and patches to me rather than implementing +them directly into the HiSax sources. + +This does not reduce your rights granted by the GNU General Public License. +If you wish to change the sources, go ahead; but note that then the +certification is invalid even if you use ELSA Quickstep cards. + +Here are the certification registration numbers for ELSA Quickstep cards: +German D133361J CETECOM ICT Services GmbH 0682 +European D133362J CETECOM ICT Services GmbH 0682 + + +Karsten Keil +keil@isdn4linux.de + +-----BEGIN PGP SIGNATURE----- +Version: 2.6.3i +Charset: noconv + +iQCVAwUBNj5OKDpxHvX/mS9tAQFHuQP/WeImlqCcDZ2d132yAvRBWFULlJoSf1P/ +c1lVTeaWvsSaY5Cu9hrKhXXhPzeEaitUbcUBPXdpzFWCA5CE902lnz7AhgRC+HF1 +0qiKgkZZyc/5HKasFymR1+IWSLw30GesP3Di/ZMR3NJi8SlY9PIjx7hnEMunGSRO +1ufPvfWWuu8= +=nGJk +-----END PGP SIGNATURE----- diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/INTERFACE linux.pre11.3/Documentation/isdn/INTERFACE --- linux.vanilla/Documentation/isdn/INTERFACE Sun Nov 8 15:08:48 1998 +++ linux.pre11.3/Documentation/isdn/INTERFACE Tue Jul 20 00:26:16 1999 @@ -1,4 +1,4 @@ -$Id: INTERFACE,v 1.8 1998/02/20 17:38:20 fritz Exp $ +$Id: INTERFACE,v 1.12 1999/07/13 20:59:59 werner Exp $ Description of the Interface between Linklevel and Hardwarelevel of isdn4linux: @@ -478,6 +478,14 @@ 1 = At least one device matching this call (RING on ttyI). HL-driver may send ALERTING on the D-channel in this case. 2 = Call will be rejected. + 3 = Incomplete number. + The CalledNumber would match, if more digits are appended. + This feature is needed for Number-Blocks assigned to + a line. In this case, the LL driver should assemble the + CalledNumber by handling keypad protocol and try again + later with a longer CalledNumber. + HL drivers serving ordinary lines should interpret this + return code like 0 (nothing matches). -1 = An error happened. (Invalid parameters for example.) ISDN_STAT_RUN: @@ -526,7 +534,9 @@ driver = driver-Id command = ISDN_STAT_BCONN arg = channel-number, locally to the driver. (starting with 0) - para = unused. + para.num = ASCII-String, containing type of connection (for analog + modem only). This will be appended to the CONNECT message + e.g. 14400/V.32bis ISDN_STAT_DHUP: @@ -645,3 +655,21 @@ arg = channel-number, locally to the driver. (starting with 0) para.errcode= ISDN_STAT_L1ERR_SEND: Packet lost while sending. ISDN_STAT_L1ERR_RECV: Packet lost while receiving. + ISDN_STAT_DISCH: + + With this call, the HL-driver signals the LL to disable or enable the + use of supplied channel and driver. + The call may be used to reduce the available number of B-channels after + loading the driver. The LL has to ignore a disabled channel when searching + for free channels. The HL driver itself never delivers STAT callbacks for + disabled channels. + The LL returns a nonzero code if the operation was not successfull or the + selected channel is actually regarded as busy. + + Parameter: + driver = driver-Id + command = ISDN_STAT_DISCH + arg = channel-number, locally to the driver. (starting with 0) + parm.num[0] = 0 if channel shall be disabled, else enabled. + + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/README linux.pre11.3/Documentation/isdn/README --- linux.vanilla/Documentation/isdn/README Sun Nov 8 15:08:48 1998 +++ linux.pre11.3/Documentation/isdn/README Tue Jul 20 00:26:16 1999 @@ -31,7 +31,7 @@ This mailinglist is bidirectionally gated to the newsgroup de.alt.comm.isdn4linux - + There is also a well maintained FAQ (both english and german) available at ftp.franken.de in /pub/isdn4linux/FAQ/ This FAQ is also available at http://www.lrz-muenchen.de/~ui161ab/www/isdn/ @@ -41,11 +41,11 @@ In the following Text, the terms MSN and EAZ are used. MSN is the abbreviation for (M)ultiple(S)ubscriber(N)umber, and applies - to Euro(EDSS1)-type lines. Usually it is simply the phone-number. + to Euro(EDSS1)-type lines. Usually it is simply the phone number. EAZ is the abbreviation of (E)ndgeraete(A)uswahl(Z)iffer and applies to German 1TR6-type lines. This is a one-digit string, - simply appended to the base phone-number + simply appended to the base phone number The internal handling is nearly identical, so replace the appropriate term to that one, which applies to your local ISDN-environment. @@ -56,13 +56,13 @@ A low-level-driver can register itself through an interface (which is defined in isdnif.h) and gets assigned a slot. The following char-devices are made available for each channel: - + A raw-control-device with the following functions: write: raw D-channel-messages (format: depends on driver). read: raw D-channel-messages (format: depends on driver). ioctl: depends on driver, i.e. for the ICN-driver, the base-address of the ports and the shared memory on the card can be set and read - also the boot-code and the protocol software can be loaded into + also the boot-code and the protocol software can be loaded into the card. O N L Y !!! for debugging (no locking against other devices): @@ -74,38 +74,38 @@ 128 tty-devices (64 cuix and 64 ttyIx) with integrated modem-emulator: The functionality is almost the same as that of a serial device - (the line-discs are handled by the kernel), which lets you run - SLIP, CSLIP and asynchronous PPP through the devices. We have tested + (the line-discs are handled by the kernel), which lets you run + SLIP, CSLIP and asynchronous PPP through the devices. We have tested Seyon, minicom, CSLIP (uri-dip) PPP and mgetty (compiled with NO_FAX), XCept. The modem-emulation supports the following: 1.3.1 Commands: - ATA Answer incoming call. - ATD Dial, the number may contain: + ATA Answer incoming call. + ATD Dial, the number may contain: [0-9] and [,#.*WPT-S] the latter are ignored until 'S'. - The 'S' must precede the number, if + The 'S' must precede the number, if the line is a SPV (German 1TR6). - ATE0 Echo off. - ATE1 Echo on (default). + ATE0 Echo off. + ATE1 Echo on (default). ATH Hang-up. - ATH1 Off hook (ignored). + ATH1 Off hook (ignored). ATH0 Hang-up. - ATI Return "ISDN for Linux...". + ATI Return "ISDN for Linux...". ATI0 " ATI1 " - ATI2 Report of last connection. + ATI2 Report of last connection. ATO On line (data mode). ATQ0 Enable result codes (default). ATQ1 Disable result codes (default). - ATSx=y Set register x to y. - ATSx? Show contents of register x. + ATSx=y Set register x to y. + ATSx? Show contents of register x. ATV0 Numeric responses. ATV1 English responses (default). - ATZ Load registers and EAZ/MSN from Profile. - AT&Bx Set Send-Packet-size to x (max. 4000) + ATZ Load registers and EAZ/MSN from Profile. + AT&Bx Set Send-Packet-size to x (max. 4000) The real packet-size may be limited by the low-level-driver used. e.g. the HiSax-Module- limit is 2000. You will get NO Error-Message, @@ -114,13 +114,13 @@ driver may not be selected (see "Automatic Assignment") however the size of outgoing packets will be limited correctly. - AT&D0 Ignore DTR - AT&D2 DTR-low-edge: Hang up and return to + AT&D0 Ignore DTR + AT&D2 DTR-low-edge: Hang up and return to command mode (default). AT&D3 Same as AT&D2 but also resets all registers. - AT&Ex Set the EAZ/MSN for this channel to x. - AT&F Reset all registers and profile to "factory-defaults" - AT&Rx Select V.110 bitrate adaption. + AT&Ex Set the EAZ/MSN for this channel to x. + AT&F Reset all registers and profile to "factory-defaults" + AT&Rx Select V.110 bitrate adaption. This command enables V.110 protocol with 9600 baud (x=9600), 19200 baud (x=19200) or 38400 baud (x=38400). A value of x=0 disables V.110 switching @@ -142,24 +142,24 @@ The value 198 is choosen arbitrarily. Users _MUST_ negotiate this value before establishing a connection. - AT&Sx Set window-size (x = 1..8) (not yet implemented) - AT&V Show all settings. + AT&Sx Set window-size (x = 1..8) (not yet implemented) + AT&V Show all settings. AT&W0 Write registers and EAZ/MSN to profile. See also iprofd (5.c in this README). - AT&X0 BTX-mode and T.70-mode off (default) - AT&X1 BTX-mode on. (S13.1=1, S13.5=0 S14=0, S16=7, S18=7, S19=0) - AT&X2 T.70-mode on. (S13.1=1, S13.5=1, S14=0, S16=7, S18=7, S19=0) + AT&X0 BTX-mode and T.70-mode off (default) + AT&X1 BTX-mode on. (S13.1=1, S13.5=0 S14=0, S16=7, S18=7, S19=0) + AT&X2 T.70-mode on. (S13.1=1, S13.5=1, S14=0, S16=7, S18=7, S19=0) For voice-mode commands refer to README.audio - 1.3.2 Escape sequence: + 1.3.2 Escape sequence: During a connection, the emulation reacts just like a normal modem to the escape sequence +++. - (The escape character - default '+' - can be set in the + (The escape character - default '+' - can be set in the register 2). - The DELAY must at least be 1.5 seconds long and delay + The DELAY must at least be 1.5 seconds long and delay between the escape characters must not exceed 0.5 seconds. - + 1.3.3 Registers: Nr. Default Description @@ -172,7 +172,7 @@ 4 10 Line feed character (ASCII). 5 8 Backspace character (ASCII). 6 3 Delay in seconds before dialing. - 7 60 Wait for carrier (ignored). + 7 60 Wait for carrier. 8 2 Pause time for comma (ignored) 9 6 Carrier detect time (ignored) 10 7 Carrier loss to disconnect time (ignored). @@ -203,8 +203,8 @@ 1 = T.70 protocol (Only for BTX!) on Bit 2: 0 = Don't hangup on DTR low. 1 = Hangup on DTR low. - Bit 3: 0 = Standard response messages - 1 = Extended response messages + Bit 3: 0 = Standard response messages + 1 = Extended response messages Bit 4: 0 = CALLER NUMBER before every RING. 1 = CALLER NUMBER after first RING. Bit 5: 0 = T.70 extended protocol off @@ -215,18 +215,25 @@ an incoming call happened (RING) and the remote party hung up before any local ATA was given. - 14 0 Layer-2 protocol: - 0 = X75/LAPB with I-frames - 1 = X75/LAPB with UI-frames + Bit 7: 0 = Don't show display messages from net + 1 = Show display messages from net + (S12 Bit 1 must be 0 too) + 14 0 Layer-2 protocol: + 0 = X75/LAPB with I-frames + 1 = X75/LAPB with UI-frames 2 = X75/LAPB with BUI-frames 3 = HDLC 4 = Transparent (audio) 7 = V.110, 9600 baud 8 = V.110, 19200 baud 9 = V.110, 38400 baud - 15 0 Layer-3 protocol: (at the moment always 0) + 10 = Analog Modem (only if hardware supports this) + 11 = Fax G3 (only if hardware supports this) + 15 0 Layer-3 protocol: 0 = transparent - 16 250 Send-Packet-size/16 + 1 = transparent with audio features (e.g. DSP) + 2 = Fax G3 (S14 has to be set to 11) + 16 250 Send-Packet-size/16 17 8 Window-size (not yet implemented) 18 4 Bit coded register, Service-Octet-1 to accept, or to be used on dialout: @@ -254,6 +261,9 @@ Set on incoming call (during RING) to octet 3a of calling party number IE (Screening info) See section 4.5.10 of ITU Q.931 + 23 0 Bit coded register: + Bit 0: 0 = Add CPN to RING message off + 1 = Add CPN to RING message on Last but not least a (at the moment fairly primitive) device to request the line-status (/dev/isdninfo) is made available. @@ -262,7 +272,7 @@ All inactive physical lines are listening to all EAZs for incoming calls and are NOT assigned to a specific tty or network interface. - When an incoming call is detected, the driver looks first for a network + When an incoming call is detected, the driver looks first for a network interface and then for an opened tty which: 1. is configured for the same EAZ. @@ -270,7 +280,7 @@ 3. (only for network interfaces if the security flag is set) contains the caller number in its access list. 4. Either the channel is not bound exclusively to another Net-interface, or - it is bound AND the other checks apply to exactly this Interface. + it is bound AND the other checks apply to exactly this interface. (For usage of the bind-features, refer to the isdnctrl-man-page) Only when a matching interface or tty is found is the call accepted @@ -301,7 +311,7 @@ Always use the latest module utilities. The current version is named in Documentation/Changes. Some old versions of insmod are not capable of setting the driver-Ids correctly. - + 3. Lowlevel-driver configuration. Configuration depends on how the drivers are built. See the @@ -310,7 +320,7 @@ 4. Device-inodes The major and minor numbers and their names are described in - Documentation/devices.txt. The major-numbers are: + Documentation/devices.txt. The major numbers are: 43 for the ISDN-tty's. 44 for the ISDN-callout-tty's. @@ -350,45 +360,64 @@ g) Set the timeout for hang-up: isdnctrl huptimeout isdn0 - h) additionally you may activate charge-hang-up (= Hang up before + h) additionally you may activate charge-hang-up (= Hang up before next charge-info, this only works, if your isdn-provider transmits the charge-info during and after the connection): isdnctrl chargehup isdn0 on - i) Setup the interface with ifconfig as usual, and set a route to it. + i) Set the dial mode of the interface: + isdnctrl dialmode isdn0 auto + "off" means that you (or the system) cannot make any connection + (neither incoming or outgoing connections are possible). Use + this if you want to be sure that no connections will be made. + "auto" means that the interface is in auto-dial mode, and will + attempt to make a connection whenever a network data packet needs + the interface's link. Note that this can cause unexpected dialouts, + and lead to a high phone bill! Some daemons or other pc's that use + this interface can cause this. + Incoming connections are also possible. + "manual" is a dial mode created to prevent the unexpected dialouts. + In this mode, the interface will never make any connections on its + own. You must explicitly initiate a connection with "isdnctrl dial + isdn0". However, after an idle time of no traffic as configured for + the huptimeout value with isdnctrl, the connection _will_ be ended. + If you don't want any automatic hangup, set the huptimeout value to 0. + "manual" is the default. - j) (optional) If you run X11 and have Tcl/Tk-wish Version 4.0, you can use + j) Setup the interface with ifconfig as usual, and set a route to it. + + k) (optional) If you run X11 and have Tcl/Tk-wish version 4.0, you can use the script tools/tcltk/isdnmon. You can add actions for line-status changes. See the comments at the beginning of the script for how to do that. There are other tty-based tools in the tools-subdirectory contributed by Michael Knigge (imon), Volker Götz (imontty) and Andreas Kool (isdnmon). - k) For initial testing, you can set the verbose-level to 2 (default: 0). + l) For initial testing, you can set the verbose-level to 2 (default: 0). Then all incoming calls are logged, even if they are not addressed to one of the configured net-interfaces: isdnctrl verbose 2 - Now you are ready! A ping to the set address should now result in a - dial-out (look at syslog kernel-messages). - The phone-numbers and EAZs can be assigned at any time with isdnctrl. + Now you are ready! A ping to the set address should now result in an + automatic dial-out (look at syslog kernel-messages). + The phone numbers and EAZs can be assigned at any time with isdnctrl. You can add as many interfaces as you like with addif following the - directions above. Of course, there may be some limitations. But we have - tested as many as 20 interfaces without any problem. However, if you - don't give an interface name to addif, the kernel will assign a name + directions above. Of course, there may be some limitations. But we have + tested as many as 20 interfaces without any problem. However, if you + don't give an interface name to addif, the kernel will assign a name which starts with "eth". The number of "eth"-interfaces is limited by the kernel. 5. Additional options for isdnctrl: - "isdnctrl secure on" + "isdnctrl secure on" Only incoming calls, for which the caller-id is listed in the access list of the interface are accepted. You can add caller-id's With the command "isdnctrl addphone in " Euro-ISDN does not transmit the leading '0' of the caller-id for an incoming call, therefore you should configure it accordingly. If the real number for the dialout e.g. is "09311234567" the number - to configure here is "9311234567". The pattern-match function + to configure here is "9311234567". The pattern-match function works similar to the shell mechanism. ? one arbitrary digit @@ -398,23 +427,23 @@ a '^' as the first character in a list inverts the list - "isdnctrl secure off" + "isdnctrl secure off" Switch off secure operation (default). - "isdnctrl ihup [on|off]" + "isdnctrl ihup [on|off]" Switch the hang-up-timer for incoming calls on or off. - "isdnctrl eaz " + "isdnctrl eaz " Returns the EAZ of an interface. - "isdnctrl delphone in|out " + "isdnctrl delphone in|out " Deletes a number from one of the access-lists of the interface. - "isdnctrl delif " + "isdnctrl delif " Removes the interface (and possible slaves) from the kernel. (You have to unregister it with "ifconfig down" before). - "isdnctrl callback [on|off]" + "isdnctrl callback [on|off]" Switches an interface to callback-mode. In this mode, an incoming call will be rejected and after this the remote-station will be called. If you test this feature by using ping, some routers will re-dial very @@ -435,14 +464,14 @@ only while an interface is down. At the moment the following values are supported: - + rawip (Default) Selects raw-IP-encapsulation. This means, MAC-headers - are stripped off. + are stripped off. ip IP with type-field. Same as IP but the type-field of the MAC-header is preserved. x25iface X.25 interface encapsulation (first byte semantics as defined in - ../networking/x25-iface.txt). Use this for running the linux - X.25 network protocol stack (AF_X25 sockets) on top of isdn. + ../networking/x25-iface.txt). Use this for running the linux + X.25 network protocol stack (AF_X25 sockets) on top of isdn. cisco-h A special-mode for communicating with a Cisco, which is configured to do "hdlc" ethernet No stripping. Packets are sent with full MAC-header. @@ -454,7 +483,7 @@ NOTE: x25iface encapsulation is currently experimental. Please - read README.x25 for further details + read README.x25 for further details Watching packets, using standard-tcpdump will fail for all encapsulations @@ -462,16 +491,16 @@ without MAC-header. A patch for tcpdump is included in the utility-package mentioned above. - "isdnctrl l2_prot " - Selects a layer-2-protocol. + "isdnctrl l2_prot " + Selects a layer-2-protocol. (With the ICN-driver and the HiSax-driver, "x75i" and "hdlc" is available. With other drivers, "x75ui", "x75bui", "x25dte", "x25dce" may be possible too. See README.x25 for x25 related l2 protocols.) - isdnctrl l3_prot + isdnctrl l3_prot The same for layer-3. (At the moment only "trans" is allowed) - "isdnctrl list " + "isdnctrl list " Shows all parameters of an interface and the charge-info. Try "all" as the interface name. @@ -479,13 +508,13 @@ Forces hangup of an interface. "isdnctrl bind , [exclusive]" - If you are using more than one ISDN-Card, it is sometimes necessary to - dial out using a specific Card or even preserve a specific Channel for - Dialout of a specific net-interface. This can be done with the above + If you are using more than one ISDN card, it is sometimes necessary to + dial out using a specific card or even preserve a specific channel for + dialout of a specific net-interface. This can be done with the above command. Replace by whatever you assigned while loading the - module. The is counting from zero. The upper Limit - depends on the card used. At the Moment no card supports more than - 2 Channels, so the upper limit is one. + module. The is counted from zero. The upper limit + depends on the card used. At the moment no card supports more than + 2 channels, so the upper limit is one. "isdnctrl unbind " unbinds a previously bound interface. @@ -494,10 +523,10 @@ If switched on, isdn4linux replies a REJECT to incoming calls, it cannot match to any configured interface. If switched off, nothing happens in this case. - You normally should NOT enable this feature, if the ISDN-adaptor is not - the only device, connected to the S0-bus. Otherwise it could happen, that + You normally should NOT enable this feature, if the ISDN adapter is not + the only device connected to the S0-bus. Otherwise it could happen that isdn4linux rejects an incoming call, which belongs to another device on - the bus. + the bus. "isdnctrl addslave Creates a slave interface for channel-bundling. Slave interfaces are @@ -539,9 +568,9 @@ isdnctrl eaz isdn1 4 # listen on 12345674(1tr6) only. ... isdnctrl eaz isdn2 987654 # listen on 987654(euro) only. - + Same scheme is used with AT&E... at the tty's. - + 6. If you want to write a new low-level-driver, you are welcome. The interface to the link-level-module is described in the file INTERFACE. If the interface should be expanded for any reason, don't do it diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/README.HiSax linux.pre11.3/Documentation/isdn/README.HiSax --- linux.vanilla/Documentation/isdn/README.HiSax Sun Nov 8 15:08:48 1998 +++ linux.pre11.3/Documentation/isdn/README.HiSax Tue Jul 20 00:26:16 1999 @@ -1,7 +1,7 @@ HiSax is a Linux hardware-level driver for passive ISDN cards with Siemens chipset (ISAC_S 2085/2086/2186, HSCX SAB 82525). It is based on the Teles driver from Jan den Ouden. -It is meant to be used with isdn4linux, an ISDN link-level module for Linux +It is meant to be used with isdn4linux, an ISDN link-level module for Linux written by Fritz Elfert. This program is free software; you can redistribute it and/or modify @@ -25,31 +25,50 @@ Teles 8.0/16.0/16.3 and compatible ones Teles 16.3c Teles S0/PCMCIA -Creatix PnP S0 +Teles PCI +Teles S0Box +Creatix S0Box +Creatix PnP S0 Compaq ISDN S0 ISA card AVM A1 (Fritz, Teledat 150) +AVM Fritz PCMCIA +AVM Fritz PnP +AVM Fritz PCI ELSA Microlink PCC-16, PCF, PCF-Pro, PCC-8 ELSA Quickstep 1000 ELSA Quickstep 1000PCI ELSA Quickstep 3000 (same settings as QS1000) +ELSA Quickstep 3000PCI ELSA PCMCIA ITK ix1-micro Rev.2 Eicon.Diehl Diva 2.0 ISA and PCI (S0 and U interface, no PRO version) +Eicon.Diehl Diva 2.01 ISA and PCI Eicon.Diehl Diva Piccola ASUSCOM NETWORK INC. ISDNLink 128K PC adapter (order code I-IN100-ST-D) Dynalink IS64PH (OEM version of ASUSCOM NETWORK INC. ISDNLink 128K adapter) +PCBIT-DP (OEM version of ASUSCOM NETWORK INC. ISDNLink) HFC-2BS0 based cards (TeleInt SA1) -Sedlbauer Speed Card (Speed Win, Teledat 100) -Sedlbauer Speed Star (PCMCIA) +Sedlbauer Speed Card (Speed Win, Teledat 100, PCI, Fax+) +Sedlbauer Speed Star/Speed Star2 (PCMCIA) +Sedlbauer ISDN-Controller PC/104 USR Sportster internal TA (compatible Stollmann tina-pp V3) -ith Kommunikationstechnik GmbH MIC 16 ISA card +ith Kommunikationstechnik GmbH MIC 16 ISA card Traverse Technologie NETjet PCI S0 card Dr. Neuhaus Niccy PnP/PCI +Siemens I-Surf +ACER P10 +HST Saphir +Berkom Telekom A4T +Scitel Quadro +Gazel ISDN cards +HFC-PCI based cards Note: PCF, PCF-Pro: up to now, only the ISDN part is supported PCC-8: not tested yet Teles PCMCIA is EXPERIMENTAL Teles 16.3c is EXPERIMENTAL + Teles PCI is EXPERIMENTAL + Teles S0Box is EXPERIMENTAL Eicon.Diehl Diva U interface not tested If you know other passive cards with the Siemens chipset, please let me know. @@ -113,7 +132,7 @@ correct one during kernel config. Valid values are "1" for German 1TR6, "2" for EDSS1 (Euro ISDN) and "3" for leased lines (no D-Channel). -The Creatix/Teles PnP cards use io1= and io2= instead of io= for specifying +The Creatix/Teles PnP cards use io1= and io2= instead of io= for specifying the I/O addresses of the ISAC and HSCX chips, respectively. Card types: @@ -135,24 +154,37 @@ 11 Eicon.Diehl Diva ISA PnP irq, io 11 Eicon.Diehl Diva PCI no parameter 12 ASUS COM ISDNLink irq, io (from isapnp setup) - 13 HFC-2BS0 based cards irq, io + 13 HFC-2BS0 based cards irq, io 14 Teles 16.3c PnP irq, io - 15 Sedlbauer Speed Card irq, io - 16 USR Sportster internal irq, io - 17 MIC card irq, io + 15 Sedlbauer Speed Card irq, io + 15 Sedlbauer PC/104 irq, io + 15 Sedlbauer Speed PCI no parameter + 16 USR Sportster internal irq, io + 17 MIC card irq, io 18 ELSA Quickstep 1000PCI no parameter 19 Compaq ISDN S0 ISA card irq, io0, io1, io (from isapnp setup io=IO2) 20 NETjet PCI card no parameter + 21 Teles PCI no parameter 22 Sedlbauer Speed Star (PCMCIA) irq, io (set with card manager) 24 Dr. Neuhaus Niccy PnP irq, io0, io1 (from isapnp setup) 24 Dr. Neuhaus Niccy PCI no parameter + 25 Teles S0Box irq, io (of the used lpt port) + 26 AVM A1 PCMCIA (Fritz!) irq, io (set with card manager) + 27 AVM PnP (Fritz!PnP) irq, io (from isapnp setup) + 27 AVM PCI (Fritz!PCI) no parameter + 28 Sedlbauer Speed Fax+ irq, io (from isapnp setup) + 29 Siemens I-Surf irq, io, memory (from isapnp setup) + 30 ACER P10 irq, io (from isapnp setup) + 31 HST Saphir irq, io + 32 Telekom A4T none + 33 Scitel Quadro subcontroller (4*S0, subctrl 1...4) + 34 Gazel ISDN cards (ISA) irq,io + 34 Gazel ISDN cards (PCI) none + 35 HFC 2BDS0 PCI none - -At the moment IRQ sharing is not possible. Please make sure that your IRQ -is free and enabled for ISA use. -Note: For using the ELSA PCMCIA you need the cardmanager under MSDOS for -enabling at the moment, then boot linux with loadlin. +At the moment IRQ sharing is only possible with PCI cards. Please make sure +that your IRQ is free and enabled for ISA use. Examples for module loading @@ -169,7 +201,7 @@ 4. Any ELSA PCC/PCF card, Euro ISDN modprobe hisax type=6 protocol=2 -5. Teles 16.3 PnP, Euro ISDN, with isapnp configured +5. Teles 16.3 PnP, Euro ISDN, with isapnp configured isapnp config: (INT 0 (IRQ 10 (MODE +E))) (IO 0 (BASE 0x0580)) (IO 1 (BASE 0x0180)) @@ -210,8 +242,8 @@ Note: the ID string must start with an alphabetical character! Card types: - - type + +type 1 Teles 16.0 pa=irq pb=membase pc=iobase 2 Teles 8.0 pa=irq pb=membase 3 Teles 16.3 pa=irq pb=iobase @@ -227,22 +259,40 @@ 12 ASUS COM ISDNLink ONLY WORKS AS A MODULE ! 13 HFC-2BS0 based cards pa=irq pb=io 14 Teles 16.3c PnP ONLY WORKS AS A MODULE ! - 15 Sedlbauer Speed Card pa=irq pb=io (Speed Win only as module !) + 15 Sedlbauer Speed Card pa=irq pb=io (Speed Win only as module !) + 15 Sedlbauer PC/104 pa=irq pb=io + 15 Sedlbauer Speed PCI no parameter 16 USR Sportster internal pa=irq pb=io 17 MIC card pa=irq pb=io 18 ELSA Quickstep 1000PCI no parameter 19 Compaq ISDN S0 ISA card ONLY WORKS AS A MODULE ! 20 NETjet PCI card no parameter - 21 Sedlbauer Speed Star (PCMCIA) pa=irq, pb=io (set with card manager) + 21 Teles PCI no parameter + 22 Sedlbauer Speed Star (PCMCIA) pa=irq, pb=io (set with card manager) + 24 Dr. Neuhaus Niccy PnP ONLY WORKS AS A MODULE ! + 24 Dr. Neuhaus Niccy PCI no parameter + 25 Teles S0Box pa=irq, pb=io (of the used lpt port) + 26 AVM A1 PCMCIA (Fritz!) pa=irq, pb=io (set with card manager) + 27 AVM PnP (Fritz!PnP) ONLY WORKS AS A MODULE ! + 27 AVM PCI (Fritz!PCI) no parameter + 28 Sedlbauer Speed Fax+ ONLY WORKS AS A MODULE ! + 29 Siemens I-Surf ONLY WORKS AS A MODULE ! + 30 ACER P10 ONLY WORKS AS A MODULE ! + 31 HST Saphir pa=irq, pb=io + 32 Telekom A4T no parameter + 33 Scitel Quadro subcontroller (4*S0, subctrl 1...4) + 34 Gazel ISDN cards (ISA) pa=irq, pb=io + 34 Gazel ISDN cards (PCI) no parameter + 35 HFC 2BDS0 PCI no parameter Running the driver ------------------ -When you insmod isdn.o and hisax.o (or with the in-kernel version, during +When you insmod isdn.o and hisax.o (or with the in-kernel version, during boot time), a few lines should appear in your syslog. Look for something like: Apr 13 21:01:59 kke01 kernel: HiSax: Driver for Siemens chip set ISDN cards -Apr 13 21:01:59 kke01 kernel: HiSax: Version 2.1 +Apr 13 21:01:59 kke01 kernel: HiSax: Version 2.9 Apr 13 21:01:59 kke01 kernel: HiSax: Revisions 1.14/1.9/1.10/1.25/1.8 Apr 13 21:01:59 kke01 kernel: HiSax: Total 1 card defined Apr 13 21:01:59 kke01 kernel: HiSax: Card 1 Protocol EDSS1 Id=HiSax1 (0) @@ -257,7 +307,7 @@ Apr 13 21:01:59 kke01 kernel: HiSax: 2 channels added This means that the card is ready for use. -Cabling problems or line-downs are not detected, and only some ELSA cards can +Cabling problems or line-downs are not detected, and only some ELSA cards can detect the S0 power. Remember that, according to the new strategy for accessing low-level drivers @@ -265,8 +315,7 @@ insmod: Simply append hisax_id= to the insmod command line. This string MUST NOT start with a digit or a small 'x'! -At this point you can run a 'cat /dev/isdnctrl0' and view debugging -messages. +At this point you can run a 'cat /dev/isdnctrl0' and view debugging messages. At the moment, debugging messages are enabled with the hisaxctrl tool: @@ -283,28 +332,35 @@ With DebugCmd set to 1: - 1 Link-level <--> hardware-level communication - 2 Top state machine - 4 D-Channel Q.931 (call control messages) - 8 D-Channel Q.921 - 16 B-Channel X.75 - 32 D-Channel l2 - 64 B-Channel l2 - 128 D-Channel link state debugging - 256 B-Channel link state debugging - 512 TEI debug - 1024 LOCK debug in callc.c - 2048 More paranoid debug in callc.c (not for normal use) + 0x0001 Link-level <--> hardware-level communication + 0x0002 Top state machine + 0x0004 D-Channel Frames for isdnlog + 0x0008 D-Channel Q.921 + 0x0010 B-Channel X.75 + 0x0020 D-Channel l2 + 0x0040 B-Channel l2 + 0x0080 D-Channel link state debugging + 0x0100 B-Channel link state debugging + 0x0200 TEI debug + 0x0400 LOCK debug in callc.c + 0x0800 More paranoid debug in callc.c (not for normal use) + 0x1000 D-Channel l1 state debugging + 0x2000 B-Channel l1 state debugging With DebugCmd set to 11: - 1 Warnings (default: on) - 2 IRQ status - 4 ISAC - 8 ISAC FIFO - 16 HSCX - 32 HSCX FIFO (attention: full B-Channel output!) - 64 D-Channel LAPD frame types + 0x0001 Warnings (default: on) + 0x0002 IRQ status + 0x0004 ISAC + 0x0008 ISAC FIFO + 0x0010 HSCX + 0x0020 HSCX FIFO (attention: full B-Channel output!) + 0x0040 D-Channel LAPD frame types + 0x0080 IPAC debug + 0x0100 HFC receive debug + 0x0200 ISAC monitor debug + 0x0400 D-Channel frames for isdnlog (set with 1 0x4 too) + 0x0800 D-Channel message verbose With DebugCmd set to 13: @@ -317,27 +373,39 @@ Because of some obscure problems with some switch equipment, the delay between the CONNECT message and sending the first data on the B-channel is now -configurable with +configurable with hisaxctrl 2 in ms Value between 50 and 800 ms is recommended. +Downloading Firmware +-------------------- +At the moment, the Sedlbauer speed fax+ is the only card, which +needs to download firmware. +The firmware is downloaded with the hisaxctrl tool: + + hisaxctrl 9 + + default is HiSax, if you didn't specify one, + +where is the filename of the firmware file. + +For example, 'hisaxctrl HiSax 9 ISAR.BIN' downloads the firmware for +ISAR based cards (like the Sedlbauer speed fax+). Warning ------- -HiSax is a work in progress and may crash your machine. It has not been -certified and therefore operation on your PTT's ISDN network is probably -illegal. - +HiSax is a work in progress and may crash your machine. +For certification look at HiSax.cert file. Limitations ----------- At this time, HiSax only works on Euro ISDN lines and German 1TR6 lines. -For leased lines see appendix. +For leased lines see appendix. -Bugs +Bugs ---- -If you find any, please let me know. +If you find any, please let me know. Thanks @@ -354,8 +422,10 @@ Stephan von Krawczynski Juergen Quade for the Leased Line part Klaus Lichtenwalder (Klaus.Lichtenwalder@WebForum.DE), for ELSA PCMCIA support + Enrik Berkhan (enrik@starfleet.inka.de) for S0BOX specific stuff + Ton van Rosmalen for Teles PCI and more people who are hunting bugs. (If I forgot somebody, please - send me a mail). + send me a mail). Firma ELSA GmbH Firma Eicon.Diehl GmbH @@ -364,20 +434,23 @@ Firma S.u.S.E Firma ith Kommunikationstechnik GmbH Firma Traverse Technologie Australia - + Firma Medusa GmbH (www.medusa.de). + Firma Quant-X Austria for sponsoring a DEC Alpha board+CPU + Firma Cologne Chip Designs GmbH + My girl friend and partner in life Ute for her patience with me. Enjoy, -Karsten Keil -keil@temic-ech.spacenet.de +Karsten Keil +keil@isdn4linux.de Appendix: Teles PCMCIA driver ----------------------------- -See +See http://www.stud.uni-wuppertal.de/~ea0141/pcmcia.html for instructions. @@ -451,7 +524,7 @@ /sbin/isdnctrl l2_prot isdn0 hdlc # Attention you must not set an outgoing number !!! This won't work !!! # The incomming number is LEASED0 for the first card, LEASED1 for the - # second and so on. + # second and so on. /sbin/isdnctrl addphone isdn0 in LEASED0 # Here is no need to bind the channel. c) in case the remote partner is a CISCO: @@ -461,11 +534,11 @@ e) set the routes /sbin/route add -host ${REMOTE_IP} isdn0 /sbin/route add default gw ${REMOTE_IP} - f) switch the card into leased mode for each used B-channel + f) switch the card into leased mode for each used B-channel /sbin/hisaxctrl HiSax 5 1 - + Remarks: -a) If you have a CISCO don't forget to switch off the KEEP ALIVE option! +a) Use state of the art isdn4k-utils Here an example script: #!/bin/sh @@ -517,6 +590,7 @@ /sbin/isdnctrl encap isdn0s cisco-h fi fi + /sbin/isdnctrl dialmode isdn0 manual # configure tcp/ip /sbin/ifconfig isdn0 ${LOCAL_IP} pointopoint ${REMOTE_IP} /sbin/route add -host ${REMOTE_IP} isdn0 @@ -526,6 +600,7 @@ /sbin/hisaxctrl HiSax 5 1 if [ ${I4L_LEASED_128K} = "yes" ]; then # B-CHANNEL 2 + sleep 10; /* Wait for master */ /sbin/hisaxctrl HiSax 5 2 fi ;; @@ -547,4 +622,3 @@ exit 1 esac exit 0 - diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/README.act2000 linux.pre11.3/Documentation/isdn/README.act2000 --- linux.vanilla/Documentation/isdn/README.act2000 Sat Jan 9 21:50:34 1999 +++ linux.pre11.3/Documentation/isdn/README.act2000 Tue Jul 20 00:26:16 1999 @@ -1,4 +1,4 @@ -$Id: README.act2000,v 1.1 1997/09/24 23:50:16 fritz Exp $ +$Id: README.act2000,v 1.2 1998/04/29 19:49:06 he Exp $ This document describes the ACT2000 driver for the IBM Active 2000 ISDN card. @@ -7,7 +7,7 @@ Version. Currently, only the ISA-Bus version of the card is supported. However MCA and PCMCIA will follow soon. -The ISA-Bus Version uses 8 IO-ports. The base port address has to be set +The ISA-Bus Version uses 8 IO-ports. The base port adress has to be set manually using the DIP switches. Setting up the DIP switches for the IBM Active 2000 ISDN card: diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/README.audio linux.pre11.3/Documentation/isdn/README.audio --- linux.vanilla/Documentation/isdn/README.audio Sun Nov 8 15:08:48 1998 +++ linux.pre11.3/Documentation/isdn/README.audio Tue Jul 20 00:26:16 1999 @@ -1,4 +1,4 @@ -$Id: README.audio,v 1.5 1997/02/23 23:53:46 fritz Exp $ +$Id: README.audio,v 1.8 1999/07/11 17:17:29 armin Exp $ ISDN subsystem for Linux. Description of audio mode. @@ -50,13 +50,25 @@ the application. See below for data format AT+VSD=x,y Set silence-detection parameters. - NO EFFECT, supported for compatibility - only. Possible parameters: - x = 0 ... 31 - y = 0 ... 255 + Possible parameters: + x = 0 ... 31 sensitivity threshold level. + (default 0 , deactivated) + y = 0 ... 255 range of interval in units + of 0.1 second. (default 70) AT+VSD=? Report possible parameters. AT+VSD? Show current parameters. + AT+VDD=x,y Set DTMF-detection parameters. + Only possible if online and during this connection. + Possible parameters: + x = 0 ... 15 sensitivity threshold level. + (default 0 , I4L soft-decode) + (1-15 soft-decode off, hardware on) + y = 0 ... 255 tone duration in units of 5ms. + Not for I4L soft decode (default 8, 40ms) + AT+VDD=? Report possible parameters. + AT+VDD? Show current parameters. + AT+VSM=x Select audio data format. Possible parameters: 2 = ADPCM-2 @@ -102,13 +114,14 @@ C Touchtone "C" received. D Touchtone "D" received. + q quiet. Silence detected after non-silence. + s silence. Silence detected from the + start of recording. + Currently unsupported DLE sequences: c FAX calling tone received. b busy tone received. - q quiet. Silence detected after non-silence. - s silence. Silence detected from the - start of recording. Audio playback. diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/README.avmb1 linux.pre11.3/Documentation/isdn/README.avmb1 --- linux.vanilla/Documentation/isdn/README.avmb1 Sun Nov 8 15:08:48 1998 +++ linux.pre11.3/Documentation/isdn/README.avmb1 Tue Jul 20 00:26:16 1999 @@ -1,10 +1,22 @@ +Driver for active AVM Controller. + The driver provides a kernel capi2.0 Interface (kernelcapi) and on top of this a User-Level-CAPI2.0-interface (capi) and a driver to connect isdn4linux with CAPI2.0 (capidrv). +The lowlevel interface can be used to implement a CAPI2.0 +also for passive cards since July 1999. -The Author can be reached at calle@calle.in-berlin.de -The command avmcapictrl is part of the isdn4linux-utils. -t4-files can be found at ftp.avm.de. +The author can be reached at calle@calle.in-berlin.de. +The command avmcapictrl is part of the isdn4k-utils. +t4-files can be found at ftp://ftp.avm.de/cardware/b1/linux/firmware + +Currently supported cards: + B1 ISA (all versions) + B1 PCI + T1/T1B (HEMA card) + M1 + M2 + B1 PCMCIA Installing ---------- @@ -26,32 +38,145 @@ AVM GmbH provides several t4-files for the different D-channel protocols (b1.t4 for Euro-ISDN). Install these file in /lib/isdn. -If you do not compile the driver as modules, you have to add the -card(s) and load them after booting: - -avmcapictrl add 0x150 15 -avmcapictrl load /lib/isdn/b1.t4 1 - -if you configure as modules you have two possibilities: +if you configure as modules load the modules this way: insmod /lib/modules/current/misc/capiutil.o -insmod /lib/modules/current/misc/kernelcapi.o portbase=0x150 irq=15 +insmod /lib/modules/current/misc/b1.o +insmod /lib/modules/current/misc/kernelcapi.o insmod /lib/modules/current/misc/capidrv.o insmod /lib/modules/current/misc/capi.o -avmcapictrl load /lib/isdn/b1.t4 -or +if you have an B1-PCI card load the module b1pci.o +insmod /lib/modules/current/misc/b1pci.o +and load the firmware with +avmcapictrl load /lib/isdn/b1.t4 1 -insmod /lib/modules/current/misc/capiutil.o -insmod /lib/modules/current/misc/kernelcapi.o -insmod /lib/modules/current/misc/capidrv.o -insmod /lib/modules/current/misc/capi.o +if you have an B1-ISA card load the module b1isa.o +and add the card by calling avmcapictrl add 0x150 15 -avmcapictrl load /lib/isdn/b1.t4 +and load the firmware by calling +avmcapictrl load /lib/isdn/b1.t4 1 + +if you have an T1-ISA card load the module t1isa.o +and add the card by calling +avmcapictrl add 0x450 15 T1 0 +and load the firmware by calling +avmcapictrl load /lib/isdn/t1.t4 1 + +if you have an PCMCIA card (B1/M1/M2) load the module b1pcmcia.o +before you insert the card. + +Leased Lines with B1 +-------------------- +Init card and load firmware. +For an D64S use "FV: 1" as phone number +For an D64S2 use "FV: 1" and "FV: 2" for multilink +or "FV: 1,2" to use CAPI channel bundling. + +/proc-Interface +----------------- + +/proc/capi: + dr-xr-xr-x 2 root root 0 Jul 1 14:03 . + dr-xr-xr-x 82 root root 0 Jun 30 19:08 .. + -r--r--r-- 1 root root 0 Jul 1 14:03 applications + -r--r--r-- 1 root root 0 Jul 1 14:03 applstats + -r--r--r-- 1 root root 0 Jul 1 14:03 capi20 + -r--r--r-- 1 root root 0 Jul 1 14:03 capidrv + -r--r--r-- 1 root root 0 Jul 1 14:03 controller + -r--r--r-- 1 root root 0 Jul 1 14:03 contrstats + -r--r--r-- 1 root root 0 Jul 1 14:03 driver + -r--r--r-- 1 root root 0 Jul 1 14:03 ncci + -r--r--r-- 1 root root 0 Jul 1 14:03 users + +/proc/capi/applications: + applid level3cnt datablkcnt datablklen ncci-cnt recvqueuelen + level3cnt: capi_register parameter + datablkcnt: capi_register parameter + ncci-cnt: current number of nccis (connections) + recvqueuelen: number of messages on receive queue + for example: +1 -2 16 2048 1 0 +2 2 7 2048 1 0 + +/proc/capi/applstats: + applid recvctlmsg nrecvdatamsg nsentctlmsg nsentdatamsg + recvctlmsg: capi messages received without DATA_B3_IND + recvdatamsg: capi DATA_B3_IND received + sentctlmsg: capi messages sent without DATA_B3_REQ + sentdatamsg: capi DATA_B3_REQ sent + for example: +1 2057 1699 1721 1699 + +/proc/capi/capi20: statistics of capi.o (/dev/capi20) + minor nopen nrecvdropmsg nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg + minor: minor device number of capi device + nopen: number of calls to devices open + nrecvdropmsg: capi messages dropped (messages in recvqueue in close) + nrecvctlmsg: capi messages received without DATA_B3_IND + nrecvdatamsg: capi DATA_B3_IND received + nsentctlmsg: capi messages sent without DATA_B3_REQ + nsentdatamsg: capi DATA_B3_REQ sent + + for example: +1 2 18 0 16 2 + +/proc/capi/capidrv: statistics of capidrv.o (capi messages) + nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg + nrecvctlmsg: capi messages received without DATA_B3_IND + nrecvdatamsg: capi DATA_B3_IND received + nsentctlmsg: capi messages sent without DATA_B3_REQ + nsentdatamsg: capi DATA_B3_REQ sent + for example: +2780 2226 2256 2226 + +/proc/capi/controller: + controller drivername state cardname controllerinfo + for example: +1 b1pci running b1pci-e000 B1 3.07-01 0xe000 19 +2 t1isa running t1isa-450 B1 3.07-01 0x450 11 0 +3 b1pcmcia running m2-150 B1 3.07-01 0x150 5 + +/proc/capi/contrstats: + controller nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg + nrecvctlmsg: capi messages received without DATA_B3_IND + nrecvdatamsg: capi DATA_B3_IND received + nsentctlmsg: capi messages sent without DATA_B3_REQ + nsentdatamsg: capi DATA_B3_REQ sent + for example: +1 2845 2272 2310 2274 +2 2 0 2 0 +3 2 0 2 0 + +/proc/capi/driver: + drivername ncontroller + for example: +b1pci 1 +t1isa 1 +b1pcmcia 1 +b1isa 0 + +/proc/capi/ncci: + apllid ncci winsize sendwindow + for example: +1 0x10101 8 0 + +/proc/capi/users: kernelmodules that use the kernelcapi. + name + for example: +capidrv +capi20 Questions --------- -Check out the FAQ (ftp.franken.de). +Check out the FAQ (ftp.franken.de) or subscribe to the +linux-avmb1@calle.in-berlin.de mailing list by sending +a mail to majordomo@calle.in-berlin.de with +subscribe linux-avmb1 +in the body. + +German documentaion and several scripts can be found at +ftp://ftp.avm.de/cardware/b1/linux/ Bugs ---- diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/README.concap linux.pre11.3/Documentation/isdn/README.concap --- linux.vanilla/Documentation/isdn/README.concap Sat Jan 9 21:50:34 1999 +++ linux.pre11.3/Documentation/isdn/README.concap Tue Jul 20 00:26:16 1999 @@ -256,3 +256,4 @@ of the concap interface when a trivial concap protocol is used. Nevertheless, the device remains able to support encapsulation protocol configuration. + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/README.eicon linux.pre11.3/Documentation/isdn/README.eicon --- linux.vanilla/Documentation/isdn/README.eicon Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/Documentation/isdn/README.eicon Tue Jul 20 00:26:16 1999 @@ -0,0 +1,88 @@ +$Id: README.eicon,v 1.4 1999/07/11 17:17:30 armin Exp $ + +(c) 1999 Cytronics & Melware + +This document describes the eicon driver for the +Eicon.Diehl active ISDN cards. + +It is meant to be used with isdn4linux, an ISDN link-level module for Linux. + + This program is free software; you can redistribute 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. + + + +Supported Cards +--------------- + +- S-Card ISA +- SX-Card ISA +- SXn-Card ISA +- SCOM-Card ISA +- Quadro-Card ISA +- S2M-Card ISA +- DIVA Server BRI/PCI 2M +- DIVA Server PRI/PCI 2M (9M 23M 30M) + (Only analog modem functions of the DSPs are currently implemented) + +ISDN D-Channel Protocols +------------------------ + +- ETSI (Euro-DSS1) +- 1TR6 (German ISDN) *not testet* + + + +You can load the module simply by using the insmod or modprobe function : + + insmod eicon [id=driverid] [membase=] [irq=] + + +The module will automatically probe the PCI-cards. If the id-options +is omitted, the driver will assume 'eicon0' for the first pci card and +increases the digit with each further card. With a given driver-id +the module appends a number starting with '0'. + +For ISA-cards you have to specify membase, irq and id. If id or +membase is missing/invalid, the driver will not be loaded except +PCI-cards were found. Additional ISA-cards and irq/membase changes +can be done with the eiconctrl utility. + +After loading the module, you have to download the protocol and +dsp-code by using the eiconctrl utility of isdn4k-utils. + + +Example for loading and starting a BRI card with E-DSS1 Protocol. + + eiconctrl [-d DriverId] load etsi + + +Example for loading and starting a PRI card with E-DSS1 Protocol. + + eiconctrl [-d DriverId] load etsi -s2 -n + + +Details about using the eiconctrl utility are in 'man eiconctrl' +or will be printed by starting eiconctrl without any parameters. + + + +Any reports about bugs, errors and even wishes are welcome. + + +Have fun ! + +Armin Schindler +mac@melware.de +http://www.melware.de diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/README.icn linux.pre11.3/Documentation/isdn/README.icn --- linux.vanilla/Documentation/isdn/README.icn Sun Nov 8 15:08:48 1998 +++ linux.pre11.3/Documentation/isdn/README.icn Tue Jul 20 00:26:16 1999 @@ -1,4 +1,4 @@ -$Id: README.icn,v 1.5 1997/04/23 18:55:55 fritz Exp $ +$Id: README.icn,v 1.6 1998/04/29 19:49:08 he Exp $ You can get the ICN-ISDN-card from: diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/README.x25 linux.pre11.3/Documentation/isdn/README.x25 --- linux.vanilla/Documentation/isdn/README.x25 Sat Jan 9 21:50:34 1999 +++ linux.pre11.3/Documentation/isdn/README.x25 Tue Jul 20 00:26:16 1999 @@ -1,29 +1,24 @@ - -X25 support within isdn4linux - - -This is experimental code and should be used with linux version 2.1.72. -or later. Use it completely at your own risk. - + +X.25 support within isdn4linux +============================== +This is alpha/beta test code. Use it completely at your own risk. As new versions appear, the stuff described here might suddenly change or become invalid without notice. Keep in mind: -You are using an experimental kernel (2.1.x series) with an experimental -x25 protocol implementation and experimental x25-on-top-of-isdn extensions. -Thus, be prepared to face problems related therefrom. +You are using several new parts of the 2.2.x kernel series which +have not been tested in a large scale. Therefore, you might encounter +more bugs as usual. -- If you connect to an x25 neighbour not operated by yourself, ASK the +- If you connect to an X.25 neighbour not operated by yourself, ASK the other side first. Be prepared that bugs in the protocol implementation - might result in problems (even crashing the peer, however such ugly events - should only happen if your peer's protocol implementation has serious bugs). + might result in problems. - This implementation has never wiped out my whole hard disk yet. But as - this is experimental code, don't blame me if that happened to you. Take - appropriate actions (such as backing up important data) before - trying this code. + this is experimental code, don't blame me if that happened to you. + Backing up important data will never harm. - Monitor your isdn connections while using this software. This should prevent you from undesired phone bills in case of driver problems. @@ -32,7 +27,7 @@ How to configure the kernel - +=========================== The ITU-T (former CCITT) X.25 network protocol layer has been implemented in the Linux source tree since version 2.1.16. The isdn subsystem might be @@ -48,32 +43,33 @@ compilation. You currently also need to enable "Prompt for development and/or incomplete code/drivers" from the "Code maturity level options" menu. For the x25trace utility to work -you also need to enable "Packet socket" (I recommend to choose "y", -not "m" for testing) from the networking options. +you also need to enable "Packet socket". +For local testing it is also recommended to enable the isdnloop driver +from the isdn subsystem's configuration menu. -For testing you should also select the isdnloop driver from the -isdn subsystem's configuration menu. +For testing, it is recommended that all isdn drivers and the X.25 PLP +protocol are compiled as loadable modules. Like this, you can recover +from certain errors by simply unloading and reloading the modules. What's it for? How to use it? +============================= - -X25 on top of isdn might be useful with two different scenarios: +X.25 on top of isdn might be useful with two different scenarios: - You might want to access a public X.25 data network from your Linux box. You can use i4l if you were physically connected to the X.25 switch - by an ISDN line (leased line as well as dial up connection should work, - but connecting to x.25 network switches is currently untested. Testing - needs to be done by somebody with access to such a switch.) - -- Or you might want to operate certain ISDN teleservices on - your linux box. A lot of those teleservices run on top of the ISO-8208 - network layer protocol. ISO-8208 is essentially the same as ITU-T X.25. + by an ISDN line (leased line as well as dial up connection should work) + +- Or you might want to operate certain ISDN teleservices on your linux + box. A lot of those teleservices run on top of the ISO-8208 + (DTE-DTE mode) network layer protocol. ISO-8208 is essentially the + same as ITU-T X.25. - Popular candidates of such teleservices are EUROFILE transfer or any - teleservice applying ITU-T recommendation T.90 (i.e., AFAIK, G4 Fax). + Popular candidates of such teleservices are EUROfile transfer or any + teleservice applying ITU-T recommendation T.90. To use the X.25 protocol on top of isdn, just create an isdn network interface as usual, configure your own and/or peer's ISDN numbers, @@ -81,21 +77,18 @@ isdnctrl encap x25iface. -Once encap is set like this, the device can be used by the x25 packet layer. +Once encap is set like this, the device can be used by the X.25 packet layer. -All the stuff needed for x25 is implemented inside the isdn link +All the stuff needed for X.25 is implemented inside the isdn link level (mainly isdn_net.c and some new source files). Thus, it should -work with every existing HL driver. I was able to successfully open x25 +work with every existing HL driver. I was able to successfully open X.25 connections on top of the isdnloop driver and the hisax driver. "x25iface"-encapsulation bypasses demand dialing. Dialing will be -initiated when the upper (x25 packet) layer requests the lapb datalink to -be established. But hangup timeout is still active. The connection -will not automatically be re-established by the isdn_net module -itself when new data arrives after the hangup timeout. But -the x25 network code will re-establish the datalink connection -(resulting in re-dialing and an x25 protocol reset) when new data is -to be transmitted. (This currently does not work properly with the -isdnloop driver, see "known problems" below) +initiated when the upper (X.25 packet) layer requests the lapb datalink to +be established. But hangup timeout is still active. Whenever a hangup +occurs, all existing X.25 connections on that link will be cleared +It is recommended to use sufficiently large hangup-timeouts for the +isdn interfaces. In order to set up a conforming protocol stack you also need to @@ -114,104 +107,64 @@ isdnctrl l2_prot x25dce However, x25dte or x25dce is currently not supported by any real HL -level driver. The main difference between x75 and x25dte/dce is that +level driver. The main difference between x75i and x25dte/dce is that x25d[tc]e uses fixed lap_b addresses. With x75i, the side which initiates the isdn connection uses the DTE's lap_b address while the -called side used the DCE's lap_b address. Thus, l2_prot x75i will -probably work if you access a public x25 network as long as the -corresponding isdn connection is set up by you. However, I've never -tested this. - - +called side used the DCE's lap_b address. Thus, l2_prot x75i might +probably work if you access a public X.25 network as long as the +corresponding isdn connection is set up by you. At least one test +was successful to connect via isdn4linux to an X.25 switch using this +trick. At the switch side, a terminal adapter X.21 was used to connect +it to the isdn. -How to use the test installation? +How to set up a test installation? +================================== -To test x25 on top of isdn, you need to get +To test X.25 on top of isdn, you need to get -- a patched version of the "isdnctrl" program that supports setting the new - x25 specific parameters. +- a recent version of the "isdnctrl" program that supports setting the new + X.25 specific parameters. -- the x25-utils-2.1.x package from ftp.pspt.fi/pub/ham/linux/ax25 - or any mirror site (i.e. ftp://ftp.gwdg.de/pub/linux/misc/ax25/). +- the x25-utils-2.X package from + ftp://ftp.hes.iki.fi/pub/ham/linux/ax25/x25utils-* + (don't confuse the x25-utils with the ax25-utils) -- a kernel patch that enhances isdn4linux to provide x25 network - interface support. (This file is part of that kernel patch). - -- an application that uses linux AF_X25 sockets program. +- an application program that uses linux PF_X25 sockets (some are + contained in the x25-util package). Before compiling the user level utilities make sure that the compiler/ -preprocessor will fetch the proper (patched) kernel header files. Either make -/usr/include/linux a symbolic link pointing to your developer kernel's -include/linux directory or set the appropriate compiler flags. - -It is recommended that all isdn drivers and the x25 PLP protocol -are compiled as loadable modules. Like this, you can recover -from certain errors by simply unloading and reloading the modules. +preprocessor will fetch the proper kernel header files of this kernel +source tree. Either make /usr/include/linux a symbolic link pointing to +this kernel's include/linux directory or set the appropriate compiler flags. When all drivers and interfaces are loaded and configured you need to -ifconfig the network interfaces up and add x25-routes to them. Use +ifconfig the network interfaces up and add X.25-routes to them. Use the usual ifconfig tool. ifconfig up But a special x25route tool (distributed with the x25-util package) -is needed to set up x25 routes. I.e. +is needed to set up X.25 routes. I.e. x25route add 01 -will cause all x.25 connections to the destination x.25-address +will cause all x.25 connections to the destination X.25-address "01" to be routed to your created isdn network interface. - -There are currently no real x25 applications available. However, for +There are currently no real X.25 applications available. However, for tests, the x25-utils package contains a modified version of telnet -and telnetd that uses x25 sockets instead of tcp/ip sockets. Use -this for your first tests. Furthermore, there is an x25.echod and a client -named "eftp" (which contains some experimental code to download files -from a remote eft server using the EUROfile transfer protocol). -It available at ftp://ftp.hamburg.pop.de/pub/LOCAL/linux/i4l-eft/eftp4linux-* +and telnetd that uses X.25 sockets instead of tcp/ip sockets. You can +use those for your first tests. Furthermore, you might check +ftp://ftp.hamburg.pop.de/pub/LOCAL/linux/i4l-eft/ which contains some +alpha-test implementation ("eftp4linux") of the EUROfile transfer +protocol. + +The scripts distributed with the eftp4linux test releases might also +provide useful examples for setting up X.25 on top of isdn. The x25-utility package also contains an x25trace tool that can be -used to monitor x25 packets received by the network interfaces. +used to monitor X.25 packets received by the network interfaces. The /proc/net/x25* files also contain useful information. -The eftp4linux test release also contains an "ix25test" script that can -be used for testing x25 on top of isdn4linux. Edit -this script according to your local needs and then call it as - -ix25test start - -This will set up a sample configuration using the isdnloop and hisax -driver and create some isdn network interfaces. -It is recommended that all other isdn drivers and the -x25 module are unloaded before calling this script. - - - -Known problems and deficiencies: - -The isdnloop HL driver apparently has problems to re-establish a -connection that has been hung up from the outgoing device. You have to -unload the isdnloop driver after the faked isdn-connection is closed -and insmod it again. With the Hisax driver, this problem is not present. - -Sometimes the x25 module cannot be unloaded (decrementation of its use -count seems to get lost occasionally). - -Using the x25 based telnet and telnetd programm to establish connection -from your own to your own computer repeatedly sometimes totally locked -up my system. However, this kernel patch also modifies -net/x25/af_x25.c to include a workaround. With this workaround -enabled, my system is stable. (If you want to disable the -workaround, just undefine ISDN_X25_FIXES in af_x25.c). - -The latter problem could be reproduced by using hisax as well as the -isdnloop driver. It seems that it is not caused by the isdn code. -Somehow, the inode of a socket is freed while a process still refers -the socket's wait queue. This causes problems when the process tries to -remove itself from the wait queue (referred by the dangling -sock->sleep pointer) before returning from a select() system call. - - Henner - diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/nbd.txt linux.pre11.3/Documentation/nbd.txt --- linux.vanilla/Documentation/nbd.txt Sun Nov 8 15:08:49 1998 +++ linux.pre11.3/Documentation/nbd.txt Mon Jul 19 23:50:34 1999 @@ -4,11 +4,11 @@ means, that it works on my computer, and it worked on one of school computers. - What is it: With this compiled in the kernel, linux can use a remote + What is it: With this compiled in the kernel, Linux can use a remote server as one of its block devices. So every time the client computer wants to read /dev/nd0, it sends a request over TCP to the server, which will reply with the data read. This can be used for stations with - low-disk space (or even diskless - if you boot from floppy) to + low disk space (or even diskless - if you boot from floppy) to borrow disk space from another computer. Unlike NFS, it is possible to put any filesystem on it etc. It is impossible to use NBD as a root filesystem, since it requires a user-level program to start. It also diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/Configurable linux.pre11.3/Documentation/networking/Configurable --- linux.vanilla/Documentation/networking/Configurable Sun Nov 8 15:08:47 1998 +++ linux.pre11.3/Documentation/networking/Configurable Mon Jul 19 23:50:47 1999 @@ -20,11 +20,11 @@ 7000 Others are already accessible via the related user space programs. -For example, MAX_WINDOW has a default of 32k which is a good choice for -modern hardware, but if you have a slow (8 bit) ethercard and/or a slow +For example, MAX_WINDOW has a default of 32 k which is a good choice for +modern hardware, but if you have a slow (8 bit) Ethernet card and/or a slow machine, then this will be far too big for the card to keep up with fast -Tx'ing machines on the same net, resulting in overruns and receive errors. -A value of about 4k would be more appropriate, which can be set via: +machines transmitting on the same net, resulting in overruns and receive errors. +A value of about 4 k would be more appropriate, which can be set via: # route add -net 192.168.3.0 window 4096 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/DLINK.txt linux.pre11.3/Documentation/networking/DLINK.txt --- linux.vanilla/Documentation/networking/DLINK.txt Sun Nov 8 15:08:47 1998 +++ linux.pre11.3/Documentation/networking/DLINK.txt Mon Jul 19 23:50:53 1999 @@ -18,8 +18,8 @@ pocket adapters, for the parallel port on a Linux based machine. Some adapter "clones" will also work. Xircom is _not_ a clone... These drivers _can_ be used as loadable modules, - and were developed for use on Linux v1.1.13 and above. - For use on Linux v1.0.X, or earlier releases, see below. + and were developed for use on Linux 1.1.13 and above. + For use on Linux 1.0.X, or earlier releases, see below. I have used these drivers for NFS, ftp, telnet and X-clients on remote machines. Transmissions with ftp seems to work as @@ -57,7 +57,7 @@ de620.h Macros for de620.c If you are upgrading from the d-link tar release, there will - also be a "dlink-patches" file that will patch Linux v1.1.18: + also be a "dlink-patches" file that will patch Linux 1.1.18: linux/drivers/net/Makefile linux/drivers/net/CONFIG linux/drivers/net/MODULES @@ -162,10 +162,10 @@ 6. USING THE DRIVERS WITH EARLIER RELEASES. - The later v1.1.X releases of the Linux kernel include some + The later 1.1.X releases of the Linux kernel include some changes in the networking layer (a.k.a. NET3). This affects these drivers in a few places. The hints that follow are - _not_ tested by me, since I don't have the diskspace to keep + _not_ tested by me, since I don't have the disk space to keep all releases on-line. Known needed changes to date: - release patchfile: some patches will fail, but they should diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/arcnet-hardware.txt linux.pre11.3/Documentation/networking/arcnet-hardware.txt --- linux.vanilla/Documentation/networking/arcnet-hardware.txt Sat Jan 9 21:50:35 1999 +++ linux.pre11.3/Documentation/networking/arcnet-hardware.txt Mon Jul 19 23:51:05 1999 @@ -20,14 +20,14 @@ ARCnet is a network type which works in a way similar to popular Ethernet networks but which is also different in some very important ways. -First of all, you can get ARCnet cards in at least two speeds: 2.5Mbps -(slower than Ethernet) and 100Mbps (faster than normal Ethernet). In fact, +First of all, you can get ARCnet cards in at least two speeds: 2.5 Mbps +(slower than Ethernet) and 100 Mbps (faster than normal Ethernet). In fact, there are others as well, but these are less common. The different hardware types, as far as I'm aware, are not compatible and so you cannot wire a -100Mbps card to a 2.5Mbps card, and so on. From what I hear, my driver does -work with 100Mbps cards, but I haven't been able to verify this myself, -since I only have the 2.5Mbps variety. It is probably not going to saturate -your 100Mbps card. Stop complaining :) +100 Mbps card to a 2.5 Mbps card, and so on. From what I hear, my driver does +work with 100 Mbps cards, but I haven't been able to verify this myself, +since I only have the 2.5 Mbps variety. It is probably not going to saturate +your 100 Mbps card. Stop complaining. :) You also cannot connect an ARCnet card to any kind of Ethernet card and expect it to work. @@ -52,17 +52,17 @@ useful for realtime networks. In addition, all known ARCnet cards have an (almost) identical programming -interface. This means that with one "arcnet" driver you can support any -card; whereas, with Ethernet, each manufacturer uses what is sometimes a +interface. This means that with one ARCnet driver you can support any +card, whereas with Ethernet each manufacturer uses what is sometimes a completely different programming interface, leading to a lot of different, sometimes very similar, Ethernet drivers. Of course, always using the same programming interface also means that when high-performance hardware -facilities like PCI busmastering DMA appear, it's hard to take advantage of +facilities like PCI bus mastering DMA appear, it's hard to take advantage of them. Let's not go into that. One thing that makes ARCnet cards difficult to program for, however, is the limit on their packet sizes; standard ARCnet can only send packets that are -up to 508 bytes in length. This is smaller than the internet "bare minimum" +up to 508 bytes in length. This is smaller than the Internet "bare minimum" of 576 bytes, let alone the Ethernet MTU of 1500. To compensate, an extra level of encapsulation is defined by RFC1201, which I call "packet splitting," that allows "virtual packets" to grow as large as 64K each, @@ -1005,9 +1005,9 @@ only (the JP0 jumper is hardwired), and BNC only. This is a LCS-8830-T made by SMC, I think ('SMC' only appears on one PLCC, -nowhere else, not even on the few xeroxed sheets from the manual). +nowhere else, not even on the few Xeroxed sheets from the manual). -SMC Arcnet Board Type LCS-8830-T +SMC ARCnet Board Type LCS-8830-T ------------------------------------ | | @@ -1070,7 +1070,7 @@ DIP Switches 1-5 of SW2 encode the RAM and ROM Address Range: -Switches Ram Rom +Switches RAM ROM 12345 Address Range Address Range 00000 C:0000-C:07ff C:2000-C:3fff 10000 C:0800-C:0fff @@ -1170,11 +1170,11 @@ DIP Switches: The DIP switches accessible on the accessible end of the card while - it is installed, is used to set the arcnet address. There are 8 + it is installed, is used to set the ARCnet address. There are 8 switches. Use an address from 1 to 254. Switch No. - 12345678 Arcnet address + 12345678 ARCnet address ----------------------------------------- 00000000 FF (Don't use this!) 00000001 FE @@ -1222,7 +1222,7 @@ from the upper memory regions, and then attempting to load ARCETHER using these addresses. - I recommend using an arcnet memory address of 0xD000, and putting + I recommend using an ARCnet memory address of 0xD000, and putting the EMS page frame at 0xC000 while using QEMM stealth mode. That way, you get contiguous high memory from 0xD100 almost all the way the end of the megabyte. @@ -1687,7 +1687,7 @@ |____________________________________________| |__| -UM9065L : Arcnet Controller +UM9065L : ARCnet Controller SW 1 : Shared Memory Address and I/O Base @@ -1800,7 +1800,7 @@ J1-J5 IRQ Select J6-J21 Unknown (Probably extra timeouts & ROM enable ...) LED1 Activity LED -BNC Coax connector (STAR arcnet) +BNC Coax connector (STAR ARCnet) RAM 2k of SRAM ROM Boot ROM socket UFS Unidentified Flying Sockets @@ -1905,7 +1905,7 @@ ------------------------ - from Vojtech Pavlik -This is another SMC 90C65 based arcnet card. I couldn't identify the +This is another SMC 90C65-based ARCnet card. I couldn't identify the manufacturer, but it might be DataPoint, because the card has the original arcNet logo in its upper right corner. @@ -1942,9 +1942,9 @@ SW2 1-8: Node ID Select SW3 1-5: IRQ Select 6-7: Extra Timeout - 8 : Rom Enable + 8 : ROM Enable BNC Coax connector -XTAL 20MHz Crystal +XTAL 20 MHz Crystal Setting the Node ID @@ -2081,11 +2081,11 @@ 6-8 Base I/O Address Select SW2 1-8 Node ID Select (ID0-ID7) J1 IRQ Select -J2 Rom Enable +J2 ROM Enable J3 Extra Timeout LED1 Activity LED -BNC Coax connector (BUS arcnet) -RJ Twisted Pair Connector (daisychain) +BNC Coax connector (BUS ARCnet) +RJ Twisted Pair Connector (daisy chain) Setting the Node ID @@ -2419,7 +2419,7 @@ Legend: -COM90C65: Arcnet Probe +COM90C65: ARCnet Probe S1 1-8: Node ID Select S2 1-3: I/O Base Address Select 4-6: Memory Base Address Select @@ -2791,7 +2791,7 @@ SW2 1-8: Node ID Select (ID0-ID7) SW3 1-5: IRQ Select 6-7: Extra Timeout - 8 : Rom Enable + 8 : ROM Enable JP1 Led connector BNC Coax connector @@ -3089,7 +3089,7 @@ 0 = Jumper Installed 1 = Open -Top Jumper line Bit 7 = Rom Enable 654=Memory location 321=I/O +Top Jumper line Bit 7 = ROM Enable 654=Memory location 321=I/O Settings for Memory Location (Top Jumper Line) 456 Address selected diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/arcnet.txt linux.pre11.3/Documentation/networking/arcnet.txt --- linux.vanilla/Documentation/networking/arcnet.txt Sun Nov 8 15:08:46 1998 +++ linux.pre11.3/Documentation/networking/arcnet.txt Mon Jul 19 23:51:05 1999 @@ -1,4 +1,3 @@ - ---------------------------------------------------------------------------- NOTE: See also arcnet-hardware.txt in this directory for jumper-setting and cabling information if you're like many of us and didn't happen to get a @@ -92,10 +91,10 @@ http://www.perftech.com/ or ftp to ftp.perftech.com. Novell makes a networking stack for DOS which includes ARCnet drivers. Try -ftp'ing to ftp.novell.com. +FTPing to ftp.novell.com. You can get the Crynwr packet driver collection (including arcether.com, the -one you'll want to use with arcnet cards) from +one you'll want to use with ARCnet cards) from oak.oakland.edu:/simtel/msdos/pktdrvr. It won't work perfectly on a 386+ without patches, though, and also doesn't like several cards. Fixed versions are available on my WWW page, or via e-mail if you don't have WWW @@ -183,7 +182,7 @@ ----------------------- Configure and rebuild Linux. When asked, answer 'm' to "Generic ARCnet -support" and to support for your ARcnet chipset if you want to use the +support" and to support for your ARCnet chipset if you want to use the loadable module. You can also say 'y' to "Generic ARCnet support" and 'm' to the chipset support if you wish. @@ -269,7 +268,7 @@ Arcether client, assuming you remember to load winpkt of course. LAN Manager and Windows for Workgroups: These programs use protocols that - are incompatible with the internet standard. They try to pretend + are incompatible with the Internet standard. They try to pretend the cards are Ethernet, and confuse everyone else on the network. However, v2.00 and higher of the Linux ARCnet driver supports this @@ -288,7 +287,7 @@ you're completely insane, and/or you need to build some kind of hybrid network that uses both encapsulation types. -OS2: I've been told it works under Warp Connect with an ARCnet driver from +OS/2: I've been told it works under Warp Connect with an ARCnet driver from SMC. You need to use the 'arc0e' interface for this. If you get the SMC driver to work with the TCP/IP stuff included in the "normal" Warp Bonus Pack, let me know. @@ -309,7 +308,7 @@ The ARCnet driver v2.10 ALPHA supports three protocols, each on its own "virtual network device": - arc0 - RFC1201 protocol, the official internet standard which just + arc0 - RFC1201 protocol, the official Internet standard which just happens to be 100% compatible with Novell's TRXNET driver. Version 1.00 of the ARCnet driver supported _only_ this protocol. arc0 is the fastest of the three protocols (for @@ -331,13 +330,13 @@ reasons yet to be determined. (Probably it's the smaller MTU that does it.) - arc0s - The "[s]imple" RFC1051 protocol is the "previous" internet + arc0s - The "[s]imple" RFC1051 protocol is the "previous" Internet standard that is completely incompatible with the new standard. Some software today, however, continues to support the old standard (and only the old standard) including NetBSD and AmiTCP. RFC1051 also does not support RFC1201's packet splitting, and the MTU of 507 is still - smaller than the internet "requirement," so it's quite + smaller than the Internet "requirement," so it's quite possible that you may run into problems. It's also slower than RFC1201 by about 25%, for the same reason as arc0e. @@ -388,16 +387,16 @@ Linux but runs the free Microsoft LANMAN Client instead. Worse, one of the Linux computers (freedom) also has a modem and acts as - a router to my internet provider. The other Linux box (insight) also has + a router to my Internet provider. The other Linux box (insight) also has its own IP address and needs to use freedom as its default gateway. The - XT (patience), however, does not have its own internet IP address and so + XT (patience), however, does not have its own Internet IP address and so I assigned it one on a "private subnet" (as defined by RFC1597). To start with, take a simple network with just insight and freedom. Insight needs to: - talk to freedom via RFC1201 (arc0) protocol, because I like it more and it's faster. - - use freedom as its internet gateway. + - use freedom as its Internet gateway. That's pretty easy to do. Set up insight like this: ifconfig arc0 insight @@ -417,20 +416,20 @@ /* and default gateway is configured by pppd */ Great, now insight talks to freedom directly on arc0, and sends packets - to the internet through freedom. If you didn't know how to do the above, + to the Internet through freedom. If you didn't know how to do the above, you should probably stop reading this section now because it only gets worse. Now, how do I add patience into the network? It will be using LANMAN Client, which means I need the arc0e device. It needs to be able to talk to both insight and freedom, and also use freedom as a gateway to the - internet. (Recall that patience has a "private IP address" which won't - work on the internet; that's okay, I configured Linux IP masquerading on + Internet. (Recall that patience has a "private IP address" which won't + work on the Internet; that's okay, I configured Linux IP masquerading on freedom for this subnet). So patience (necessarily; I don't have another IP number from my provider) has an IP address on a different subnet than freedom and - insight, but needs to use freedom as an internet gateway. Worse, most + insight, but needs to use freedom as an Internet gateway. Worse, most DOS networking programs, including LANMAN, have braindead networking schemes that rely completely on the netmask and a 'default gateway' to determine how to route packets. This means that to get to freedom or @@ -449,7 +448,7 @@ This way, freedom will send all packets for patience through arc0e, giving its IP address as gatekeeper (on the private subnet). When it - talks to insight or the internet, it will use its "freedom" internet IP + talks to insight or the Internet, it will use its "freedom" Internet IP address. You will notice that we haven't configured the arc0e device on insight. @@ -473,7 +472,7 @@ [RFC1201 NETWORK] [ETHER-ENCAP NETWORK] - (registered internet subnet) (RFC1597 private subnet) + (registered Internet subnet) (RFC1597 private subnet) (IP Masquerade) /---------------\ * /---------------\ @@ -523,7 +522,7 @@ Once the driver is running, you can run the arcdump shell script (available from me or in the full ARCnet package, if you have it) as root to list the contents of the arcnet buffers at any time. To make any sense at all out of -this, you should grab the pertinent RFC's. (some are listed near the top of +this, you should grab the pertinent RFCs. (some are listed near the top of arcnet.c). arcdump assumes your card is at 0xD0000. If it isn't, edit the script. diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/olympic.txt linux.pre11.3/Documentation/networking/olympic.txt --- linux.vanilla/Documentation/networking/olympic.txt Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/Documentation/networking/olympic.txt Mon Jul 19 23:28:59 1999 @@ -0,0 +1,75 @@ + +IBM PCI Pit/Pit-Phy/Olympic CHIPSET BASED TOKEN RING CARDS README + +Release 0.2.0 - Release + June 8th 1999 Peter De Schrijver & Mike Phillips + + +Thanks: +Erik De Cock, Adrian Bridgett and Frank Fiene for their +patience and testing. +Paul Norton without whose tr.c code we would have had +a lot more work to do. + +Options: + +The driver accepts three options: ringspeed, pkt_buf_sz, and +message_level. + +These options can be specified differently for each card found. + +ringspeed: Has one of three settings 0 (default), 4 or 16. 0 will +make the card autosense the ringspeed and join at the appropriate speed, +this will be the default option for most people. 4 or 16 allow you to +explicitly force the card to operate at a certain speed. The card will fail +if you try to insert it at the wrong speed. (Although some hubs will allow +this so be *very* careful). The main purpose for explicitly setting the ring +speed is for when the card is first on the ring. In autosense mode, if the card +cannot detect any active monitors on the ring it will not open, so you must +re-init the card at the appropriate speed. Unfortunately at present the only +way of doing this is rmmod and insmod which is a bit tough if it is compiled +in the kernel. + +pkt_buf_sz: This is this initial receive buffer allocation size. This will +default to 4096 if no value is entered. You may increase performance of the +driver by setting this to a value larger than the network packet size, although +the driver now re-sizes buffers based on MTU settings as well. + +message_level: Controls level of messages created by the driver. Defaults to 0: +which only displays start-up and critical messages. Presently any non-zero +value will display all soft messages as well. NB This does not turn +debuging messages on, that must be done by modified the source code. + +Multi-card: + +The driver will detect multiple cards and will work with shared interrupts, +each card is assigned the next token ring device, i.e. tr0 , tr1, tr2. The +driver should also happily reside in the system with other drivers. It has +been tested with ibmtr.c running, and I personnally have had one Olicom PCI +card and two IBM olympic cards (all on the same interrupt), all running +together. + +Variable MTU size: + +The driver can handle a MTU size upto either 4500 or 18000 depending upon +ring speed. The driver also changes the size of the receive buffers as part +of the mtu re-sizing, so if you set mtu = 18000, you will need to be able +to allocate 16 * (sk_buff with 18000 buffer size) call it 18500 bytes per ring +position = 296,000 bytes of memory space, plus of course anything +necessary for the tx sk_buff's. Remember this is per card, so if you are +building routers, gateway's etc, you could start to use a lot of memory +real fast. + +Network Monitor Mode: + +By modifying the #define OLYMPIC_NETWORK_MONITOR from 0 to 1 in the +source code the driver will implement a quasi network monitoring +mode. All unexpected MAC frames (beaconing etc.) will be received +by the driver and the source and destination addresses printed. +Also an entry will be added in /proc/net called olympic_tr. This +displays low level information about the configuration of the ring and +the adapter. This feature has been designed for network adiministrators +to assist in the diagnosis of network / ring problems. + +6/8/99 Peter De Schrijver and Mike Phillips + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/policy-routing.txt linux.pre11.3/Documentation/networking/policy-routing.txt --- linux.vanilla/Documentation/networking/policy-routing.txt Sun Nov 8 15:08:47 1998 +++ linux.pre11.3/Documentation/networking/policy-routing.txt Mon Jul 19 23:28:58 1999 @@ -83,7 +83,7 @@ 2. Opposite case. Just forget all that you know about routing tables. Every rule is supplied with its own gateway, device info. record. This approach is not appropriate for automated - route maintanance, but it is ideal for manual configuration. + route maintenance, but it is ideal for manual configuration. HOWTO: iproute addrule [ from PREFIX ] [ to PREFIX ] [ tos TOS ] [ dev INPUTDEV] [ pref PREFERENCE ] route [ gw GATEWAY ] diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/z8530drv.txt linux.pre11.3/Documentation/networking/z8530drv.txt --- linux.vanilla/Documentation/networking/z8530drv.txt Sun Nov 8 15:08:46 1998 +++ linux.pre11.3/Documentation/networking/z8530drv.txt Mon Jul 19 23:28:58 1999 @@ -252,7 +252,7 @@ speed 1200 # the default baudrate clock dpll # clock source: - # dpll = normal halfduplex operation + # dpll = normal half duplex operation # external = MODEM provides own Rx/Tx clock # divider = use full duplex divider if # installed (1) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sound/Introduction linux.pre11.3/Documentation/sound/Introduction --- linux.vanilla/Documentation/sound/Introduction Thu May 27 22:11:48 1999 +++ linux.pre11.3/Documentation/sound/Introduction Mon Jul 19 23:29:00 1999 @@ -1,6 +1,6 @@ -Soundcore Notes on Modular Sound Drivers and Soundcore +Introduction Notes on Modular Sound Drivers and Soundcore Wade Hampton -11/20/1998 +6/30/1999 Purpose: ======== @@ -10,13 +10,21 @@ Note, some of this probably should be added to the Sound-HOWTO! + Copying: ======== none + History: ======== -0.1.0 11/20/1998 First version +0.1.0 11/20/1998 First version, draft +1.0.0 11/1998 Alan Cox changes, incorporation in 2.2.0 + as /usr/src/linux/Documentation/sound/Introduction +1.1.0 6/30/1999 Second version, added notes on making the drivers, + added info on multiple sound cards of similar types,] + added more diagnostics info, added info about esd. + added info on OSS and ALSA. Modular Sound Drivers: @@ -58,6 +66,53 @@ for the same or a similar feature (dma1= versus dma16=). As a last resort, inspect the code (search for MODULE_PARM). +Notes: + +1. There is a new OpenSource sound driver called ALSA which is + currently under development: http://www.alsa-project.org/ + I have not tried it nor am I aware of its status, but it is + currently under development. + +2. The commercial OSS driver may be obtained from the site: + http://www/opensound.com. This may be used for cards that + are unsupported by the kernel driver, or may be used + by other operating systems. + +3. The enlightenment sound daemon may be used for playing + multiple sounds at the same time via a single card, eliminating + some of the requirements for multiple sound card systems. For + more information, see: http://www.tux.org/~ricdude/EsounD.html + The "esd" program may be used with the real-player and mpeg + players like mpg123 and x11amp. + + +Building the Modules: +===================== + +This document does not provide full details on building the +kernel, etc. The notes below apply only to making the kernel +sound modules. If this conflicts with the kernel's README, +the README takes precedence. + +1. To make the kernel sound modules, cd to your /usr/src/linux + directory (typically) and type make config, make menuconfig, + or make xconfig (to start the command line, dialog, or x-based + configuration tool). + +2. Select the Sound option and a dialog will be displayed. + +3. Select M (module) for "Sound card support". + +4. Select your sound driver(s) as a module. For ProAudio, Sound + Blaster, etc., select M (module) for OSS sound modules. + [thanks to marvin stodolsky ]A + +5. Make the kernel (e.g., make dep ; make bzImage), and install + the kernel. + +6. Make the modules and install them (make modules; make modules_install). + + INSMOD: ======= @@ -82,6 +137,9 @@ /sbin/insmod uart401 /sbin/insmod sb io=$SB_BASE irq=$SB_IRQ dma=$SB_DMA dma16=$SB_DMA2 mpu_io=$SB_MP +When using sound as a module, I typically put these commands +in a file such as /root/soundon.sh. + MODPROBE: ========= @@ -117,8 +175,8 @@ soundcore 1968 8 [sb sound] -Removing Sound: -=============== +Removing Sound: +=============== Sound may be removed by using /sbin/rmmod in the reverse order in which you load the modules. Note, if a program has a sound device @@ -134,6 +192,25 @@ /sbin/rmmod soundlow /sbin/rmmod soundcore +When using sound as a module, I typically put these commands +in a script such as /root/soundoff.sh. + + +Removing Sound for use with OSS: +================================ + +If you get really stuck or have a card that the kernel modules +will not support, you can get a commercial sound driver from +http://www.opensound.com. Before loading the commercial sound +driver, you should do the following: + +1. remove sound modules (detailed above) +2. remove the sound modules from /etc/conf.modules +3. move the sound modules from /lib/modules//misc + (for example, I make a /lib/modules//misc/tmp + directory and copy the sound module files to that + directory). + Multiple Sound Cards: ===================== @@ -154,11 +231,30 @@ first (in my case "sb") and then load the other one (in my case "cs4232"). +If you have two cards of the same type that are jumpered +cards or different PnP revisions, you may load the same +module twice. For example, I have a SoundBlaster vibra 16 +and an older SoundBlaster 16 (jumpers). To load the module +twice, you need to do the following: + +1. Copy the sound modules to a new name. For example + sb.o could be copied (or symlinked) to sb1.o for the + second SoundBlasster. + +2. Make a second entry in /etc/conf.modules, for example, + sound1 or sb1. This second entry should refer to the + new module names for example sb1, and should include + the I/O, etc. for the second sound card. + +3. Update your soundon.sh script, etc. + Warning: I have never been able to get two PnP sound cards of the same type to load at the same time. I have tried this several times with the Soundblaster Vibra 16 cards. OSS has indicated that this is a PnP problem.... If anyone has any luck doing this, please -send me an E-MAIL. PCI sound cards should not have this problem. +send me an E-MAIL. PCI sound cards should not have this problem.a +Since this was originally release, I have received a couple of +mails from people who have accomplished this! Sound Problems: @@ -175,6 +271,8 @@ write down what addresses, IRQ, and DMA channels those were using for the same hardware. You probably can use these addresses, IRQs, and DMA channels. + You should really do this BEFORE attempting to get + sound working! B) Check (cat) /proc/interrupts, /proc/ioports, and /proc/dma. Are you trying to use an address, @@ -184,22 +282,44 @@ may need a kernel patch to get this device). D) Inspect your /var/log/messages file. Often that will - indicate what IRQ or IO port could not be obtained + indicate what IRQ or IO port could not be obtained. E) Try another port or IRQ. Note this may involve using the PnP tools to move the sound card to - another location. + another location. Sometimes this is the only way + and it is more or less trial and error. -2) If you get motorboating (the same sound or part of a +2) If you get motor-boating (the same sound or part of a sound clip repeated), you probably have either an IRQ - or DMA conflict. Move the card to another address. This - has happened to me when playing long files when I had - an IRQ conflict. + or DMA conflict. Move the card to another IRQ or DMA + port. This has happened to me when playing long files + when I had an IRQ conflict. + +3. If you get dropouts or pauses when playing high sample + rate files such as using mpg123 or x11amp/xmms, you may + have too slow of a CPU and may have to use the options to + play the files at 1/2 speed. For example, you may use + the -2 or -4 option on mpg123. You may also get this + when trying to play mpeg files stored on a CD-ROM + (my Toshiba T8000 PII/366 sometimes has this problem). + +4. If you get "cannot access device" errors, your /dev/dsp + files, etc. may be set to owner root, mode 600. You + may have to use the command: + chmod 666 /dev/dsp /dev/mixer /dev/audio + +5. If you get "device busy" errors, another program has the + sound device open. For example, if using the Enlightenment + sound daemon "esd", the "esd" program has the sound device. + If using "esd", please RTFM the docs on ESD. For example, + esddsp may be used to play files via a non-esd + aware program. + -3) Ask for help on the sound list or send E-MAIL to the +6) Ask for help on the sound list or send E-MAIL to the sound driver author/maintainer. -4) Turn on debug in drivers/sound/sound_config.h (DEB, DDB, MDB). +7) Turn on debug in drivers/sound/sound_config.h (DEB, DDB, MDB). Configuring Sound: @@ -210,7 +330,8 @@ 1) Hardcoded in the kernel at compile time (not applicable when using sound modules). This was the OLD way! -2) On the command line when using insmod. +2) On the command line when using insmod or in a bash script + using command line calls to load sound. 3) In /etc/conf.modules when using modprobe. @@ -224,7 +345,6 @@ Anyone want to write a linuxconf module for configuring sound? - For More Information (RTFM): ============================ 1) Information on kernel modules: linux/Documentation/modules.txt @@ -242,12 +362,17 @@ 7) The sndconfig and rhsound documentation from Red Hat. -8) The Linux-sound mailing list: sound-list@redhat.com +8) The Linux-sound mailing list: sound-list@redhat.com. + +9) Enlightenment documentation (for info on esd) + http://www.tux.org/~ricdude/EsounD.html. +10) ALSA home page: http://www.alsa-project.org/ Contact Information: ==================== Wade Hampton: (whampton@staffnet.com) + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sound/OPL3-SA2 linux.pre11.3/Documentation/sound/OPL3-SA2 --- linux.vanilla/Documentation/sound/OPL3-SA2 Tue Jan 19 02:57:22 1999 +++ linux.pre11.3/Documentation/sound/OPL3-SA2 Mon Jul 19 23:29:00 1999 @@ -46,6 +46,21 @@ then email me if you are willing to experiment in an effort to make it work. +************************************************************************ +* I have now had two such machines, and I have fixed this to work +* properly when built into the kernel. The Toshiba Libretto series, or +* at least models 70CT and 110CT which I have owned, use a Yamaha +* OPL3-SAx (OPL3-SA3 according to documentation) sound chip, IRQ 5, +* IO addresses 220/530/388/330/370 and DMA 1,0 (_not_ 0,1). All these +* configuration settings can be gathered by booting another OS which +* recognizes the card already. +* +* I have made things 'just work' for the non-modular case on such +* machines when configured properly. +* +* David Luyer +************************************************************************ + If you are using isapnp, follow the directions in its documentation to produce a configuration file. Here is the relevant excerpt I use for my SAx card from my isapnp.conf: diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sysctl/README linux.pre11.3/Documentation/sysctl/README --- linux.vanilla/Documentation/sysctl/README Fri Apr 16 22:10:51 1999 +++ linux.pre11.3/Documentation/sysctl/README Mon Jul 19 23:29:00 1999 @@ -1,4 +1,4 @@ -Documentation for /proc/sys/ kernel version 2.2.5 +Documentation for /proc/sys/ kernel version 2.2.10 (c) 1998, 1999, Rik van Riel 'Why', I hear you ask, 'would anyone even _want_ documentation diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sysctl/fs.txt linux.pre11.3/Documentation/sysctl/fs.txt --- linux.vanilla/Documentation/sysctl/fs.txt Fri Apr 16 22:10:51 1999 +++ linux.pre11.3/Documentation/sysctl/fs.txt Mon Jul 19 23:29:00 1999 @@ -1,4 +1,4 @@ -Documentation for /proc/sys/fs/* kernel version 2.2.5 +Documentation for /proc/sys/fs/* kernel version 2.2.10 (c) 1998, 1999, Rik van Riel For general info and legal blurb, please look in README. diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sysctl/kernel.txt linux.pre11.3/Documentation/sysctl/kernel.txt --- linux.vanilla/Documentation/sysctl/kernel.txt Fri Apr 16 22:10:51 1999 +++ linux.pre11.3/Documentation/sysctl/kernel.txt Mon Jul 19 23:29:00 1999 @@ -1,4 +1,4 @@ -Documentation for /proc/sys/kernel/* kernel version 2.2.5 +Documentation for /proc/sys/kernel/* kernel version 2.2.10 (c) 1998, 1999, Rik van Riel For general info and legal blurb, please look in README. @@ -76,12 +76,21 @@ domainname & hostname: -These files can be controlled to set the domainname and -hostname of your box. For the classic darkstar.frop.org -a simple: +These files can be used to set the NIS/YP domainname and the +hostname of your box in exactly the same way as the commands +domainname and hostname, i.e.: # echo "darkstar" > /proc/sys/kernel/hostname -# echo "frop.org" > /proc/sys/kernel/domainname -would suffice to set your hostname and domainname. +# echo "mydomain" > /proc/sys/kernel/domainname +has the same effect as +# hostname "darkstar" > /proc/sys/kernel/hostname +# domainname "mydomain" > /proc/sys/kernel/domainname + +Note, however, that the classic darkstar.frop.org has the +hostname "darkstar" and DNS (Internet Domain Name Server) +domainname "frop.org", not to be confused with the NIS (Network +Information Service) or YP (Yellow Pages) domainname. These two +domain names are in general different. For a detailed discussion +see the hostname(1) man page. ============================================================== diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sysctl/sunrpc.txt linux.pre11.3/Documentation/sysctl/sunrpc.txt --- linux.vanilla/Documentation/sysctl/sunrpc.txt Fri Apr 16 22:10:51 1999 +++ linux.pre11.3/Documentation/sysctl/sunrpc.txt Mon Jul 19 23:29:00 1999 @@ -1,4 +1,4 @@ -Documentation for /proc/sys/sunrpc/* kernel version 2.2.5 +Documentation for /proc/sys/sunrpc/* kernel version 2.2.10 (c) 1998, 1999, Rik van Riel For general info and legal blurb, please look in README. diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sysctl/vm.txt linux.pre11.3/Documentation/sysctl/vm.txt --- linux.vanilla/Documentation/sysctl/vm.txt Thu May 27 22:11:48 1999 +++ linux.pre11.3/Documentation/sysctl/vm.txt Mon Jul 19 23:29:00 1999 @@ -1,4 +1,4 @@ -Documentation for /proc/sys/vm/* kernel version 2.2.5 +Documentation for /proc/sys/vm/* kernel version 2.2.10 (c) 1998, 1999, Rik van Riel For general info and legal blurb, please look in README. diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sysrq.txt linux.pre11.3/Documentation/sysrq.txt --- linux.vanilla/Documentation/sysrq.txt Sun Nov 8 15:08:50 1998 +++ linux.pre11.3/Documentation/sysrq.txt Mon Jul 19 23:29:00 1999 @@ -9,8 +9,8 @@ * How do I enable the magic SysRQ key? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You need to say yes to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when -configuring the kernel. This option is only available it 2.1.x or later +You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when +configuring the kernel. This option is only available in 2.1.x or later kernels. * How do I use the magic SysRQ key? diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/MAINTAINERS linux.pre11.3/MAINTAINERS --- linux.vanilla/MAINTAINERS Tue Jun 15 16:49:45 1999 +++ linux.pre11.3/MAINTAINERS Tue Jul 20 00:26:35 1999 @@ -16,8 +16,8 @@ SMC etherpower for that.) 3. Make sure your changes compile correctly in multiple - configurations. In paticular check changes work both as a module - and built into the kernel. + configurations. In particular check that changes work both as a + module and built into the kernel. 4. When you are happy with a change make it generally available for testing and await feedback. @@ -28,7 +28,7 @@ and variable names. These aren't as silly as they seem. One job the maintainers (and especially Linus) do is to keep things looking the same. Sometimes this means that the clever hack in - your driver to get around a problem actual needs to become a + your driver to get around a problem actually needs to become a generalized kernel feature ready for next time. See Documentation/CodingStyle for guidance here. @@ -49,8 +49,8 @@ Maintainers List (try to look for most precise areas first) -Note: For the hard of thinking, this list is meant to remain in Alphabetical -order. If you could add yourselves to it in Alphabetical order that would +Note: For the hard of thinking, this list is meant to remain in alphabetical +order. If you could add yourselves to it in alphabetical order that would so much easier [Ed] P: Person @@ -170,6 +170,12 @@ W: http://www.dandelion.com/Linux/ S: Maintained +CIRRUS LOGIC GENERIC FBDEV DRIVER +P: Jeff Garzik +M: jgarzik@pobox.com +L: linux-fbdev@vuser.vu.union.edu +S: Maintained + CONFIGURE, MENUCONFIG, XCONFIG P: Michael Elizabeth Chastain M: mec@shout.net @@ -258,6 +264,18 @@ L: linux-eata@i-connect.net, linux-scsi@vger.rutgers.edu S: Maintained +COMPAQ SMART2 RAID DRIVER +P: Charles White +M: Charles White +L: compaqandlinux@yps.org +S: Maintained + +DAC960 RAID DRIVER +P: Leonard N. Zubkoff +M: Leonard N. Zubkoff +L: linux-raid@vger.rutgers.edu +S: Maintained + EATA ISA/EISA/PCI SCSI DRIVER P: Dario Ballabio M: dario@milano.europe.dg.com @@ -447,6 +465,12 @@ L: linux-pmac@samba.anu.edu.au S: Maintained +LOGICAL VOLUME MANAGER +P: Heinz Mauelshagen +M: linux.LVM@ez-darmstadt.telekom.de +W: http://linux.msede.com/lvm +S: Maintained + M68K P: Jes Sorensen M: Jes.Sorensen@cern.ch @@ -560,6 +584,16 @@ L: linux-kernel@vger.rutgers.edu S: Maintained +OLYMPIC NETWORK DRIVER +P: Peter De Shrijver +M: p2@ace.ulyssis.sutdent.kuleuven.ac.be +P: Mike Phillips +M: phillim@amtrak.com +L: linux-net@vger.rutgers.edu +L: linux-tr@emissary.aus-etc.com +W: http://www.linuxtr.net +S: Maintained + OPL3-SA2, SA3, and SAx DRIVER P: Scott Murray M: scottm@interlog.com @@ -626,7 +660,7 @@ REAL TIME CLOCK DRIVER P: Paul Gortmaker -M gpg109@rsphy1.anu.edu.au +M: gpg109@rsphy1.anu.edu.au L: linux-kernel@vger.rutgers.edu S: Maintained @@ -655,11 +689,6 @@ W: http://www.torque.net/sg S: Maintained -SCSI GENERIC -L: linux-scsi@vger.rutgers.edu -M: douglas.gilbert@rbcds.com -S: Maintained - SCSI SUBSYSTEM L: linux-scsi@vger.rutgers.edu S: Unmaintained @@ -678,9 +707,10 @@ S: Maintained SMB FILESYSTEM -P: Volker Lendecke -M: vl@kki.org -L: samba@listproc.anu.edu.au +P: Andrew Tridgell +M: tridge@samba.org +W: http://samba.org/ +L: samba@samba.org S: Maintained SMP: (except SPARC) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Makefile linux.pre11.3/Makefile --- linux.vanilla/Makefile Tue Jun 15 16:49:45 1999 +++ linux.pre11.3/Makefile Mon Jul 19 23:51:45 1999 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 2 -SUBLEVEL = 10 +SUBLEVEL = 11 EXTRAVERSION = ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) @@ -27,6 +27,7 @@ AR =$(CROSS_COMPILE)ar NM =$(CROSS_COMPILE)nm STRIP =$(CROSS_COMPILE)strip +OBJCOPY =$(CROSS_COMPILE)objcopy OBJDUMP =$(CROSS_COMPILE)objdump MAKE =make GENKSYMS=/sbin/genksyms @@ -70,7 +71,7 @@ # # INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory # relocations required by build roots. This is not defined in the -# makefile but the arguement can be passed to make if needed. +# makefile but the argument can be passed to make if needed. # # @@ -88,6 +89,9 @@ CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer +# use '-fno-strict-aliasing', but only if the compiler can take it +CFLAGS += $(shell if $(CC) -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-strict-aliasing"; fi) + ifdef CONFIG_SMP CFLAGS += -D__SMP__ AFLAGS += -D__SMP__ @@ -162,6 +166,10 @@ DRIVERS := $(DRIVERS) drivers/pnp/pnp.a endif +ifdef CONFIG_SGI +DRIVERS := $(DRIVERS) drivers/sgi/sgi.a +endif + ifdef CONFIG_VT DRIVERS := $(DRIVERS) drivers/video/video.a endif @@ -174,6 +182,10 @@ DRIVERS := $(DRIVERS) drivers/net/hamradio/hamradio.a endif +ifeq ($(CONFIG_TC),y) +DRIVERS := $(DRIVERS) drivers/tc/tc.a +endif + ifeq ($(CONFIG_USB),y) DRIVERS := $(DRIVERS) drivers/usb/usb.a endif @@ -287,7 +299,7 @@ fs lib mm ipc kernel drivers net: dummy $(MAKE) $(subst $@, _dir_$@, $@) -MODFLAGS = -DMODULE +MODFLAGS += -DMODULE ifdef CONFIG_MODULES ifdef CONFIG_MODVERSIONS MODFLAGS += -DMODVERSIONS -include $(HPATH)/linux/modversions.h @@ -323,7 +335,7 @@ if [ -f FC4_MODULES ]; then inst_mod FC4_MODULES fc4; fi; \ if [ -f IRDA_MODULES ]; then inst_mod IRDA_MODULES net; fi; \ \ - ls *.o > $$MODLIB/.allmods; \ + for f in *.o; do [ -r $$f ] && echo $$f; done > $$MODLIB/.allmods; \ echo $$MODULES | tr ' ' '\n' | sort | comm -23 $$MODLIB/.allmods - > $$MODLIB/.misc; \ if [ -s $$MODLIB/.misc ]; then inst_mod $$MODLIB/.misc misc; fi; \ rm -f $$MODLIB/.misc $$MODLIB/.allmods; \ @@ -343,8 +355,8 @@ clean: archclean rm -f kernel/ksyms.lst include/linux/compile.h - rm -f core `find . -name '*.[oas]' ! -regex '.*lxdialog/.*' \ - ! -regex '.*ksymoops/.*' -print` + rm -f core `find . -name '*.[oas]' ! \( -regex '.*lxdialog/.*' \ + -o -regex '.*ksymoops/.*' \) -print` rm -f core `find . -type f -name 'core' -print` rm -f core `find . -name '.*.flags' -print` rm -f vmlinux System.map @@ -391,7 +403,7 @@ sums: find . -type f -print | sort | xargs sum > .SUMS -dep-files: scripts/mkdep archdep include/linux/version.h +dep-files: scripts/mkdep archdep include/linux/version.h new-genksyms scripts/mkdep init/*.c > .depend scripts/mkdep `find $(FINDHPATH) -follow -name \*.h ! -name modversions.h -print` > .hdepend # set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i fastdep ;done @@ -401,7 +413,19 @@ MODVERFILE := ifdef CONFIG_MODVERSIONS + MODVERFILE := $(TOPDIR)/include/linux/modversions.h + +new-genksyms: + @$(GENKSYMS) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) /dev/null || ( echo -e "\nYou need a new version of the genksyms\ + program, which is part of\nthe modutils package. Please read the file\ + Documentation/Changes\nfor more information.\n"; exit 1 ) + +else + +new-genksyms: + endif depend dep: dep-files $(MODVERFILE) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/README linux.pre11.3/README --- linux.vanilla/README Tue Jun 15 16:49:45 1999 +++ linux.pre11.3/README Mon Jul 19 23:51:51 1999 @@ -91,7 +91,7 @@ SOFTWARE REQUIREMENTS - Compiling and running the 2.2.x kernels requires up-to-date + Compiling and running the 2.2.xx kernels requires up-to-date versions of various software packages. Consult ./Documentation/Changes for the minimum version numbers required and how to get updates for these packages. Beware that using diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/boot/bootp.c linux.pre11.3/arch/alpha/boot/bootp.c --- linux.vanilla/arch/alpha/boot/bootp.c Sun Nov 8 15:08:23 1998 +++ linux.pre11.3/arch/alpha/boot/bootp.c Mon Jul 19 23:28:33 1999 @@ -200,11 +200,11 @@ load(START_ADDR+(4*KERNEL_SIZE), KERNEL_ORIGIN, KERNEL_SIZE); load(START_ADDR, START_ADDR+(4*KERNEL_SIZE), KERNEL_SIZE); - memset((char*)ZERO_PAGE, 0, PAGE_SIZE); - strcpy((char*)ZERO_PAGE, envval); + memset((char*)ZERO_PAGE(0), 0, PAGE_SIZE); + strcpy((char*)ZERO_PAGE(0), envval); #ifdef INITRD_SIZE - ((long *)(ZERO_PAGE+256))[0] = initrd_start; - ((long *)(ZERO_PAGE+256))[1] = INITRD_SIZE; + ((long *)(ZERO_PAGE(0)+256))[0] = initrd_start; + ((long *)(ZERO_PAGE(0)+256))[1] = INITRD_SIZE; #endif runkernel(); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/boot/main.c linux.pre11.3/arch/alpha/boot/main.c --- linux.vanilla/arch/alpha/boot/main.c Wed Mar 10 21:13:00 1999 +++ linux.pre11.3/arch/alpha/boot/main.c Mon Jul 19 23:28:33 1999 @@ -182,7 +182,7 @@ nbytes = 0; } envval[nbytes] = '\0'; - strcpy((char*)ZERO_PAGE, envval); + strcpy((char*)ZERO_PAGE(0), envval); srm_printk(" Ok\nNow booting the kernel\n"); runkernel(); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/Makefile linux.pre11.3/arch/alpha/kernel/Makefile --- linux.vanilla/arch/alpha/kernel/Makefile Thu Jan 14 01:25:21 1999 +++ linux.pre11.3/arch/alpha/kernel/Makefile Mon Jul 19 23:28:33 1999 @@ -105,7 +105,7 @@ endif # Device support -ifdef CONFIG_ALPHA_MIATA +ifneq ($(CONFIG_ALPHA_MIATA)$(CONFIG_ALPHA_DP264),) O_OBJS += es1888.o endif ifneq ($(CONFIG_ALPHA_SX164)$(CONFIG_ALPHA_MIATA)$(CONFIG_ALPHA_DP264),) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/core_cia.c linux.pre11.3/arch/alpha/kernel/core_cia.c --- linux.vanilla/arch/alpha/kernel/core_cia.c Tue Jun 15 16:49:45 1999 +++ linux.pre11.3/arch/alpha/kernel/core_cia.c Mon Jul 19 23:28:34 1999 @@ -535,8 +535,6 @@ * Set up the PCI->physical memory translation windows. * For now, windows 1,2 and 3 are disabled. In the future, * we may want to use them to do scatter/gather DMA. - * - * Window 0 goes at 1 GB and is 1 GB large. */ *(vuip)CIA_IOC_PCI_W0_BASE = 1U | (CIA_DMA_WIN_BASE_DEFAULT & 0xfff00000U); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/core_mcpcia.c linux.pre11.3/arch/alpha/kernel/core_mcpcia.c --- linux.vanilla/arch/alpha/kernel/core_mcpcia.c Sun Nov 8 15:08:25 1998 +++ linux.pre11.3/arch/alpha/kernel/core_mcpcia.c Mon Jul 19 23:28:34 1999 @@ -18,7 +18,6 @@ #include #include #include -#include #define __EXTERN_INLINE inline #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/core_pyxis.c linux.pre11.3/arch/alpha/kernel/core_pyxis.c --- linux.vanilla/arch/alpha/kernel/core_pyxis.c Sun Nov 8 15:08:25 1998 +++ linux.pre11.3/arch/alpha/kernel/core_pyxis.c Mon Jul 19 23:28:34 1999 @@ -425,17 +425,22 @@ { /* * Set up the PCI->physical memory translation windows. - * For now, windows 1,2 and 3 are disabled. In the future, we may + * For now, windows 2 and 3 are disabled. In the future, we may * want to use them to do scatter/gather DMA. * * Window 0 goes at 1 GB and is 1 GB large. + * Window 1 goes at 2 GB and is 1 GB large. */ - *(vuip)PYXIS_W0_BASE = 1U | (PYXIS_DMA_WIN_BASE_DEFAULT & 0xfff00000U); + *(vuip)PYXIS_W0_BASE = PYXIS_DMA_WIN_BASE_DEFAULT | 1U; *(vuip)PYXIS_W0_MASK = (PYXIS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U; *(vuip)PYXIS_T0_BASE = 0; - *(vuip)PYXIS_W1_BASE = 0x0 ; + *(vuip)PYXIS_W1_BASE = (PYXIS_DMA_WIN_BASE_DEFAULT + + PYXIS_DMA_WIN_SIZE_DEFAULT) | 1U; + *(vuip)PYXIS_W1_MASK = (PYXIS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U; + *(vuip)PYXIS_T1_BASE = PYXIS_DMA_WIN_SIZE_DEFAULT; + *(vuip)PYXIS_W2_BASE = 0x0 ; *(vuip)PYXIS_W3_BASE = 0x0 ; mb(); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/entry.S linux.pre11.3/arch/alpha/kernel/entry.S --- linux.vanilla/arch/alpha/kernel/entry.S Thu May 27 22:11:48 1999 +++ linux.pre11.3/arch/alpha/kernel/entry.S Mon Jul 19 23:28:33 1999 @@ -527,6 +527,8 @@ call_pal PAL_swpctx unop bsr $1,undo_switch_stack + lda $8,0x3fff + bic $30,$8,$8 mov $17,$0 ret $31,($26),1 .end alpha_switch_to diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/es1888.c linux.pre11.3/arch/alpha/kernel/es1888.c --- linux.vanilla/arch/alpha/kernel/es1888.c Sun Nov 8 15:08:24 1998 +++ linux.pre11.3/arch/alpha/kernel/es1888.c Mon Jul 19 23:28:33 1999 @@ -32,6 +32,7 @@ continue; inb(0x022a); /* pause */ outb(0xc6, 0x022c); /* enable extended mode */ + inb(0x022a); /* pause, also forces the write */ while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */ continue; outb(0xb1, 0x022c); /* setup for write to Interrupt CR */ @@ -44,4 +45,5 @@ while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */ continue; outb(0x18, 0x022c); /* set DMA channel 1 */ + inb(0x022c); /* force the write */ } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/irq.h linux.pre11.3/arch/alpha/kernel/irq.h --- linux.vanilla/arch/alpha/kernel/irq.h Thu Dec 31 18:10:39 1998 +++ linux.pre11.3/arch/alpha/kernel/irq.h Mon Jul 19 23:28:33 1999 @@ -24,6 +24,23 @@ extern void handle_irq(int irq, int ack, struct pt_regs * regs); +extern char _stext; +static inline void alpha_do_profile (unsigned long pc) +{ + if (prof_buffer && current->pid) { + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + /* + * Don't ignore out-of-bounds PC values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + if (pc > prof_len - 1) + pc = prof_len - 1; + atomic_inc((atomic_t *)&prof_buffer[pc]); + } +} + #define RTC_IRQ 8 #ifdef CONFIG_RTC #define TIMER_IRQ 0 /* timer is the pit */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/machvec.h linux.pre11.3/arch/alpha/kernel/machvec.h --- linux.vanilla/arch/alpha/kernel/machvec.h Thu Jan 14 01:25:21 1999 +++ linux.pre11.3/arch/alpha/kernel/machvec.h Mon Jul 19 23:28:34 1999 @@ -36,7 +36,6 @@ #define DO_EV4_MMU \ max_asn: EV4_MAX_ASN, \ - mmu_context_mask: ~0UL, \ mv_get_mmu_context: ev4_get_mmu_context, \ mv_flush_tlb_current: ev4_flush_tlb_current, \ mv_flush_tlb_other: ev4_flush_tlb_other, \ @@ -44,7 +43,6 @@ #define DO_EV5_MMU \ max_asn: EV5_MAX_ASN, \ - mmu_context_mask: ~0UL, \ mv_get_mmu_context: ev5_get_mmu_context, \ mv_flush_tlb_current: ev5_flush_tlb_current, \ mv_flush_tlb_other: ev5_flush_tlb_other, \ @@ -52,7 +50,6 @@ #define DO_EV6_MMU \ max_asn: EV6_MAX_ASN, \ - mmu_context_mask: 0xfffffffffful, \ mv_get_mmu_context: ev5_get_mmu_context, \ mv_flush_tlb_current: ev5_flush_tlb_current, \ mv_flush_tlb_other: ev5_flush_tlb_other, \ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/osf_sys.c linux.pre11.3/arch/alpha/kernel/osf_sys.c --- linux.vanilla/arch/alpha/kernel/osf_sys.c Thu May 27 22:11:48 1999 +++ linux.pre11.3/arch/alpha/kernel/osf_sys.c Mon Jul 19 23:28:33 1999 @@ -925,6 +925,7 @@ return -EINVAL; cpu = (struct percpu_struct*) ((char*)hwrpb + hwrpb->processor_offset); + w = cpu->type; if (put_user(w, (unsigned long *)buffer)) return -EFAULT; return 1; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/process.c linux.pre11.3/arch/alpha/kernel/process.c --- linux.vanilla/arch/alpha/kernel/process.c Tue Jun 15 16:49:45 1999 +++ linux.pre11.3/arch/alpha/kernel/process.c Mon Jul 19 23:52:02 1999 @@ -76,7 +75,7 @@ } #ifdef __SMP__ -void +int cpu_idle(void *unused) { /* An endless idle loop with no priority at all. */ @@ -329,7 +328,6 @@ p->tss.ksp = (unsigned long) childstack; p->tss.pal_flags = 1; /* set FEN, clear everything else */ p->tss.flags = current->tss.flags; - p->mm->context = 0; return 0; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/proto.h linux.pre11.3/arch/alpha/kernel/proto.h --- linux.vanilla/arch/alpha/kernel/proto.h Tue Jun 15 16:49:45 1999 +++ linux.pre11.3/arch/alpha/kernel/proto.h Mon Jul 19 23:28:33 1999 @@ -193,7 +193,7 @@ /* process.c */ extern void generic_kill_arch (int mode, char *reboot_cmd); -extern void cpu_idle(void *) __attribute__((noreturn)); +extern int cpu_idle(void *) __attribute__((noreturn)); /* ptrace.c */ extern int ptrace_set_bpt (struct task_struct *child); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/setup.c linux.pre11.3/arch/alpha/kernel/setup.c --- linux.vanilla/arch/alpha/kernel/setup.c Tue Jun 15 16:49:45 1999 +++ linux.pre11.3/arch/alpha/kernel/setup.c Mon Jul 19 23:28:33 1999 @@ -66,7 +66,7 @@ * initialized, we need to copy things out into a more permanent * place. */ -#define PARAM ZERO_PAGE +#define PARAM ZERO_PAGE(0) #define COMMAND_LINE ((char*)(PARAM + 0x0000)) #define COMMAND_LINE_SIZE 256 #define INITRD_START (*(unsigned long *) (PARAM+0x100)) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/signal.c linux.pre11.3/arch/alpha/kernel/signal.c --- linux.vanilla/arch/alpha/kernel/signal.c Tue Jun 15 16:49:45 1999 +++ linux.pre11.3/arch/alpha/kernel/signal.c Mon Jul 19 23:52:02 1999 @@ -16,7 +16,6 @@ #include #include #include -#include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/smp.c linux.pre11.3/arch/alpha/kernel/smp.c --- linux.vanilla/arch/alpha/kernel/smp.c Tue Jun 15 16:49:45 1999 +++ linux.pre11.3/arch/alpha/kernel/smp.c Mon Jul 19 23:52:02 1999 @@ -95,6 +95,8 @@ smp_store_cpu_info(int cpuid) { cpu_data[cpuid].loops_per_sec = loops_per_sec; + cpu_data[cpuid].last_asn + = (cpuid << WIDTH_HARDWARE_ASN) + ASN_FIRST_VERSION; } /* @@ -105,12 +107,6 @@ { cpu_data[cpuid].prof_counter = 1; cpu_data[cpuid].prof_multiplier = 1; - -#ifdef NOT_YET_PROFILING - load_profile_irq(mid_xlate[cpu], lvl14_resolution); - if (cpu == smp_boot_cpuid) - enable_pil_irq(14); -#endif } /* @@ -587,11 +583,9 @@ int user = user_mode(regs); struct cpuinfo_alpha *data = &cpu_data[cpu]; -#ifdef NOT_YET_PROFILING - clear_profile_irq(mid_xlate[cpu]); + /* Record kernel PC */ if (!user) alpha_do_profile(regs->pc); -#endif if (!--data->prof_counter) { /* We need to make like a normal interrupt -- otherwise @@ -628,28 +622,7 @@ int __init setup_profiling_timer(unsigned int multiplier) { -#ifdef NOT_YET_PROFILING - int i; - unsigned long flags; - - /* Prevent level14 ticker IRQ flooding. */ - if((!multiplier) || (lvl14_resolution / multiplier) < 500) - return -EINVAL; - - save_and_cli(flags); - for (i = 0; i < NR_CPUS; i++) { - if (cpu_present_mask & (1L << i)) { - load_profile_irq(mid_xlate[i], - lvl14_resolution / multiplier); - prof_multiplier[i] = multiplier; - } - } - restore_flags(flags); - - return 0; -#else return -EINVAL; -#endif } @@ -891,9 +864,11 @@ void flush_tlb_mm(struct mm_struct *mm) { - if (mm == current->mm) + if (mm == current->mm) { flush_tlb_current(mm); - else + if (atomic_read(&mm->count) == 1) + return; + } else flush_tlb_other(mm); if (smp_call_function(ipi_flush_tlb_mm, mm, 1, 1)) { @@ -921,15 +896,17 @@ struct flush_tlb_page_struct data; struct mm_struct *mm = vma->vm_mm; + if (mm == current->mm) { + flush_tlb_current_page(mm, vma, addr); + if (atomic_read(¤t->mm->count) == 1) + return; + } else + flush_tlb_other(mm); + data.vma = vma; data.mm = mm; data.addr = addr; - if (mm == current->mm) - flush_tlb_current_page(mm, vma, addr); - else - flush_tlb_other(mm); - if (smp_call_function(ipi_flush_tlb_page, &data, 1, 1)) { printk(KERN_CRIT "flush_tlb_page: timed out\n"); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/sys_dp264.c linux.pre11.3/arch/alpha/kernel/sys_dp264.c --- linux.vanilla/arch/alpha/kernel/sys_dp264.c Tue Jun 15 16:49:45 1999 +++ linux.pre11.3/arch/alpha/kernel/sys_dp264.c Mon Jul 19 23:28:34 1999 @@ -393,8 +393,8 @@ { layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); common_pci_fixup(monet_map_irq, monet_swizzle); - /* es1888_init(); */ /* later? */ SMC669_Init(1); + es1888_init(); } static void __init diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/time.c linux.pre11.3/arch/alpha/kernel/time.c --- linux.vanilla/arch/alpha/kernel/time.c Tue Jun 15 16:49:45 1999 +++ linux.pre11.3/arch/alpha/kernel/time.c Mon Jul 19 23:28:33 1999 @@ -94,6 +94,11 @@ smp_percpu_timer_interrupt(regs); if (smp_processor_id() != smp_boot_cpuid) return; +#else + /* Not SMP, do kernel PC profiling here */ + if (!user_mode(regs)) { + alpha_do_profile(regs->pc); + } #endif write_lock(&xtime_lock); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/math-emu/ieee-math.c linux.pre11.3/arch/alpha/math-emu/ieee-math.c --- linux.vanilla/arch/alpha/math-emu/ieee-math.c Thu May 27 22:11:48 1999 +++ linux.pre11.3/arch/alpha/math-emu/ieee-math.c Mon Jul 19 23:28:34 1999 @@ -704,20 +704,21 @@ * FPCR_INV if invalid operation occurred, etc. */ unsigned long -ieee_CVTQT (int f, unsigned long a, unsigned long *b) +ieee_CVTQT (int f, long a, unsigned long *b) { EXTENDED op_b; - op_b.s = 0; - op_b.f[0] = a; - op_b.f[1] = 0; - if (sign(a) < 0) { - op_b.s = 1; - op_b.f[0] = -a; + if (a != 0) { + op_b.s = (a < 0 ? 1 : 0); + op_b.f[0] = (a < 0 ? -a : a); + op_b.f[1] = 0; + op_b.e = 55; + normalize(&op_b); + return round_t_ieee(f, &op_b, b); + } else { + *b = 0; + return 0; } - op_b.e = 55; - normalize(&op_b); - return round_t_ieee(f, &op_b, b); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/math-emu/ieee-math.h linux.pre11.3/arch/alpha/math-emu/ieee-math.h --- linux.vanilla/arch/alpha/math-emu/ieee-math.h Thu May 27 22:11:48 1999 +++ linux.pre11.3/arch/alpha/math-emu/ieee-math.h Mon Jul 19 23:28:34 1999 @@ -20,7 +20,7 @@ extern unsigned long ieee_CVTST (int rm, unsigned long a, unsigned long *b); extern unsigned long ieee_CVTTS (int rm, unsigned long a, unsigned long *b); extern unsigned long ieee_CVTQS (int rm, unsigned long a, unsigned long *b); -extern unsigned long ieee_CVTQT (int rm, unsigned long a, unsigned long *b); +extern unsigned long ieee_CVTQT (int rm, long a, unsigned long *b); extern unsigned long ieee_CVTTQ (int rm, unsigned long a, unsigned long *b); extern unsigned long ieee_CMPTEQ (unsigned long a, unsigned long b, diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/mm/fault.c linux.pre11.3/arch/alpha/mm/fault.c --- linux.vanilla/arch/alpha/mm/fault.c Sun Nov 8 15:08:23 1998 +++ linux.pre11.3/arch/alpha/mm/fault.c Mon Jul 19 23:52:02 1999 @@ -7,6 +7,7 @@ #include #include #include +#include #define __EXTERN_INLINE inline #include @@ -28,64 +29,20 @@ extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *); -#ifdef __SMP__ -unsigned long last_asn[NR_CPUS] = { /* gag */ - ASN_FIRST_VERSION + (0 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (1 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (2 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (3 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (4 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (5 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (6 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (7 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (8 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (9 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (10 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (11 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (12 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (13 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (14 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (15 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (16 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (17 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (18 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (19 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (20 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (21 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (22 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (23 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (24 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (25 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (26 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (27 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (28 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (29 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (30 << WIDTH_HARDWARE_ASN), - ASN_FIRST_VERSION + (31 << WIDTH_HARDWARE_ASN) -}; -#else -unsigned long asn_cache = ASN_FIRST_VERSION; -#endif /* __SMP__ */ - /* - * Select a new ASN for a task. + * Force a new ASN for a task. */ +#ifndef __SMP__ +unsigned long last_asn = ASN_FIRST_VERSION; +#endif + void get_new_mmu_context(struct task_struct *p, struct mm_struct *mm) { - unsigned long asn = asn_cache; - - if ((asn & HARDWARE_ASN_MASK) < MAX_ASN) - ++asn; - else { - tbiap(); - imb(); - asn = (asn & ~HARDWARE_ASN_MASK) + ASN_FIRST_VERSION; - } - asn_cache = asn; - mm->context = asn; /* full version + asn */ - p->tss.asn = asn & HARDWARE_ASN_MASK; /* just asn */ + unsigned long new = __get_new_mmu_context(); + mm->context = new; + p->tss.asn = new & HARDWARE_ASN_MASK; } /* diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/mm/init.c linux.pre11.3/arch/alpha/mm/init.c --- linux.vanilla/arch/alpha/mm/init.c Tue Jun 15 16:49:46 1999 +++ linux.pre11.3/arch/alpha/mm/init.c Mon Jul 19 23:28:33 1999 @@ -174,7 +174,7 @@ extern unsigned long free_area_init(unsigned long, unsigned long); -static struct thread_struct * +static inline struct thread_struct * load_PCB(struct thread_struct * pcb) { register unsigned long sp __asm__("$30"); @@ -219,7 +219,7 @@ /* Initialize the kernel's page tables. Linux puts the vptb in the last slot of the L1 page table. */ - memset((void *) ZERO_PAGE, 0, PAGE_SIZE); + memset((void *) ZERO_PAGE(0), 0, PAGE_SIZE); memset(swapper_pg_dir, 0, PAGE_SIZE); newptbr = ((unsigned long) swapper_pg_dir - PAGE_OFFSET) >> PAGE_SHIFT; pgd_val(swapper_pg_dir[1023]) = diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/process.c linux.pre11.3/arch/arm/kernel/process.c --- linux.vanilla/arch/arm/kernel/process.c Sun Nov 8 15:08:44 1998 +++ linux.pre11.3/arch/arm/kernel/process.c Mon Jul 19 23:52:23 1999 @@ -27,9 +27,7 @@ #include #include #include -#include #include -#include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/time.c linux.pre11.3/arch/arm/kernel/time.c --- linux.vanilla/arch/arm/kernel/time.c Wed Mar 24 10:55:10 1999 +++ linux.pre11.3/arch/arm/kernel/time.c Mon Jul 19 23:52:23 1999 @@ -23,8 +23,6 @@ #include #include #include -#include -#include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/Makefile linux.pre11.3/arch/i386/Makefile --- linux.vanilla/arch/i386/Makefile Thu Dec 31 18:10:39 1998 +++ linux.pre11.3/arch/i386/Makefile Mon Jul 19 23:28:28 1999 @@ -62,6 +62,13 @@ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot +vmlinux: arch/i386/vmlinux.lds + +arch/i386/vmlinux.lds: arch/i386/vmlinux.lds.S FORCE + gcc -E -C -P -I$(HPATH) -imacros $(HPATH)/asm-i386/page_offset.h -Ui386 arch/i386/vmlinux.lds.S >arch/i386/vmlinux.lds + +FORCE: ; + zImage: vmlinux @$(MAKEBOOT) zImage diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/boot/setup.S linux.pre11.3/arch/i386/boot/setup.S --- linux.vanilla/arch/i386/boot/setup.S Tue Jun 15 16:49:46 1999 +++ linux.pre11.3/arch/i386/boot/setup.S Mon Jul 19 23:28:27 1999 @@ -757,11 +757,11 @@ ! with no keyboard attached... empty_8042: - push cx - mov cx,#0xFFFF + push ecx + mov ecx,#0xFFFFFF empty_8042_loop: - dec cx + dec ecx jz empty_8042_end_loop call delay @@ -775,7 +775,7 @@ test al,#2 ! is input buffer full? jnz empty_8042_loop ! yes - loop empty_8042_end_loop: - pop cx + pop ecx ret ! Binary files linux.vanilla/arch/i386/boot/tools/build and linux.pre11.3/arch/i386/boot/tools/build differ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/config.in linux.pre11.3/arch/i386/config.in --- linux.vanilla/arch/i386/config.in Wed Apr 28 19:14:24 1999 +++ linux.pre11.3/arch/i386/config.in Mon Jul 19 23:28:28 1999 @@ -33,6 +33,10 @@ define_bool CONFIG_X86_GOOD_APIC y fi +choice 'Maximum Physical Memory' \ + "1GB CONFIG_1GB \ + 2GB CONFIG_2GB" 1GB + bool 'Math emulation' CONFIG_MATH_EMULATION bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR bool 'Symmetric multi-processing support' CONFIG_SMP diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/defconfig linux.pre11.3/arch/i386/defconfig --- linux.vanilla/arch/i386/defconfig Fri Apr 16 22:10:51 1999 +++ linux.pre11.3/arch/i386/defconfig Mon Jul 19 23:52:37 1999 @@ -21,6 +21,8 @@ CONFIG_X86_POPAD_OK=y CONFIG_X86_TSC=y CONFIG_X86_GOOD_APIC=y +CONFIG_1GB=y +# CONFIG_2GB is not set # CONFIG_MATH_EMULATION is not set # CONFIG_MTRR is not set CONFIG_SMP=y diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/kernel/i386_ksyms.c linux.pre11.3/arch/i386/kernel/i386_ksyms.c --- linux.vanilla/arch/i386/kernel/i386_ksyms.c Thu May 27 22:11:49 1999 +++ linux.pre11.3/arch/i386/kernel/i386_ksyms.c Mon Jul 19 23:28:30 1999 @@ -42,6 +42,8 @@ EXPORT_SYMBOL(disable_irq_nosync); EXPORT_SYMBOL(kernel_thread); +EXPORT_SYMBOL(init_mm); + EXPORT_SYMBOL_NOVERS(__down_failed); EXPORT_SYMBOL_NOVERS(__down_failed_interruptible); EXPORT_SYMBOL_NOVERS(__down_failed_trylock); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/kernel/irq.c linux.pre11.3/arch/i386/kernel/irq.c --- linux.vanilla/arch/i386/kernel/irq.c Thu May 27 22:11:49 1999 +++ linux.pre11.3/arch/i386/kernel/irq.c Mon Jul 19 23:53:05 1999 @@ -139,7 +139,7 @@ /* * Controller mappings for all interrupt sources: */ -irq_desc_t irq_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = { 0, &no_irq_type, }}; +irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { [0 ... NR_IRQS-1] = { 0, &no_irq_type, }}; /* @@ -927,6 +927,17 @@ return; spin_lock_irqsave(&irq_controller_lock,flags); + +#ifdef __SMP__ + /* Make sure no interrupt handler is in progress when we + manipulate the action list and free the structure */ + while (irq_desc[irq].status & IRQ_INPROGRESS) { + spin_unlock_irqrestore(&irq_controller_lock,flags); + udelay(1000); + spin_lock_irqsave(&irq_controller_lock,flags); + } +#endif + for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next) { if (action->dev_id != dev_id) continue; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/kernel/irq.h linux.pre11.3/arch/i386/kernel/irq.h --- linux.vanilla/arch/i386/kernel/irq.h Thu May 27 22:11:49 1999 +++ linux.pre11.3/arch/i386/kernel/irq.h Tue Jul 20 01:50:34 1999 @@ -40,6 +40,7 @@ struct hw_interrupt_type *handler; /* handle/enable/disable functions */ struct irqaction *action; /* IRQ action list */ unsigned int depth; /* Disable depth for nested irq disables */ + unsigned int unused[4]; } irq_desc_t; /* @@ -214,8 +215,8 @@ "\n" __ALIGN_STR"\n" \ "common_interrupt:\n\t" \ SAVE_ALL \ - "pushl $ret_from_intr\n\t" \ - "jmp "SYMBOL_NAME_STR(do_IRQ)); + "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \ + "jmp ret_from_intr\n"); /* * subtle. orig_eax is used by the signal code to distinct between diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/math-emu/fpu_emu.h linux.pre11.3/arch/i386/math-emu/fpu_emu.h --- linux.vanilla/arch/i386/math-emu/fpu_emu.h Sun Nov 8 15:08:21 1998 +++ linux.pre11.3/arch/i386/math-emu/fpu_emu.h Mon Jul 19 23:53:16 1999 @@ -165,8 +165,6 @@ #define signpositive(a) ( (signbyte(a) & 0x80) == 0 ) #define signnegative(a) (signbyte(a) & 0x80) -#include "fpu_proto.h" - static inline void reg_copy(FPU_REG const *x, FPU_REG *y) { *(short *)&(y->exp) = *(const short *)&(x->exp); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/mm/init.c linux.pre11.3/arch/i386/mm/init.c --- linux.vanilla/arch/i386/mm/init.c Tue Jan 26 09:44:20 1999 +++ linux.pre11.3/arch/i386/mm/init.c Mon Jul 19 23:53:23 1999 @@ -168,6 +168,8 @@ printk("%d reserved pages\n",reserved); printk("%d pages shared\n",shared); printk("%d pages swap cached\n",cached); + printk("%ld pages in file cache\n",page_cache_size-cached); + printk("%ld pages in page cache\n",page_cache_size); printk("%ld pages in page table cache\n",pgtable_cache_size); show_buffers(); #ifdef CONFIG_NET diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/mm/ioremap.c linux.pre11.3/arch/i386/mm/ioremap.c --- linux.vanilla/arch/i386/mm/ioremap.c Thu Dec 3 14:11:59 1998 +++ linux.pre11.3/arch/i386/mm/ioremap.c Mon Jul 19 23:28:28 1999 @@ -93,12 +93,17 @@ { void * addr; struct vm_struct * area; - unsigned long offset; + unsigned long offset, last_addr; + + /* Don't allow wraparound or zero size */ + last_addr = phys_addr + size - 1; + if (!size || last_addr < phys_addr) + return NULL; /* * Don't remap the low PCI/ISA area, it's always mapped.. */ - if (phys_addr >= 0xA0000 && (phys_addr+size) <= 0x100000) + if (phys_addr >= 0xA0000 && last_addr < 0x100000) return phys_to_virt(phys_addr); /* @@ -112,13 +117,7 @@ */ offset = phys_addr & ~PAGE_MASK; phys_addr &= PAGE_MASK; - size = PAGE_ALIGN(size + offset); - - /* - * Don't allow mappings that wrap.. - */ - if (!size || size > phys_addr + size) - return NULL; + size = PAGE_ALIGN(last_addr) - phys_addr; /* * Ok, go for it.. diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/vmlinux.lds linux.pre11.3/arch/i386/vmlinux.lds --- linux.vanilla/arch/i386/vmlinux.lds Mon Dec 28 23:09:40 1998 +++ linux.pre11.3/arch/i386/vmlinux.lds Tue Jul 20 01:51:19 1999 @@ -1,12 +1,12 @@ /* ld script to make i386 Linux kernel - * Written by Martin Mares + * Written by Martin Mares ; */ OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) ENTRY(_start) SECTIONS { - . = 0xC0000000 + 0x100000; + . = 0xC0000000 + 0x100000; _text = .; /* Text and read-only data */ .text : { *(.text) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/vmlinux.lds.S linux.pre11.3/arch/i386/vmlinux.lds.S --- linux.vanilla/arch/i386/vmlinux.lds.S Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/i386/vmlinux.lds.S Mon Jul 19 23:28:33 1999 @@ -0,0 +1,69 @@ +/* ld script to make i386 Linux kernel + * Written by Martin Mares ; + */ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) +SECTIONS +{ + . = PAGE_OFFSET_RAW + 0x100000; + _text = .; /* Text and read-only data */ + .text : { + *(.text) + *(.fixup) + *(.gnu.warning) + } = 0x9090 + .text.lock : { *(.text.lock) } /* out-of-line lock text */ + .rodata : { *(.rodata) } + .kstrtab : { *(.kstrtab) } + + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + __ksymtab : { *(__ksymtab) } + __stop___ksymtab = .; + + _etext = .; /* End of text section */ + + .data : { /* Data */ + *(.data) + CONSTRUCTORS + } + + _edata = .; /* End of data section */ + + . = ALIGN(8192); /* init_task */ + .data.init_task : { *(.data.init_task) } + + . = ALIGN(4096); /* Init code and data */ + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + . = ALIGN(32); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + + . = ALIGN(4096); + .data.page_aligned : { *(.data.idt) } + + + __bss_start = .; /* BSS */ + .bss : { + *(.bss) + } + _end = . ; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/Makefile linux.pre11.3/arch/mips/Makefile --- linux.vanilla/arch/mips/Makefile Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/Makefile Mon Jul 19 23:28:37 1999 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.13 1998/08/17 10:16:23 ralf Exp $ +# $Id: Makefile,v 1.17 1999/05/02 20:56:18 harald Exp $ # # 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 @@ -36,7 +36,7 @@ CROSS_COMPILE = $(tool-prefix) endif -LINKFLAGS = -static #-N +LINKFLAGS = -static -N MODFLAGS += -mlong-calls # @@ -97,22 +97,37 @@ SUBDIRS += arch/mips/algor #LOADADDR += 0x80000000 endif + +# +# DECstation family +# +ifdef CONFIG_DECSTATION +CORE_FILES += arch/mips/dec/dec.o +SUBDIRS += arch/mips/dec arch/mips/dec/prom +LIBS += arch/mips/dec/prom/rexlib.a +LOADADDR += 0x80040000 +endif + # # Acer PICA 61, Mips Magnum 4000 and Olivetti M700. # ifdef CONFIG_MIPS_JAZZ CORE_FILES += arch/mips/jazz/jazz.o -SUBDIRS += arch/mips/jazz -LOADADDR += 0x80000000 +SUBDIRS += arch/mips/jazz arch/mips/arc +LIBS += arch/mips/arc/arclib.a +LOADADDR += 0x80080000 endif + ifdef CONFIG_SNI_RM200_PCI CORE_FILES += arch/mips/sni/sni.o -SUBDIRS += arch/mips/sni -LOADADDR += 0x80000000 +SUBDIRS += arch/mips/sni arch/mips/arc +LIBS += arch/mips/arc/arclib.a +LOADADDR += 0x80080000 endif + ifdef CONFIG_SGI -LIBS += arch/mips/sgi/kernel/sgikern.a arch/mips/sgi/prom/promlib.a -SUBDIRS += arch/mips/sgi/kernel arch/mips/sgi/prom +LIBS += arch/mips/sgi/kernel/sgikern.a arch/mips/arc/arclib.a +SUBDIRS += arch/mips/sgi/kernel arch/mips/arc # # Set LOADADDR to >= 0x88069000 if you want to leave space for symmon, # 0x88002000 for production kernels. Note that the value must be @@ -123,6 +138,14 @@ endif # +# Baget/MIPS +# +ifdef CONFIG_BAGET_MIPS +SUBDIRS += arch/mips/baget arch/mips/baget/prom +LIBS += arch/mips/baget/baget.a arch/mips/baget/prom/bagetlib.a +endif + +# # Choosing incompatible machines durings configuration will result in # error messages during linking. Select a default linkscript if # none has been choosen above. @@ -150,7 +173,16 @@ SUBDIRS := $(SUBDIRS) $(addprefix arch/mips/, kernel mm lib tools) CORE_FILES := arch/mips/kernel/kernel.o arch/mips/mm/mm.o $(CORE_FILES) -LIBS := arch/mips/lib/lib.a $(LIBS) arch/mips/lib/lib.a +LIBS := arch/mips/lib/lib.a $(LIBS) + +ifdef CONFIG_BAGET_MIPS + +BAGETBOOT = $(MAKE) -C arch/$(ARCH)/baget + +balo: vmlinux + $(BAGETBOOT) balo + +endif MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/algor/README linux.pre11.3/arch/mips/algor/README --- linux.vanilla/arch/mips/algor/README Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/algor/README Mon Jul 19 23:28:47 1999 @@ -0,0 +1,5 @@ +The code for the Algorithmics P4032 evaluation board is currently under +development. I'll release it when it's up to the same strength as +the other ports. + + Ralf diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/Makefile linux.pre11.3/arch/mips/arc/Makefile --- linux.vanilla/arch/mips/arc/Makefile Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/arc/Makefile Mon Jul 19 23:28:47 1999 @@ -0,0 +1,23 @@ +# $Id: Makefile,v 1.1 1998/10/18 13:32:08 tsbogend Exp $ +# Makefile for the SGI arcs prom monitor library routines +# under Linux. +# +# 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... + +OBJS = console.o init.o printf.o memory.o tree.o env.o \ + cmdline.o misc.o time.o file.o identify.o + +all: arclib.a + +arclib.a: $(OBJS) + $(AR) rcs arclib.a $(OBJS) + sync + +dep: + $(CPP) -M *.c > .depend + +include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/cmdline.c linux.pre11.3/arch/mips/arc/cmdline.c --- linux.vanilla/arch/mips/arc/cmdline.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/arc/cmdline.c Mon Jul 19 23:28:47 1999 @@ -0,0 +1,64 @@ +/* + * cmdline.c: Kernel command line creation using ARCS argc/argv. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: cmdline.c,v 1.1 1998/10/18 13:32:08 tsbogend Exp $ + */ +#include +#include +#include + +#include +#include + +/* #define DEBUG_CMDLINE */ + +char arcs_cmdline[CL_SIZE]; + +__initfunc(char *prom_getcmdline(void)) +{ + return &(arcs_cmdline[0]); +} + +static char *ignored[] = { + "ConsoleIn=", + "ConsoleOut=", + "SystemPartition=", + "OSLoader=", + "OSLoadPartition=", + "OSLoadFilename=" +}; +#define NENTS(foo) ((sizeof((foo)) / (sizeof((foo[0]))))) + +__initfunc(void prom_init_cmdline(void)) +{ + char *cp; + int actr, i; + + actr = 1; /* Always ignore argv[0] */ + + cp = &(arcs_cmdline[0]); + while(actr < prom_argc) { + for(i = 0; i < NENTS(ignored); i++) { + int len = strlen(ignored[i]); + + if(!strncmp(prom_argv[actr], ignored[i], len)) + goto pic_cont; + } + /* Ok, we want it. */ + strcpy(cp, prom_argv[actr]); + cp += strlen(prom_argv[actr]); + *cp++ = ' '; + + pic_cont: + actr++; + } + if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ + --cp; + *cp = '\0'; + +#ifdef DEBUG_CMDLINE + prom_printf("prom_init_cmdline: %s\n", &(arcs_cmdline[0])); +#endif +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/console.c linux.pre11.3/arch/mips/arc/console.c --- linux.vanilla/arch/mips/arc/console.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/arc/console.c Mon Jul 19 23:53:54 1999 @@ -0,0 +1,50 @@ +/* + * console.c: SGI arcs console code. + * + * Copyright (C) 1996 David S. Miller (dm@sgi.com) + * Compability with board caches, Ulf Carlsson + * + * $Id: console.c,v 1.2 1999/06/12 18:42:38 ulfc Exp $ + */ +#include +#include +#include +#include + +/* The romvec is not compatible with board caches. Thus we disable it during + * romvec action. Since r4xx0.c is always compiled and linked with your kernel, + * this shouldn't cause any harm regardless what MIPS processor you have. + * + * The romvec write and read functions seem to interfere with the serial lines + * in some way. You should be careful with them. + */ +extern struct bcache_ops *bcops; + +#ifdef CONFIG_SGI_PROM_CONSOLE +void prom_putchar(char c) +#else +__initfunc(void prom_putchar(char c)) +#endif +{ + long cnt; + char it = c; + + bcops->bc_disable(); + romvec->write(1, &it, 1, &cnt); + bcops->bc_enable(); +} + +#ifdef CONFIG_SGI_PROM_CONSOLE +char prom_getchar(void) +#else +__initfunc(char prom_getchar(void)) +#endif +{ + long cnt; + char c; + + bcops->bc_disable(); + romvec->read(0, &c, 1, &cnt); + bcops->bc_enable(); + return c; +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/env.c linux.pre11.3/arch/mips/arc/env.c --- linux.vanilla/arch/mips/arc/env.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/arc/env.c Mon Jul 19 23:28:47 1999 @@ -0,0 +1,22 @@ +/* + * env.c: ARCS environment variable routines. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: env.c,v 1.1 1998/10/18 13:32:08 tsbogend Exp $ + */ +#include +#include +#include + +#include + +__initfunc(char *prom_getenv(char *name)) +{ + return romvec->get_evar(name); +} + +__initfunc(long prom_setenv(char *name, char *value)) +{ + return romvec->set_evar(name, value); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/file.c linux.pre11.3/arch/mips/arc/file.c --- linux.vanilla/arch/mips/arc/file.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/arc/file.c Mon Jul 19 23:28:47 1999 @@ -0,0 +1,59 @@ +/* + * file.c: ARCS firmware interface to files. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: file.c,v 1.1 1998/10/18 13:32:08 tsbogend Exp $ + */ +#include +#include + +__initfunc(long prom_getvdirent(unsigned long fd, struct linux_vdirent *ent, unsigned long num, unsigned long *cnt)) +{ + return romvec->get_vdirent(fd, ent, num, cnt); +} + +__initfunc(long prom_open(char *name, enum linux_omode md, unsigned long *fd)) +{ + return romvec->open(name, md, fd); +} + +__initfunc(long prom_close(unsigned long fd)) +{ + return romvec->close(fd); +} + +__initfunc(long prom_read(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt)) +{ + return romvec->read(fd, buf, num, cnt); +} + +__initfunc(long prom_getrstatus(unsigned long fd)) +{ + return romvec->get_rstatus(fd); +} + +__initfunc(long prom_write(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt)) +{ + return romvec->write(fd, buf, num, cnt); +} + +__initfunc(long prom_seek(unsigned long fd, struct linux_bigint *off, enum linux_seekmode sm)) +{ + return romvec->seek(fd, off, sm); +} + +__initfunc(long prom_mount(char *name, enum linux_mountops op)) +{ + return romvec->mount(name, op); +} + +__initfunc(long prom_getfinfo(unsigned long fd, struct linux_finfo *buf)) +{ + return romvec->get_finfo(fd, buf); +} + +__initfunc(long prom_setfinfo(unsigned long fd, unsigned long flags, unsigned long msk)) +{ + return romvec->set_finfo(fd, flags, msk); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/identify.c linux.pre11.3/arch/mips/arc/identify.c --- linux.vanilla/arch/mips/arc/identify.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/arc/identify.c Mon Jul 19 23:28:47 1999 @@ -0,0 +1,68 @@ +/* + * identify.c: identify machine by looking up system identifier + * + * Copyright (C) 1998 Thomas Bogendoerfer + * + * This code is based on arch/mips/sgi/kernel/system.c, which is + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: identify.c,v 1.2 1999/02/25 21:04:13 tsbogend Exp $ + */ +#include +#include +#include +#include + +#include +#include +#include + +struct smatch { + char *name; + int group; + int type; + int flags; +}; + +static struct smatch mach_table[] = { + { "SGI-IP22", MACH_GROUP_SGI, MACH_SGI_INDY, PROM_FLAG_ARCS }, + { "Microsoft-Jazz", MACH_GROUP_JAZZ, MACH_MIPS_MAGNUM_4000, 0 }, + { "PICA-61", MACH_GROUP_JAZZ, MACH_ACER_PICA_61, 0 }, + { "RM200PCI", MACH_GROUP_SNI_RM, MACH_SNI_RM200_PCI, 0 } +}; + +int prom_flags; + +static struct smatch * __init string_to_mach(char *s) +{ + int i; + + for (i = 0; i < sizeof (mach_table); i++) { + if(!strcmp(s, mach_table[i].name)) + return &mach_table[i]; + } + prom_printf("\nYeee, could not determine architecture type <%s>\n", s); + prom_printf("press a key to reboot\n"); + prom_getchar(); + romvec->imode(); + return NULL; +} + +void __init prom_identify_arch(void) +{ + pcomponent *p; + struct smatch *mach; + + /* The root component tells us what machine architecture we + * have here. + */ + p = prom_getchild(PROM_NULL_COMPONENT); + printk("ARCH: %s\n", p->iname); + mach = string_to_mach(p->iname); + + mips_machgroup = mach->group; + mips_machtype = mach->type; + prom_flags = mach->flags; +} + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/init.c linux.pre11.3/arch/mips/arc/init.c --- linux.vanilla/arch/mips/arc/init.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/arc/init.c Mon Jul 19 23:28:47 1999 @@ -0,0 +1,67 @@ +/* + * init.c: PROM library initialisation code. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: init.c,v 1.2 1999/02/25 21:22:49 tsbogend Exp $ + */ +#include +#include +#include + +#include + +/* #define DEBUG_PROM_INIT */ + +/* Master romvec interface. */ +struct linux_romvec *romvec; +struct linux_promblock *sgi_pblock; +int prom_argc; +char **prom_argv, **prom_envp; +unsigned short prom_vers, prom_rev; + +extern void prom_testtree(void); + +__initfunc(int prom_init(int argc, char **argv, char **envp)) +{ + struct linux_promblock *pb; + + romvec = ROMVECTOR; + pb = sgi_pblock = PROMBLOCK; + prom_argc = argc; + prom_argv = argv; + prom_envp = envp; + + if(pb->magic != 0x53435241) { + prom_printf("Aieee, bad prom vector magic %08lx\n", pb->magic); + while(1) + ; + } + + prom_init_cmdline(); + + prom_vers = pb->ver; + prom_rev = pb->rev; + prom_identify_arch(); +#ifdef CONFIG_SGI + printk("PROMLIB: SGI ARCS firmware Version %d Revision %d\n", + prom_vers, prom_rev); +#else + printk("PROMLIB: ARC firmware Version %d Revision %d\n", + prom_vers, prom_rev); +#endif + prom_meminit(); + +#if 0 + prom_testtree(); +#endif + +#ifdef DEBUG_PROM_INIT + { + prom_printf("Press a key to reboot\n"); + (void) prom_getchar(); + romvec->imode(); + } +#endif + return 0; +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/memory.c linux.pre11.3/arch/mips/arc/memory.c --- linux.vanilla/arch/mips/arc/memory.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/arc/memory.c Mon Jul 19 23:53:54 1999 @@ -0,0 +1,208 @@ +/* + * memory.c: PROM library functions for acquiring/using memory descriptors + * given to us from the ARCS firmware. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: memory.c,v 1.5 1999/04/14 21:25:02 tsbogend Exp $ + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* #define DEBUG */ + +__initfunc(struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr)) +{ + return romvec->get_mdesc(curr); +} + +#ifdef DEBUG /* convenient for debugging */ +static char *arcs_mtypes[8] = { + "Exception Block", + "ARCS Romvec Page", + "Free/Contig RAM", + "Generic Free RAM", + "Bad Memory", + "Standlong Program Pages", + "ARCS Temp Storage Area", + "ARCS Permanent Storage Area" +}; + +static char *arc_mtypes[8] = { + "Exception Block", + "SystemParameterBlock", + "FreeMemory", + "Bad Memory", + "LoadedProgram", + "FirmwareTemporary", + "FirmwarePermanent", + "FreeContigiuous" +}; +#define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] : arc_mtypes[a.arc] +#endif + +static struct prom_pmemblock prom_pblocks[PROM_MAX_PMEMBLOCKS]; + +__initfunc(struct prom_pmemblock *prom_getpblock_array(void)) +{ + return &prom_pblocks[0]; +} + +#define MEMTYPE_DONTUSE 0 +#define MEMTYPE_PROM 1 +#define MEMTYPE_FREE 2 + +static int __init prom_memtype_classify (union linux_memtypes type) +{ + if (prom_flags & PROM_FLAG_ARCS) { + switch (type.arcs) { + case arcs_free: + case arcs_fcontig: + return MEMTYPE_FREE; + case arcs_atmp: + case arcs_aperm: + return MEMTYPE_PROM; + default: + return MEMTYPE_DONTUSE; + } + } else { + switch (type.arc) { + case arc_free: + case arc_fcontig: + return MEMTYPE_FREE; + case arc_rvpage: + case arc_atmp: + case arc_aperm: + return MEMTYPE_PROM; + default: + return MEMTYPE_DONTUSE; + } + } +} + +__initfunc(static void prom_setup_memupper(void)) +{ + struct prom_pmemblock *p, *highest; + + for(p = prom_getpblock_array(), highest = 0; p->size != 0; p++) { + if(p->base == 0xdeadbeef) + prom_printf("WHEEE, bogus pmemblock\n"); + if(!highest || p->base > highest->base) + highest = p; + } + mips_memory_upper = highest->base + highest->size; +#ifdef DEBUG + prom_printf("prom_setup_memupper: mips_memory_upper = %08lx\n", + mips_memory_upper); +#endif +} + +__initfunc(void prom_meminit(void)) +{ + struct linux_mdesc *p; + int totram; + int i = 0; + + p = prom_getmdesc(PROM_NULL_MDESC); +#ifdef DEBUG + prom_printf("ARCS MEMORY DESCRIPTOR dump:\n"); + while(p) { + prom_printf("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n", + i, p, p->base, p->pages, mtypes(p->type)); + p = prom_getmdesc(p); + i++; + } +#endif + p = prom_getmdesc(PROM_NULL_MDESC); + totram = 0; + i = 0; + while(p) { + prom_pblocks[i].type = prom_memtype_classify (p->type); + prom_pblocks[i].base = ((p->base<pages << PAGE_SHIFT; + switch (prom_pblocks[i].type) { + case MEMTYPE_FREE: + totram += prom_pblocks[i].size; +#ifdef DEBUG + prom_printf("free_chunk[%d]: base=%08lx size=%d\n", + i, prom_pblocks[i].base, + prom_pblocks[i].size); +#endif + i++; + break; + case MEMTYPE_PROM: +#ifdef DEBUG + prom_printf("prom_chunk[%d]: base=%08lx size=%d\n", + i, prom_pblocks[i].base, + prom_pblocks[i].size); +#endif + i++; + break; + default: + break; + } + p = prom_getmdesc(p); + } + prom_pblocks[i].base = 0xdeadbeef; + prom_pblocks[i].size = 0; /* indicates last elem. of array */ + printk("PROMLIB: Total free ram %d bytes (%dK,%dMB)\n", + totram, (totram/1024), (totram/1024/1024)); + + /* Setup upper physical memory bound. */ + prom_setup_memupper(); +} + +/* Called from mem_init() to fixup the mem_map page settings. */ +__initfunc(void prom_fixup_mem_map(unsigned long start, unsigned long end)) +{ + struct prom_pmemblock *p; + int i, nents; + + /* Determine number of pblockarray entries. */ + p = prom_getpblock_array(); + for(i = 0; p[i].size; i++) + ; + nents = i; +restart: + while(start < end) { + for(i = 0; i < nents; i++) { + if((p[i].type == MEMTYPE_FREE) && + (start >= (p[i].base)) && + (start < (p[i].base + p[i].size))) { + start = p[i].base + p[i].size; + start &= PAGE_MASK; + goto restart; + } + } + set_bit(PG_reserved, &mem_map[MAP_NR(start)].flags); + start += PAGE_SIZE; + } +} + +void prom_free_prom_memory (void) +{ + struct prom_pmemblock *p; + unsigned long addr; + unsigned long num_pages = 0; + + for(p = prom_getpblock_array(); p->size != 0; p++) { + if (p->type == MEMTYPE_PROM) { + for (addr = p->base; addr < p->base + p->size; addr += PAGE_SIZE) { + mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved); + atomic_set(&mem_map[MAP_NR(addr)].count, 1); + free_page(addr); + num_pages++; + } + } + } + printk ("Freeing prom memory: %dk freed\n",num_pages << (PAGE_SHIFT - 10)); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/misc.c linux.pre11.3/arch/mips/arc/misc.c --- linux.vanilla/arch/mips/arc/misc.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/arc/misc.c Mon Jul 19 23:28:47 1999 @@ -0,0 +1,84 @@ +/* $Id: misc.c,v 1.1 1998/10/18 13:32:09 tsbogend Exp $ + * + * misc.c: Miscellaneous ARCS PROM routines. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ +#include +#include +#include + +#include +#include +#include +#include + +extern unsigned long mips_cputype; +extern void *sgiwd93_host; +extern void reset_wd33c93(void *instance); + +void prom_halt(void) +{ + bcops->bc_disable(); + cli(); +#if CONFIG_SCSI_SGIWD93 + reset_wd33c93(sgiwd93_host); +#endif + romvec->halt(); +} + +void prom_powerdown(void) +{ + bcops->bc_disable(); + cli(); +#if CONFIG_SCSI_SGIWD93 + reset_wd33c93(sgiwd93_host); +#endif + romvec->pdown(); +} + +/* XXX is this a soft reset basically? XXX */ +void prom_restart(void) +{ + bcops->bc_disable(); + cli(); +#if CONFIG_SCSI_SGIWD93 + reset_wd33c93(sgiwd93_host); +#endif + romvec->restart(); +} + +void prom_reboot(void) +{ + bcops->bc_disable(); + cli(); +#if CONFIG_SCSI_SGIWD93 + reset_wd33c93(sgiwd93_host); +#endif + romvec->reboot(); +} + +void prom_imode(void) +{ + bcops->bc_disable(); + cli(); +#if CONFIG_SCSI_SGIWD93 + reset_wd33c93(sgiwd93_host); +#endif + romvec->imode(); +} + +long prom_cfgsave(void) +{ + return romvec->cfg_save(); +} + +struct linux_sysid *prom_getsysid(void) +{ + return romvec->get_sysid(); +} + +__initfunc(void prom_cacheflush(void)) +{ + romvec->cache_flush(); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/printf.c linux.pre11.3/arch/mips/arc/printf.c --- linux.vanilla/arch/mips/arc/printf.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/arc/printf.c Mon Jul 19 23:53:54 1999 @@ -0,0 +1,40 @@ +/* + * printf.c: Putting things on the screen using SGI arcs + * PROM facilities. + * + * Copyright (C) 1996 David S. Miller (dm@sgi.com) + * + * $Id: printf.c,v 1.2 1999/06/12 18:42:38 ulfc Exp $ + */ +#include +#include +#include + +#include + +static char ppbuf[1024]; + +#ifdef CONFIG_SGI_PROM_CONSOLE +void prom_printf(char *fmt, ...) +#else +__initfunc(void prom_printf(char *fmt, ...)) +#endif +{ + va_list args; + char ch, *bptr; + int i; + + va_start(args, fmt); + i = vsprintf(ppbuf, fmt, args); + + bptr = ppbuf; + + while((ch = *(bptr++)) != 0) { + if(ch == '\n') + prom_putchar('\r'); + + prom_putchar(ch); + } + va_end(args); + return; +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/salone.c linux.pre11.3/arch/mips/arc/salone.c --- linux.vanilla/arch/mips/arc/salone.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/arc/salone.c Mon Jul 19 23:28:47 1999 @@ -0,0 +1,25 @@ +/* + * salone.c: Routines to load into memory and execute stand-along + * program images using ARCS PROM firmware. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: salone.c,v 1.1 1998/10/18 13:32:09 tsbogend Exp $ + */ +#include +#include + +__initfunc(long prom_load(char *name, unsigned long end, unsigned long *pc, unsigned long *eaddr)) +{ + return romvec->load(name, end, pc, eaddr); +} + +__initfunc(long prom_invoke(unsigned long pc, unsigned long sp, long argc, char **argv, char **envp)) +{ + return romvec->invoke(pc, sp, argc, argv, envp); +} + +__initfunc(long prom_exec(char *name, long argc, char **argv, char **envp)) +{ + return romvec->exec(name, argc, argv, envp); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/time.c linux.pre11.3/arch/mips/arc/time.c --- linux.vanilla/arch/mips/arc/time.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/arc/time.c Mon Jul 19 23:28:47 1999 @@ -0,0 +1,19 @@ +/* + * time.c: Extracting time information from ARCS prom. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: time.c,v 1.1 1998/10/18 13:32:10 tsbogend Exp $ + */ +#include +#include + +__initfunc(struct linux_tinfo *prom_gettinfo(void)) +{ + return romvec->get_tinfo(); +} + +__initfunc(unsigned long prom_getrtime(void)) +{ + return romvec->get_rtime(); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/tree.c linux.pre11.3/arch/mips/arc/tree.c --- linux.vanilla/arch/mips/arc/tree.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/arc/tree.c Mon Jul 19 23:28:47 1999 @@ -0,0 +1,109 @@ +/* + * tree.c: PROM component device tree code. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * $Id: tree.c,v 1.1 1998/10/18 13:32:10 tsbogend Exp $ + */ +#include +#include + +#define DEBUG_PROM_TREE + +__initfunc(pcomponent *prom_getsibling(pcomponent *this)) +{ + if(this == PROM_NULL_COMPONENT) + return PROM_NULL_COMPONENT; + return romvec->next_component(this); +} + +__initfunc(pcomponent *prom_getchild(pcomponent *this)) +{ + return romvec->child_component(this); +} + +__initfunc(pcomponent *prom_getparent(pcomponent *child)) +{ + if(child == PROM_NULL_COMPONENT) + return PROM_NULL_COMPONENT; + return romvec->parent_component(child); +} + +__initfunc(long prom_getcdata(void *buffer, pcomponent *this)) +{ + return romvec->component_data(buffer, this); +} + +__initfunc(pcomponent *prom_childadd(pcomponent *this, pcomponent *tmp, void *data)) +{ + return romvec->child_add(this, tmp, data); +} + +__initfunc(long prom_delcomponent(pcomponent *this)) +{ + return romvec->comp_del(this); +} + +__initfunc(pcomponent *prom_componentbypath(char *path)) +{ + return romvec->component_by_path(path); +} + +#ifdef DEBUG_PROM_TREE +static char *classes[] = { + "system", "processor", "cache", "adapter", "controller", "peripheral", + "memory" +}; + +static char *types[] = { + "arc", "cpu", "fpu", "picache", "pdcache", "sicache", "sdcache", "sccache", + "memdev", "eisa adapter", "tc adapter", "scsi adapter", "dti adapter", + "multi-func adapter", "disk controller", "tp controller", + "cdrom controller", "worm controller", "serial controller", + "net controller", "display controller", "parallel controller", + "pointer controller", "keyboard controller", "audio controller", + "misc controller", "disk peripheral", "floppy peripheral", + "tp peripheral", "modem peripheral", "monitor peripheral", + "printer peripheral", "pointer peripheral", "keyboard peripheral", + "terminal peripheral", "line peripheral", "net peripheral", + "misc peripheral", "anonymous" +}; + +static char *iflags[] = { + "bogus", "read only", "removable", "console in", "console out", + "input", "output" +}; + +__initfunc(static void dump_component(pcomponent *p)) +{ + prom_printf("[%p]:class<%s>type<%s>flags<%s>ver<%d>rev<%d>", + p, classes[p->class], types[p->type], + iflags[p->iflags], p->vers, p->rev); + prom_printf("key<%08lx>\n\tamask<%08lx>cdsize<%d>ilen<%d>iname<%s>\n", + p->key, p->amask, (int)p->cdsize, (int)p->ilen, p->iname); +} + +__initfunc(static void traverse(pcomponent *p, int op)) +{ + dump_component(p); + if(prom_getchild(p)) + traverse(prom_getchild(p), 1); + if(prom_getsibling(p) && op) + traverse(prom_getsibling(p), 1); +} + +__initfunc(void prom_testtree(void)) +{ + pcomponent *p; + + p = prom_getchild(PROM_NULL_COMPONENT); + dump_component(p); + p = prom_getchild(p); + while(p) { + dump_component(p); + p = prom_getsibling(p); + } + prom_printf("press a key\n"); + prom_getchar(); +} +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/Makefile linux.pre11.3/arch/mips/baget/Makefile --- linux.vanilla/arch/mips/baget/Makefile Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/baget/Makefile Mon Jul 19 23:28:47 1999 @@ -0,0 +1,75 @@ +# $Id$ +# +# Makefile for the Baget specific kernel interface routines +# under Linux. +# +# 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... + +all: baget.a + +image: ../../../vmlinux + cp -f $< $@ + +O_TARGET := baget.a +O_OBJS := baget.o print.o setup.o time.o irq.o bagetIRQ.o reset.o wbflush.o + +ifeq ($(CONFIG_SERIAL),y) + OX_OBJS += vacserial.o +else + ifeq ($(CONFIG_SERIAL),m) + MX_OBJS += vacserial.o + endif +endif +ifeq ($(CONFIG_VAC_RTC),y) + OX_OBJS += vacrtc.o +else + ifeq ($(CONFIG_VAC_RTC),m) + MX_OBJS += vacrtc.o + endif +endif + +bagetIRQ.o : bagetIRQ.S + $(CC) $(CFLAGS) -c -o $@ $< + + +##################### Baget Loader stuff ######################## + +dummy.c: + touch $@ + +image.bin: image + $(OBJCOPY) -O binary $< $@ + +ramdisk.bin: + echo "Dummy ramdisk used. Provide your own if needed !" > $@ + +dummy.o: dummy.c image.bin ramdisk.bin + $(CC) $(CFLAGS) -c -o $@ $< + $(OBJCOPY) --add-section=.vmlinux=image.bin \ + --add-section=.ramdisk=ramdisk.bin $@ + +balo.h: image + $(NM) $< | awk ' \ + BEGIN { printf "/* DO NOT EDIT THIS FILE */\n" } \ + /kernel_entry/ { printf "#define START 0x%s\n", $$1 } \ + /balo_ramdisk_base/ { printf "#define RAMDISK_BASE 0x%s\n", $$1 } \ + /balo_ramdisk_size/ { printf "#define RAMDISK_SIZE 0x%s\n", $$1 } \ + ' > $@ +balo.o: balo.c balo.h + $(CC) $(CFLAGS) -c $< + +balo_supp.o: balo_supp.S + $(CC) $(CFLAGS) -c $< + +balo: balo.o dummy.o balo_supp.o print.o + $(LD) $(LDFLAGS) -T ld.script.balo -o $@ $^ + +clean: + rm -f balo.o balo.h dummy.o dummy.c hello.o image.bin image balo_supp.o + rm -f $(O_OBJS) $(O_TARGET) + +include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/baget.c linux.pre11.3/arch/mips/baget/baget.c --- linux.vanilla/arch/mips/baget/baget.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/baget/baget.c Mon Jul 19 23:28:47 1999 @@ -0,0 +1,104 @@ +/* $Id$ + * + * baget.c: Baget low level stuff + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + * + */ +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* + * Following values are set by BALO into RAM disk buffer parameters + */ +unsigned long balo_ramdisk_base = 0xBA; /* Signature for BALO ! */ +unsigned long balo_ramdisk_size = 0; + + +/* + * Following code is based on routines from 'mm/vmalloc.c' + * Additional parameters ioaddr is needed to iterate across real I/O address. + */ +static inline int alloc_area_pte(pte_t * pte, unsigned long address, + unsigned long size, unsigned long ioaddr) +{ + unsigned long end; + + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + while (address < end) { + unsigned long page; + if (!pte_none(*pte)) + printk("kseg2_alloc_io: page already exists\n"); + /* + * For MIPS looks pretty to have transparent mapping + * for KSEG2 areas -- user can't access one, and no + * problems with virtual <--> physical translation. + */ + page = ioaddr & PAGE_MASK; + + set_pte(pte, __pte(page | pgprot_val(PAGE_USERIO) | + _PAGE_GLOBAL | __READABLE | __WRITEABLE)); + address += PAGE_SIZE; + ioaddr += PAGE_SIZE; + pte++; + } + return 0; +} + +static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, + unsigned long size, unsigned long ioaddr) +{ + unsigned long end; + + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + while (address < end) { + pte_t * pte = pte_alloc_kernel(pmd, address); + if (!pte) + return -ENOMEM; + if (alloc_area_pte(pte, address, end - address, ioaddr)) + return -ENOMEM; + address = (address + PMD_SIZE) & PMD_MASK; + ioaddr += PMD_SIZE; + pmd++; + } + return 0; +} + +int kseg2_alloc_io (unsigned long address, unsigned long size) +{ + pgd_t * dir; + unsigned long end = address + size; + + dir = pgd_offset_k(address); + flush_cache_all(); + while (address < end) { + pmd_t *pmd; + pgd_t olddir = *dir; + + pmd = pmd_alloc_kernel(dir, address); + if (!pmd) + return -ENOMEM; + if (alloc_area_pmd(pmd, address, end - address, address)) + return -ENOMEM; + if (pgd_val(olddir) != pgd_val(*dir)) + set_pgdir(address, *dir); + address = (address + PGDIR_SIZE) & PGDIR_MASK; + dir++; + } + flush_tlb_all(); + return 0; +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/bagetIRQ.S linux.pre11.3/arch/mips/baget/bagetIRQ.S --- linux.vanilla/arch/mips/baget/bagetIRQ.S Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/baget/bagetIRQ.S Mon Jul 19 23:28:47 1999 @@ -0,0 +1,98 @@ +/* $Id$ + * bagetIRQ.S: Interrupt exception dispatch code for Baget/MIPS + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + */ + +#include +#include +#include +#include +#include +#include + + .text + .set mips1 + .set reorder + .set macro + .set noat + .align 5 + +NESTED(bagetIRQ, PT_SIZE, sp) + SAVE_ALL + CLI # Important: mark KERNEL mode ! + + la a1, baget_interrupt + .set push + .set noreorder + jal a1 + .set pop + move a0, sp + + la a1, ret_from_irq + jr a1 +END(bagetIRQ) + +#define DBE_HANDLER 0x1C + +NESTED(try_read, PT_SIZE, sp) + mfc0 t3, CP0_STATUS # save flags and + CLI # disable interrupts + + li t0, KSEG2 + sltu t1, t0, a0 # Is it KSEG2 address ? + beqz t1, mapped # No - already mapped ! + + move t0, a0 + ori t0, 0xfff + xori t0, 0xfff # round address to page + + ori t1, t0, 0xf00 # prepare EntryLo (N,V,D,G) + + mfc0 t2, CP0_ENTRYHI # save ASID value + mtc0 zero, CP0_INDEX + mtc0 t0, CP0_ENTRYHI # Load MMU values ... + mtc0 t1, CP0_ENTRYLO0 + nop # let it understand + nop + tlbwi # ... and write ones + nop + nop + mtc0 t2, CP0_ENTRYHI + +mapped: + la t0, exception_handlers + lw t1, DBE_HANDLER(t0) # save real handler + la t2, dbe_handler + sw t2, DBE_HANDLER(t0) # set temporary local handler + li v0, -1 # default (failure) value + + li t2, 1 + beq t2, a1, 1f + li t2, 2 + beq t2, a1, 2f + li t2, 4 + beq t2, a1, 4f + b out + +1: lbu v0, (a0) # byte + b out + +2: lhu v0, (a0) # short + b out + +4: lw v0, (a0) # word + +out: + sw t1, DBE_HANDLER(t0) # restore real handler + mtc0 t3, CP0_STATUS # restore CPU flags + jr ra + +dbe_handler: + li v0, -1 # mark our failure + .set push + .set noreorder + b out # "no problems !" + rfe # return from trap + .set pop +END(try_read) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/balo.c linux.pre11.3/arch/mips/baget/balo.c --- linux.vanilla/arch/mips/baget/balo.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/baget/balo.c Mon Jul 19 23:28:47 1999 @@ -0,0 +1,190 @@ +/* $Id$ + * + * balo.c: BAget LOader + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + * + */ +#include +#include +#include +#include + +#include + +#include "balo.h" /* Includes some kernel symbol values */ + +static char *banner = "\nBaget Linux Loader v0.2\n"; + +static void mem_move (long *to, long *from, long size) +{ + while (size > 0) { + *to++ = *from++; + size -= sizeof(long); + } +} + +static volatile int *mem_limit = (volatile int*)KSEG1; +static volatile int *mem_limit_dbe = (volatile int*)KSEG1; + +static int can_write (volatile int* p) { + return p < (int*)(KSEG1+BALO_OFFSET) || + p >= (int*)(KSEG1+BALO_OFFSET+BALO_SIZE); +} + +static volatile enum balo_state_enum { + BALO_INIT, + MEM_INIT, + MEM_PROBE, + START_KERNEL +} balo_state = BALO_INIT; + + +static __inline__ void reset_and_jump(int start, int mem_upper) +{ + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "mfc0\t$1,$12\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "ori\t$1,$1,0xff00\n\t" + "xori\t$1,$1,0xff00\n\t" + "mtc0\t$1,$12\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "move\t$4,%1\n\t" + "jr\t%0\n\t" + "nop\n\t" + ".set\tat\n\t" + ".set\treorder" + : /* no outputs */ + :"Ir" (start), "Ir" (mem_upper) + :"$1", "$4", "memory"); +} + +static void start_kernel(void) +{ + extern char _vmlinux_start, _vmlinux_end; + extern char _ramdisk_start, _ramdisk_end; + + outs( "Relocating Linux... " ); + mem_move((long*)KSEG0, (long*)&_vmlinux_start, + &_vmlinux_end-&_vmlinux_start); + outs("done.\n"); + + if (&_ramdisk_start != &_ramdisk_end) { + outs("Setting up RAMDISK... "); + if (*(unsigned long*)RAMDISK_BASE != 0xBA) { + outs("Bad RAMDISK_BASE signature in system image.\n"); + balo_hungup(); + } + *(unsigned long*)RAMDISK_BASE = (unsigned long)&_ramdisk_start; + *(unsigned long*)RAMDISK_SIZE = &_ramdisk_end -&_ramdisk_start; + outs("done.\n"); + } + + { + extern void flush_cache_low(int isize, int dsize); + flush_cache_low(256*1024,256*1024); + } + + balo_printf( "Kernel entry: %x\n\n", START); + balo_state = START_KERNEL; + reset_and_jump(START, (int)mem_limit-KSEG1+KSEG0); +} + + +static void mem_probe(void) +{ + balo_state = MEM_PROBE; + outs("RAM: <"); + while(mem_limit < mem_limit_dbe) { + if (can_write(mem_limit) && *mem_limit != 0) + break; /* cycle found */ + outc('.'); + if (can_write(mem_limit)) + *mem_limit = -1; /* mark */ + mem_limit += 0x40000; + } + outs(">\n"); + start_kernel(); +} + +volatile unsigned int int_cause; +volatile unsigned int epc; +volatile unsigned int badvaddr; + +static void print_regs(void) +{ + balo_printf("CAUSE=%x EPC=%x BADVADDR=%x\n", + int_cause, epc, badvaddr); +} + +void int_handler(struct pt_regs *regs) +{ + switch (balo_state) { + case BALO_INIT: + balo_printf("\nBALO: trap in balo itself.\n"); + print_regs(); + balo_hungup(); + break; + case MEM_INIT: + if ((int_cause & CAUSE_MASK) != CAUSE_DBE) { + balo_printf("\nBALO: unexpected trap during memory init.\n"); + print_regs(); + balo_hungup(); + } else { + mem_probe(); + } + break; + case MEM_PROBE: + balo_printf("\nBALO: unexpected trap during memory probe.\n"); + print_regs(); + balo_hungup(); + break; + case START_KERNEL: + balo_printf("\nBALO: unexpected kernel trap.\n"); + print_regs(); + balo_hungup(); + break; + } + balo_printf("\nBALO: unexpected return from handler.\n"); + print_regs(); + balo_hungup(); +} + +static void mem_init(void) +{ + balo_state = MEM_INIT; + + while(1) { + *mem_limit_dbe; + if (can_write(mem_limit_dbe)) + *mem_limit_dbe = 0; + + mem_limit_dbe += 0x40000; /* +1M */ + } + /* no return: must go to int_handler */ +} + +void balo_entry(void) +{ + extern void except_vec3_generic(void); + + cli(); + outs(banner); + memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80); + mem_init(); +} + +/* Needed for linking */ + +int vsprintf(char *buf, const char *fmt, va_list arg) +{ + outs("BALO: vsprintf called.\n"); + balo_hungup(); + return 0; +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/balo_supp.S linux.pre11.3/arch/mips/baget/balo_supp.S --- linux.vanilla/arch/mips/baget/balo_supp.S Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/baget/balo_supp.S Mon Jul 19 23:53:54 1999 @@ -0,0 +1,143 @@ +/* $Id$ + * balo_supp.S: BAget Loader supplement + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + */ + +#include +#include +#include +#include +#include + + .text + .set mips1 + + /* General exception vector. */ +NESTED(except_vec3_generic, 0, sp) + .set noat + la k0, except_vec3_generic_code + jr k0 +END(except_vec3_generic) + +NESTED(except_vec3_generic_code, 0, sp) + SAVE_ALL + mfc0 k1, CP0_CAUSE + la k0, int_cause + sw k1, (k0) + + mfc0 k1, CP0_EPC + la k0, epc + sw k1, (k0) + + mfc0 k1, CP0_BADVADDR + la k0, badvaddr + sw k1, (k0) + + la k0, int_handler + .set noreorder + jal k0 + .set reorder + move a0, sp + + RESTORE_ALL_AND_RET +END(except_vec3_generic_code) + + .align 5 +NESTED(flush_cache_low, PT_SIZE, sp) + .set at + .set macro + .set noreorder + + move t1, a0 # ISIZE + move t2, a1 # DSIZE + + mfc0 t3, CP0_STATUS # Save the status register. + mtc0 zero, CP0_STATUS # Disable interrupts. + la v0, 1f + or v0, KSEG1 # Run uncached. + j v0 + nop +/* + * Flush the instruction cache. + */ +1: + li v0, ST0_DE | ST0_CE + mtc0 v0, CP0_STATUS # Isolate and swap caches. + li t0, KSEG1 + subu t0, t0, t1 + li t1, KSEG1 + la v0, 1f # Run cached + j v0 + nop +1: + addu t0, t0, 64 + sb zero, -64(t0) + sb zero, -60(t0) + sb zero, -56(t0) + sb zero, -52(t0) + sb zero, -48(t0) + sb zero, -44(t0) + sb zero, -40(t0) + sb zero, -36(t0) + sb zero, -32(t0) + sb zero, -28(t0) + sb zero, -24(t0) + sb zero, -20(t0) + sb zero, -16(t0) + sb zero, -12(t0) + sb zero, -8(t0) + bne t0, t1, 1b + sb zero, -4(t0) + + la v0, 1f + or v0, KSEG1 + j v0 # Run uncached + nop +/* + * Flush the data cache. + */ +1: + li v0, ST0_DE + mtc0 v0, CP0_STATUS # Isolate and swap back caches + li t0, KSEG1 + subu t0, t0, t2 + la v0, 1f + j v0 # Back to cached mode + nop +1: + addu t0, t0, 64 + sb zero, -64(t0) + sb zero, -60(t0) + sb zero, -56(t0) + sb zero, -52(t0) + sb zero, -48(t0) + sb zero, -44(t0) + sb zero, -40(t0) + sb zero, -36(t0) + sb zero, -32(t0) + sb zero, -28(t0) + sb zero, -24(t0) + sb zero, -20(t0) + sb zero, -16(t0) + sb zero, -12(t0) + sb zero, -8(t0) + bne t0, t1, 1b + sb zero, -4(t0) + + nop # Insure isolated stores + nop # out of pipe. + nop + nop + mtc0 t3, CP0_STATUS # Restore status reg. + nop # Insure cache unisolated. + nop + nop + nop + j ra + nop +END(flush_cache_low) + +/* To satisfy macros only */ +EXPORT(kernelsp) + PTR 0x80001000 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/irq.c linux.pre11.3/arch/mips/baget/irq.c --- linux.vanilla/arch/mips/baget/irq.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/baget/irq.c Mon Jul 19 23:28:47 1999 @@ -0,0 +1,438 @@ +/* + * Code to handle Baget/MIPS IRQs plus some generic interrupt stuff. + * + * Copyright (C) 1998 Vladimir Roganov & Gleb Raiko + * Code (mostly sleleton and comments) derived from DECstation IRQ + * handling. + * + * $Id$ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +unsigned int local_bh_count[NR_CPUS]; +unsigned int local_irq_count[NR_CPUS]; +unsigned long spurious_count = 0; + +atomic_t __mips_bh_counter; + +/* + * This table is a correspondence between IRQ numbers and CPU PILs + */ + +static int irq_to_pil_map[BAGET_IRQ_NR] = { + 7/*fixme: dma_err -1*/,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 0x00 - 0x0f */ + -1,-1,-1,-1, 3,-1,-1,-1, 2, 2, 2,-1, 3,-1,-1,3/*fixme: lance*/, /* 0x10 - 0x1f */ + -1,-1,-1,-1,-1,-1, 5,-1,-1,-1,-1,-1, 7,-1,-1,-1, /* 0x20 - 0x2f */ + -1, 3, 2/*fixme systimer:3*/, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 /* 0x30 - 0x3f */ +}; + +static inline int irq_to_pil(int irq_nr) +{ + int pil = -1; + + if (irq_nr >= BAGET_IRQ_NR) + baget_printk("irq_to_pil: too large irq_nr = 0x%x\n", irq_nr); + else { + pil = irq_to_pil_map[irq_nr]; + if (pil == -1) + baget_printk("irq_to_pil: unknown irq = 0x%x\n", irq_nr); + } + + return pil; +} + +/* Function for careful CP0 interrupt mask access */ + +static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask) +{ + unsigned long status = read_32bit_cp0_register(CP0_STATUS); + status &= ~((clr_mask & 0xFF) << 8); + status |= (set_mask & 0xFF) << 8; + write_32bit_cp0_register(CP0_STATUS, status); +} + +/* + * These two functions may be used for unconditional IRQ + * masking via their PIL protection. + */ + +static inline void mask_irq(unsigned int irq_nr) +{ + modify_cp0_intmask(irq_to_pil(irq_nr), 0); +} + +static inline void unmask_irq(unsigned int irq_nr) +{ + modify_cp0_intmask(0, irq_to_pil(irq_nr)); +} + +/* + * The following section is introduced for masking/unasking IRQ + * only while no more IRQs uses same CPU PIL. + * + * These functions are used in request_irq, free_irq, but it looks + * they cannot change something: CP0_STATUS is private for any + * process, and their action is invisible for system. + */ + +static volatile unsigned int pil_in_use[BAGET_PIL_NR] = { 0, }; + +void mask_irq_count(int irq_nr) +{ + unsigned long flags; + int pil = irq_to_pil(irq_nr); + + save_and_cli(flags); + if (!--pil_in_use[pil]) + mask_irq(irq_nr); + restore_flags(flags); +} + +void unmask_irq_count(int irq_nr) +{ + unsigned long flags; + int pil = irq_to_pil(irq_nr); + + save_and_cli(flags); + if (!pil_in_use[pil]++) + unmask_irq(irq_nr); + restore_flags(flags); +} + +/* + * Two functions below are exported versions of mask/unmask IRQ + */ + +void disable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + save_and_cli(flags); + mask_irq(irq_nr); + restore_flags(flags); +} + +void enable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + save_and_cli(flags); + unmask_irq(irq_nr); + restore_flags(flags); +} + +/* + * Data definition for static irqaction allocation. + * It is used while SLAB module is not initialized. + */ + +#define MAX_STATIC_ALLOC 4 +struct irqaction static_irqaction[MAX_STATIC_ALLOC]; +int static_irq_count = 0; + +/* + * Pointers to the low-level handlers: first the general ones, then the + * fast ones, then the bad ones. + */ +static struct irqaction *irq_action[BAGET_IRQ_NR] = { NULL, }; + +int get_irq_list(char *buf) +{ + int i, len = 0; + struct irqaction * action; + + for (i = 0 ; i < BAGET_IRQ_NR ; i++) { + action = irq_action[i]; + if (!action) + continue; + len += sprintf(buf+len, "%2d: %8d %c %s", + i, kstat.irqs[0][i], + (action->flags & SA_INTERRUPT) ? '+' : ' ', + action->name); + for (action=action->next; action; action = action->next) { + len += sprintf(buf+len, ",%s %s", + (action->flags & SA_INTERRUPT) ? " +" : "", + action->name); + } + len += sprintf(buf+len, "\n"); + } + return len; +} + + +/* + * do_IRQ handles IRQ's that have been installed without the + * SA_INTERRUPT flag: it uses the full signal-handling return + * and runs with other interrupts enabled. All relatively slow + * IRQ's should use this format: notably the keyboard/timer + * routines. + */ +static void do_IRQ(int irq, struct pt_regs * regs) +{ + struct irqaction *action; + int do_random, cpu; + + cpu = smp_processor_id(); + hardirq_enter(cpu); + kstat.irqs[cpu][irq]++; + + mask_irq(irq); + action = *(irq + irq_action); + if (action) { + if (!(action->flags & SA_INTERRUPT)) + __sti(); + action = *(irq + irq_action); + do_random = 0; + do { + do_random |= action->flags; + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + if (do_random & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + __cli(); + } else { + printk("do_IRQ: Unregistered IRQ (0x%X) occured\n", irq); + } + unmask_irq(irq); + hardirq_exit(cpu); + + /* unmasking and bottom half handling is done magically for us. */ +} + +/* + * What to do in case of 'no VIC register available' for current interrupt + */ +static void vic_reg_error(unsigned long address, unsigned char active_pils) +{ + printk("\nNo VIC register found: reg=%08lx active_pils=%02x\n" + "Current interrupt mask from CP0_CAUSE: %02x\n", + address, 0xff & active_pils, + 0xff & (read_32bit_cp0_register(CP0_CAUSE)>>8)); + { int i; for (i=0; i<10000; i++) udelay(1000); } +} + +static char baget_fpu_irq = BAGET_FPU_IRQ; +#define BAGET_INT_FPU {(unsigned long)&baget_fpu_irq, 1} + +/* + * Main interrupt handler: interrupt demultiplexer + */ +asmlinkage void baget_interrupt(struct pt_regs *regs) +{ + static struct baget_int_reg int_reg[BAGET_PIL_NR] = { + BAGET_INT_NONE, BAGET_INT_NONE, BAGET_INT0_ACK, BAGET_INT1_ACK, + BAGET_INT_NONE, BAGET_INT_FPU, BAGET_INT_NONE, BAGET_INT5_ACK + }; + unsigned char active_pils; + while ((active_pils = read_32bit_cp0_register(CP0_CAUSE)>>8)) { + int pil; + struct baget_int_reg* reg; + + for (pil = 0; pil < BAGET_PIL_NR; pil++) { + if (!(active_pils & (1<address) { + extern int try_read(unsigned long,int); + int irq = try_read(reg->address, reg->size); + + if (irq != -1) + do_IRQ(BAGET_IRQ_MASK(irq), regs); + else + vic_reg_error(reg->address, active_pils); + } else { + printk("baget_interrupt: unknown interrupt " + "(pil = %d)\n", pil); + } + } + } +} + +/* + * Idea is to put all interrupts + * in a single table and differenciate them just by number. + */ +int setup_baget_irq(int irq, struct irqaction * new) +{ + int shared = 0; + struct irqaction *old, **p; + unsigned long flags; + + p = irq_action + irq; + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) + return -EBUSY; + + /* Can't share interrupts unless both are same type */ + if ((old->flags ^ new->flags) & SA_INTERRUPT) + return -EBUSY; + + /* add new interrupt at end of irq queue */ + do { + p = &old->next; + old = *p; + } while (old); + shared = 1; + } + + if (new->flags & SA_SAMPLE_RANDOM) + rand_initialize_irq(irq); + + save_and_cli(flags); + *p = new; + restore_flags(flags); + + if (!shared) { + unmask_irq_count(irq); + } + + return 0; +} + +int request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, + const char * devname, + void *dev_id) +{ + int retval; + struct irqaction * action = NULL; + + if (irq >= BAGET_IRQ_NR) + return -EINVAL; + if (!handler) + return -EINVAL; + if (irq_to_pil_map[irq] < 0) + return -EINVAL; + + if (irqflags & SA_STATIC_ALLOC) { + unsigned long flags; + + save_and_cli(flags); + if (static_irq_count < MAX_STATIC_ALLOC) + action = &static_irqaction[static_irq_count++]; + else + printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed " + "using kmalloc\n", irq, devname); + restore_flags(flags); + } + + if (action == NULL) + action = (struct irqaction *) + kmalloc(sizeof(struct irqaction), GFP_KERNEL); + + if (!action) + return -ENOMEM; + + action->handler = handler; + action->flags = irqflags; + action->mask = 0; + action->name = devname; + action->next = NULL; + action->dev_id = dev_id; + + retval = setup_baget_irq(irq, action); + + if (retval) + kfree(action); + + return retval; +} + +void free_irq(unsigned int irq, void *dev_id) +{ + struct irqaction * action, **p; + unsigned long flags; + + if (irq >= BAGET_IRQ_NR) + printk("Trying to free IRQ%d\n",irq); + + for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { + if (action->dev_id != dev_id) + continue; + + /* Found it - now free it */ + save_and_cli(flags); + *p = action->next; + if (!irq[irq_action]) + unmask_irq_count(irq); + restore_flags(flags); + + if (action->flags & SA_STATIC_ALLOC) + { + /* This interrupt is marked as specially allocated + * so it is a bad idea to free it. + */ + printk("Attempt to free statically allocated " + "IRQ%d (%s)\n", irq, action->name); + return; + } + + kfree(action); + return; + } + printk("Trying to free free IRQ%d\n",irq); +} + +static int baget_irq_canonicalize(int irq) +{ + return irq; +} + +int (*irq_cannonicalize)(int irq) = baget_irq_canonicalize; + +unsigned long probe_irq_on (void) +{ + /* TODO */ + return 0; +} + +int probe_irq_off (unsigned long irqs) +{ + /* TODO */ + return 0; +} + + +static void write_err_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + *(volatile char*) BAGET_WRERR_ACK = 0; +} + +__initfunc(void init_IRQ(void)) +{ + irq_setup(); + + /* Enable access to VIC interrupt registers */ + vac_outw(0xacef | 0x8200, VAC_PIO_FUNC); + + /* Enable interrupts for pils 2 and 3 (lines 0 and 1) */ + modify_cp0_intmask(0, (1<<2)|(1<<3)); + + if (request_irq(0/*fixme*/, write_err_interrupt, + SA_INTERRUPT|SA_STATIC_ALLOC, "write_err", NULL) < 0) + printk("init_IRQ: unable to register write_err irq\n"); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/ld.script.balo linux.pre11.3/arch/mips/baget/ld.script.balo --- linux.vanilla/arch/mips/baget/ld.script.balo Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/baget/ld.script.balo Mon Jul 19 23:28:47 1999 @@ -0,0 +1,124 @@ +OUTPUT_FORMAT("elf32-bigmips") +OUTPUT_ARCH(mips) +ENTRY(balo_entry) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0x80400000; + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } =0 + .text : + { + _ftext = . ; + *(.text) + *(.rodata) + *(.rodata1) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + + _etext = .; + PROVIDE (etext = .); + + /* Startup code */ + . = ALIGN(4096); + __init_begin = .; + *(.text.init) + *(.data.init) + . = ALIGN(4096); /* Align double page for init_task_union */ + __init_end = .; + + *(.fini) + *(.reginfo) + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. It would + be more correct to do this: + . = .; + The current expression does not correctly handle the case of a + text segment ending precisely at the end of a page; it causes the + data segment to skip a page. The above expression does not have + this problem, but it will currently (2/95) cause BFD to allocate + a single segment, combining both text and data, for this case. + This will prevent the text segment from being shared among + multiple executions of the program; I think that is more + important than losing a page of the virtual address space (note + that no actual memory is lost; the page which is skipped can not + be referenced). */ + . = .; + _fdata = . ; + *(.data) + CONSTRUCTORS + + *(.data1) + _gp = . + 0x8000; + *(.lit8) + *(.lit4) + *(.ctors) + *(.dtors) + *(.got.plt) *(.got) + *(.dynamic) + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + *(.sdata) + _edata = .; + PROVIDE (edata = .); + + __bss_start = .; + _fbss = .; + + *(.dynbss) + *(.bss) + *(COMMON) + _end = . ; + PROVIDE (end = .); + *(.sbss) + *(.scommon) + + /* These are needed for ELF backends which have not yet been + converted to the new style linker. */ + *(.stab) + *(.stabstr) + /* DWARF debug sections. + Symbols in the .debug DWARF section are relative to the beginning of the + section so we begin .debug at 0. It's not clear yet what needs to happen + for the others. */ + *(.debug) + *(.debug_srcinfo) + *(.debug_aranges) + *(.debug_pubnames) + *(.debug_sfnames) + *(.line) + /* These must appear regardless of . */ + *(.gptab.data) *(.gptab.sdata) + *(.gptab.bss) *(.gptab.sbss) + + _vmlinux_start = .; + *(.vmlinux) + _vmlinux_end = .; + + _ramdisk_start = .; + *(.ramdisk) + _ramdisk_end = .; + +} =0 + +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/print.c linux.pre11.3/arch/mips/baget/print.c --- linux.vanilla/arch/mips/baget/print.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/baget/print.c Mon Jul 19 23:28:47 1999 @@ -0,0 +1,118 @@ +/* $Id$ + * + * print.c: Simple print fascility + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + * + */ +#include +#include +#include + +#include + +/* + * Define this to see 'baget_printk' (debug) messages + */ +// #define BAGET_PRINTK + +/* + * This function is same for BALO and Linux baget_printk, + * and normally prints characted to second (UART A) console. + */ + +static void delay(void) {} + +static void outc_low(char c) +{ + int i; + vac_outb(c, VAC_UART_B_TX); + for (i=0; i<10000; i++) + delay(); +} + +void outc(char c) +{ + if (c == '\n') + outc_low('\r'); + outc_low(c); +} + +void outs(char *s) +{ + while(*s) outc(*s++); +} + +void baget_write(char *s, int l) +{ + while(l--) + outc(*s++); +} + +int baget_printk(const char *fmt, ...) +{ +#ifdef BAGET_PRINTK + va_list args; + int i; + static char buf[1024]; + + va_start(args, fmt); + i = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf)-4 */ + va_end(args); + baget_write(buf, i); + return i; +#else + return 0; +#endif +} + +static __inline__ void puthex( int a ) +{ + static char s[9]; + static char e[] = "0123456789ABCDEF"; + int i; + for( i = 7; i >= 0; i--, a >>= 4 ) s[i] = e[a & 0x0F]; + s[8] = '\0'; + outs( s ); +} + +__initfunc(void balo_printf( char *f, ... )) +{ + int *arg = (int*)&f + 1; + char c; + int format = 0; + + while((c = *f++) != 0) { + switch(c) { + default: + if(format) { + outc('%'); + format = 0; + } + outc( c ); + break; + case '%': + if( format ){ + format = 0; + outc(c); + } else format = 1; + break; + case 'x': + if(format) puthex( *arg++ ); + else outc(c); + format = 0; + break; + case 's': + if( format ) outs((char *)*arg++); + else outc(c); + format = 0; + break; + } + } +} + +__initfunc(void balo_hungup(void)) +{ + outs("Hunging up.\n"); + while(1); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/prom/Makefile linux.pre11.3/arch/mips/baget/prom/Makefile --- linux.vanilla/arch/mips/baget/prom/Makefile Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/baget/prom/Makefile Mon Jul 19 23:28:47 1999 @@ -0,0 +1,15 @@ +# $Id$ +# Makefile for the Baget/MIPS prom emulator library routines. +# +# 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 := bagetlib.a +O_OBJS := init.o + +all: $(O_TARGET) + +include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/prom/init.c linux.pre11.3/arch/mips/baget/prom/init.c --- linux.vanilla/arch/mips/baget/prom/init.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/baget/prom/init.c Mon Jul 19 23:53:54 1999 @@ -0,0 +1,20 @@ +/* + * init.c: PROM library initialisation code. + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + * + * $Id$ + */ +#include +#include + +char arcs_cmdline[CL_SIZE]; + +__initfunc(int prom_init(unsigned int mem_upper)) +{ + mips_memory_upper = mem_upper; + mips_machgroup = MACH_GROUP_UNKNOWN; + mips_machtype = MACH_UNKNOWN; + arcs_cmdline[0] = 0; + return 0; +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/reset.c linux.pre11.3/arch/mips/baget/reset.c --- linux.vanilla/arch/mips/baget/reset.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/baget/reset.c Mon Jul 19 23:28:47 1999 @@ -0,0 +1,32 @@ +#include +#include +#include + + +#define R3000_RESET_VEC 0xbfc00000 +typedef void vector(void); + + +static void baget_reboot(char *from_fun) +{ + cli(); + baget_printk("\n%s: jumping to RESET code...\n", from_fun); + (*(vector*)R3000_RESET_VEC)(); +} + +/* fixme: proper functionality */ + +void baget_machine_restart(char *command) +{ + baget_reboot("restart"); +} + +void baget_machine_halt(void) +{ + baget_reboot("halt"); +} + +void baget_machine_power_off(void) +{ + baget_reboot("power off"); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/setup.c linux.pre11.3/arch/mips/baget/setup.c --- linux.vanilla/arch/mips/baget/setup.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/baget/setup.c Mon Jul 19 23:53:54 1999 @@ -0,0 +1,494 @@ +/* $Id$ + * + * setup.c: Baget/MIPS specific setup, including init of the feature struct. + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + * + */ +#include +#include +#include +#include +#include +#include + +#include + +extern long mips_memory_upper; + +extern void wbflush_setup(void); + +#define CACHEABLE_STR(val) ((val) ? "not cached" : "cached") +#define MIN(a,b) (((a)<(b)) ? (a):(b)) + +__initfunc(static void vac_show(void)) +{ + int i; + unsigned short val, decode = vac_inw(VAC_DECODE_CTRL); + unsigned short a24_base = vac_inw(VAC_A24_BASE); + unsigned long a24_addr = ((unsigned long) + (a24_base & VAC_A24_MASK)) << 16; + char *decode_mode[] = { "eprom", "vsb", "shared", "dram" }; + char *address_mode[] = { "", ", A16", ", A32/A24", ", A32/A24/A16" }; + char *state[] = { "", " on write", " on read", " on read/write", }; + char *region_mode[] = { "inactive", "shared", "vsb", "vme" }; + char *asiz[] = { "user", "A32", "A16", "A24" }; + unsigned short regs[] = { VAC_REG1, VAC_REG2, VAC_REG3 }; + unsigned short bndr[] = { VAC_DRAM_MASK,VAC_BNDR2,VAC_BNDR3 }; + unsigned short io_sels[] = { VAC_IOSEL0_CTRL, + VAC_IOSEL1_CTRL, + VAC_IOSEL2_CTRL, + VAC_IOSEL3_CTRL, + VAC_IOSEL4_CTRL, + VAC_IOSEL5_CTRL }; + + printk("[DSACKi %s, DRAMCS%s qualified, boundary%s qualified%s]\n", + (decode & VAC_DECODE_DSACKI) ? "on" : "off", + (decode & VAC_DECODE_QFY_DRAMCS) ? "" : " not", + (decode & VAC_DECODE_QFY_BNDR) ? "" : " not", + (decode & VAC_DECODE_FPUCS) ? ", fpu" : ""); + + printk("slave0 "); + if (decode & VAC_DECODE_RDR_SLSEL0) + printk("at %08lx (%d MB)\t[dram %s]\n", + ((unsigned long)vac_inw(VAC_SLSEL0_BASE))<<16, + ((0xffff ^ vac_inw(VAC_SLSEL0_MASK)) + 1) >> 4, + (decode & VAC_DECODE_QFY_SLSEL0) ? "qualified" : ""); + else + printk("off\n"); + + printk("slave1 "); + if (decode & VAC_DECODE_RDR_SLSEL1) + printk("at %08lx (%d MB)\t[%s%s, %s]\n", + ((unsigned long)vac_inw(VAC_SLSEL1_BASE))<<16, + ((0xffff ^ vac_inw(VAC_SLSEL1_MASK)) + 1) >> 4, + decode_mode[VAC_DECODE_MODE_VAL(decode)], + address_mode[VAC_DECODE_CMP_SLSEL1_VAL(decode)], + (decode & VAC_DECODE_QFY_SLSEL1) ? "qualified" : ""); + else + printk("off\n"); + + printk("icf global at %04x, module at %04x [%s]\n", + ((unsigned int) + VAC_ICFSEL_GLOBAL_VAL(vac_inw(VAC_ICFSEL_BASE)))<<4, + ((unsigned int) + VAC_ICFSEL_MODULE_VAL(vac_inw(VAC_ICFSEL_BASE)))<<4, + (decode & VAC_DECODE_QFY_ICFSEL) ? "qualified" : ""); + + + printk("region0 at 00000000 (%dMB)\t[dram, %s, delay %d cpuclk" + ", cached]\n", + (vac_inw(VAC_DRAM_MASK)+1)>>4, + (decode & VAC_DECODE_DSACK) ? "D32" : "3state", + VAC_DECODE_CPUCLK_VAL(decode)); + + for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) { + unsigned long from = + ((unsigned long)vac_inw(bndr[i]))<<16; + unsigned long to = + ((unsigned long) + ((i+1 == sizeof(bndr)/sizeof(bndr[0])) ? + 0xff00 : vac_inw(bndr[i+1])))<<16; + + + val = vac_inw(regs[i]); + printk("region%d at %08lx (%dMB)\t[%s %s/%s, %s]\n", + i+1, + from, + (unsigned int)((to - from) >> 20), + region_mode[VAC_REG_MODE(val)], + asiz[VAC_REG_ASIZ_VAL(val)], + ((val & VAC_REG_WORD) ? "D16" : "D32"), + CACHEABLE_STR(val&VAC_A24_A24_CACHINH)); + + if (a24_addr >= from && a24_addr < to) + printk("\ta24 at %08lx (%dMB)\t[vme, A24/%s, %s]\n", + a24_addr, + MIN((unsigned int)(a24_addr - from)>>20, 32), + (a24_base & VAC_A24_DATAPATH) ? "user" : + ((a24_base & VAC_A24_D32_ENABLE) ? + "D32" : "D16"), + CACHEABLE_STR(a24_base & VAC_A24_A24_CACHINH)); + } + + printk("region4 at ff000000 (15MB)\t[eprom]\n"); + val = vac_inw(VAC_EPROMCS_CTRL); + printk("\t[ack %d cpuclk%s, %s%srecovery %d cpuclk, " + "read %d%s, write %d%s, assert %d%s]\n", + VAC_CTRL_DELAY_DSACKI_VAL(val), + state[val & (VAC_CTRL_IORD|VAC_CTRL_IOWR)], + (val & VAC_CTRL_DSACK0) ? "dsack0*, " : "", + (val & VAC_CTRL_DSACK1) ? "dsack1*, " : "", + VAC_CTRL_RECOVERY_IOSELI_VAL(val), + VAC_CTRL_DELAY_IORD_VAL(val)/2, + (VAC_CTRL_DELAY_IORD_VAL(val)&1) ? ".5" : "", + VAC_CTRL_DELAY_IOWR_VAL(val)/2, + (VAC_CTRL_DELAY_IOWR_VAL(val)&1) ? ".5" : "", + VAC_CTRL_DELAY_IOSELI_VAL(val)/2, + (VAC_CTRL_DELAY_IOSELI_VAL(val)&1) ? ".5" : ""); + + printk("region5 at fff00000 (896KB)\t[local io, %s]\n", + CACHEABLE_STR(vac_inw(VAC_A24_BASE) & VAC_A24_IO_CACHINH)); + + for (i = 0; i < sizeof(io_sels)/sizeof(io_sels[0]); i++) { + val = vac_inw(io_sels[i]); + printk("\tio%d[ack %d cpuclk%s, %s%srecovery %d cpuclk, " + "\n\t read %d%s cpuclk, write %d%s cpuclk, " + "assert %d%s%s cpuclk]\n", + i, + VAC_CTRL_DELAY_DSACKI_VAL(val), + state[val & (VAC_CTRL_IORD|VAC_CTRL_IOWR)], + (val & VAC_CTRL_DSACK0) ? "dsack0*, " : "", + (val & VAC_CTRL_DSACK1) ? "dsack1*, " : "", + VAC_CTRL_RECOVERY_IOSELI_VAL(val), + VAC_CTRL_DELAY_IORD_VAL(val)/2, + (VAC_CTRL_DELAY_IORD_VAL(val)&1) ? ".5" : "", + VAC_CTRL_DELAY_IOWR_VAL(val)/2, + (VAC_CTRL_DELAY_IOWR_VAL(val)&1) ? ".5" : "", + VAC_CTRL_DELAY_IOSELI_VAL(val)/2, + (VAC_CTRL_DELAY_IOSELI_VAL(val)&1) ? ".5" : "", + (vac_inw(VAC_DEV_LOC) & VAC_DEV_LOC_IOSEL(i)) ? + ", id" : ""); + } + + printk("region6 at fffe0000 (128KB)\t[vme, A16/%s, " + "not cached]\n", + (a24_base & VAC_A24_A16D32_ENABLE) ? + ((a24_base & VAC_A24_A16D32) ? "D32" : "D16") : "user"); + + val = vac_inw(VAC_SHRCS_CTRL); + printk("shared[ack %d cpuclk%s, %s%srecovery %d cpuclk, " + "read %d%s, write %d%s, assert %d%s]\n", + VAC_CTRL_DELAY_DSACKI_VAL(val), + state[val & (VAC_CTRL_IORD|VAC_CTRL_IOWR)], + (val & VAC_CTRL_DSACK0) ? "dsack0*, " : "", + (val & VAC_CTRL_DSACK1) ? "dsack1*, " : "", + VAC_CTRL_RECOVERY_IOSELI_VAL(val), + VAC_CTRL_DELAY_IORD_VAL(val)/2, + (VAC_CTRL_DELAY_IORD_VAL(val)&1) ? ".5" : "", + VAC_CTRL_DELAY_IOWR_VAL(val)/2, + (VAC_CTRL_DELAY_IOWR_VAL(val)&1) ? ".5" : "", + VAC_CTRL_DELAY_IOSELI_VAL(val)/2, + (VAC_CTRL_DELAY_IOSELI_VAL(val)&1) ? ".5" : ""); +} + +__initfunc(static void vac_init(void)) +{ + unsigned short mem_limit = ((mips_memory_upper-KSEG0) >> 16); + + switch(vac_inw(VAC_ID)) { + case 0x1AC0: + printk("VAC068-F5: "); + break; + case 0x1AC1: + printk("VAC068A: "); + break; + default: + panic("Unknown VAC revision number"); + } + + vac_outw(mem_limit-1, VAC_DRAM_MASK); + vac_outw(mem_limit, VAC_BNDR2); + vac_outw(mem_limit, VAC_BNDR3); + vac_outw(((BAGET_A24M_BASE>>16)&~VAC_A24_D32_ENABLE)|VAC_A24_DATAPATH, + VAC_A24_BASE); + vac_outw(VAC_REG_INACTIVE|VAC_REG_ASIZ0,VAC_REG1); + vac_outw(VAC_REG_INACTIVE|VAC_REG_ASIZ0,VAC_REG2); + vac_outw(VAC_REG_MWB|VAC_REG_ASIZ1,VAC_REG3); + vac_outw(BAGET_A24S_BASE>>16,VAC_SLSEL0_BASE); + vac_outw(BAGET_A24S_MASK>>16,VAC_SLSEL0_MASK); + vac_outw(BAGET_A24S_BASE>>16,VAC_SLSEL1_BASE); + vac_outw(BAGET_A24S_MASK>>16,VAC_SLSEL1_MASK); + vac_outw(BAGET_GSW_BASE|BAGET_MSW_BASE(0),VAC_ICFSEL_BASE); + vac_outw(VAC_DECODE_FPUCS| + VAC_DECODE_CPUCLK(3)| + VAC_DECODE_RDR_SLSEL0|VAC_DECODE_RDR_SLSEL1| + VAC_DECODE_DSACK| + VAC_DECODE_QFY_BNDR| + VAC_DECODE_QFY_ICFSEL| + VAC_DECODE_QFY_SLSEL1|VAC_DECODE_QFY_SLSEL0| + VAC_DECODE_CMP_SLSEL1_HI| + VAC_DECODE_DRAMCS| + VAC_DECODE_QFY_DRAMCS| + VAC_DECODE_DSACKI,VAC_DECODE_CTRL); + vac_outw(VAC_PIO_FUNC_UART_A_TX|VAC_PIO_FUNC_UART_A_RX| + VAC_PIO_FUNC_UART_B_TX|VAC_PIO_FUNC_UART_B_RX| + VAC_PIO_FUNC_IOWR| + VAC_PIO_FUNC_IOSEL3| + VAC_PIO_FUNC_IRQ7|VAC_PIO_FUNC_IRQ10|VAC_PIO_FUNC_IRQ11| + VAC_PIO_FUNC_IOSEL2| + VAC_PIO_FUNC_FCIACK,VAC_PIO_FUNC); + vac_outw(VAC_PIO_DIR_FCIACK | + VAC_PIO_DIR_OUT(0) | + VAC_PIO_DIR_OUT(1) | + VAC_PIO_DIR_OUT(2) | + VAC_PIO_DIR_OUT(3) | + VAC_PIO_DIR_IN(4) | + VAC_PIO_DIR_OUT(5) | + VAC_PIO_DIR_OUT(6) | + VAC_PIO_DIR_OUT(7) | + VAC_PIO_DIR_OUT(8) | + VAC_PIO_DIR_IN(9) | + VAC_PIO_DIR_OUT(10)| + VAC_PIO_DIR_OUT(11)| + VAC_PIO_DIR_OUT(12)| + VAC_PIO_DIR_OUT(13),VAC_PIO_DIRECTION); + vac_outw(VAC_DEV_LOC_IOSEL(2),VAC_DEV_LOC); + vac_outw(VAC_CTRL_IOWR| + VAC_CTRL_DELAY_IOWR(3)| + VAC_CTRL_DELAY_IORD(3)| + VAC_CTRL_RECOVERY_IOSELI(1)| + VAC_CTRL_DELAY_DSACKI(8),VAC_SHRCS_CTRL); + vac_outw(VAC_CTRL_IOWR| + VAC_CTRL_DELAY_IOWR(3)| + VAC_CTRL_DELAY_IORD(3)| + VAC_CTRL_RECOVERY_IOSELI(1)| + VAC_CTRL_DSACK0|VAC_CTRL_DSACK1| + VAC_CTRL_DELAY_DSACKI(8),VAC_EPROMCS_CTRL); + vac_outw(VAC_CTRL_IOWR| + VAC_CTRL_DELAY_IOWR(3)| + VAC_CTRL_DELAY_IORD(3)| + VAC_CTRL_RECOVERY_IOSELI(2)| + VAC_CTRL_DSACK0|VAC_CTRL_DSACK1| + VAC_CTRL_DELAY_DSACKI(8),VAC_IOSEL0_CTRL); + vac_outw(VAC_CTRL_IOWR| + VAC_CTRL_DELAY_IOWR(3)| + VAC_CTRL_DELAY_IORD(3)| + VAC_CTRL_RECOVERY_IOSELI(2)| + VAC_CTRL_DSACK0|VAC_CTRL_DSACK1| + VAC_CTRL_DELAY_DSACKI(8),VAC_IOSEL1_CTRL); + vac_outw(VAC_CTRL_IOWR| + VAC_CTRL_DELAY_IOWR(3)| + VAC_CTRL_DELAY_IORD(3)| + VAC_CTRL_RECOVERY_IOSELI(2)| + VAC_CTRL_DSACK0|VAC_CTRL_DSACK1| + VAC_CTRL_DELAY_DSACKI(8),VAC_IOSEL2_CTRL); + vac_outw(VAC_CTRL_IOWR| + VAC_CTRL_DELAY_IOWR(3)| + VAC_CTRL_DELAY_IORD(3)| + VAC_CTRL_RECOVERY_IOSELI(2)| + VAC_CTRL_DSACK0|VAC_CTRL_DSACK1| + VAC_CTRL_DELAY_DSACKI(8),VAC_IOSEL3_CTRL); + vac_outw(VAC_CTRL_IOWR| + VAC_CTRL_DELAY_IOWR(3)| + VAC_CTRL_DELAY_IORD(3)| + VAC_CTRL_RECOVERY_IOSELI(2)| + VAC_CTRL_DELAY_DSACKI(8),VAC_IOSEL4_CTRL); + vac_outw(VAC_CTRL_IOWR| + VAC_CTRL_DELAY_IOWR(3)| + VAC_CTRL_DELAY_IORD(3)| + VAC_CTRL_RECOVERY_IOSELI(2)| + VAC_CTRL_DELAY_DSACKI(8),VAC_IOSEL5_CTRL); + + vac_show(); +} + +__initfunc(static void vac_start(void)) +{ + vac_outw(0, VAC_ID); + vac_outw(VAC_INT_CTRL_TIMER_DISABLE| + VAC_INT_CTRL_UART_B_DISABLE| + VAC_INT_CTRL_UART_A_DISABLE| + VAC_INT_CTRL_MBOX_DISABLE| + VAC_INT_CTRL_PIO4_DISABLE| + VAC_INT_CTRL_PIO7_DISABLE| + VAC_INT_CTRL_PIO8_DISABLE| + VAC_INT_CTRL_PIO9_DISABLE,VAC_INT_CTRL); + vac_outw(VAC_INT_CTRL_TIMER_PIO10| + VAC_INT_CTRL_UART_B_PIO7| + VAC_INT_CTRL_UART_A_PIO7,VAC_INT_CTRL); + /* + * Set quadro speed for both UARTs. + * To do it we need use formulae from VIC/VAC manual, + * keeping in mind Baget's 50MHz frequency... + */ + vac_outw((500000/(384*16))<<8,VAC_CPU_CLK_DIV); +} + +__initfunc(static void vic_show(void)) +{ + unsigned char val; + char *timeout[] = { "4", "16", "32", "64", "128", "256", "disabled" }; + char *deadlock[] = { "[dedlk only]", "[dedlk only]", + "[dedlk], [halt w/ rmc], [lberr]", + "[dedlk], [halt w/o rmc], [lberr]" }; + + val = vic_inb(VIC_IFACE_CFG); + if (val & VIC_IFACE_CFG_VME) + printk("VMEbus controller "); + if (val & VIC_IFACE_CFG_TURBO) + printk("turbo "); + if (val & VIC_IFACE_CFG_MSTAB) + printk("metastability delay "); + printk("%s ", + deadlock[VIC_IFACE_CFG_DEADLOCK_VAL(val)]); + + + printk("interrupts: "); + val = vic_inb(VIC_ERR_INT); + if (!(val & VIC_ERR_INT_SYSFAIL)) + printk("[sysfail]"); + if (!(val & VIC_ERR_INT_TIMO)) + printk("[timeout]"); + if (!(val & VIC_ERR_INT_WRPOST)) + printk("[write post]"); + if (!(val & VIC_ERR_INT_ACFAIL)) + printk("[acfail] "); + printk("\n"); + + printk("timeouts: "); + val = vic_inb(VIC_XFER_TIMO); + printk("local %s, vme %s ", + timeout[VIC_XFER_TIMO_LOCAL_PERIOD_VAL(val)], + timeout[VIC_XFER_TIMO_VME_PERIOD_VAL(val)]); + if (val & VIC_XFER_TIMO_VME) + printk("acquisition "); + if (val & VIC_XFER_TIMO_ARB) + printk("arbitration "); + printk("\n"); + + val = vic_inb(VIC_LOCAL_TIM); + printk("pas time: (%d,%d), ds time: %d\n", + VIC_LOCAL_TIM_PAS_ASSERT_VAL(val), + VIC_LOCAL_TIM_PAS_DEASSERT_VAL(val), + VIC_LOCAT_TIM_DS_DEASSERT_VAL(val)); + + val = vic_inb(VIC_BXFER_DEF); + printk("dma: "); + if (val & VIC_BXFER_DEF_DUAL) + printk("[dual path]"); + if (val & VIC_BXFER_DEF_LOCAL_CROSS) + printk("[local boundary cross]"); + if (val & VIC_BXFER_DEF_VME_CROSS) + printk("[vme boundary cross]"); + +} + +__initfunc(static void vic_init(void)) +{ + unsigned char id = vic_inb(VIC_ID); + if ((id & 0xf0) != 0xf0) + panic("VIC not found"); + printk(" VIC068A Rev. %X: ", id & 0x0f); + + vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE,VIC_VME_II); + vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE,VIC_VME_INT1); + vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE,VIC_VME_INT2); + vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE,VIC_VME_INT3); + vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE,VIC_VME_INT4); +/* + vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE, VIC_VME_INT5); +*/ + vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE, VIC_VME_INT6); + + vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE, VIC_VME_INT7); + vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE, VIC_DMA_INT); + vic_outb(VIC_INT_IPL(3)|VIC_INT_NOAUTO|VIC_INT_EDGE| + VIC_INT_LOW|VIC_INT_DISABLE, VIC_LINT1); + vic_outb(VIC_INT_IPL(3)|VIC_INT_NOAUTO|VIC_INT_EDGE| + VIC_INT_HIGH|VIC_INT_DISABLE, VIC_LINT2); + vic_outb(VIC_INT_IPL(3)|VIC_INT_NOAUTO|VIC_INT_EDGE| + VIC_INT_HIGH|VIC_INT_DISABLE, VIC_LINT3); + vic_outb(VIC_INT_IPL(3)|VIC_INT_NOAUTO|VIC_INT_EDGE| + VIC_INT_LOW|VIC_INT_DISABLE, VIC_LINT4); +/* + vic_outb(VIC_INT_IPL(3)|VIC_INT_NOAUTO|VIC_INT_LEVEL| + VIC_INT_LOW|VIC_INT_DISABLE, VIC_LINT5); +*/ + vic_outb(VIC_INT_IPL(6)|VIC_INT_NOAUTO|VIC_INT_EDGE| + VIC_INT_LOW|VIC_INT_DISABLE, VIC_LINT6); + vic_outb(VIC_INT_IPL(6)|VIC_INT_NOAUTO|VIC_INT_EDGE| + VIC_INT_LOW|VIC_INT_DISABLE, VIC_LINT7); + + vic_outb(VIC_INT_IPL(3)| + VIC_INT_SWITCH(0)| + VIC_INT_SWITCH(1)| + VIC_INT_SWITCH(2)| + VIC_INT_SWITCH(3), VIC_ICGS_INT); + vic_outb(VIC_INT_IPL(3)| + VIC_INT_SWITCH(0)| + VIC_INT_SWITCH(1)| + VIC_INT_SWITCH(2)| + VIC_INT_SWITCH(3), VIC_ICMS_INT); + vic_outb(VIC_INT_IPL(6)| + VIC_ERR_INT_SYSFAIL| + VIC_ERR_INT_TIMO| + VIC_ERR_INT_WRPOST| + VIC_ERR_INT_ACFAIL, VIC_ERR_INT); + vic_outb(VIC_ICxS_BASE_ID(0xf), VIC_ICGS_BASE); + vic_outb(VIC_ICxS_BASE_ID(0xe), VIC_ICMS_BASE); + vic_outb(VIC_LOCAL_BASE_ID(0x6), VIC_LOCAL_BASE); + vic_outb(VIC_ERR_BASE_ID(0x3), VIC_ERR_BASE); + vic_outb(VIC_XFER_TIMO_VME_PERIOD_32| + VIC_XFER_TIMO_LOCAL_PERIOD_32, VIC_XFER_TIMO); + vic_outb(VIC_LOCAL_TIM_PAS_ASSERT(2)| + VIC_LOCAT_TIM_DS_DEASSERT(1)| + VIC_LOCAL_TIM_PAS_DEASSERT(1), VIC_LOCAL_TIM); + vic_outb(VIC_BXFER_DEF_VME_CROSS| + VIC_BXFER_DEF_LOCAL_CROSS| + VIC_BXFER_DEF_AMSR| + VIC_BXFER_DEF_DUAL, VIC_BXFER_DEF); + vic_outb(VIC_SSxCR0_LOCAL_XFER_SINGLE| + VIC_SSxCR0_A32|VIC_SSxCR0_D32| + VIC_SS0CR0_TIMER_FREQ_NONE, VIC_SS0CR0); + vic_outb(VIC_SSxCR1_TF1(0xf)| + VIC_SSxCR1_TF2(0xf), VIC_SS0CR1); + vic_outb(VIC_SSxCR0_LOCAL_XFER_SINGLE| + VIC_SSxCR0_A24|VIC_SSxCR0_D32, VIC_SS1CR0); + vic_outb(VIC_SSxCR1_TF1(0xf)| + VIC_SSxCR1_TF2(0xf), VIC_SS1CR1); + vic_outb(VIC_IFACE_CFG_NOHALT| + VIC_IFACE_CFG_NOTURBO, VIC_IFACE_CFG); + vic_outb(VIC_AMS_CODE(0), VIC_AMS); + vic_outb(VIC_BXFER_CTRL_INTERLEAVE(0), VIC_BXFER_CTRL); + vic_outb(0, VIC_BXFER_LEN_LO); + vic_outb(0, VIC_BXFER_LEN_HI); + vic_outb(VIC_REQ_CFG_FAIRNESS_DISABLED| + VIC_REQ_CFG_LEVEL(3)| + VIC_REQ_CFG_RR_ARBITRATION, VIC_REQ_CFG); + vic_outb(VIC_RELEASE_BLKXFER_BLEN(0)| + VIC_RELEASE_RWD, VIC_RELEASE); + vic_outb(VIC_IC6_RUN, VIC_IC6); + vic_outb(0, VIC_IC7); + + vic_show(); +} + +static void vic_start(void) +{ + vic_outb(VIC_INT_IPL(3)| + VIC_INT_NOAUTO| + VIC_INT_EDGE| + VIC_INT_HIGH| + VIC_INT_ENABLE, VIC_LINT7); +} + +__initfunc(void baget_irq_setup(void)) +{ + extern void bagetIRQ(void); + + /* Now, it's safe to set the exception vector. */ + set_except_vector(0, bagetIRQ); +} + +extern void baget_machine_restart(char *command); +extern void baget_machine_halt(void); +extern void baget_machine_power_off(void); + +__initfunc(void baget_setup(void)) +{ + printk("BT23/63-201n found.\n"); + *BAGET_WRERR_ACK = 0; + irq_setup = baget_irq_setup; + + wbflush_setup(); + + _machine_restart = baget_machine_restart; + _machine_halt = baget_machine_halt; + _machine_power_off = baget_machine_power_off; + + vac_init(); + vic_init(); + vac_start(); + vic_start(); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/time.c linux.pre11.3/arch/mips/baget/time.c --- linux.vanilla/arch/mips/baget/time.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/baget/time.c Mon Jul 19 23:28:47 1999 @@ -0,0 +1,96 @@ +/* $Id$ + * time.c: Baget/MIPS specific time handling details + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +/* + * To have precision clock, we need to fix available clock frequency + */ +#define FREQ_NOM 79125 /* Baget frequency ratio */ +#define FREQ_DEN 10000 +static inline int timer_intr_valid(void) +{ + static unsigned long long ticks, valid_ticks; + + if (ticks++ * FREQ_DEN >= valid_ticks * FREQ_NOM) { + /* + * We need no overflow checks, + * due baget unable to work 3000 years... + * At least without reboot... + */ + valid_ticks++; + return 1; + } + return 0; +} + +void static timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + if (timer_intr_valid()) { + sti(); + do_timer(regs); + } +} + +__initfunc(static void timer_enable(void)) +{ + unsigned char ss0cr0 = vic_inb(VIC_SS0CR0); + ss0cr0 &= ~VIC_SS0CR0_TIMER_FREQ_MASK; + ss0cr0 |= VIC_SS0CR0_TIMER_FREQ_1000HZ; + vic_outb(ss0cr0, VIC_SS0CR0); + + vic_outb(VIC_INT_IPL(6)|VIC_INT_NOAUTO|VIC_INT_EDGE| + VIC_INT_LOW|VIC_INT_ENABLE, VIC_LINT2); +} + +__initfunc(void time_init(void)) +{ + if (request_irq(BAGET_VIC_TIMER_IRQ, timer_interrupt, + SA_INTERRUPT|SA_STATIC_ALLOC, "timer", NULL) < 0) + printk("time_init: unable request irq for system timer\n"); + + timer_enable(); + + /* We don't call sti() here, because it is too early for baget */ +} + +void do_gettimeofday(struct timeval *tv) +{ + unsigned long flags; + + save_and_cli(flags); + *tv = xtime; + restore_flags(flags); +} + +void do_settimeofday(struct timeval *tv) +{ + unsigned long flags; + + save_and_cli(flags); + xtime = *tv; + time_state = TIME_BAD; + time_maxerror = MAXPHASE; + time_esterror = MAXPHASE; + restore_flags(flags); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/vacserial.c linux.pre11.3/arch/mips/baget/vacserial.c --- linux.vanilla/arch/mips/baget/vacserial.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/baget/vacserial.c Mon Jul 19 23:28:47 1999 @@ -0,0 +1,2943 @@ +/* $Id$ + * vacserial.c: VAC UART serial driver + * This code stealed and adopted from linux/drivers/char/serial.c + * See that for author info + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + */ + +#undef SERIAL_PARANOIA_CHECK +#define CONFIG_SERIAL_NOPAUSE_IO +#define SERIAL_DO_RESTART + +#define CONFIG_SERIAL_SHARE_IRQ + +/* Set of debugging defines */ + +#undef SERIAL_DEBUG_INTR +#undef SERIAL_DEBUG_OPEN +#undef SERIAL_DEBUG_FLOW +#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + +#define RS_STROBE_TIME (10*HZ) +#define RS_ISR_PASS_LIMIT 2 /* Beget is not a super-computer (old=256) */ + +#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) + +#define SERIAL_INLINE + +#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT) +#define DBG_CNT(s) baget_printk("(%s):[%x] refc=%d, serc=%d, ttyc=%d-> %s\n", \ + kdevname(tty->device),(info->flags),serial_refcount,info->count,tty->count,s) +#else +#define DBG_CNT(s) +#endif + +#define QUAD_UART_SPEED /* Useful for Baget */ + +/* + * End of serial driver configuration section. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_SERIAL_CONSOLE +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#define BAGET_VAC_UART_IRQ 0x35 + +/* + * Implementation note: + * It was descovered by means of advanced electronic tools, + * if the driver works via TX_READY interrupts then VIC generates + * strange self-eliminating traps. Thus, the driver is rewritten to work + * via TX_EMPTY + */ + +/* VAC-specific check/debug switches */ + +#undef CHECK_REG_INDEX +#undef DEBUG_IO_PORT_A + +#ifdef SERIAL_INLINE +#define _INLINE_ inline +#endif + +static char *serial_name = "VAC Serial driver"; +static char *serial_version = "4.26"; + +static DECLARE_TASK_QUEUE(tq_serial); + +static struct tty_driver serial_driver, callout_driver; +static int serial_refcount; + +/* number of characters left in xmit buffer before we ask for more */ +#define WAKEUP_CHARS 256 + +/* + * IRQ_timeout - How long the timeout should be for each IRQ + * should be after the IRQ has been active. + */ + +static struct async_struct *IRQ_ports[NR_IRQS]; +static int IRQ_timeout[NR_IRQS]; +#ifdef CONFIG_SERIAL_CONSOLE +static struct console sercons; +#endif + +static void autoconfig(struct serial_state * info); +static void change_speed(struct async_struct *info); +static void rs_wait_until_sent(struct tty_struct *tty, int timeout); + +/* + * Here we define the default xmit fifo size used for each type of + * UART + */ +static struct serial_uart_config uart_config[] = { + { "unknown", 1, 0 }, /* Must go first -- used as unasigned */ + { "VAC UART", 1, 0 } +}; +#define VAC_UART_TYPE 1 /* Just index in above array */ + +static struct serial_state rs_table[] = { +/* + * VAC has tricky layout for pair of his SIO registers, + * so we need special function to access ones. + * To identify port we use their TX offset + */ + { 0, 9600, VAC_UART_B_TX, BAGET_VAC_UART_IRQ, + STD_COM_FLAGS }, /* VAC UART B */ + { 0, 9600, VAC_UART_A_TX, BAGET_VAC_UART_IRQ, + STD_COM_FLAGS } /* VAC UART A */ +}; + +#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state)) + +static struct tty_struct *serial_table[NR_PORTS]; +static struct termios *serial_termios[NR_PORTS]; +static struct termios *serial_termios_locked[NR_PORTS]; + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* + * tmp_buf is used as a temporary buffer by serial_write. We need to + * lock it in case the copy_from_user blocks while swapping in a page, + * and some other program tries to do a serial write at the same time. + * Since the lock will only come under contention when the system is + * swapping and available memory is low, it makes sense to share one + * buffer across all the serial ports, since it significantly saves + * memory if large numbers of serial ports are open. + */ +static unsigned char *tmp_buf; +static struct semaphore tmp_buf_sem = MUTEX; + +static inline int serial_paranoia_check(struct async_struct *info, + kdev_t device, const char *routine) +{ +#ifdef SERIAL_PARANOIA_CHECK + static const char *badmagic = + "Warning: bad magic number for serial struct (%s) in %s\n"; + static const char *badinfo = + "Warning: null async_struct for (%s) in %s\n"; + + if (!info) { + printk(badinfo, kdevname(device), routine); + return 1; + } + if (info->magic != SERIAL_MAGIC) { + printk(badmagic, kdevname(device), routine); + return 1; + } +#endif + return 0; +} + +/* + To unify UART A/B access we will use following function + to compute register offsets by register index. + */ + +#define VAC_UART_MODE 0 +#define VAC_UART_TX 1 +#define VAC_UART_RX 2 +#define VAC_UART_INT_MASK 3 +#define VAC_UART_INT_STATUS 4 + +#define VAC_UART_REG_NR 5 + +static inline int uart_offset_map(unsigned long port, int reg_index) +{ + static const unsigned int ind_to_reg[VAC_UART_REG_NR][NR_PORTS] = { + { VAC_UART_B_MODE, VAC_UART_A_MODE }, + { VAC_UART_B_TX, VAC_UART_A_TX }, + { VAC_UART_B_RX, VAC_UART_A_RX }, + { VAC_UART_B_INT_MASK, VAC_UART_A_INT_MASK }, + { VAC_UART_B_INT_STATUS, VAC_UART_A_INT_STATUS } + }; +#ifdef CHECK_REG_INDEX + if (reg_index > VAC_UART_REG_NR) panic("vacserial: bad reg_index"); +#endif + return ind_to_reg[reg_index][port == VAC_UART_B_TX ? 0 : 1]; +} + +static inline unsigned int serial_inw(struct async_struct *info, int offset) +{ + int val = vac_inw(uart_offset_map(info->port,offset)); +#ifdef DEBUG_IO_PORT_A + if (info->port == VAC_UART_A_TX) + printk("UART_A_IN: reg = 0x%04x, val = 0x%04x\n", + uart_offset_map(info->port,offset), val); +#endif + return val; +} + +static inline unsigned int serial_inp(struct async_struct *info, int offset) +{ + return serial_inw(info, offset); +} + +static inline unsigned int serial_in(struct async_struct *info, int offset) +{ + return serial_inw(info, offset); +} + +static inline void serial_outw(struct async_struct *info,int offset, int value) +{ +#ifdef DEBUG_IO_PORT_A + if (info->port == VAC_UART_A_TX) + printk("UART_A_OUT: offset = 0x%04x, val = 0x%04x\n", + uart_offset_map(info->port,offset), value); +#endif + vac_outw(value, uart_offset_map(info->port,offset)); +} + +static inline void serial_outp(struct async_struct *info,int offset, int value) +{ + serial_outw(info,offset,value); +} + +static inline void serial_out(struct async_struct *info,int offset, int value) +{ + serial_outw(info,offset,value); +} + +/* + * ------------------------------------------------------------ + * rs_stop() and rs_start() + * + * This routines are called before setting or resetting tty->stopped. + * They enable or disable transmitter interrupts, as necessary. + * ------------------------------------------------------------ + */ +static void rs_stop(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_stop")) + return; + + save_flags(flags); cli(); + if (info->IER & VAC_UART_INT_TX_EMPTY) { + info->IER &= ~VAC_UART_INT_TX_EMPTY; + serial_out(info, VAC_UART_INT_MASK, info->IER); + } + restore_flags(flags); +} + +static void rs_start(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_start")) + return; + + save_flags(flags); cli(); + if (info->xmit_cnt && info->xmit_buf + && !(info->IER & VAC_UART_INT_TX_EMPTY)) { + info->IER |= VAC_UART_INT_TX_EMPTY; + serial_out(info, VAC_UART_INT_MASK, info->IER); + } + restore_flags(flags); +} + +/* + * ---------------------------------------------------------------------- + * + * Here starts the interrupt handling routines. All of the following + * subroutines are declared as inline and are folded into + * rs_interrupt(). They were separated out for readability's sake. + * + * Note: rs_interrupt() is a "fast" interrupt, which means that it + * runs with interrupts turned off. People who may want to modify + * rs_interrupt() should try to keep the interrupt handler as fast as + * possible. After you are done making modifications, it is not a bad + * idea to do: + * + * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c + * + * and look at the resulting assemble code in serial.s. + * + * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 + * ----------------------------------------------------------------------- + */ + +/* + * This routine is used by the interrupt handler to schedule + * processing in the software interrupt portion of the driver. + */ +static _INLINE_ void rs_sched_event(struct async_struct *info, + int event) +{ + info->event |= 1 << event; + queue_task(&info->tqueue, &tq_serial); + mark_bh(SERIAL_BH); +} + +static _INLINE_ void receive_chars(struct async_struct *info, + int *status) +{ + struct tty_struct *tty = info->tty; + unsigned short rx; + unsigned char ch; + int ignored = 0; + struct async_icount *icount; + + icount = &info->state->icount; + do { + rx = serial_inw(info, VAC_UART_RX); + ch = VAC_UART_RX_DATA_MASK & rx; + + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + break; + *tty->flip.char_buf_ptr = ch; + icount->rx++; + +#ifdef SERIAL_DEBUG_INTR + baget_printk("DR%02x:%02x...", rx, *status); +#endif + *tty->flip.flag_buf_ptr = 0; + if (*status & (VAC_UART_STATUS_RX_BREAK_CHANGE + | VAC_UART_STATUS_RX_ERR_PARITY + | VAC_UART_STATUS_RX_ERR_FRAME + | VAC_UART_STATUS_RX_ERR_OVERRUN)) { + /* + * For statistics only + */ + if (*status & VAC_UART_STATUS_RX_BREAK_CHANGE) { + *status &= ~(VAC_UART_STATUS_RX_ERR_FRAME + | VAC_UART_STATUS_RX_ERR_PARITY); + icount->brk++; + } else if (*status & VAC_UART_STATUS_RX_ERR_PARITY) + icount->parity++; + else if (*status & VAC_UART_STATUS_RX_ERR_FRAME) + icount->frame++; + if (*status & VAC_UART_STATUS_RX_ERR_OVERRUN) + icount->overrun++; + + /* + * Now check to see if character should be + * ignored, and mask off conditions which + * should be ignored. + */ + if (*status & info->ignore_status_mask) { + if (++ignored > 100) + break; + goto ignore_char; + } + *status &= info->read_status_mask; + + if (*status & (VAC_UART_STATUS_RX_BREAK_CHANGE)) { +#ifdef SERIAL_DEBUG_INTR + baget_printk("handling break...."); +#endif + *tty->flip.flag_buf_ptr = TTY_BREAK; + if (info->flags & ASYNC_SAK) + do_SAK(tty); + } else if (*status & VAC_UART_STATUS_RX_ERR_PARITY) + *tty->flip.flag_buf_ptr = TTY_PARITY; + else if (*status & VAC_UART_STATUS_RX_ERR_FRAME) + *tty->flip.flag_buf_ptr = TTY_FRAME; + if (*status & VAC_UART_STATUS_RX_ERR_OVERRUN) { + /* + * Overrun is special, since it's + * reported immediately, and doesn't + * affect the current character + */ + if (tty->flip.count < TTY_FLIPBUF_SIZE) { + tty->flip.count++; + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + *tty->flip.flag_buf_ptr = TTY_OVERRUN; + } + } + } + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + ignore_char: + *status = serial_inw(info, VAC_UART_INT_STATUS); + } while ((*status & VAC_UART_STATUS_RX_READY)); + tty_flip_buffer_push(tty); +} + +static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) +{ + int count; + + if (info->x_char) { + serial_outw(info, VAC_UART_TX, + (((unsigned short)info->x_char)<<8)); + info->state->icount.tx++; + info->x_char = 0; + if (intr_done) + *intr_done = 0; + return; + } + if ((info->xmit_cnt <= 0) || info->tty->stopped || + info->tty->hw_stopped) { + info->IER &= ~VAC_UART_INT_TX_EMPTY; + serial_outw(info, VAC_UART_INT_MASK, info->IER); + return; + } + count = info->xmit_fifo_size; + do { + serial_out(info, VAC_UART_TX, + (unsigned short)info->xmit_buf[info->xmit_tail++] \ + << 8); + info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); + info->state->icount.tx++; + if (--info->xmit_cnt <= 0) + break; + } while (--count > 0); + + if (info->xmit_cnt < WAKEUP_CHARS) + rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); + +#ifdef SERIAL_DEBUG_INTR + baget_printk("THRE..."); +#endif + if (intr_done) + *intr_done = 0; + + if (info->xmit_cnt <= 0) { + info->IER &= ~VAC_UART_INT_TX_EMPTY; + serial_outw(info, VAC_UART_INT_MASK, info->IER); + } +} + +static _INLINE_ void check_modem_status(struct async_struct *info) +{ +#if 0 /* VAC hasn't modem control */ + wake_up_interruptible(&info->open_wait); + rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); +#endif +} + +#ifdef CONFIG_SERIAL_SHARE_IRQ + + +/* + * Specific functions needed for VAC UART interrupt enter/leave + */ + +#define VAC_INT_CTRL_UART_ENABLE \ + (VAC_INT_CTRL_TIMER_PIO10|VAC_INT_CTRL_UART_B_PIO7|VAC_INT_CTRL_UART_A_PIO7) + +#define VAC_INT_CTRL_UART_DISABLE(info) \ + (VAC_INT_CTRL_TIMER_PIO10 | \ + ((info->port == VAC_UART_A_TX) ? \ + (VAC_INT_CTRL_UART_A_DISABLE|VAC_INT_CTRL_UART_B_PIO7) : \ + (VAC_INT_CTRL_UART_A_PIO7|VAC_INT_CTRL_UART_B_DISABLE))) + +/* + * Following two functions were proposed by Pavel Osipenko + * to make VAC/VIC behaviour more regular. + */ +static void intr_begin(struct async_struct* info) +{ + serial_outw(info, VAC_UART_INT_MASK, 0); +} + +static void intr_end(struct async_struct* info) +{ + vac_outw(VAC_INT_CTRL_UART_DISABLE(info), VAC_INT_CTRL); + vac_outw(VAC_INT_CTRL_UART_ENABLE, VAC_INT_CTRL); + + serial_outw(info, VAC_UART_INT_MASK, info->IER); +} + +/* + * This is the serial driver's generic interrupt routine + */ +static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + int status; + struct async_struct * info; + int pass_counter = 0; + struct async_struct *end_mark = 0; + +#ifdef SERIAL_DEBUG_INTR + baget_printk("rs_interrupt(%d)...", irq); +#endif + + info = IRQ_ports[irq]; + if (!info) + return; + + do { + intr_begin(info); /* Mark we begin port handling */ + + if (!info->tty || + (serial_inw (info, VAC_UART_INT_STATUS) + & VAC_UART_STATUS_INTS) == 0) + { + if (!end_mark) + end_mark = info; + goto next; + } + end_mark = 0; + + info->last_active = jiffies; + + status = serial_inw(info, VAC_UART_INT_STATUS); +#ifdef SERIAL_DEBUG_INTR + baget_printk("status = %x...", status); +#endif + if (status & VAC_UART_STATUS_RX_READY) { + receive_chars(info, &status); + } + check_modem_status(info); + if (status & VAC_UART_STATUS_TX_EMPTY) + transmit_chars(info, 0); + + next: + intr_end(info); /* Mark this port handled */ + + info = info->next_port; + if (!info) { + info = IRQ_ports[irq]; + if (pass_counter++ > RS_ISR_PASS_LIMIT) { + break; /* Prevent infinite loops */ + } + continue; + } + } while (end_mark != info); +#ifdef SERIAL_DEBUG_INTR + baget_printk("end.\n"); +#endif + + +} +#endif /* #ifdef CONFIG_SERIAL_SHARE_IRQ */ + + +/* The original driver was simplified here: + two functions were joined to reduce code */ + +#define rs_interrupt_single rs_interrupt + + +/* + * ------------------------------------------------------------------- + * Here ends the serial interrupt routines. + * ------------------------------------------------------------------- + */ + +/* + * This routine is used to handle the "bottom half" processing for the + * serial driver, known also the "software interrupt" processing. + * This processing is done at the kernel interrupt level, after the + * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This + * is where time-consuming activities which can not be done in the + * interrupt driver proper are done; the interrupt driver schedules + * them using rs_sched_event(), and they get done here. + */ +static void do_serial_bh(void) +{ + run_task_queue(&tq_serial); +} + +static void do_softint(void *private_) +{ + struct async_struct *info = (struct async_struct *) private_; + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; + + if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); + } +} + +/* + * --------------------------------------------------------------- + * Low level utility subroutines for the serial driver: routines to + * figure out the appropriate timeout for an interrupt chain, routines + * to initialize and startup a serial port, and routines to shutdown a + * serial port. Useful stuff like that. + * --------------------------------------------------------------- + */ + +/* + * This routine figures out the correct timeout for a particular IRQ. + * It uses the smallest timeout of all of the serial ports in a + * particular interrupt chain. Now only used for IRQ 0.... + */ +static void figure_IRQ_timeout(int irq) +{ + struct async_struct *info; + int timeout = 60*HZ; /* 60 seconds === a long time :-) */ + + info = IRQ_ports[irq]; + if (!info) { + IRQ_timeout[irq] = 60*HZ; + return; + } + while (info) { + if (info->timeout < timeout) + timeout = info->timeout; + info = info->next_port; + } + if (!irq) + timeout = timeout / 2; + IRQ_timeout[irq] = timeout ? timeout : 1; +} + +static int startup(struct async_struct * info) +{ + unsigned long flags; + int retval=0; + void (*handler)(int, void *, struct pt_regs *); + struct serial_state *state= info->state; + unsigned long page; + + page = get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + save_flags(flags); cli(); + + if (info->flags & ASYNC_INITIALIZED) { + free_page(page); + goto errout; + } + if (!state->port || !state->type) { + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + free_page(page); + goto errout; + } + if (info->xmit_buf) + free_page(page); + else + info->xmit_buf = (unsigned char *) page; + +#ifdef SERIAL_DEBUG_OPEN + baget_printk("starting up ttys%d (irq %d)...", info->line, state->irq); +#endif + + if (uart_config[info->state->type].flags & UART_STARTECH) { + /* Wake up UART */ + serial_outp(info, VAC_UART_MODE, 0); + serial_outp(info, VAC_UART_INT_MASK, 0); + } + + /* + * Allocate the IRQ if necessary + */ + if (state->irq && (!IRQ_ports[state->irq] || + !IRQ_ports[state->irq]->next_port)) { + + if (IRQ_ports[state->irq]) { +#ifdef CONFIG_SERIAL_SHARE_IRQ + free_irq(state->irq, NULL); + handler = rs_interrupt; +#else + retval = -EBUSY; + goto errout; +#endif /* CONFIG_SERIAL_SHARE_IRQ */ + } else + handler = rs_interrupt_single; + + + retval = request_irq(state->irq, handler, IRQ_T(info), + "serial", NULL); + if (retval) { + if (capable(CAP_SYS_ADMIN)) { + if (info->tty) + set_bit(TTY_IO_ERROR, + &info->tty->flags); + retval = 0; + } + goto errout; + } + } + + /* + * Insert serial port into IRQ chain. + */ + info->prev_port = 0; + info->next_port = IRQ_ports[state->irq]; + if (info->next_port) + info->next_port->prev_port = info; + IRQ_ports[state->irq] = info; + figure_IRQ_timeout(state->irq); + + /* + * Clear the interrupt registers. + */ + /* (void) serial_inw(info, VAC_UART_INT_STATUS); */ /* (see above) */ + (void) serial_inw(info, VAC_UART_RX); + + /* + * Now, initialize the UART + */ + serial_outp(info, VAC_UART_MODE, VAC_UART_MODE_INITIAL); /*reset DLAB*/ + + /* + * Finally, enable interrupts + */ + info->IER = VAC_UART_INT_RX_BREAK_CHANGE | VAC_UART_INT_RX_ERRS | \ + VAC_UART_INT_RX_READY; + serial_outp(info, VAC_UART_INT_MASK, info->IER); /*enable interrupts*/ + + /* + * And clear the interrupt registers again for luck. + */ + (void)serial_inp(info, VAC_UART_INT_STATUS); + (void)serial_inp(info, VAC_UART_RX); + + if (info->tty) + clear_bit(TTY_IO_ERROR, &info->tty->flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + /* + * Set up serial timers... + */ + timer_table[RS_TIMER].expires = jiffies + 2*HZ/100; + timer_active |= 1 << RS_TIMER; + + /* + * and set the speed of the serial port + */ + change_speed(info); + + info->flags |= ASYNC_INITIALIZED; + restore_flags(flags); + return 0; + +errout: + restore_flags(flags); + return retval; +} + +/* + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. + */ +static void shutdown(struct async_struct * info) +{ + unsigned long flags; + struct serial_state *state; + int retval; + + if (!(info->flags & ASYNC_INITIALIZED)) + return; + + state = info->state; + +#ifdef SERIAL_DEBUG_OPEN + baget_printk("Shutting down serial port %d (irq %d)....", info->line, + state->irq); +#endif + + save_flags(flags); cli(); /* Disable interrupts */ + + /* + * clear delta_msr_wait queue to avoid mem leaks: we may free the irq + * here so the queue might never be waken up + */ + wake_up_interruptible(&info->delta_msr_wait); + + /* + * First unlink the serial port from the IRQ chain... + */ + if (info->next_port) + info->next_port->prev_port = info->prev_port; + if (info->prev_port) + info->prev_port->next_port = info->next_port; + else + IRQ_ports[state->irq] = info->next_port; + figure_IRQ_timeout(state->irq); + + /* + * Free the IRQ, if necessary + */ + if (state->irq && (!IRQ_ports[state->irq] || + !IRQ_ports[state->irq]->next_port)) { + if (IRQ_ports[state->irq]) { + free_irq(state->irq, NULL); + retval = request_irq(state->irq, rs_interrupt_single, + IRQ_T(info), "serial", NULL); + + if (retval) + printk("serial shutdown: request_irq: error %d" + " Couldn't reacquire IRQ.\n", retval); + } else + free_irq(state->irq, NULL); + } + + if (info->xmit_buf) { + free_page((unsigned long) info->xmit_buf); + info->xmit_buf = 0; + } + + info->IER = 0; + serial_outp(info, VAC_UART_INT_MASK, 0x00); /* disable all intrs */ + + /* disable break condition */ + serial_out(info, VAC_UART_MODE, serial_inp(info, VAC_UART_MODE) & \ + ~VAC_UART_MODE_SEND_BREAK); + + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + + info->flags &= ~ASYNC_INITIALIZED; + restore_flags(flags); +} + +/* + * When we set line mode, we call this function + * for Baget-specific adjustments. + */ + +static inline unsigned short vac_uart_mode_fixup (unsigned short cval) +{ +#ifdef QUAD_UART_SPEED + /* + * When we are using 4-x advantage in speed: + * + * Disadvantage : can't support 75, 150 bauds + * Advantage : can support 19200, 38400 bauds + */ + char speed = 7 & (cval >> 10); + cval &= ~(7 << 10); + cval |= VAC_UART_MODE_BAUD(speed-2); +#endif + + /* + * In general, we have Tx and Rx ON all time + * and use int mask flag for their disabling. + */ + cval |= VAC_UART_MODE_RX_ENABLE; + cval |= VAC_UART_MODE_TX_ENABLE; + cval |= VAC_UART_MODE_CHAR_RX_ENABLE; + cval |= VAC_UART_MODE_CHAR_TX_ENABLE; + + /* Low 4 bits are not used in UART */ + cval &= ~0xf; + + return cval; +} + +/* + * This routine is called to set the UART divisor registers to match + * the specified baud rate for a serial port. + */ +static void change_speed(struct async_struct *info) +{ + unsigned short port; + int quot = 0, baud_base, baud; + unsigned cflag, cval; + int bits; + unsigned long flags; + + if (!info->tty || !info->tty->termios) + return; + cflag = info->tty->termios->c_cflag; + if (!(port = info->port)) + return; + + /* byte size and parity */ + switch (cflag & CSIZE) { + case CS7: cval = 0x0; bits = 9; break; + case CS8: cval = VAC_UART_MODE_8BIT_CHAR; bits = 10; break; + /* Never happens, but GCC is too dumb to figure it out */ + case CS5: + case CS6: + default: cval = 0x0; bits = 9; break; + } + cval &= ~VAC_UART_MODE_PARITY_ENABLE; + if (cflag & PARENB) { + cval |= VAC_UART_MODE_PARITY_ENABLE; + bits++; + } + if (cflag & PARODD) + cval |= VAC_UART_MODE_PARITY_ODD; + + /* Determine divisor based on baud rate */ + baud = tty_get_baud_rate(info->tty); + baud_base = info->state->baud_base; + if (baud == 38400 && + ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) + quot = info->state->custom_divisor; + else { + if (baud == 134) + /* Special case since 134 is really 134.5 */ + quot = (2*baud_base / 269); + else if (baud) + quot = baud_base / baud; + } + /* If the quotient is ever zero, default to 9600 bps */ + if (!quot) + quot = baud_base / 9600; + info->quot = quot; + info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base); + info->timeout += HZ/50; /* Add .02 seconds of slop */ + + serial_out(info, VAC_UART_INT_MASK, info->IER); + + /* + * Set up parity check flag + */ +#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) + + info->read_status_mask = VAC_UART_STATUS_RX_ERR_OVERRUN | \ + VAC_UART_STATUS_TX_EMPTY | VAC_UART_STATUS_RX_READY; + if (I_INPCK(info->tty)) + info->read_status_mask |= VAC_UART_STATUS_RX_ERR_FRAME | \ + VAC_UART_STATUS_RX_ERR_PARITY; + if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) + info->read_status_mask |= VAC_UART_STATUS_RX_BREAK_CHANGE; + + /* + * Characters to ignore + */ + info->ignore_status_mask = 0; + if (I_IGNPAR(info->tty)) + info->ignore_status_mask |= VAC_UART_STATUS_RX_ERR_PARITY | \ + VAC_UART_STATUS_RX_ERR_FRAME; + if (I_IGNBRK(info->tty)) { + info->ignore_status_mask |= VAC_UART_STATUS_RX_BREAK_CHANGE; + /* + * If we're ignore parity and break indicators, ignore + * overruns too. (For real raw support). + */ + if (I_IGNPAR(info->tty)) + info->ignore_status_mask |= \ + VAC_UART_STATUS_RX_ERR_OVERRUN; + } + /* + * !!! ignore all characters if CREAD is not set + */ + if ((cflag & CREAD) == 0) + info->ignore_status_mask |= VAC_UART_STATUS_RX_READY; + save_flags(flags); cli(); + + + switch (baud) { + default: + case 9600: + cval |= VAC_UART_MODE_BAUD(7); + break; + case 4800: + cval |= VAC_UART_MODE_BAUD(6); + break; + case 2400: + cval |= VAC_UART_MODE_BAUD(5); + break; + case 1200: + cval |= VAC_UART_MODE_BAUD(4); + break; + case 600: + cval |= VAC_UART_MODE_BAUD(3); + break; + case 300: + cval |= VAC_UART_MODE_BAUD(2); + break; +#ifndef QUAD_UART_SPEED + case 150: +#else + case 38400: +#endif + cval |= VAC_UART_MODE_BAUD(1); + break; +#ifndef QUAD_UART_SPEED + case 75: +#else + case 19200: +#endif + cval |= VAC_UART_MODE_BAUD(0); + break; + } + + /* Baget VAC need some adjustments for computed value */ + cval = vac_uart_mode_fixup(cval); + + serial_outp(info, VAC_UART_MODE, cval); + restore_flags(flags); +} + +static void rs_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_put_char")) + return; + + if (!tty || !info->xmit_buf) + return; + + save_flags(flags); cli(); + if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { + restore_flags(flags); + return; + } + + info->xmit_buf[info->xmit_head++] = ch; + info->xmit_head &= SERIAL_XMIT_SIZE-1; + info->xmit_cnt++; + restore_flags(flags); +} + +static void rs_flush_chars(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_flush_chars")) + return; + + if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || + !info->xmit_buf) + return; + + save_flags(flags); cli(); + info->IER |= VAC_UART_INT_TX_EMPTY; + serial_out(info, VAC_UART_INT_MASK, info->IER); + restore_flags(flags); +} + +static int rs_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + int c, ret = 0; + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_write")) + return 0; + + if (!tty || !info->xmit_buf || !tmp_buf) + return 0; + + save_flags(flags); + if (from_user) { + down(&tmp_buf_sem); + while (1) { + c = MIN(count, + MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) + break; + + c -= copy_from_user(tmp_buf, buf, c); + if (!c) { + if (!ret) + ret = -EFAULT; + break; + } + cli(); + c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); + info->xmit_head = ((info->xmit_head + c) & + (SERIAL_XMIT_SIZE-1)); + info->xmit_cnt += c; + restore_flags(flags); + buf += c; + count -= c; + ret += c; + } + up(&tmp_buf_sem); + } else { + while (1) { + cli(); + c = MIN(count, + MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { + restore_flags(flags); + break; + } + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = ((info->xmit_head + c) & + (SERIAL_XMIT_SIZE-1)); + info->xmit_cnt += c; + restore_flags(flags); + buf += c; + count -= c; + ret += c; + } + } + if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped && + !(info->IER & VAC_UART_INT_TX_EMPTY)) { + info->IER |= VAC_UART_INT_TX_EMPTY; + serial_out(info, VAC_UART_INT_MASK, info->IER); + } + return ret; +} + +static int rs_write_room(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + int ret; + + if (serial_paranoia_check(info, tty->device, "rs_write_room")) + return 0; + ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) + ret = 0; + return ret; +} + +static int rs_chars_in_buffer(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer")) + return 0; + return info->xmit_cnt; +} + +static void rs_flush_buffer(struct tty_struct *tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_flush_buffer")) + return; + + save_flags(flags); cli(); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + restore_flags(flags); + + wake_up_interruptible(&tty->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} + +/* + * This function is used to send a high-priority XON/XOFF character to + * the device + */ +static void rs_send_xchar(struct tty_struct *tty, char ch) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_send_char")) + return; + + info->x_char = ch; + if (ch) { + /* Make sure transmit interrupts are on */ + info->IER |= VAC_UART_INT_TX_EMPTY; + serial_out(info, VAC_UART_INT_MASK, info->IER); + } +} + +/* + * ------------------------------------------------------------ + * rs_throttle() + * + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + * ------------------------------------------------------------ + */ +static void rs_throttle(struct tty_struct * tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + baget_printk("throttle %s: %d....\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->device, "rs_throttle")) + return; + + if (I_IXOFF(tty)) + rs_send_xchar(tty, STOP_CHAR(tty)); +} + +static void rs_unthrottle(struct tty_struct * tty) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + baget_printk("unthrottle %s: %d....\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->device, "rs_unthrottle")) + return; + + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + rs_send_xchar(tty, START_CHAR(tty)); + } +} + +/* + * ------------------------------------------------------------ + * rs_ioctl() and friends + * ------------------------------------------------------------ + */ + +static int get_serial_info(struct async_struct * info, + struct serial_struct * retinfo) +{ + struct serial_struct tmp; + struct serial_state *state = info->state; + + if (!retinfo) + return -EFAULT; + memset(&tmp, 0, sizeof(tmp)); + tmp.type = state->type; + tmp.line = state->line; + tmp.port = state->port; + tmp.irq = state->irq; + tmp.flags = state->flags; + tmp.xmit_fifo_size = state->xmit_fifo_size; + tmp.baud_base = state->baud_base; + tmp.close_delay = state->close_delay; + tmp.closing_wait = state->closing_wait; + tmp.custom_divisor = state->custom_divisor; + tmp.hub6 = state->hub6; + if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) + return -EFAULT; + return 0; +} + +static int set_serial_info(struct async_struct * info, + struct serial_struct * new_info) +{ + struct serial_struct new_serial; + struct serial_state old_state, *state; + unsigned int i,change_irq,change_port; + int retval = 0; + + if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) + return -EFAULT; + state = info->state; + old_state = *state; + + change_irq = new_serial.irq != state->irq; + change_port = (new_serial.port != state->port) || + (new_serial.hub6 != state->hub6); + + if (!capable(CAP_SYS_ADMIN)) { + if (change_irq || change_port || + (new_serial.baud_base != state->baud_base) || + (new_serial.type != state->type) || + (new_serial.close_delay != state->close_delay) || + (new_serial.xmit_fifo_size != state->xmit_fifo_size) || + ((new_serial.flags & ~ASYNC_USR_MASK) != + (state->flags & ~ASYNC_USR_MASK))) + return -EPERM; + state->flags = ((state->flags & ~ASYNC_USR_MASK) | + (new_serial.flags & ASYNC_USR_MASK)); + info->flags = ((state->flags & ~ASYNC_USR_MASK) | + (info->flags & ASYNC_USR_MASK)); + state->custom_divisor = new_serial.custom_divisor; + goto check_and_exit; + } + + new_serial.irq = irq_cannonicalize(new_serial.irq); + + if ((new_serial.irq >= NR_IRQS) || (new_serial.port > 0xffff) || + (new_serial.baud_base == 0) || (new_serial.type < PORT_UNKNOWN) || + (new_serial.type > PORT_MAX) || (new_serial.type == PORT_CIRRUS) || + (new_serial.type == PORT_STARTECH)) { + return -EINVAL; + } + + if ((new_serial.type != state->type) || + (new_serial.xmit_fifo_size <= 0)) + new_serial.xmit_fifo_size = + uart_config[state->type].dfl_xmit_fifo_size; + + /* Make sure address is not already in use */ + if (new_serial.type) { + for (i = 0 ; i < NR_PORTS; i++) + if ((state != &rs_table[i]) && + (rs_table[i].port == new_serial.port) && + rs_table[i].type) + return -EADDRINUSE; + } + + if ((change_port || change_irq) && (state->count > 1)) + return -EBUSY; + + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + + state->baud_base = new_serial.baud_base; + state->flags = ((state->flags & ~ASYNC_FLAGS) | + (new_serial.flags & ASYNC_FLAGS)); + info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) | + (info->flags & ASYNC_INTERNAL_FLAGS)); + state->custom_divisor = new_serial.custom_divisor; + state->type = new_serial.type; + state->close_delay = new_serial.close_delay * HZ/100; + state->closing_wait = new_serial.closing_wait * HZ/100; + info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + info->xmit_fifo_size = state->xmit_fifo_size = + new_serial.xmit_fifo_size; + + release_region(state->port,8); + if (change_port || change_irq) { + /* + * We need to shutdown the serial port at the old + * port/irq combination. + */ + shutdown(info); + state->irq = new_serial.irq; + info->port = state->port = new_serial.port; + info->hub6 = state->hub6 = new_serial.hub6; + } + if (state->type != PORT_UNKNOWN) + request_region(state->port,8,"serial(set)"); + + +check_and_exit: + if (!state->port || !state->type) + return 0; + if (state->flags & ASYNC_INITIALIZED) { + if (((old_state.flags & ASYNC_SPD_MASK) != + (state->flags & ASYNC_SPD_MASK)) || + (old_state.custom_divisor != state->custom_divisor)) { + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + info->tty->alt_speed = 57600; + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + info->tty->alt_speed = 115200; + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + info->tty->alt_speed = 230400; + if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + info->tty->alt_speed = 460800; + change_speed(info); + } + } else + retval = startup(info); + return retval; +} + + +/* + * get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int get_lsr_info(struct async_struct * info, unsigned int *value) +{ + unsigned short status; + unsigned int result; + unsigned long flags; + + save_flags(flags); cli(); + status = serial_inw(info, VAC_UART_INT_STATUS); + restore_flags(flags); + result = ((status & VAC_UART_STATUS_TX_EMPTY) ? TIOCSER_TEMT : 0); + return put_user(result,value); +} + + +static int get_modem_info(struct async_struct * info, unsigned int *value) +{ + unsigned int result; + + result = TIOCM_CAR | TIOCM_DSR; + return put_user(result,value); +} + +static int set_modem_info(struct async_struct * info, unsigned int cmd, + unsigned int *value) +{ + int error; + unsigned int arg; + + error = get_user(arg, value); + if (error) + return error; + switch (cmd) { + default: + return -EINVAL; + } + return 0; +} + +static int do_autoconfig(struct async_struct * info) +{ + int retval; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (info->state->count > 1) + return -EBUSY; + + shutdown(info); + + autoconfig(info->state); + + retval = startup(info); + if (retval) + return retval; + return 0; +} + +/* + * rs_break() --- routine which turns the break handling on or off + */ +static void rs_break(struct tty_struct *tty, int break_state) +{ + struct async_struct * info = (struct async_struct *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_break")) + return; + + if (!info->port) + return; + save_flags(flags); cli(); + if (break_state == -1) + serial_outp(info, VAC_UART_MODE, + serial_inp(info, VAC_UART_MODE) | \ + VAC_UART_MODE_SEND_BREAK); + else + serial_outp(info, VAC_UART_MODE, + serial_inp(info, VAC_UART_MODE) & \ + ~VAC_UART_MODE_SEND_BREAK); + restore_flags(flags); +} + +static int rs_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + int error; + struct async_struct * info = (struct async_struct *)tty->driver_data; + struct async_icount cprev, cnow; /* kernel counter temps */ + struct serial_icounter_struct *p_cuser; /* user space */ + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_ioctl")) + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && + (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + case TIOCMGET: + return get_modem_info(info, (unsigned int *) arg); + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + return set_modem_info(info, cmd, (unsigned int *) arg); + case TIOCGSERIAL: + return get_serial_info(info, + (struct serial_struct *) arg); + case TIOCSSERIAL: + return set_serial_info(info, + (struct serial_struct *) arg); + case TIOCSERCONFIG: + return do_autoconfig(info); + + case TIOCSERGETLSR: /* Get line status register */ + return get_lsr_info(info, (unsigned int *) arg); + + case TIOCSERGSTRUCT: + if (copy_to_user((struct async_struct *) arg, + info, sizeof(struct async_struct))) + return -EFAULT; + return 0; + + /* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)to change + * - mask passed in arg for lines of interest + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) + * Caller should use TIOCGICOUNT to see which one it was + */ + case TIOCMIWAIT: + save_flags(flags); cli(); + /* note the counters on entry */ + cprev = info->state->icount; + restore_flags(flags); + while (1) { + interruptible_sleep_on(&info->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + save_flags(flags); cli(); + cnow = info->state->icount; /* atomic copy */ + restore_flags(flags); + if (cnow.rng == cprev.rng && + cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && + cnow.cts == cprev.cts) + return -EIO; /* no change => error */ + if ( ((arg & TIOCM_RNG) && + (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && + (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && + (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && + (cnow.cts != cprev.cts)) ) { + return 0; + } + cprev = cnow; + } + /* NOTREACHED */ + + /* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ + case TIOCGICOUNT: + save_flags(flags); cli(); + cnow = info->state->icount; + restore_flags(flags); + p_cuser = (struct serial_icounter_struct *) arg; + error = put_user(cnow.cts, &p_cuser->cts); + if (error) return error; + error = put_user(cnow.dsr, &p_cuser->dsr); + if (error) return error; + error = put_user(cnow.rng, &p_cuser->rng); + if (error) return error; + error = put_user(cnow.dcd, &p_cuser->dcd); + if (error) return error; + error = put_user(cnow.rx, &p_cuser->rx); + if (error) return error; + error = put_user(cnow.tx, &p_cuser->tx); + if (error) return error; + error = put_user(cnow.frame, &p_cuser->frame); + if (error) return error; + error = put_user(cnow.overrun, &p_cuser->overrun); + if (error) return error; + error = put_user(cnow.parity, &p_cuser->parity); + if (error) return error; + error = put_user(cnow.brk, &p_cuser->brk); + if (error) return error; + error = put_user(cnow.buf_overrun, &p_cuser->buf_overrun); + + if (error) return error; + return 0; + + case TIOCSERGWILD: + case TIOCSERSWILD: + /* "setserial -W" is called in Debian boot */ + printk ("TIOCSER?WILD ioctl obsolete, ignored.\n"); + return 0; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + struct async_struct *info = (struct async_struct *)tty->driver_data; + + if ( (tty->termios->c_cflag == old_termios->c_cflag) + && ( RELEVANT_IFLAG(tty->termios->c_iflag) + == RELEVANT_IFLAG(old_termios->c_iflag))) + return; + + change_speed(info); + + /* Handle turning off CRTSCTS */ + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + rs_start(tty); + } + +} + +/* + * ------------------------------------------------------------ + * rs_close() + * + * This routine is called when the serial port gets closed. First, we + * wait for the last remaining data to be sent. Then, we unlink its + * async structure from the interrupt chain if necessary, and we free + * that IRQ if nothing is left in the chain. + * ------------------------------------------------------------ + */ +static void rs_close(struct tty_struct *tty, struct file * filp) +{ + struct async_struct * info = (struct async_struct *)tty->driver_data; + struct serial_state *state; + unsigned long flags; + + if (!info || serial_paranoia_check(info, tty->device, "rs_close")) + return; + + state = info->state; + + save_flags(flags); cli(); + + if (tty_hung_up_p(filp)) { + DBG_CNT("before DEC-hung"); + MOD_DEC_USE_COUNT; + restore_flags(flags); + return; + } + +#ifdef SERIAL_DEBUG_OPEN + baget_printk("rs_close ttys%d, count = %d\n", + info->line, state->count); +#endif + if ((tty->count == 1) && (state->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. state->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + baget_printk("rs_close: bad serial port count; " + "tty->count is 1, " + "state->count is %d\n", state->count); + state->count = 1; + } + if (--state->count < 0) { + baget_printk("rs_close: bad serial port count for " + "ttys%d: %d\n", + info->line, state->count); + state->count = 0; + } + if (state->count) { + DBG_CNT("before DEC-2"); + MOD_DEC_USE_COUNT; + restore_flags(flags); + return; + } + info->flags |= ASYNC_CLOSING; + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & ASYNC_NORMAL_ACTIVE) + info->state->normal_termios = *tty->termios; + if (info->flags & ASYNC_CALLOUT_ACTIVE) + info->state->callout_termios = *tty->termios; + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->closing_wait); + /* + * At this point we stop accepting input. To do this, we + * disable the receive line status interrupts, and tell the + * interrupt driver to stop checking the data ready bit in the + * line status register. + */ + info->IER &= ~(VAC_UART_INT_RX_BREAK_CHANGE | VAC_UART_INT_RX_ERRS); + info->read_status_mask &= ~VAC_UART_STATUS_RX_READY; + if (info->flags & ASYNC_INITIALIZED) { + serial_outw(info, VAC_UART_INT_MASK, info->IER); + /* + * Before we drop DTR, make sure the UART transmitter + * has completely drained; this is especially + * important if there is a transmit FIFO! + */ + rs_wait_until_sent(tty, info->timeout); + } + shutdown(info); + if (tty->driver.flush_buffer) + tty->driver.flush_buffer(tty); + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + tty->closing = 0; + info->event = 0; + info->tty = 0; + if (info->blocked_open) { + if (info->close_delay) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(info->close_delay); + } + wake_up_interruptible(&info->open_wait); + } + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| + ASYNC_CLOSING); + wake_up_interruptible(&info->close_wait); + MOD_DEC_USE_COUNT; + restore_flags(flags); +} + +/* + * rs_wait_until_sent() --- wait until the transmitter is empty + */ +static void rs_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct async_struct * info = (struct async_struct *)tty->driver_data; + unsigned long orig_jiffies, char_time; + int lsr; + + if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent")) + return; + + if (info->state->type == PORT_UNKNOWN) + return; + + if (info->xmit_fifo_size == 0) + return; /* Just in case.... */ + + orig_jiffies = jiffies; + /* + * Set the check interval to be 1/5 of the estimated time to + * send a single character, and make it at least 1. The check + * interval should also be less than the timeout. + * + * Note: we have to use pretty tight timings here to satisfy + * the NIST-PCTS. + */ + char_time = (info->timeout - HZ/50) / info->xmit_fifo_size; + char_time = char_time / 5; + if (char_time == 0) + char_time = 1; + if (timeout) + char_time = MIN(char_time, timeout); +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + baget_printk("In rs_wait_until_sent(%d) check=%lu...", + timeout, char_time); + baget_printk("jiff=%lu...", jiffies); +#endif + while (!((lsr = serial_inp(info, VAC_UART_INT_STATUS)) & \ + VAC_UART_STATUS_TX_EMPTY)) { +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + baget_printk("lsr = %d (jiff=%lu)...", lsr, jiffies); +#endif + current->state = TASK_INTERRUPTIBLE; + current->counter = 0; /* make us low-priority */ + schedule_timeout(char_time); + if (signal_pending(current)) + break; + if (timeout && ((orig_jiffies + timeout) < jiffies)) + break; + } + current->state = TASK_RUNNING; +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + baget_printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); +#endif +} + +/* + * rs_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +static void rs_hangup(struct tty_struct *tty) +{ + struct async_struct * info = (struct async_struct *)tty->driver_data; + struct serial_state *state = info->state; + + if (serial_paranoia_check(info, tty->device, "rs_hangup")) + return; + + state = info->state; + + rs_flush_buffer(tty); + shutdown(info); + info->event = 0; + state->count = 0; + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE); + info->tty = 0; + wake_up_interruptible(&info->open_wait); +} + +/* + * ------------------------------------------------------------ + * rs_open() and friends + * ------------------------------------------------------------ + */ +static int block_til_ready(struct tty_struct *tty, struct file * filp, + struct async_struct *info) +{ + struct wait_queue wait = { current, NULL }; + struct serial_state *state = info->state; + int retval; + int do_clocal = 0, extra_count = 0; + unsigned long flags; + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (tty_hung_up_p(filp) || + (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->close_wait); +#ifdef SERIAL_DO_RESTART + return ((info->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); +#else + return -EAGAIN; +#endif + } + + /* + * If this is a callout device, then just make sure the normal + * device isn't being used. + */ + if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { + if (info->flags & ASYNC_NORMAL_ACTIVE) + return -EBUSY; + if ((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_SESSION_LOCKOUT) && + (info->session != current->session)) + return -EBUSY; + if ((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_PGRP_LOCKOUT) && + (info->pgrp != current->pgrp)) + return -EBUSY; + info->flags |= ASYNC_CALLOUT_ACTIVE; + return 0; + } + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || + (tty->flags & (1 << TTY_IO_ERROR))) { + if (info->flags & ASYNC_CALLOUT_ACTIVE) + return -EBUSY; + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + + if (info->flags & ASYNC_CALLOUT_ACTIVE) { + if (state->normal_termios.c_cflag & CLOCAL) + do_clocal = 1; + } else { + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + } + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, state->count is dropped by one, so that + * rs_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue(&info->open_wait, &wait); +#ifdef SERIAL_DEBUG_OPEN + baget_printk("block_til_ready before block: ttys%d, count = %d\n", + state->line, state->count); +#endif + save_flags(flags); cli(); + if (!tty_hung_up_p(filp)) { + extra_count = 1; + state->count--; + } + restore_flags(flags); + info->blocked_open++; + while (1) { + current->state = TASK_INTERRUPTIBLE; + if (tty_hung_up_p(filp) || + !(info->flags & ASYNC_INITIALIZED)) { +#ifdef SERIAL_DO_RESTART + if (info->flags & ASYNC_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; +#else + retval = -EAGAIN; +#endif + break; + } + if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && + !(info->flags & ASYNC_CLOSING)) + break; + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } +#ifdef SERIAL_DEBUG_OPEN + baget_printk("block_til_ready blocking: ttys%d, count = %d\n", + info->line, state->count); +#endif + schedule(); + } + current->state = TASK_RUNNING; + remove_wait_queue(&info->open_wait, &wait); + if (extra_count) + state->count++; + info->blocked_open--; +#ifdef SERIAL_DEBUG_OPEN + baget_printk("block_til_ready after blocking: ttys%d, count = %d\n", + info->line, state->count); +#endif + if (retval) + return retval; + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; +} + +static int get_async_struct(int line, struct async_struct **ret_info) +{ + struct async_struct *info; + struct serial_state *sstate; + + sstate = rs_table + line; + sstate->count++; + if (sstate->info) { + *ret_info = sstate->info; + return 0; + } + info = kmalloc(sizeof(struct async_struct), GFP_KERNEL); + if (!info) { + sstate->count--; + return -ENOMEM; + } + memset(info, 0, sizeof(struct async_struct)); + info->magic = SERIAL_MAGIC; + info->port = sstate->port; + info->flags = sstate->flags; + info->xmit_fifo_size = sstate->xmit_fifo_size; + info->line = line; + info->tqueue.routine = do_softint; + info->tqueue.data = info; + info->state = sstate; + if (sstate->info) { + kfree_s(info, sizeof(struct async_struct)); + *ret_info = sstate->info; + return 0; + } + *ret_info = sstate->info = info; + return 0; +} + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port, linking in its async structure into + * the IRQ chain. It also performs the serial-specific + * initialization for the tty structure. + */ +static int rs_open(struct tty_struct *tty, struct file * filp) +{ + struct async_struct *info; + int retval, line; + unsigned long page; + + MOD_INC_USE_COUNT; + line = MINOR(tty->device) - tty->driver.minor_start; + if ((line < 0) || (line >= NR_PORTS)) { + MOD_DEC_USE_COUNT; + return -ENODEV; + } + retval = get_async_struct(line, &info); + if (retval) { + MOD_DEC_USE_COUNT; + return retval; + } + tty->driver_data = info; + info->tty = tty; + if (serial_paranoia_check(info, tty->device, "rs_open")) { + /* MOD_DEC_USE_COUNT; "info->tty" will cause this */ + return -ENODEV; + } + +#ifdef SERIAL_DEBUG_OPEN + baget_printk("rs_open %s%d, count = %d\n", + tty->driver.name, info->line, + info->state->count); +#endif + info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + + if (!tmp_buf) { + page = get_free_page(GFP_KERNEL); + if (!page) { + /* MOD_DEC_USE_COUNT; "info->tty" will cause this */ + return -ENOMEM; + } + if (tmp_buf) + free_page(page); + else + tmp_buf = (unsigned char *) page; + } + + /* + * If the port is the middle of closing, bail out now + */ + if (tty_hung_up_p(filp) || + (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->close_wait); + /* MOD_DEC_USE_COUNT; "info->tty" will cause this */ +#ifdef SERIAL_DO_RESTART + return ((info->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); +#else + return -EAGAIN; +#endif + } + + /* + * Start up serial port + */ + retval = startup(info); + if (retval) { + /* MOD_DEC_USE_COUNT; "info->tty" will cause this */ + return retval; + } + + retval = block_til_ready(tty, filp, info); + if (retval) { + /* MOD_DEC_USE_COUNT; "info->tty" will cause this */ +#ifdef SERIAL_DEBUG_OPEN + baget_printk("rs_open returning after block_til_ready " + "with %d\n", + retval); +#endif + return retval; + } + + if ((info->state->count == 1) && + (info->flags & ASYNC_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->state->normal_termios; + else + *tty->termios = info->state->callout_termios; + change_speed(info); + } +#ifdef CONFIG_SERIAL_CONSOLE + if (sercons.cflag && sercons.index == line) { + tty->termios->c_cflag = sercons.cflag; + sercons.cflag = 0; + change_speed(info); + } +#endif + info->session = current->session; + info->pgrp = current->pgrp; + +#ifdef SERIAL_DEBUG_OPEN + baget_printk("rs_open ttys%d successful...", info->line); +#endif + return 0; +} + +/* + * /proc fs routines.... + */ + +static inline int line_info(char *buf, struct serial_state *state) +{ + struct async_struct *info = state->info, scr_info; + int ret; + + ret = sprintf(buf, "%d: uart:%s port:%X irq:%d", + state->line, uart_config[state->type].name, + state->port, state->irq); + + if (!state->port || (state->type == PORT_UNKNOWN)) { + ret += sprintf(buf+ret, "\n"); + return ret; + } + + /* + * Figure out the current RS-232 lines + */ + if (!info) { + info = &scr_info; /* This is just for serial_{in,out} */ + + info->magic = SERIAL_MAGIC; + info->port = state->port; + info->flags = state->flags; + info->quot = 0; + info->tty = 0; + } + + if (info->quot) { + ret += sprintf(buf+ret, " baud:%d", + state->baud_base / info->quot); + } + + ret += sprintf(buf+ret, " tx:%d rx:%d", + state->icount.tx, state->icount.rx); + + if (state->icount.frame) + ret += sprintf(buf+ret, " fe:%d", state->icount.frame); + + if (state->icount.parity) + ret += sprintf(buf+ret, " pe:%d", state->icount.parity); + + if (state->icount.brk) + ret += sprintf(buf+ret, " brk:%d", state->icount.brk); + + if (state->icount.overrun) + ret += sprintf(buf+ret, " oe:%d", state->icount.overrun); + + return ret; +} + +int rs_read_proc(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + int i, len = 0, l; + off_t begin = 0; + + len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version); + for (i = 0; i < NR_PORTS && len < 4000; i++) { + l = line_info(page + len, &rs_table[i]); + len += l; + if (len+begin > off+count) + goto done; + if (len+begin < off) { + begin += len; + len = 0; + } + } + *eof = 1; +done: + if (off >= len+begin) + return 0; + *start = page + (begin-off); + return ((count < begin+len-off) ? count : begin+len-off); +} + +/* + * --------------------------------------------------------------------- + * rs_init() and friends + * + * rs_init() is called at boot-time to initialize the serial driver. + * --------------------------------------------------------------------- + */ + +/* + * This routine prints out the appropriate serial driver version + * number, and identifies which options were configured into this + * driver. + */ +static _INLINE_ void show_serial_version(void) +{ + printk(KERN_INFO "%s version %s with", serial_name, serial_version); +#ifdef CONFIG_SERIAL_SHARE_IRQ + printk(" SHARE_IRQ"); +#endif +#define SERIAL_OPT +#ifdef CONFIG_SERIAL_DETECT_IRQ + printk(" DETECT_IRQ"); +#endif +#ifdef SERIAL_OPT + printk(" enabled\n"); +#else + printk(" no serial options enabled\n"); +#endif +#undef SERIAL_OPT +} + + +/* + * This routine is called by rs_init() to initialize a specific serial + * port. It determines what type of UART chip this serial port is + * using: 8250, 16450, 16550, 16550A. The important question is + * whether or not this UART is a 16550A or not, since this will + * determine whether or not we can use its FIFO features or not. + */ + +/* + * Functionality of this function is reduced: we already know we have a VAC, + * but still need to perform some important actions (see code :-). + */ +static void autoconfig(struct serial_state * state) +{ + struct async_struct *info, scr_info; + unsigned long flags; + + /* Setting up important parameters */ + state->type = VAC_UART_TYPE; + state->xmit_fifo_size = uart_config[state->type].dfl_xmit_fifo_size; + + info = &scr_info; /* This is just for serial_{in,out} */ + + info->magic = SERIAL_MAGIC; + info->port = state->port; + info->flags = state->flags; + + save_flags(flags); cli(); + + /* + Flush VAC input fifo */ + (void)serial_in(info, VAC_UART_RX); + (void)serial_in(info, VAC_UART_RX); + (void)serial_in(info, VAC_UART_RX); + (void)serial_in(info, VAC_UART_RX); + + /* Disable interrupts */ + serial_outp(info, VAC_UART_INT_MASK, 0); + + restore_flags(flags); +} + +int register_serial(struct serial_struct *req); +void unregister_serial(int line); + +EXPORT_SYMBOL(register_serial); +EXPORT_SYMBOL(unregister_serial); + +/* + * Important function for VAC UART check and reanimation. + */ + +static void rs_timer(void) +{ + static unsigned long last_strobe = 0; + struct async_struct *info; + unsigned int i; + unsigned long flags; + + if ((jiffies - last_strobe) >= RS_STROBE_TIME) { + for (i=1; i < NR_IRQS; i++) { + info = IRQ_ports[i]; + if (!info) + continue; + save_flags(flags); cli(); +#ifdef CONFIG_SERIAL_SHARE_IRQ + if (info->next_port) { + do { + serial_out(info, VAC_UART_INT_MASK, 0); + info->IER |= VAC_UART_INT_TX_EMPTY; + serial_out(info, VAC_UART_INT_MASK, + info->IER); + info = info->next_port; + } while (info); + rs_interrupt(i, NULL, NULL); + } else +#endif /* CONFIG_SERIAL_SHARE_IRQ */ + rs_interrupt_single(i, NULL, NULL); + restore_flags(flags); + } + } + last_strobe = jiffies; + timer_table[RS_TIMER].expires = jiffies + RS_STROBE_TIME; + timer_active |= 1 << RS_TIMER; + + /* + * It looks this code for case we share IRQ with console... + */ + + if (IRQ_ports[0]) { + save_flags(flags); cli(); +#ifdef CONFIG_SERIAL_SHARE_IRQ + rs_interrupt(0, NULL, NULL); +#else + rs_interrupt_single(0, NULL, NULL); +#endif + restore_flags(flags); + + timer_table[RS_TIMER].expires = jiffies + IRQ_timeout[0] - 2; + } +} + +/* + * The serial driver boot-time initialization code! + */ +__initfunc(int rs_init(void)) +{ + int i; + struct serial_state * state; + extern void atomwide_serial_init (void); + extern void dualsp_serial_init (void); + +#ifdef CONFIG_ATOMWIDE_SERIAL + atomwide_serial_init (); +#endif +#ifdef CONFIG_DUALSP_SERIAL + dualsp_serial_init (); +#endif + + init_bh(SERIAL_BH, do_serial_bh); + timer_table[RS_TIMER].fn = rs_timer; + timer_table[RS_TIMER].expires = 0; + + for (i = 0; i < NR_IRQS; i++) { + IRQ_ports[i] = 0; + IRQ_timeout[i] = 0; + } + + +/* + * It is not a good idea to share interrupts with console, + * but it looks we cannot avoid it. + */ +#if 0 + +#ifdef CONFIG_SERIAL_CONSOLE + /* + * The interrupt of the serial console port + * can't be shared. + */ + if (sercons.flags & CON_CONSDEV) { + for(i = 0; i < NR_PORTS; i++) + if (i != sercons.index && + rs_table[i].irq == rs_table[sercons.index].irq) + rs_table[i].irq = 0; + } +#endif + +#endif + show_serial_version(); + + /* Initialize the tty_driver structure */ + + memset(&serial_driver, 0, sizeof(struct tty_driver)); + serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.driver_name = "serial"; + serial_driver.name = "ttyS"; + serial_driver.major = TTY_MAJOR; + serial_driver.minor_start = 64; + serial_driver.num = NR_PORTS; + serial_driver.type = TTY_DRIVER_TYPE_SERIAL; + serial_driver.subtype = SERIAL_TYPE_NORMAL; + serial_driver.init_termios = tty_std_termios; + serial_driver.init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver.flags = TTY_DRIVER_REAL_RAW; + serial_driver.refcount = &serial_refcount; + serial_driver.table = serial_table; + serial_driver.termios = serial_termios; + serial_driver.termios_locked = serial_termios_locked; + + serial_driver.open = rs_open; + serial_driver.close = rs_close; + serial_driver.write = rs_write; + serial_driver.put_char = rs_put_char; + serial_driver.flush_chars = rs_flush_chars; + serial_driver.write_room = rs_write_room; + serial_driver.chars_in_buffer = rs_chars_in_buffer; + serial_driver.flush_buffer = rs_flush_buffer; + serial_driver.ioctl = rs_ioctl; + serial_driver.throttle = rs_throttle; + serial_driver.unthrottle = rs_unthrottle; + serial_driver.send_xchar = rs_send_xchar; + serial_driver.set_termios = rs_set_termios; + serial_driver.stop = rs_stop; + serial_driver.start = rs_start; + serial_driver.hangup = rs_hangup; + serial_driver.break_ctl = rs_break; + serial_driver.wait_until_sent = rs_wait_until_sent; + serial_driver.read_proc = rs_read_proc; + + /* + * The callout device is just like normal device except for + * major number and the subtype code. + */ + callout_driver = serial_driver; + callout_driver.name = "cua"; + callout_driver.major = TTYAUX_MAJOR; + callout_driver.subtype = SERIAL_TYPE_CALLOUT; + callout_driver.read_proc = 0; + callout_driver.proc_entry = 0; + + if (tty_register_driver(&serial_driver)) + panic("Couldn't register serial driver\n"); + if (tty_register_driver(&callout_driver)) + panic("Couldn't register callout driver\n"); + + for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { + state->magic = SSTATE_MAGIC; + state->line = i; + state->type = PORT_UNKNOWN; + state->custom_divisor = 0; + state->close_delay = 5*HZ/10; + state->closing_wait = 30*HZ; + state->callout_termios = callout_driver.init_termios; + state->normal_termios = serial_driver.init_termios; + state->icount.cts = state->icount.dsr = + state->icount.rng = state->icount.dcd = 0; + state->icount.rx = state->icount.tx = 0; + state->icount.frame = state->icount.parity = 0; + state->icount.overrun = state->icount.brk = 0; + state->irq = irq_cannonicalize(state->irq); + if (check_region(state->port,8)) + continue; + if (state->flags & ASYNC_BOOT_AUTOCONF) + autoconfig(state); + } + + /* + * Detect the IRQ only once every port is initialised, + * because some 16450 do not reset to 0 the MCR register. + */ + for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { + if (state->type == PORT_UNKNOWN) + continue; + printk(KERN_INFO "ttyS%02d%s at 0x%04x (irq = %d) is a %s\n", + state->line, + (state->flags & ASYNC_FOURPORT) ? " FourPort" : "", + state->port, state->irq, + uart_config[state->type].name); + } + return 0; +} + +/* + * register_serial and unregister_serial allows for serial ports to be + * configured at run-time, to support PCMCIA modems. + */ +int register_serial(struct serial_struct *req) +{ + int i; + unsigned long flags; + struct serial_state *state; + + save_flags(flags); + cli(); + for (i = 0; i < NR_PORTS; i++) { + if (rs_table[i].port == req->port) + break; + } + if (i == NR_PORTS) { + for (i = 0; i < NR_PORTS; i++) + if ((rs_table[i].type == PORT_UNKNOWN) && + (rs_table[i].count == 0)) + break; + } + if (i == NR_PORTS) { + restore_flags(flags); + return -1; + } + state = &rs_table[i]; + if (rs_table[i].count) { + restore_flags(flags); + printk("Couldn't configure serial #%d (port=%d,irq=%d): " + "device already open\n", i, req->port, req->irq); + return -1; + } + state->irq = req->irq; + state->port = req->port; + state->flags = req->flags; + + autoconfig(state); + if (state->type == PORT_UNKNOWN) { + restore_flags(flags); + printk("register_serial(): autoconfig failed\n"); + return -1; + } + restore_flags(flags); + + printk(KERN_INFO "tty%02d at 0x%04x (irq = %d) is a %s\n", + state->line, state->port, state->irq, + uart_config[state->type].name); + return state->line; +} + +void unregister_serial(int line) +{ + unsigned long flags; + struct serial_state *state = &rs_table[line]; + + save_flags(flags); + cli(); + if (state->info && state->info->tty) + tty_hangup(state->info->tty); + state->type = PORT_UNKNOWN; + printk(KERN_INFO "tty%02d unloaded\n", state->line); + restore_flags(flags); +} + +#ifdef MODULE +int init_module(void) +{ + return rs_init(); +} + +void cleanup_module(void) +{ + unsigned long flags; + int e1, e2; + int i; + + printk("Unloading %s: version %s\n", serial_name, serial_version); + save_flags(flags); + cli(); + + timer_active &= ~(1 << RS_TIMER); + timer_table[RS_TIMER].fn = NULL; + timer_table[RS_TIMER].expires = 0; + remove_bh(SERIAL_BH); + + if ((e1 = tty_unregister_driver(&serial_driver))) + printk("SERIAL: failed to unregister serial driver (%d)\n", + e1); + if ((e2 = tty_unregister_driver(&callout_driver))) + printk("SERIAL: failed to unregister callout driver (%d)\n", + e2); + restore_flags(flags); + + for (i = 0; i < NR_PORTS; i++) { + if (rs_table[i].type != PORT_UNKNOWN) + release_region(rs_table[i].port, 8); + } + if (tmp_buf) { + free_page((unsigned long) tmp_buf); + tmp_buf = NULL; + } +} +#endif /* MODULE */ + + +/* + * ------------------------------------------------------------ + * Serial console driver + * ------------------------------------------------------------ + */ +#ifdef CONFIG_SERIAL_CONSOLE + +#define BOTH_EMPTY (VAC_UART_STATUS_TX_EMPTY | VAC_UART_STATUS_TX_EMPTY) + +/* + * Wait for transmitter & holding register to empty + */ +static inline void wait_for_xmitr(struct async_struct *info) +{ + int lsr; + unsigned int tmout = 1000000; + + do { + lsr = serial_inp(info, VAC_UART_INT_STATUS); + if (--tmout == 0) break; + } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY); +} + +/* + * Print a string to the serial port trying not to disturb + * any possible real use of the port... + */ +static void serial_console_write(struct console *co, const char *s, + unsigned count) +{ + struct serial_state *ser; + int ier; + unsigned i; + struct async_struct scr_info; /* serial_{in,out} because HUB6 */ + + ser = rs_table + co->index; + scr_info.magic = SERIAL_MAGIC; + scr_info.port = ser->port; + scr_info.flags = ser->flags; + + /* + * First save the IER then disable the interrupts + */ + ier = serial_inp(&scr_info, VAC_UART_INT_MASK); + serial_outw(&scr_info, VAC_UART_INT_MASK, 0x00); + + /* + * Now, do each character + */ + for (i = 0; i < count; i++, s++) { + wait_for_xmitr(&scr_info); + + /* + * Send the character out. + * If a LF, also do CR... + */ + serial_outp(&scr_info, VAC_UART_TX, (unsigned short)*s << 8); + if (*s == 10) { + wait_for_xmitr(&scr_info); + serial_outp(&scr_info, VAC_UART_TX, 13 << 8); + } + } + + /* + * Finally, Wait for transmitter & holding register to empty + * and restore the IER + */ + wait_for_xmitr(&scr_info); + serial_outp(&scr_info, VAC_UART_INT_MASK, ier); +} + +/* + * Receive character from the serial port + */ +static int serial_console_wait_key(struct console *co) +{ + struct serial_state *ser; + int ier; + int lsr; + int c; + struct async_struct scr_info; /* serial_{in,out} because HUB6 */ + + ser = rs_table + co->index; + scr_info.magic = SERIAL_MAGIC; + scr_info.port = ser->port; + scr_info.flags = ser->flags; + + /* + * First save the IER then disable the interrupts so + * that the real driver for the port does not get the + * character. + */ + ier = serial_inp(&scr_info, VAC_UART_INT_MASK); + serial_outp(&scr_info, VAC_UART_INT_MASK, 0x00); + + do { + lsr = serial_inp(&scr_info, VAC_UART_INT_STATUS); + } while (!(lsr & VAC_UART_STATUS_RX_READY)); + c = serial_inp(&scr_info, VAC_UART_RX); + + /* + * Restore the interrupts + */ + serial_outp(&scr_info, VAC_UART_INT_MASK, ier); + + return c; +} + +static kdev_t serial_console_device(struct console *c) +{ + return MKDEV(TTY_MAJOR, 64 + c->index); +} + +/* + * Setup initial baud/bits/parity. We do two things here: + * - construct a cflag setting for the first rs_open() + * - initialize the serial port + * Return non-zero if we didn't find a serial port. + */ +__initfunc(static int serial_console_setup(struct console *co, char *options)) +{ + struct serial_state *ser; + unsigned cval; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int cflag = CREAD | HUPCL | CLOCAL; + int quot = 0; + char *s; + struct async_struct scr_info; /* serial_{in,out} because HUB6 */ + + if (options) { + baud = simple_strtoul(options, NULL, 10); + s = options; + while(*s >= '0' && *s <= '9') + s++; + if (*s) parity = *s++; + if (*s) bits = *s - '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; + } + co->cflag = cflag; + + /* + * Divisor, bytesize and parity + */ + ser = rs_table + co->index; + scr_info.magic = SERIAL_MAGIC; + scr_info.port = ser->port; + scr_info.flags = ser->flags; + + quot = ser->baud_base / baud; + cval = cflag & (CSIZE | CSTOPB); + + cval >>= 4; + + cval &= ~VAC_UART_MODE_PARITY_ENABLE; + if (cflag & PARENB) + cval |= VAC_UART_MODE_PARITY_ENABLE; + if (cflag & PARODD) + cval |= VAC_UART_MODE_PARITY_ODD; + + /* + * Disable UART interrupts, set DTR and RTS high + * and set speed. + */ + switch (baud) { + default: + case 9600: + cval |= VAC_UART_MODE_BAUD(7); + break; + case 4800: + cval |= VAC_UART_MODE_BAUD(6); + break; + case 2400: + cval |= VAC_UART_MODE_BAUD(5); + break; + case 1200: + cval |= VAC_UART_MODE_BAUD(4); + break; + case 600: + cval |= VAC_UART_MODE_BAUD(3); + break; + case 300: + cval |= VAC_UART_MODE_BAUD(2); + break; +#ifndef QUAD_UART_SPEED + case 150: +#else + case 38400: +#endif + cval |= VAC_UART_MODE_BAUD(1); + break; +#ifndef QUAD_UART_SPEED + case 75: +#else + case 19200: +#endif + cval |= VAC_UART_MODE_BAUD(0); + break; + } + + /* Baget VAC need some adjustments for computed value */ + cval = vac_uart_mode_fixup(cval); + + serial_outp(&scr_info, VAC_UART_MODE, cval); + serial_outp(&scr_info, VAC_UART_INT_MASK, 0); + + return 0; +} + +static struct console sercons = { + "ttyS", + serial_console_write, + NULL, + serial_console_device, + serial_console_wait_key, + NULL, + serial_console_setup, + CON_PRINTBUFFER, + -1, + 0, + NULL +}; + +/* + * Register console. + */ +__initfunc (long serial_console_init(long kmem_start, long kmem_end)) +{ + register_console(&sercons); + return kmem_start; +} +#endif + +#ifdef CONFIG_REMOTE_DEBUG +#undef PRINT_DEBUG_PORT_INFO + +/* + * This is the interface to the remote debugger stub. + * I've put that here to be able to control the serial + * device more directly. + */ + +static int initialized = 0; + +static int rs_debug_init(struct async_struct *info) +{ + int quot; + + autoconfig(info); /* autoconfigure ttyS0, whatever that is */ + +#ifdef PRINT_DEBUG_PORT_INFO + baget_printk("kgdb debug interface:: tty%02d at 0x%04x", + info->line, info->port); + switch (info->type) { + case PORT_8250: + baget_printk(" is a 8250\n"); + break; + case PORT_16450: + baget_printk(" is a 16450\n"); + break; + case PORT_16550: + baget_printk(" is a 16550\n"); + break; + case PORT_16550A: + baget_printk(" is a 16550A\n"); + break; + case PORT_16650: + baget_printk(" is a 16650\n"); + break; + default: + baget_printk(" is of unknown type -- unusable\n"); + break; + } +#endif + + if (info->port == PORT_UNKNOWN) + return -1; + + /* + * Clear all interrupts + */ + + (void)serial_inp(info, VAC_UART_INT_STATUS); + (void)serial_inp(info, VAC_UART_RX); + + /* + * Now, initialize the UART + */ + serial_outp(info,VAC_UART_MODE,VAC_UART_MODE_INITIAL); /* reset DLAB */ + if (info->flags & ASYNC_FOURPORT) { + info->MCR = UART_MCR_DTR | UART_MCR_RTS; + info->MCR_noint = UART_MCR_DTR | UART_MCR_OUT1; + } else { + info->MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2; + info->MCR_noint = UART_MCR_DTR | UART_MCR_RTS; + } + + info->MCR = info->MCR_noint; /* no interrupts, please */ + /* + * and set the speed of the serial port + * (currently hardwired to 9600 8N1 + */ + + quot = info->baud_base / 9600; /* baud rate is fixed to 9600 */ + /* FIXME: if rs_debug interface is needed, we need to set speed here */ + + return 0; +} + +int putDebugChar(char c) +{ + struct async_struct *info = rs_table; + + if (!initialized) { /* need to init device first */ + if (rs_debug_init(info) == 0) + initialized = 1; + else + return 0; + } + + while ((serial_inw(info, VAC_UART_INT_STATUS) & \ + VAC_UART_STATUS_TX_EMPTY) == 0) + ; + serial_out(info, VAC_UART_TX, (unsigned short)c << 8); + + return 1; +} + +char getDebugChar(void) +{ + struct async_struct *info = rs_table; + + if (!initialized) { /* need to init device first */ + if (rs_debug_init(info) == 0) + initialized = 1; + else + return 0; + } + while (!(serial_inw(info, VAC_UART_INT_STATUS) & \ + VAC_UART_STATUS_RX_READY)) + ; + + return(serial_inp(info, VAC_UART_RX)); +} + +#endif /* CONFIG_REMOTE_DEBUG */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/wbflush.c linux.pre11.3/arch/mips/baget/wbflush.c --- linux.vanilla/arch/mips/baget/wbflush.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/baget/wbflush.c Mon Jul 19 23:28:47 1999 @@ -0,0 +1,24 @@ +/* + * Setup the right wbflush routine for Baget/MIPS. + * + * Copyright (C) 1999 Gleb Raiko & Vladimir Roganov + */ + +#include +#include + +void (*__wbflush) (void); + +static void wbflush_baget(void); + +__initfunc(void wbflush_setup(void)) +{ + __wbflush = wbflush_baget; +} + +/* + * Baget/MIPS doesnt need to write back the WB. + */ +static void wbflush_baget(void) +{ +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/boot/Makefile linux.pre11.3/arch/mips/boot/Makefile --- linux.vanilla/arch/mips/boot/Makefile Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/boot/Makefile Mon Jul 19 23:28:36 1999 @@ -1,11 +1,10 @@ -# -# arch/mips/boot/Makefile +# $Id: Makefile,v 1.9 1999/04/07 18:45:23 harald Exp $ # # 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. # -# Copyright (C) 1995 by Ralf Baechle +# Copyright (C) 1995, 1998 by Ralf Baechle # .S.s: @@ -16,35 +15,37 @@ OBJS = milo.o a.out.o # +# Some DECstations need all possible sections of an ECOFF executable +# +ifdef CONFIG_DECSTATION + E2EFLAGS = -a +else + E2EFLAGS = +endif + +# # Drop some uninteresting sections in the kernel. # This is only relevant for ELF kernels but doesn't hurt a.out # drop-sections = .reginfo .mdebug strip-flags = $(addprefix --remove-section=,$(drop-sections)) -# -# Fake compressed boot -# -zImage: $(CONFIGURE) mkboot $(TOPDIR)/vmlinux - $(OBJCOPY) $(strip-flags) $(TOPDIR)/vmlinux zImage.tmp - ./mkboot zImage.tmp zImage - rm -f zImage.tmp +all: vmlinux.ecoff addinitrd -mkboot: mkboot.c +vmlinux.ecoff: $(CONFIGURE) elf2ecoff $(TOPDIR)/vmlinux + ./elf2ecoff $(TOPDIR)/vmlinux vmlinux.ecoff $(E2EFLAGS) + +elf2ecoff: elf2ecoff.c $(HOSTCC) -o $@ $^ -zdisk: zImage - if [ -f /etc/remote-mcopy ]; then \ - ssh rio mcopy -o - a:vmlinux +#include +#include +#include + +#include "ecoff.h" + +#define MIPS_PAGE_SIZE 4096 +#define MIPS_PAGE_MASK (MIPS_PAGE_SIZE-1) + +#define swab16(x) \ + ((unsigned short)( \ + (((unsigned short)(x) & (unsigned short)0x00ffU) << 8) | \ + (((unsigned short)(x) & (unsigned short)0xff00U) >> 8) )) + +#define swab32(x) \ + ((unsigned int)( \ + (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \ + (((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) | \ + (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) | \ + (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) )) + +#define SWAB(a) (swab ? swab32(a) : (a)) + +void die (char *s) +{ + perror (s); + exit (1); +} + +int main (int argc, char *argv[]) +{ + int fd_vmlinux,fd_initrd,fd_outfile; + FILHDR efile; + AOUTHDR eaout; + SCNHDR esecs[3]; + struct stat st; + char buf[1024]; + unsigned long loadaddr; + unsigned long initrd_header[2]; + int i; + int swab = 0; + + if (argc != 4) { + printf ("Usage: %s \n",argv[0]); + exit (1); + } + + if ((fd_vmlinux = open (argv[1],O_RDWR)) < 0) + die ("open vmlinux"); + if (read (fd_vmlinux, &efile, sizeof efile) != sizeof efile) + die ("read file header"); + if (read (fd_vmlinux, &eaout, sizeof eaout) != sizeof eaout) + die ("read aout header"); + if (read (fd_vmlinux, esecs, sizeof esecs) != sizeof esecs) + die ("read section headers"); + + /* + * check whether the file is good for us + */ + /* TBD */ + + /* + * check, if we have to swab words + */ + if (ntohs(0xaa55) == 0xaa55) { + if (efile.f_magic == swab16(MIPSELMAGIC)) + swab = 1; + } else { + if (efile.f_magic == swab16(MIPSEBMAGIC)) + swab = 1; + } + + if ((fd_initrd = open (argv[2], O_RDONLY)) < 0) + die ("open initrd"); + if (fstat (fd_initrd, &st) < 0) + die ("fstat initrd"); + loadaddr = ((SWAB(esecs[2].s_vaddr) + SWAB(esecs[2].s_size) + + MIPS_PAGE_SIZE-1) & ~MIPS_PAGE_MASK) - 8; + if (loadaddr < (SWAB(esecs[2].s_vaddr) + SWAB(esecs[2].s_size))) + loadaddr += MIPS_PAGE_SIZE; + initrd_header[0] = SWAB(0x494E5244); + initrd_header[1] = SWAB(st.st_size); + eaout.dsize = esecs[1].s_size = initrd_header[1] = SWAB(st.st_size+8); + eaout.data_start = esecs[1].s_vaddr = esecs[1].s_paddr = SWAB(loadaddr); + + if ((fd_outfile = open (argv[3], O_RDWR|O_CREAT|O_TRUNC,0666)) < 0) + die ("open outfile"); + if (write (fd_outfile, &efile, sizeof efile) != sizeof efile) + die ("write file header"); + if (write (fd_outfile, &eaout, sizeof eaout) != sizeof eaout) + die ("write aout header"); + if (write (fd_outfile, esecs, sizeof esecs) != sizeof esecs) + die ("write section headers"); + while ((i = read (fd_vmlinux, buf, sizeof buf)) > 0) + if (write (fd_outfile, buf, i) != i) + die ("write vmlinux"); + if (write (fd_outfile, initrd_header, sizeof initrd_header) != sizeof initrd_header) + die ("write initrd header"); + while ((i = read (fd_initrd, buf, sizeof buf)) > 0) + if (write (fd_outfile, buf, i) != i) + die ("write initrd"); + close (fd_vmlinux); + close (fd_initrd); + return 0; +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/boot/ecoff.h linux.pre11.3/arch/mips/boot/ecoff.h --- linux.vanilla/arch/mips/boot/ecoff.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/boot/ecoff.h Mon Jul 19 23:28:36 1999 @@ -0,0 +1,62 @@ +/* + * Some ECOFF definitions. + */ +typedef struct filehdr { + unsigned short f_magic; /* magic number */ + unsigned short f_nscns; /* number of sections */ + long f_timdat; /* time & date stamp */ + long f_symptr; /* file pointer to symbolic header */ + long f_nsyms; /* sizeof(symbolic hdr) */ + unsigned short f_opthdr; /* sizeof(optional hdr) */ + unsigned short f_flags; /* flags */ +} FILHDR; +#define FILHSZ sizeof(FILHDR) + +#define OMAGIC 0407 +#define MIPSEBMAGIC 0x160 +#define MIPSELMAGIC 0x162 + +typedef struct scnhdr { + char s_name[8]; /* section name */ + long s_paddr; /* physical address, aliased s_nlib */ + long s_vaddr; /* virtual address */ + long s_size; /* section size */ + long s_scnptr; /* file ptr to raw data for section */ + long s_relptr; /* file ptr to relocation */ + long s_lnnoptr; /* file ptr to gp histogram */ + unsigned short s_nreloc; /* number of relocation entries */ + unsigned short s_nlnno; /* number of gp histogram entries */ + long s_flags; /* flags */ +} SCNHDR; +#define SCNHSZ sizeof(SCNHDR) +#define SCNROUND ((long)16) + +typedef struct aouthdr { + short magic; /* see above */ + short vstamp; /* version stamp */ + long tsize; /* text size in bytes, padded to DW bdry*/ + long dsize; /* initialized data " " */ + long bsize; /* uninitialized data " " */ + long entry; /* entry pt. */ + long text_start; /* base of text used for this file */ + long data_start; /* base of data used for this file */ + long bss_start; /* base of bss used for this file */ + long gprmask; /* general purpose register mask */ + long cprmask[4]; /* co-processor register masks */ + long gp_value; /* the gp value used for this object */ +} AOUTHDR; +#define AOUTHSZ sizeof(AOUTHDR) + +#define OMAGIC 0407 +#define NMAGIC 0410 +#define ZMAGIC 0413 +#define SMAGIC 0411 +#define LIBMAGIC 0443 + +#define N_TXTOFF(f, a) \ + ((a).magic == ZMAGIC || (a).magic == LIBMAGIC ? 0 : \ + ((a).vstamp < 23 ? \ + ((FILHSZ + AOUTHSZ + (f).f_nscns * SCNHSZ + 7) & 0xfffffff8) : \ + ((FILHSZ + AOUTHSZ + (f).f_nscns * SCNHSZ + SCNROUND-1) & ~(SCNROUND-1)) ) ) +#define N_DATOFF(f, a) \ + N_TXTOFF(f, a) + (a).tsize; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/boot/elf2ecoff.c linux.pre11.3/arch/mips/boot/elf2ecoff.c --- linux.vanilla/arch/mips/boot/elf2ecoff.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/boot/elf2ecoff.c Mon Jul 19 23:53:54 1999 @@ -0,0 +1,639 @@ +/* + * Copyright (c) 1995 + * Ted Lemon (hereinafter referred to as the author) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* elf2ecoff.c + + This program converts an elf executable to an ECOFF executable. + No symbol table is retained. This is useful primarily in building + net-bootable kernels for machines (e.g., DECstation and Alpha) which + only support the ECOFF object file format. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ecoff.h" + +/* + * Some extra ELF definitions + * MIPS hosts may already have definitions, so we define it conditional. + */ +#ifndef PT_MIPS_REGINFO +#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ +#endif + +/* -------------------------------------------------------------------- */ + +struct sect { + unsigned long vaddr; + unsigned long len; +}; + +int phcmp (); +char *saveRead (int file, off_t offset, off_t len, char *name); +int copy (int, int, off_t, off_t); +int translate_syms (int, int, off_t, off_t, off_t, off_t); +void convert_elf_hdr (Elf32_Ehdr *); +void convert_elf_phdrs (Elf32_Phdr *, int); +void convert_elf_shdrs (Elf32_Shdr *, int); +void convert_ecoff_filehdr(struct filehdr *); +void convert_ecoff_aouthdr(struct aouthdr *); +void convert_ecoff_esecs(struct scnhdr *, int); +extern int errno; +int *symTypeTable; +int must_convert_endian = 0; +int format_bigendian = 0; + +main (int argc, char **argv, char **envp) +{ + Elf32_Ehdr ex; + Elf32_Phdr *ph; + Elf32_Shdr *sh; + Elf32_Sym *symtab; + char *shstrtab; + int strtabix, symtabix; + int i, pad; + struct sect text, data, bss; + struct filehdr efh; + struct aouthdr eah; + struct scnhdr esecs [6]; + int infile, outfile; + unsigned long cur_vma = ULONG_MAX; + int addflag = 0; + int nosecs; + + text.len = data.len = bss.len = 0; + text.vaddr = data.vaddr = bss.vaddr = 0; + + /* Check args... */ + if (argc < 3 || argc > 4) + { + usage: + fprintf (stderr, + "usage: elf2aout [-a]\n"); + exit (1); + } + if (argc == 4) + { + if (strcmp (argv [3], "-a")) + goto usage; + addflag = 1; + } + + /* Try the input file... */ + if ((infile = open (argv [1], O_RDONLY)) < 0) + { + fprintf (stderr, "Can't open %s for read: %s\n", + argv [1], strerror (errno)); + exit (1); + } + + /* Read the header, which is at the beginning of the file... */ + i = read (infile, &ex, sizeof ex); + if (i != sizeof ex) + { + fprintf (stderr, "ex: %s: %s.\n", + argv [1], i ? strerror (errno) : "End of file reached"); + exit (1); + } + + if (ex.e_ident[EI_DATA] == ELFDATA2MSB) + format_bigendian = 1; + + if (ntohs (0xaa55) == 0xaa55) { + if (!format_bigendian) + must_convert_endian = 1; + } else { + if (format_bigendian) + must_convert_endian = 1; + } + if (must_convert_endian) + convert_elf_hdr (&ex); + + /* Read the program headers... */ + ph = (Elf32_Phdr *)saveRead (infile, ex.e_phoff, + ex.e_phnum * sizeof (Elf32_Phdr), "ph"); + if (must_convert_endian) + convert_elf_phdrs (ph, ex.e_phnum); + /* Read the section headers... */ + sh = (Elf32_Shdr *)saveRead (infile, ex.e_shoff, + ex.e_shnum * sizeof (Elf32_Shdr), "sh"); + if (must_convert_endian) + convert_elf_shdrs (sh, ex.e_shnum); + /* Read in the section string table. */ + shstrtab = saveRead (infile, sh [ex.e_shstrndx].sh_offset, + sh [ex.e_shstrndx].sh_size, "shstrtab"); + + /* Figure out if we can cram the program header into an ECOFF + header... Basically, we can't handle anything but loadable + segments, but we can ignore some kinds of segments. We can't + handle holes in the address space. Segments may be out of order, + so we sort them first. */ + + qsort (ph, ex.e_phnum, sizeof (Elf32_Phdr), phcmp); + + for (i = 0; i < ex.e_phnum; i++) + { + /* Section types we can ignore... */ + if (ph [i].p_type == PT_NULL || ph [i].p_type == PT_NOTE || + ph [i].p_type == PT_PHDR || ph [i].p_type == PT_MIPS_REGINFO) + continue; + /* Section types we can't handle... */ + else if (ph [i].p_type != PT_LOAD) + { + fprintf (stderr, "Program header %d type %d can't be converted.\n"); + exit (1); + } + /* Writable (data) segment? */ + if (ph [i].p_flags & PF_W) + { + struct sect ndata, nbss; + + ndata.vaddr = ph [i].p_vaddr; + ndata.len = ph [i].p_filesz; + nbss.vaddr = ph [i].p_vaddr + ph [i].p_filesz; + nbss.len = ph [i].p_memsz - ph [i].p_filesz; + + combine (&data, &ndata, 0); + combine (&bss, &nbss, 1); + } + else + { + struct sect ntxt; + + ntxt.vaddr = ph [i].p_vaddr; + ntxt.len = ph [i].p_filesz; + + combine (&text, &ntxt, 0); + } + /* Remember the lowest segment start address. */ + if (ph [i].p_vaddr < cur_vma) + cur_vma = ph [i].p_vaddr; + } + + /* Sections must be in order to be converted... */ + if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr || + text.vaddr + text.len > data.vaddr || data.vaddr + data.len > bss.vaddr) + { + fprintf (stderr, "Sections ordering prevents a.out conversion.\n"); + exit (1); + } + + /* If there's a data section but no text section, then the loader + combined everything into one section. That needs to be the + text section, so just make the data section zero length following + text. */ + if (data.len && !text.len) + { + text = data; + data.vaddr = text.vaddr + text.len; + data.len = 0; + } + + /* If there is a gap between text and data, we'll fill it when we copy + the data, so update the length of the text segment as represented in + a.out to reflect that, since a.out doesn't allow gaps in the program + address space. */ + if (text.vaddr + text.len < data.vaddr) + text.len = data.vaddr - text.vaddr; + + /* We now have enough information to cons up an a.out header... */ + eah.magic = OMAGIC; + eah.vstamp = 200; + eah.tsize = text.len; + eah.dsize = data.len; + eah.bsize = bss.len; + eah.entry = ex.e_entry; + eah.text_start = text.vaddr; + eah.data_start = data.vaddr; + eah.bss_start = bss.vaddr; + eah.gprmask = 0xf3fffffe; + memset (&eah.cprmask, '\0', sizeof eah.cprmask); + eah.gp_value = 0; /* unused. */ + + if (format_bigendian) + efh.f_magic = MIPSEBMAGIC; + else + efh.f_magic = MIPSELMAGIC; + if (addflag) + nosecs = 6; + else + nosecs = 3; + efh.f_nscns = nosecs; + efh.f_timdat = 0; /* bogus */ + efh.f_symptr = 0; + efh.f_nsyms = 0; + efh.f_opthdr = sizeof eah; + efh.f_flags = 0x100f; /* Stripped, not sharable. */ + + memset (esecs, 0, sizeof esecs); + strcpy (esecs [0].s_name, ".text"); + strcpy (esecs [1].s_name, ".data"); + strcpy (esecs [2].s_name, ".bss"); + if (addflag) { + strcpy (esecs [3].s_name, ".rdata"); + strcpy (esecs [4].s_name, ".sdata"); + strcpy (esecs [5].s_name, ".sbss"); + } + esecs [0].s_paddr = esecs [0].s_vaddr = eah.text_start; + esecs [1].s_paddr = esecs [1].s_vaddr = eah.data_start; + esecs [2].s_paddr = esecs [2].s_vaddr = eah.bss_start; + if (addflag) { + esecs [3].s_paddr = esecs [3].s_vaddr = 0; + esecs [4].s_paddr = esecs [4].s_vaddr = 0; + esecs [5].s_paddr = esecs [5].s_vaddr = 0; + } + esecs [0].s_size = eah.tsize; + esecs [1].s_size = eah.dsize; + esecs [2].s_size = eah.bsize; + if (addflag) { + esecs [3].s_size = 0; + esecs [4].s_size = 0; + esecs [5].s_size = 0; + } + esecs [0].s_scnptr = N_TXTOFF (efh, eah); + esecs [1].s_scnptr = N_DATOFF (efh, eah); +#define ECOFF_SEGMENT_ALIGNMENT(a) 0x10 +#define ECOFF_ROUND(s,a) (((s)+(a)-1)&~((a)-1)) + esecs [2].s_scnptr = esecs [1].s_scnptr + + ECOFF_ROUND (esecs [1].s_size, ECOFF_SEGMENT_ALIGNMENT (&eah)); + if (addflag) { + esecs [3].s_scnptr = 0; + esecs [4].s_scnptr = 0; + esecs [5].s_scnptr = 0; + } + esecs [0].s_relptr = esecs [1].s_relptr + = esecs [2].s_relptr = 0; + esecs [0].s_lnnoptr = esecs [1].s_lnnoptr + = esecs [2].s_lnnoptr = 0; + esecs [0].s_nreloc = esecs [1].s_nreloc = esecs [2].s_nreloc = 0; + esecs [0].s_nlnno = esecs [1].s_nlnno = esecs [2].s_nlnno = 0; + if (addflag) { + esecs [3].s_relptr = esecs [4].s_relptr + = esecs [5].s_relptr = 0; + esecs [3].s_lnnoptr = esecs [4].s_lnnoptr + = esecs [5].s_lnnoptr = 0; + esecs [3].s_nreloc = esecs [4].s_nreloc = esecs [5].s_nreloc = 0; + esecs [3].s_nlnno = esecs [4].s_nlnno = esecs [5].s_nlnno = 0; + } + esecs [0].s_flags = 0x20; + esecs [1].s_flags = 0x40; + esecs [2].s_flags = 0x82; + if (addflag) { + esecs [3].s_flags = 0x100; + esecs [4].s_flags = 0x200; + esecs [5].s_flags = 0x400; + } + + /* Make the output file... */ + if ((outfile = open (argv [2], O_WRONLY | O_CREAT, 0777)) < 0) + { + fprintf (stderr, "Unable to create %s: %s\n", argv [2], strerror (errno)); + exit (1); + } + + if (must_convert_endian) + convert_ecoff_filehdr (&efh); + /* Write the headers... */ + i = write (outfile, &efh, sizeof efh); + if (i != sizeof efh) + { + perror ("efh: write"); + exit (1); + + for (i = 0; i < nosecs; i++) + { + printf ("Section %d: %s phys %x size %x file offset %x\n", + i, esecs [i].s_name, esecs [i].s_paddr, + esecs [i].s_size, esecs [i].s_scnptr); + } + } + fprintf (stderr, "wrote %d byte file header.\n", i); + + if (must_convert_endian) + convert_ecoff_aouthdr (&eah); + i = write (outfile, &eah, sizeof eah); + if (i != sizeof eah) + { + perror ("eah: write"); + exit (1); + } + fprintf (stderr, "wrote %d byte a.out header.\n", i); + + if (must_convert_endian) + convert_ecoff_esecs (&esecs[0], nosecs); + i = write (outfile, &esecs, nosecs * sizeof(struct scnhdr)); + if (i != nosecs * sizeof(struct scnhdr)) + { + perror ("esecs: write"); + exit (1); + } + fprintf (stderr, "wrote %d bytes of section headers.\n", i); + + if (pad = ((sizeof efh + sizeof eah + nosecs * sizeof(struct scnhdr)) & 15)) + { + pad = 16 - pad; + i = write (outfile, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", pad); + if (i < 0) + { + perror ("ipad: write"); + exit (1); + } + fprintf (stderr, "wrote %d byte pad.\n", i); + } + + /* Copy the loadable sections. Zero-fill any gaps less than 64k; + complain about any zero-filling, and die if we're asked to zero-fill + more than 64k. */ + for (i = 0; i < ex.e_phnum; i++) + { + /* Unprocessable sections were handled above, so just verify that + the section can be loaded before copying. */ + if (ph [i].p_type == PT_LOAD && ph [i].p_filesz) + { + if (cur_vma != ph [i].p_vaddr) + { + unsigned long gap = ph [i].p_vaddr - cur_vma; + char obuf [1024]; + if (gap > 65536) + { + fprintf (stderr, "Intersegment gap (%d bytes) too large.\n", + gap); + exit (1); + } + fprintf (stderr, "Warning: %d byte intersegment gap.\n", gap); + memset (obuf, 0, sizeof obuf); + while (gap) + { + int count = write (outfile, obuf, (gap > sizeof obuf + ? sizeof obuf : gap)); + if (count < 0) + { + fprintf (stderr, "Error writing gap: %s\n", + strerror (errno)); + exit (1); + } + gap -= count; + } + } +fprintf (stderr, "writing %d bytes...\n", ph [i].p_filesz); + copy (outfile, infile, ph [i].p_offset, ph [i].p_filesz); + cur_vma = ph [i].p_vaddr + ph [i].p_filesz; + } + } + + /* + * Write a page of padding for boot PROMS that read entire pages. + * Without this, they may attempt to read past the end of the + * data section, incur an error, and refuse to boot. + */ + { + char obuf[4096]; + memset(obuf, 0, sizeof obuf); + if (write(outfile, obuf, sizeof(obuf)) != sizeof(obuf)) { + fprintf(stderr, "Error writing PROM padding: %s\n", + strerror(errno)); + exit(1); + } + } + + /* Looks like we won... */ + exit (0); +} + +copy (out, in, offset, size) + int out, in; + off_t offset, size; +{ + char ibuf [4096]; + int remaining, cur, count; + + /* Go the the start of the ELF symbol table... */ + if (lseek (in, offset, SEEK_SET) < 0) + { + perror ("copy: lseek"); + exit (1); + } + + remaining = size; + while (remaining) + { + cur = remaining; + if (cur > sizeof ibuf) + cur = sizeof ibuf; + remaining -= cur; + if ((count = read (in, ibuf, cur)) != cur) + { + fprintf (stderr, "copy: read: %s\n", + count ? strerror (errno) : "premature end of file"); + exit (1); + } + if ((count = write (out, ibuf, cur)) != cur) + { + perror ("copy: write"); + exit (1); + } + } +} + +/* Combine two segments, which must be contiguous. If pad is true, it's + okay for there to be padding between. */ +combine (base, new, pad) + struct sect *base, *new; + int pad; +{ + if (!base -> len) + *base = *new; + else if (new -> len) + { + if (base -> vaddr + base -> len != new -> vaddr) + { + if (pad) + base -> len = new -> vaddr - base -> vaddr; + else + { + fprintf (stderr, + "Non-contiguous data can't be converted.\n"); + exit (1); + } + } + base -> len += new -> len; + } +} + +phcmp (h1, h2) + Elf32_Phdr *h1, *h2; +{ + if (h1 -> p_vaddr > h2 -> p_vaddr) + return 1; + else if (h1 -> p_vaddr < h2 -> p_vaddr) + return -1; + else + return 0; +} + +char *saveRead (int file, off_t offset, off_t len, char *name) +{ + char *tmp; + int count; + off_t off; + if ((off = lseek (file, offset, SEEK_SET)) < 0) + { + fprintf (stderr, "%s: fseek: %s\n", name, strerror (errno)); + exit (1); + } + if (!(tmp = (char *)malloc (len))) + { + fprintf (stderr, "%s: Can't allocate %d bytes.\n", name, len); + exit (1); + } + count = read (file, tmp, len); + if (count != len) + { + fprintf (stderr, "%s: read: %s.\n", + name, count ? strerror (errno) : "End of file reached"); + exit (1); + } + return tmp; +} + +#define swab16(x) \ + ((unsigned short)( \ + (((unsigned short)(x) & (unsigned short)0x00ffU) << 8) | \ + (((unsigned short)(x) & (unsigned short)0xff00U) >> 8) )) + +#define swab32(x) \ + ((unsigned int)( \ + (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \ + (((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) | \ + (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) | \ + (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) )) + +void convert_elf_hdr (Elf32_Ehdr *e) +{ + e->e_type = swab16(e->e_type); + e->e_machine = swab16(e->e_machine); + e->e_version = swab32(e->e_version); + e->e_entry = swab32(e->e_entry); + e->e_phoff = swab32(e->e_phoff); + e->e_shoff = swab32(e->e_shoff); + e->e_flags = swab32(e->e_flags); + e->e_ehsize = swab16(e->e_ehsize); + e->e_phentsize = swab16(e->e_phentsize); + e->e_phnum = swab16(e->e_phnum); + e->e_shentsize = swab16(e->e_shentsize); + e->e_shnum = swab16(e->e_shnum); + e->e_shstrndx = swab16(e->e_shstrndx); +} + +void convert_elf_phdrs (Elf32_Phdr *p, int num) +{ + int i; + + for (i = 0; i < num; i++,p++) { + p->p_type = swab32(p->p_type); + p->p_offset = swab32(p->p_offset); + p->p_vaddr = swab32(p->p_vaddr); + p->p_paddr = swab32(p->p_paddr); + p->p_filesz = swab32(p->p_filesz); + p->p_memsz = swab32(p->p_memsz); + p->p_flags = swab32(p->p_flags); + p->p_align = swab32(p->p_align); + } + +} + +void convert_elf_shdrs (Elf32_Shdr *s, int num) +{ + int i; + + for (i = 0; i < num; i++,s++) { + s->sh_name = swab32(s->sh_name); + s->sh_type = swab32(s->sh_type); + s->sh_flags = swab32(s->sh_flags); + s->sh_addr = swab32(s->sh_addr); + s->sh_offset = swab32(s->sh_offset); + s->sh_size = swab32(s->sh_size); + s->sh_link = swab32(s->sh_link); + s->sh_info = swab32(s->sh_info); + s->sh_addralign = swab32(s->sh_addralign); + s->sh_entsize = swab32(s->sh_entsize); + } +} + +void convert_ecoff_filehdr(struct filehdr *f) +{ + f->f_magic = swab16(f->f_magic); + f->f_nscns = swab16(f->f_nscns); + f->f_timdat = swab32(f->f_timdat); + f->f_symptr = swab32(f->f_symptr); + f->f_nsyms = swab32(f->f_nsyms); + f->f_opthdr = swab16(f->f_opthdr); + f->f_flags = swab16(f->f_flags); +} + +void convert_ecoff_aouthdr(struct aouthdr *a) +{ + a->magic = swab16(a->magic); + a->vstamp = swab16(a->vstamp); + a->tsize = swab32(a->tsize); + a->dsize = swab32(a->dsize); + a->bsize = swab32(a->bsize); + a->entry = swab32(a->entry); + a->text_start = swab32(a->text_start); + a->data_start = swab32(a->data_start); + a->bss_start = swab32(a->bss_start); + a->gprmask = swab32(a->gprmask); + a->cprmask[0] = swab32(a->cprmask[0]); + a->cprmask[1] = swab32(a->cprmask[1]); + a->cprmask[2] = swab32(a->cprmask[2]); + a->cprmask[3] = swab32(a->cprmask[3]); + a->gp_value = swab32(a->gp_value); +} + +void convert_ecoff_esecs(struct scnhdr *s, int num) +{ + int i; + + for (i = 0; i < num; i++, s++) { + s->s_paddr = swab32(s->s_paddr); + s->s_vaddr = swab32(s->s_vaddr); + s->s_size = swab32(s->s_size); + s->s_scnptr = swab32(s->s_scnptr); + s->s_relptr = swab32(s->s_relptr); + s->s_lnnoptr = swab32(s->s_lnnoptr); + s->s_nreloc = swab16(s->s_nreloc); + s->s_nlnno = swab16(s->s_nlnno); + s->s_flags = swab32(s->s_flags); + } +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/config.in linux.pre11.3/arch/mips/config.in --- linux.vanilla/arch/mips/config.in Tue Feb 23 14:21:32 1999 +++ linux.pre11.3/arch/mips/config.in Mon Jul 19 23:28:36 1999 @@ -14,6 +14,8 @@ bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool 'Support for Algorithmics P4032' CONFIG_ALGOR_P4032 + bool 'Support for BAGET MIPS series' CONFIG_BAGET_MIPS + bool 'Support for DECstations' CONFIG_DECSTATION fi bool 'Support for Mips Magnum 4000' CONFIG_MIPS_MAGNUM_4000 bool 'Support for Olivetti M700-10' CONFIG_OLIVETTI_M700 @@ -33,14 +35,13 @@ if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \ "$CONFIG_OLIVETTI_M700" = "y" ]; then define_bool CONFIG_MIPS_JAZZ y - define_bool CONFIG_VIDEO_G364 y - define_bool CONFIG_VGA_CONSOLE y + define_bool CONFIG_FB y + define_bool CONFIG_FB_G364 y fi if [ "$CONFIG_ACER_PICA_61" = "y" ]; then define_bool CONFIG_MIPS_JAZZ y fi if [ "$CONFIG_SNI_RM200_PCI" = "y" ]; then - define_bool CONFIG_VGA_CONSOLE y define_bool CONFIG_PCI y fi endmenu @@ -61,14 +62,23 @@ mainmenu_option next_comment comment 'General setup' + +if [ "$CONFIG_PCI" = "y" ]; then + bool ' PCI quirks' CONFIG_PCI_QUIRKS + if [ "$CONFIG_PCI_QUIRKS" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool ' PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE + fi + bool ' Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC +fi + if [ "$CONFIG_DECSTATION" = "y" ]; then - bool 'Compile the kernel into the ECOFF object format' CONFIG_ECOFF_KERNEL define_bool CONFIG_CPU_LITTLE_ENDIAN y else - define_bool CONFIG_ELF_KERNEL y bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN fi +define_bool CONFIG_ELF_KERNEL y + if [ "$CONFIG_CPU_LITTLE_ENDIAN" = "n" ]; then define_bool CONFIG_BINFMT_IRIX y define_bool CONFIG_FORWARD_KEYBOARD y @@ -77,7 +87,6 @@ define_bool CONFIG_BINFMT_ELF y tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC tristate 'Kernel support for JAVA binaries (obsolete)' CONFIG_BINFMT_JAVA fi @@ -86,7 +95,7 @@ bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL -if [ "$CONFIG_SGI" != "y" ]; then +if [ "$CONFIG_SGI" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "y" ]; then tristate 'Parallel port support' CONFIG_PARPORT fi endmenu @@ -105,6 +114,16 @@ endmenu +if [ "$CONFIG_DECSTATION" = "y" ]; then + mainmenu_option next_comment + comment 'TURBOchannel support' + bool 'TURBOchannel support' CONFIG_TC +# if [ "$CONFIG_TC" = "y" ]; then +# tristate 'MAGMA Parallel port support' CONFIG_PARPORT +# fi + endmenu +fi + source drivers/block/Config.in if [ "$CONFIG_NET" = "y" ]; then @@ -117,7 +136,7 @@ tristate 'SCSI support' CONFIG_SCSI if [ "$CONFIG_SCSI" != "n" ]; then - if [ "$CONFIG_SGI" = "y" ]; then + if [ "$CONFIG_SGI" = "y" -o "$CONFIG_DECSTATION" = "y" ]; then comment 'SCSI support type (disk, tape, CDrom)' dep_tristate 'SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI @@ -133,9 +152,15 @@ #mainmenu_option next_comment comment 'SCSI low-level drivers' - + if [ "$CONFIG_SGI" = "y" ]; then dep_tristate 'SGI wd93 Scsi Driver' CONFIG_SCSI_SGIWD93 $CONFIG_SCSI else + if [ "$CONFIG_TC" = "y" ]; then + dep_tristate 'DEC NCR53C94 Scsi Driver' CONFIG_SCSI_DECNCR $CONFIG_SCSI + fi + dep_tristate 'DEC SII Scsi Driver' CONFIG_SCSI_DECSII $CONFIG_SCSI + fi + else source drivers/scsi/Config.in fi fi @@ -147,7 +172,7 @@ bool 'Network device support' CONFIG_NETDEVICES if [ "$CONFIG_NETDEVICES" = "y" ]; then - if [ "$CONFIG_SGI" != "y" ]; then + if [ "$CONFIG_SGI" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "y" ]; then source drivers/net/Config.in else tristate 'Dummy net driver support' CONFIG_DUMMY @@ -160,52 +185,113 @@ if [ ! "$CONFIG_PPP" = "n" ]; then comment 'CCP compressors for PPP are only built as modules.' fi + if [ "$CONFIG_SGI" = "y" ]; then bool 'SGI Seeq ethernet controller support' CONFIG_SGISEEQ fi + if [ "$CONFIG_DECSTATION" = "y" ]; then + bool 'DEC LANCE ethernet controller support' CONFIG_DECLANCE + fi + if [ "$CONFIG_BAGET_MIPS" = "y" ]; then + tristate 'Baget AMD LANCE support' CONFIG_BAGETLANCE + tristate 'Baget Backplane Shared Memory support' CONFIG_BAGETBSM + fi + fi fi endmenu fi -if [ "$CONFIG_SGI" != "y" ]; then - source drivers/net/hamradio/Config.in +if [ "$CONFIG_SGI" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "y" ]; then + source drivers/net/hamradio/Config.in - mainmenu_option next_comment - comment 'ISDN subsystem' - tristate 'ISDN support' CONFIG_ISDN - if [ "$CONFIG_ISDN" != "n" ]; then - source drivers/isdn/Config.in - fi - endmenu + mainmenu_option next_comment + comment 'ISDN subsystem' - mainmenu_option next_comment - comment 'Old CD-ROM drivers (not SCSI, not IDE)' + if [ "$CONFIG_NET" != "n" ]; then + tristate 'ISDN support' CONFIG_ISDN + if [ "$CONFIG_ISDN" != "n" ]; then + source drivers/isdn/Config.in + fi + fi + endmenu - bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI - if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then - source drivers/cdrom/Config.in - fi - endmenu + + mainmenu_option next_comment + comment comment 'Old CD-ROM drivers (not SCSI, not IDE)' + + bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI + if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then + source drivers/cdrom/Config.in + fi + endmenu +fi + +if [ "$CONFIG_DECSTATION" != "y" ]; then + source drivers/char/Config.in +else + mainmenu_option next_comment + comment 'DECstation Character devices' + + bool 'Virtual terminal' CONFIG_VT + if [ "$CONFIG_VT" = "y" ]; then + bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE + fi + tristate 'Standard/generic (dumb) serial support' CONFIG_SERIAL + if [ "$CONFIG_SGI" = "y" ]; then + bool 'SGI PROM Console Support' CONFIG_SGI_PROM_CONSOLE + fi + if [ "$CONFIG_SERIAL" = "y" ]; then + bool 'DZ11 Serial Support' CONFIG_DZ + if [ "$CONFIG_TC" = "y" ]; then + bool 'Z85C30 Serial Support' CONFIG_ZS + fi + bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE + fi + bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS + if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then + int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 + fi + bool 'Keyboard Support' CONFIG_KEYBOARD + bool 'Mouse Support' CONFIG_MOUSE +# bool 'Enhanced Real Time Clock Support' CONFIG_RTC + endmenu fi -source drivers/char/Config.in +# source drivers/usb/Config.in source fs/Config.in -comment 'Console drivers' -source drivers/video/Config.in +if [ "$CONFIG_VT" = "y" ]; then + mainmenu_option next_comment + comment 'Console drivers' + if [ "$CONFIG_SGI" = "y" ]; then + tristate 'SGI Newport Console support' CONFIG_SGI_NEWPORT_CONSOLE + if [ "$CONFIG_SGI_NEWPORT_CONSOLE" != "y" ]; then + define_bool CONFIG_DUMMY_CONSOLE y + fi + else + if [ "$CONFIG_DECSTATION" != "y" ]; then + bool 'VGA text console' CONFIG_VGA_CONSOLE + fi + bool 'Support for frame buffer devices' CONFIG_FB + source drivers/video/Config.in + fi + endmenu +fi -mainmenu_option next_comment -comment 'Sound' +if [ "$CONFIG_DECSTATION" != "y" ]; then + mainmenu_option next_comment + comment 'Sound' -tristate 'Sound card support' CONFIG_SOUND -if [ "$CONFIG_SOUND" != "n" ]; then + tristate 'Sound card support' CONFIG_SOUND + if [ "$CONFIG_SOUND" != "n" ]; then source drivers/sound/Config.in + fi + endmenu fi -endmenu if [ "$CONFIG_SGI" = "y" ]; then - source drivers/sgi/char/Config.in + source drivers/sgi/Config.in fi mainmenu_option next_comment @@ -216,6 +302,8 @@ if [ "$CONFIG_MODULES" = "y" ]; then bool ' Build fp execption handler module' CONFIG_MIPS_FPE_MODULE fi -bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG +if [ "$CONFIG_SERIAL" = "y" ]; then + bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG +fi bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ endmenu diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/Makefile linux.pre11.3/arch/mips/dec/Makefile --- linux.vanilla/arch/mips/dec/Makefile Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/dec/Makefile Mon Jul 19 23:28:46 1999 @@ -0,0 +1,30 @@ +# +# Makefile for the DECstation family specific parts of the kernel +# +# 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). +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +all: dec.o +O_TARGET := dec.o +O_OBJS := int-handler.o setup.o irq.o time.o reset.o rtc-dec.o wbflush.o + +ifdef CONFIG_PROM_CONSOLE +O_OBJS += promcon.o +endif + +ifdef CONFIG_SERIAL +O_OBJS += serial.o +endif + +int-handler.o: int-handler.S + +clean: + +include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/boot/Makefile linux.pre11.3/arch/mips/dec/boot/Makefile --- linux.vanilla/arch/mips/dec/boot/Makefile Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/dec/boot/Makefile Mon Jul 19 23:28:46 1999 @@ -0,0 +1,26 @@ +# +# Makefile for the DECstation family specific parts of the kernel +# +# 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). +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +netboot: all + mipsel-linux-ld -N -G 0 -T ld.ecoff ../../boot/zImage \ + dec_boot.o ramdisk.img -o nbImage + +all: dec_boot.o + +O_TARGET := dec_boot.o +O_OBJS := decstation.o + +clean: + rm -f nbImage + +include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/boot/decstation.c linux.pre11.3/arch/mips/dec/boot/decstation.c --- linux.vanilla/arch/mips/dec/boot/decstation.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/dec/boot/decstation.c Mon Jul 19 23:28:46 1999 @@ -0,0 +1,91 @@ +/* + * arch/mips/dec/decstation.c + */ +#include + +#define RELOC +#define INITRD +#define DEBUG_BOOT + +/* + * Magic number indicating REX PROM available on DECSTATION. + */ +#define REX_PROM_MAGIC 0x30464354 + +#define REX_PROM_CLEARCACHE 0x7c/4 +#define REX_PROM_PRINTF 0x30/4 + +#define VEC_RESET 0xBFC00000 /* Prom base address */ +#define PMAX_PROM_ENTRY(x) (VEC_RESET+((x)*8)) /* Prom jump table */ +#define PMAX_PROM_PRINTF PMAX_PROM_ENTRY(17) + +#define PARAM (k_start + 0x2000) + +#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210)) +#define INITRD_START (*(unsigned long *) (PARAM+0x218)) +#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c)) + +extern int _ftext, _end; /* begin and end of kernel image */ +extern void *__rd_start, *__rd_end; /* begin and end of ramdisk image */ +extern void kernel_entry(int, char **, unsigned long, int *); + +void * memcpy(void * dest, const void *src, unsigned int count) +{ + unsigned long *tmp = (unsigned long *) dest, *s = (unsigned long *) src; + + count >>= 2; + while (count--) + *tmp++ = *s++; + + return dest; +} + +void dec_entry(int argc, char **argv, + unsigned long magic, int *prom_vec) +{ + void (*rex_clear_cache)(void); + int (*prom_printf)(char *, ...); + unsigned long k_start, len; + + /* + * The DS5100 leaves cpu with BEV enabled, clear it. + */ + asm( "lui\t$8,0x3000\n\t" + "mtc0\t$8,$12\n\t" + ".section\t.sdata\n\t" + ".section\t.sbss\n\t" + ".section\t.text" + : : : "$8"); + +#ifdef DEBUG_BOOT + if (magic == REX_PROM_MAGIC) { + prom_printf = (int (*)(char *, ...)) *(prom_vec + REX_PROM_PRINTF); + } else { + prom_printf = (int (*)(char *, ...)) PMAX_PROM_PRINTF; + } + prom_printf("Launching kernel...\n"); +#endif + + k_start = (unsigned long) (&kernel_entry) & 0xffff0000; + +#ifdef RELOC + /* + * Now copy kernel image to it's destination. + */ + len = ((unsigned long) (&_end) - k_start); + memcpy((void *)k_start, &_ftext, len); +#endif + + if (magic == REX_PROM_MAGIC) { + rex_clear_cache = (void (*)(void)) * (prom_vec + REX_PROM_CLEARCACHE); + rex_clear_cache(); + } + +#ifdef CONFIG_BLK_DEV_INITRD + LOADER_TYPE = 1; + INITRD_START = (long)&__rd_start; + INITRD_SIZE = (long)&__rd_end - (long)&__rd_start; +#endif + + kernel_entry(argc, argv, magic, prom_vec); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/boot/ld.ecoff linux.pre11.3/arch/mips/dec/boot/ld.ecoff --- linux.vanilla/arch/mips/dec/boot/ld.ecoff Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/dec/boot/ld.ecoff Mon Jul 19 23:28:46 1999 @@ -0,0 +1,43 @@ +OUTPUT_FORMAT("ecoff-littlemips") +OUTPUT_ARCH(mips) +ENTRY(dec_entry) +SECTIONS +{ + . = 0x80200000; + + .text : + { + _ftext = .; + *(.text) + *(.fixup) + } + .rdata : + { + *(.rodata .rdata) + } + .data : + { + . = ALIGN(0x1000); + ramdisk.img (.data) + *(.data) + } + .sdata : + { + *(.sdata) + } + _gp = .; + .sbss : + { + *(.sbss) + *(.scommon) + } + .bss : + { + *(.dynbss) + *(.bss) + *(COMMON) + } + /DISCARD/ : { + *(.reginfo .mdebug .note) + } +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/int-handler.S linux.pre11.3/arch/mips/dec/int-handler.S --- linux.vanilla/arch/mips/dec/int-handler.S Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/dec/int-handler.S Mon Jul 19 23:28:46 1999 @@ -0,0 +1,362 @@ +/* + * arch/mips/dec/int-handler.S + * + * Copyright (C) 1995, 1996, 1997 Paul M. Antoine and Harald Koerfgen + * + * Written by Ralf Baechle and Andreas Busse, modified for DECStation + * support by Paul Antoine and Harald Koerfgen. + * + * completly rewritten: + * Copyright (C) 1998 Harald Koerfgen + * + */ +#include +#include +#include +#include +#include + +#include + + + .text + .set noreorder +/* + * decstation_handle_int: Interrupt handler for DECStations + * + * FIXME: Detection of spurious interrupts not yet implemented! + * + * We follow the model in the Indy interrupt code by David Miller, where he + * says: a lot of complication here is taken away because: + * + * 1) We handle one interrupt and return, sitting in a loop + * and moving across all the pending IRQ bits in the cause + * register is _NOT_ the answer, the common case is one + * pending IRQ so optimize in that direction. + * + * 2) We need not check against bits in the status register + * IRQ mask, that would make this routine slow as hell. + * + * 3) Linux only thinks in terms of all IRQs on or all IRQs + * off, nothing in between like BSD spl() brain-damage. + * + * Furthermore, the IRQs on the DECStations look basically (barring + * software IRQs which we don't use at all) like... + * + * DS2100/3100's, aka kn01, aka Pmax: + * + * MIPS IRQ Source + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 SCSI + * 3 Lance Ethernet + * 4 DZ11 serial + * 5 RTC + * 6 Memory Controller + * 7 FPU + * + * DS5000/200, aka kn02, aka 3max: + * + * MIPS IRQ Source + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 TurboChannel + * 3 RTC + * 4 Reserved + * 5 Memory Controller + * 6 Reserved + * 7 FPU + * + * DS5000/1xx's, aka kn02ba, aka 3min: + * + * MIPS IRQ Source + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 TurboChannel Slot 0 + * 3 TurboChannel Slot 1 + * 4 TurboChannel Slot 2 + * 5 TurboChannel Slot 3 (ASIC) + * 6 Halt button + * 7 FPU + * + * DS5000/2x's, aka kn02ca, aka maxine: + * + * MIPS IRQ Source + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 Periodic Interrupt (100usec) + * 3 RTC + * 4 I/O write timeout + * 5 TurboChannel (ASIC) + * 6 Halt Keycode from Access.Bus keyboard (CTRL-ALT-ENTER) + * 7 FPU + * + * DS5000/2xx's, aka kn03, aka 3maxplus: + * + * MIPS IRQ Source + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 System Board (ASIC) + * 3 RTC + * 4 Reserved + * 5 Memory + * 6 Halt Button + * 7 FPU + * + * We handle the IRQ according to _our_ priority. + * Priority is: + * + * Highest ---- RTC + * SCSI (if separate from TC) + * Ethernet (if separate from TC) + * Serial (if separate from TC) + * TurboChannel (if there is one!) + * Memory Controller (execept kmin) + * Lowest ---- Halt (if there is one!) + * + * then we just return, if multiple IRQs are pending then we will just take + * another exception, big deal. + * + */ + .align 5 + NESTED(decstation_handle_int, PT_SIZE, ra) + .set noat + SAVE_ALL + CLI # TEST: interrupts should be off + .set at + .set noreorder + + /* + * Get pending Interrupts + */ + mfc0 t0,CP0_CAUSE # get pending interrupts + mfc0 t2,CP0_STATUS + la t1,cpu_mask_tbl + and t0,t2 # isolate allowed ones + + /* insert detection of spurious interrupts here */ + + /* + * Find irq with highest priority + */ +1: lw t2,(t1) + move t3,t0 + and t3,t2 + beq t3,zero,1b + addu t1,PTRSIZE # delay slot + + /* + * Do the low-level stuff + */ + lw a0,%lo(cpu_irq_nr-cpu_mask_tbl-PTRSIZE)(t1) + lw t0,%lo(cpu_ivec_tbl-cpu_mask_tbl-PTRSIZE)(t1) + bgez a0, handle_it # irq_nr >= 0? + # irq_nr < 0: a0 contains an address + nop + jr t0 + nop # delay slot + +/* + * Handle "IRQ Controller" Interrupts + * Masked Interrupts are still visible and have to be masked "by hand". + * %hi(KN02_CSR_ADDR) does not work so all addresses are hardcoded :-(. + */ + EXPORT(kn02_io_int) +kn02_io_int: lui t0,0xbff0 # get interrupt status and mask + lw t0,(t0) + la t1,asic_mask_tbl + move t3,t0 + sll t3,16 # shift interrupt status + b find_int + and t0,t3 # mask out allowed ones + + EXPORT(kn03_io_int) +kn03_io_int: lui t2,0xbf84 # upper part of IOASIC Address + lw t0,0x0110(t2) # get status: IOASIC isr + lw t3,0x0120(t2) # get mask: IOASIC isrm + la t1,asic_mask_tbl + b find_int + and t0,t3 # mask out allowed ones + + EXPORT(kn02ba_io_int) +kn02ba_io_int: lui t2,0xbc04 + lw t0,0x0110(t2) # IOASIC isr, works for maxine also + lw t3,0x0120(t2) # IOASIC isrm + la t1,asic_mask_tbl + and t0,t3 + + /* + * Find irq with highest priority + */ +find_int: lw t2,(t1) + move t3,t0 + and t3,t2 + beq zero,t3,find_int + addu t1,PTRSIZE # delay slot + + /* + * Do the low-level stuff + */ + lw a0,%lo(asic_irq_nr-asic_mask_tbl-PTRSIZE)(t1) + nop + +handle_it: jal do_IRQ + move a1,sp + j ret_from_irq + nop + + END(decstation_handle_int) +/* + * Interrupt routines common to all DECStations first. + */ + EXPORT(dec_intr_fpu) +dec_intr_fpu: PANIC("Unimplemented FPU interrupt handler") + +/* + * Halt interrupt + */ + EXPORT(intr_halt) +intr_halt: la k0,0xbc000000 + jr k0 + nop + +/* + * Generic unimplemented interrupt routines - ivec_tbl is initialised to + * point all interrupts here. The table is then filled in by machine-specific + * initialisation in dec_setup(). + */ + EXPORT(dec_intr_unimplemented) +dec_intr_unimplemented: + mfc0 a1,CP0_CAUSE # cheats way of printing an arg! + nop # to be sure... + PANIC("Unimplemented cpu interrupt! CP0_CAUSE: 0x%x"); + + EXPORT(asic_intr_unimplemented) +asic_intr_unimplemented: + move a1,t0 # cheats way of printing an arg! + PANIC("Unimplemented asic interrupt! ASIC ISR: 0x%x"); + +/* + * FIXME: This interrupt vector table is experimental. It is initialised with + * *_intr_unimplemented and filled in with the addresses of + * machine-specific interrupt routines in dec_setup() Paul 10/5/97. + * + * The mask_tbls contain the interrupt masks which are used. It is + * initialised with all possible interrupt status bits set, so that + * unused Interrupts are catched. Harald + */ + .data + EXPORT(cpu_mask_tbl) +cpu_mask_tbl: + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 # these two are unlikely + .word 0x00000000 # to be used + .word 0x0000ff00 # End of list + + EXPORT(cpu_irq_nr) +cpu_irq_nr: + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 # these two are unlikely + .word 0x00000000 # to be used + .word 0x00ffffff # End of list + + EXPORT(cpu_ivec_tbl) +cpu_ivec_tbl: + PTR dec_intr_unimplemented + PTR dec_intr_unimplemented + PTR dec_intr_unimplemented + PTR dec_intr_unimplemented + PTR dec_intr_unimplemented + PTR dec_intr_unimplemented + PTR dec_intr_unimplemented # these two are unlikely + PTR dec_intr_unimplemented # to be used + PTR dec_intr_unimplemented # EOL + + EXPORT(asic_mask_tbl) +asic_mask_tbl: + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0xffffffff # EOL + + EXPORT(asic_irq_nr) +asic_irq_nr: + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0xffffffff # EOL + + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/irq.c linux.pre11.3/arch/mips/dec/irq.c --- linux.vanilla/arch/mips/dec/irq.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/dec/irq.c Mon Jul 19 23:28:46 1999 @@ -0,0 +1,269 @@ +/* + * Code to handle DECstation IRQs plus some generic interrupt stuff. + * + * Copyright (C) 1992 Linus Torvalds + * Copyright (C) 1994, 1995, 1996, 1997 Ralf Baechle + * + * $Id: irq.c,v 1.3 1999/04/11 17:06:16 harald Exp $ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +extern volatile unsigned int *isr; /* address of the interrupt status register */ +extern volatile unsigned int *imr; /* address of the interrupt mask register */ +extern decint_t dec_interrupt[NR_INTS]; + +unsigned int local_bh_count[NR_CPUS]; +unsigned int local_irq_count[NR_CPUS]; +unsigned long spurious_count = 0; + +static inline void mask_irq(unsigned int irq_nr) +{ + unsigned int dummy; + + if (dec_interrupt[irq_nr].iemask) { /* This is an ASIC interrupt */ + *imr &= ~dec_interrupt[irq_nr].iemask; + dummy = *imr; + dummy = *imr; + } else /* This is a cpu interrupt */ + set_cp0_status(ST0_IM, read_32bit_cp0_register(CP0_STATUS) & ~dec_interrupt[irq_nr].cpu_mask); +} + +static inline void unmask_irq(unsigned int irq_nr) +{ + unsigned int dummy; + + if (dec_interrupt[irq_nr].iemask) { /* This is an ASIC interrupt */ + *imr |= dec_interrupt[irq_nr].iemask; + dummy = *imr; + dummy = *imr; + } + set_cp0_status(ST0_IM, read_32bit_cp0_register(CP0_STATUS) | dec_interrupt[irq_nr].cpu_mask); +} + +void disable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + save_and_cli(flags); + mask_irq(irq_nr); + restore_flags(flags); +} + +void enable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + save_and_cli(flags); + unmask_irq(irq_nr); + restore_flags(flags); +} + +/* + * Pointers to the low-level handlers: first the general ones, then the + * fast ones, then the bad ones. + */ +extern void interrupt(void); + +static struct irqaction *irq_action[32] = +{ + 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, NULL, NULL, NULL, NULL +}; + +int get_irq_list(char *buf) +{ + int i, len = 0; + struct irqaction *action; + + for (i = 0; i < 32; i++) { + action = irq_action[i]; + if (!action) + continue; + len += sprintf(buf + len, "%2d: %8d %c %s", + i, kstat.irqs[0][i], + (action->flags & SA_INTERRUPT) ? '+' : ' ', + action->name); + for (action = action->next; action; action = action->next) { + len += sprintf(buf + len, ",%s %s", + (action->flags & SA_INTERRUPT) ? " +" : "", + action->name); + } + len += sprintf(buf + len, "\n"); + } + return len; +} + +atomic_t __mips_bh_counter; + +/* + * do_IRQ handles IRQ's that have been installed without the + * SA_INTERRUPT flag: it uses the full signal-handling return + * and runs with other interrupts enabled. All relatively slow + * IRQ's should use this format: notably the keyboard/timer + * routines. + */ +asmlinkage void do_IRQ(int irq, struct pt_regs *regs) +{ + struct irqaction *action; + int do_random, cpu; + + cpu = smp_processor_id(); + hardirq_enter(cpu); + kstat.irqs[cpu][irq]++; + + mask_irq(irq); + action = *(irq + irq_action); + if (action) { + if (!(action->flags & SA_INTERRUPT)) + __sti(); + action = *(irq + irq_action); + do_random = 0; + do { + do_random |= action->flags; + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + if (do_random & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + unmask_irq(irq); + __cli(); + } + hardirq_exit(cpu); + + /* unmasking and bottom half handling is done magically for us. */ +} + +/* + * Idea is to put all interrupts + * in a single table and differenciate them just by number. + */ +int setup_dec_irq(int irq, struct irqaction *new) +{ + int shared = 0; + struct irqaction *old, **p; + unsigned long flags; + + p = irq_action + irq; + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) + return -EBUSY; + + /* Can't share interrupts unless both are same type */ + if ((old->flags ^ new->flags) & SA_INTERRUPT) + return -EBUSY; + + /* add new interrupt at end of irq queue */ + do { + p = &old->next; + old = *p; + } while (old); + shared = 1; + } + if (new->flags & SA_SAMPLE_RANDOM) + rand_initialize_irq(irq); + + save_and_cli(flags); + *p = new; + + if (!shared) { + unmask_irq(irq); + } + restore_flags(flags); + return 0; +} + +int request_irq(unsigned int irq, + void (*handler) (int, void *, struct pt_regs *), + unsigned long irqflags, + const char *devname, + void *dev_id) +{ + int retval; + struct irqaction *action; + + if (irq >= 32) + return -EINVAL; + if (!handler) + return -EINVAL; + + action = (struct irqaction *) kmalloc(sizeof(struct irqaction), GFP_KERNEL); + if (!action) + return -ENOMEM; + + action->handler = handler; + action->flags = irqflags; + action->mask = 0; + action->name = devname; + action->next = NULL; + action->dev_id = dev_id; + + retval = setup_dec_irq(irq, action); + + if (retval) + kfree(action); + return retval; +} + +void free_irq(unsigned int irq, void *dev_id) +{ + struct irqaction *action, **p; + unsigned long flags; + + if (irq > 39) { + printk("Trying to free IRQ%d\n", irq); + return; + } + for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { + if (action->dev_id != dev_id) + continue; + + /* Found it - now free it */ + save_and_cli(flags); + *p = action->next; + if (!irq[irq_action]) + mask_irq(irq); + restore_flags(flags); + kfree(action); + return; + } + printk("Trying to free free IRQ%d\n", irq); +} + +unsigned long probe_irq_on(void) +{ + /* TODO */ + return 0; +} + +int probe_irq_off(unsigned long irqs) +{ + /* TODO */ + return 0; +} + +__initfunc(void init_IRQ(void)) +{ + irq_setup(); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/prom/Makefile linux.pre11.3/arch/mips/dec/prom/Makefile --- linux.vanilla/arch/mips/dec/prom/Makefile Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/dec/prom/Makefile Mon Jul 19 23:28:46 1999 @@ -0,0 +1,29 @@ +# $Id: $ +# Makefile for the DECstation prom monitor library routines +# under Linux. +# +# 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... + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +OBJS = init.o memory.o cmdline.o identify.o locore.o + +all: rexlib.a + +rexlib.a: $(OBJS) + $(AR) rcs rexlib.a $(OBJS) + sync + +locore.o: locore.S + +dep: + $(CPP) -M *.c > .depend + +include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/prom/cmdline.c linux.pre11.3/arch/mips/dec/prom/cmdline.c --- linux.vanilla/arch/mips/dec/prom/cmdline.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/dec/prom/cmdline.c Mon Jul 19 23:53:54 1999 @@ -0,0 +1,46 @@ +/* + * cmdline.c: read the command line passed to us by the PROM. + * + * Copyright (C) 1998 Harald Koerfgen + * + * $Id: $ + */ +#include +#include +#include + +#include + +#include "prom.h" + +#undef PROM_DEBUG + +#ifdef PROM_DEBUG +extern int (*prom_printf)(char *, ...); +#endif + +char arcs_cmdline[CL_SIZE]; + +__initfunc(void prom_init_cmdline(int argc, char **argv, unsigned long magic)) +{ + int start_arg, i; + + /* + * collect args and prepare cmd_line + */ + if (magic != REX_PROM_MAGIC) + start_arg = 1; + else + start_arg = 2; + for (i = start_arg; i < argc; i++) { + strcat(arcs_cmdline, argv[i]); + if (i < (argc - 1)) + strcat(arcs_cmdline, " "); + } + +#ifdef PROM_DEBUG + prom_printf("arcs_cmdline: %s\n", &(arcs_cmdline[0])); +#endif + +} + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/prom/dectypes.h linux.pre11.3/arch/mips/dec/prom/dectypes.h --- linux.vanilla/arch/mips/dec/prom/dectypes.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/dec/prom/dectypes.h Mon Jul 19 23:28:46 1999 @@ -0,0 +1,14 @@ +#ifndef DECTYPES +#define DECTYPES + +#define DS2100_3100 1 /* DS2100/3100 Pmax */ +#define DS5000_200 2 /* DS5000/200 3max */ +#define DS5000_1XX 3 /* DS5000/1xx kmin */ +#define DS5000_2X0 4 /* DS5000/2x0 3max+ */ +#define DS5800 5 /* DS5800 Isis */ +#define DS5400 6 /* DS5400 MIPSfair */ +#define DS5000_XX 7 /* DS5000/xx maxine */ +#define DS5500 11 /* DS5500 MIPSfair-2 */ +#define DS5100 12 /* DS5100 MIPSmate */ + +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/prom/identify.c linux.pre11.3/arch/mips/dec/prom/identify.c --- linux.vanilla/arch/mips/dec/prom/identify.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/dec/prom/identify.c Mon Jul 19 23:53:54 1999 @@ -0,0 +1,98 @@ +/* + * identify.c: machine identification code. + * + * Copyright (C) 1998 Harald Koerfgen and Paul M. Antoine + * + * $Id: $ + */ +#include +#include +#include + +#include + +#include "dectypes.h" +#include "prom.h" + +extern char *(*prom_getenv)(char *); +extern int (*prom_printf)(char *, ...); +extern int (*rex_getsysid)(void); + +extern unsigned long mips_machgroup; +extern unsigned long mips_machtype; + +__initfunc(void prom_identify_arch (unsigned int magic)) +{ + unsigned char dec_cpunum, dec_firmrev, dec_etc; + int dec_systype; + unsigned long dec_sysid; + + if (magic != REX_PROM_MAGIC) { + dec_sysid = simple_strtoul(prom_getenv("systype"), (char **)0, 0); + } else { + dec_sysid = rex_getsysid(); + if (dec_sysid == 0) { + prom_printf("Zero sysid returned from PROMs! Assuming PMAX-like machine.\n"); + dec_sysid = 1; + } + } + + dec_cpunum = (dec_sysid & 0xff000000) >> 24; + dec_systype = (dec_sysid & 0xff0000) >> 16; + dec_firmrev = (dec_sysid & 0xff00) >> 8; + dec_etc = dec_sysid & 0xff; + + /* We're obviously one of the DEC machines */ + mips_machgroup = MACH_GROUP_DEC; + + /* + * FIXME: This may not be an exhaustive list of DECStations/Servers! + * Put all model-specific initialisation calls here. + */ + prom_printf("This DECstation is a "); + + switch (dec_systype) { + case DS2100_3100: + prom_printf("DS2100/3100\n"); + mips_machtype = MACH_DS23100; + break; + case DS5100: /* DS5100 MIPSMATE */ + prom_printf("DS5100\n"); + mips_machtype = MACH_DS5100; + break; + case DS5000_200: /* DS5000 3max */ + prom_printf("DS5000/200\n"); + mips_machtype = MACH_DS5000_200; + break; + case DS5000_1XX: /* DS5000/100 3min */ + prom_printf("DS5000/1xx\n"); + mips_machtype = MACH_DS5000_1XX; + break; + case DS5000_2X0: /* DS5000/240 3max+ */ + prom_printf("DS5000/2x0\n"); + mips_machtype = MACH_DS5000_2X0; + break; + case DS5000_XX: /* Personal DS5000/2x */ + prom_printf("Personal DS5000/xx\n"); + mips_machtype = MACH_DS5000_XX; + break; + case DS5800: /* DS5800 Isis */ + prom_printf("DS5800\n"); + mips_machtype = MACH_DS5800; + break; + case DS5400: /* DS5400 MIPSfair */ + prom_printf("DS5400\n"); + mips_machtype = MACH_DS5400; + break; + case DS5500: /* DS5500 MIPSfair-2 */ + prom_printf("DS5500\n"); + mips_machtype = MACH_DS5500; + break; + default: + prom_printf("unknown, id is %x", dec_systype); + mips_machtype = MACH_DSUNKNOWN; + break; + } +} + + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/prom/init.c linux.pre11.3/arch/mips/dec/prom/init.c --- linux.vanilla/arch/mips/dec/prom/init.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/dec/prom/init.c Mon Jul 19 23:53:55 1999 @@ -0,0 +1,95 @@ +/* + * init.c: PROM library initialisation code. + * + * Copyright (C) 1998 Harald Koerfgen + * + * $Id: $ + */ +#include +#include "prom.h" + +/* + * PROM Interface (whichprom.c) + */ +typedef struct { + int pagesize; + unsigned char bitmap[0]; +} memmap; + +int (*rex_bootinit)(void); +int (*rex_bootread)(void); +int (*rex_getbitmap)(memmap *); +unsigned long *(*rex_slot_address)(int); +void *(*rex_gettcinfo)(void); +int (*rex_getsysid)(void); +void (*rex_clear_cache)(void); + +int (*prom_getchar)(void); +char *(*prom_getenv)(char *); +int (*prom_printf)(char *, ...); + +int (*pmax_open)(char*, int); +int (*pmax_lseek)(int, long, int); +int (*pmax_read)(int, void *, int); +int (*pmax_close)(int); + +extern void prom_meminit(unsigned int); +extern void prom_identify_arch(unsigned int); +extern void prom_init_cmdline(int, char **, unsigned long); + +/* + * Detect which PROM's the DECSTATION has, and set the callback vectors + * appropriately. + */ +__initfunc(void which_prom(unsigned long magic, int *prom_vec)) +{ + /* + * No sign of the REX PROM's magic number means we assume a non-REX + * machine (i.e. we're on a DS2100/3100, DS5100 or DS5000/2xx) + */ + if (magic == REX_PROM_MAGIC) + { + /* + * Set up prom abstraction structure with REX entry points. + */ + rex_bootinit = (int (*)(void)) *(prom_vec + REX_PROM_BOOTINIT); + rex_bootread = (int (*)(void)) *(prom_vec + REX_PROM_BOOTREAD); + rex_getbitmap = (int (*)(memmap *)) *(prom_vec + REX_PROM_GETBITMAP); + prom_getchar = (int (*)(void)) *(prom_vec + REX_PROM_GETCHAR); + prom_getenv = (char *(*)(char *)) *(prom_vec + REX_PROM_GETENV); + rex_getsysid = (int (*)(void)) *(prom_vec + REX_PROM_GETSYSID); + rex_gettcinfo = (void *(*)(void)) *(prom_vec + REX_PROM_GETTCINFO); + prom_printf = (int (*)(char *, ...)) *(prom_vec + REX_PROM_PRINTF); + rex_slot_address = (unsigned long *(*)(int)) *(prom_vec + REX_PROM_SLOTADDR); + rex_clear_cache = (void (*)(void)) * (prom_vec + REX_PROM_CLEARCACHE); + } + else + { + /* + * Set up prom abstraction structure with non-REX entry points. + */ + prom_getchar = (int (*)(void)) PMAX_PROM_GETCHAR; + prom_getenv = (char *(*)(char *)) PMAX_PROM_GETENV; + prom_printf = (int (*)(char *, ...)) PMAX_PROM_PRINTF; + pmax_open = (int (*)(char *, int)) PMAX_PROM_OPEN; + pmax_lseek = (int (*)(int, long, int)) PMAX_PROM_LSEEK; + pmax_read = (int (*)(int, void *, int)) PMAX_PROM_READ; + pmax_close = (int (*)(int)) PMAX_PROM_CLOSE; + } +} + +__initfunc(int prom_init(int argc, char **argv, + unsigned long magic, int *prom_vec)) +{ + /* Determine which PROM's we have (and therefore which machine we're on!) */ + which_prom(magic, prom_vec); + + if (magic == REX_PROM_MAGIC) + rex_clear_cache(); + + prom_meminit(magic); + prom_identify_arch(magic); + prom_init_cmdline(argc, argv, magic); + + return 0; +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/prom/locore.S linux.pre11.3/arch/mips/dec/prom/locore.S --- linux.vanilla/arch/mips/dec/prom/locore.S Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/dec/prom/locore.S Mon Jul 19 23:28:46 1999 @@ -0,0 +1,30 @@ +/* + * locore.S + */ +#include +#include +#include + + .text + +/* + * Simple general exception handling routine. This one is used for the + * Memory sizing routine for pmax machines. HK + */ + +NESTED(genexcept_early, 0, sp) + .set noat + .set noreorder + + mfc0 k0, CP0_STATUS + la k1, mem_err + + sw k0,0(k1) + + mfc0 k0, CP0_EPC + nop + addiu k0,4 # skip the causing instruction + jr k0 + rfe +END(genexcept_early) + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/prom/memory.c linux.pre11.3/arch/mips/dec/prom/memory.c --- linux.vanilla/arch/mips/dec/prom/memory.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/dec/prom/memory.c Mon Jul 19 23:53:55 1999 @@ -0,0 +1,103 @@ +/* + * memory.c: memory initialisation code. + * + * Copyright (C) 1998 Harald Koerfgen, Frieder Streffer and Paul M. Antoine + * + * $Id: $ + */ +#include +#include +#include +#include "prom.h" + +typedef struct { + int pagesize; + unsigned char bitmap[0]; +} memmap; + +extern int (*rex_getbitmap)(memmap *); + +#undef PROM_DEBUG + +#ifdef PROM_DEBUG +extern int (*prom_printf)(char *, ...); +#endif + +extern unsigned long mips_memory_upper; + +volatile unsigned long mem_err = 0; /* So we know an error occured */ + +/* + * Probe memory in 4MB chunks, waiting for an error to tell us we've fallen + * off the end of real memory. Only suitable for the 2100/3100's (PMAX). + */ + +#define CHUNK_SIZE 0x400000 + +__initfunc(unsigned long pmax_get_memory_size(void)) +{ + volatile unsigned char *memory_page, dummy; + char old_handler[0x80]; + extern char genexcept_early; + + /* Install exception handler */ + memcpy(&old_handler, (void *)(KSEG0 + 0x80), 0x80); + memcpy((void *)(KSEG0 + 0x80), &genexcept_early, 0x80); + + /* read unmapped and uncached (KSEG1) + * DECstations have at least 4MB RAM + * Assume less than 480MB of RAM, as this is max for 5000/2xx + * FIXME this should be replaced by the first free page! + */ + for (memory_page = (unsigned char *) KSEG1 + CHUNK_SIZE; + (mem_err== 0) && (memory_page < ((unsigned char *) KSEG1+0x1E000000)); + memory_page += CHUNK_SIZE) { + dummy = *memory_page; + } + memcpy((void *)(KSEG0 + 0x80), &old_handler, 0x80); + return (unsigned long)memory_page - KSEG1 - CHUNK_SIZE; +} + +/* + * Use the REX prom calls to get hold of the memory bitmap, and thence + * determine memory size. + */ +__initfunc(unsigned long rex_get_memory_size(void)) +{ + int i, bitmap_size; + unsigned long mem_size = 0; + memmap *bm; + + /* some free 64k */ + bm = (memmap *) 0x80028000; + + bitmap_size = rex_getbitmap(bm); + + for (i = 0; i < bitmap_size; i++) { + /* FIXME: very simplistically only add full sets of pages */ + if (bm->bitmap[i] == 0xff) + mem_size += (8 * bm->pagesize); + } + return (mem_size); +} + +__initfunc(void prom_meminit(unsigned int magic)) +{ + if (magic != REX_PROM_MAGIC) + mips_memory_upper = KSEG0 + pmax_get_memory_size(); + else + mips_memory_upper = KSEG0 + rex_get_memory_size(); + +#ifdef PROM_DEBUG + prom_printf("mips_memory_upper: 0x%08x\n", mips_memory_upper); +#endif +} + +/* Called from mem_init() to fixup the mem_map page settings. */ +__initfunc(void prom_fixup_mem_map(unsigned long start, unsigned long end)) +{ +} + +void prom_free_prom_memory (void) +{ +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/prom/prom.h linux.pre11.3/arch/mips/dec/prom/prom.h --- linux.vanilla/arch/mips/dec/prom/prom.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/dec/prom/prom.h Mon Jul 19 23:28:46 1999 @@ -0,0 +1,51 @@ +/* + * Miscellaneous definitions used to call the routines contained in the boot + * PROMs on various models of DECSTATION's. + * the rights to redistribute these changes. + */ + +#ifndef __ASM_DEC_PROM_H +#define __ASM_DEC_PROM_H + +/* + * PMAX/3MAX PROM entry points for DS2100/3100's and DS5000/2xx's. Many of + * these will work for MIPSen as well! + */ +#define VEC_RESET 0xBFC00000 /* Prom base address */ +#define PMAX_PROM_ENTRY(x) (VEC_RESET+((x)*8)) /* Prom jump table */ + +#define PMAX_PROM_HALT PMAX_PROM_ENTRY(2) /* valid on MIPSen */ +#define PMAX_PROM_AUTOBOOT PMAX_PROM_ENTRY(5) /* valid on MIPSen */ +#define PMAX_PROM_OPEN PMAX_PROM_ENTRY(6) +#define PMAX_PROM_READ PMAX_PROM_ENTRY(7) +#define PMAX_PROM_CLOSE PMAX_PROM_ENTRY(10) +#define PMAX_PROM_LSEEK PMAX_PROM_ENTRY(11) +#define PMAX_PROM_GETCHAR PMAX_PROM_ENTRY(12) +#define PMAX_PROM_PUTCHAR PMAX_PROM_ENTRY(13) /* 12 on MIPSen */ +#define PMAX_PROM_GETS PMAX_PROM_ENTRY(15) +#define PMAX_PROM_PRINTF PMAX_PROM_ENTRY(17) +#define PMAX_PROM_GETENV PMAX_PROM_ENTRY(33) /* valid on MIPSen */ + +/* + * Magic number indicating REX PROM available on DECSTATION. Found in + * register a2 on transfer of control to program from PROM. + */ +#define REX_PROM_MAGIC 0x30464354 + +/* + * 3MIN/MAXINE PROM entry points for DS5000/1xx's, DS5000/xx's, and + * DS5000/2x0. + */ +#define REX_PROM_GETBITMAP 0x84/4 /* get mem bitmap */ +#define REX_PROM_GETCHAR 0x24/4 /* getch() */ +#define REX_PROM_GETENV 0x64/4 /* get env. variable */ +#define REX_PROM_GETSYSID 0x80/4 /* get system id */ +#define REX_PROM_GETTCINFO 0xa4/4 +#define REX_PROM_PRINTF 0x30/4 /* printf() */ +#define REX_PROM_SLOTADDR 0x6c/4 /* slotaddr */ +#define REX_PROM_BOOTINIT 0x54/4 /* open() */ +#define REX_PROM_BOOTREAD 0x58/4 /* read() */ +#define REX_PROM_CLEARCACHE 0x7c/4 + +#endif /* __ASM_DEC_PROM_H */ + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/promcon.c linux.pre11.3/arch/mips/dec/promcon.c --- linux.vanilla/arch/mips/dec/promcon.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/dec/promcon.c Mon Jul 19 23:28:46 1999 @@ -0,0 +1,71 @@ +/* + * Wrap-around code for a console using the + * DECstation PROM io-routines. + * + * Copyright (c) 1998 Harald Koerfgen + */ + +#include +#include +#include +#include +#include +#include + +extern int (*prom_getchar) (void); +extern int (*prom_printf) (char *,...); + +static void prom_console_write(struct console *co, const char *s, + unsigned count) +{ + unsigned i; + + /* + * Now, do each character + */ + for (i = 0; i < count; i++) { + if (*s == 10) + prom_printf("%c", 13); + prom_printf("%c", *s++); + } +} + +static int prom_console_wait_key(struct console *co) +{ + return prom_getchar(); +} + +__initfunc(static int prom_console_setup(struct console *co, char *options)) +{ + return 0; +} + +static kdev_t prom_console_device(struct console *c) +{ + return MKDEV(TTY_MAJOR, 64 + c->index); +} + +static struct console sercons = +{ + "ttyS", + prom_console_write, + NULL, + prom_console_device, + prom_console_wait_key, + NULL, + prom_console_setup, + CON_PRINTBUFFER, + -1, + 0, + NULL +}; + +/* + * Register console. + */ + +__initfunc(long prom_console_init(long kmem_start, long kmem_end)) +{ + register_console(&sercons); + return kmem_start; +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/reset.c linux.pre11.3/arch/mips/dec/reset.c --- linux.vanilla/arch/mips/dec/reset.c Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/dec/reset.c Mon Jul 19 23:28:46 1999 @@ -0,0 +1,25 @@ +/* + * $Id: reset.c,v 1.4 1999/04/11 17:06:16 harald Exp $ + * + * Reset a DECstation machine. + * + */ + +void (*back_to_prom)(void) = (void (*)(void))0xBFC00000; + +void dec_machine_restart(char *command) +{ + back_to_prom(); +} + +void dec_machine_halt(void) +{ + back_to_prom(); +} + +void dec_machine_power_off(void) +{ + /* DECstations don't have a software power switch */ + back_to_prom(); +} + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/rtc-dec.c linux.pre11.3/arch/mips/dec/rtc-dec.c --- linux.vanilla/arch/mips/dec/rtc-dec.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/dec/rtc-dec.c Mon Jul 19 23:28:46 1999 @@ -0,0 +1,36 @@ + +/* $Id: rtc-jazz.c,v 1.2 1998/06/25 20:19:14 ralf Exp $ + + * 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. + * + * RTC routines for DECstation style attached Dallas chip. + * + * Copyright (C) 1998 by Ralf Baechle, Harald Koerfgen + */ +#include + +extern char *dec_rtc_base; + +static unsigned char dec_rtc_read_data(unsigned long addr) +{ + return (dec_rtc_base[addr * 4]); +} + +static void dec_rtc_write_data(unsigned char data, unsigned long addr) +{ + dec_rtc_base[addr * 4] = data; +} + +static int dec_rtc_bcd_mode(void) +{ + return 0; +} + +struct rtc_ops dec_rtc_ops = +{ + &dec_rtc_read_data, + &dec_rtc_write_data, + &dec_rtc_bcd_mode +}; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/serial.c linux.pre11.3/arch/mips/dec/serial.c --- linux.vanilla/arch/mips/dec/serial.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/dec/serial.c Mon Jul 19 23:53:55 1999 @@ -0,0 +1,98 @@ +/* + * sercons.c + * choose the right serial device at boot time + * + * triemer 6-SEP-1998 + * sercons.c is designed to allow the three different kinds + * of serial devices under the decstation world to co-exist + * in the same kernel. The idea here is to abstract + * the pieces of the drivers that are common to this file + * so that they do not clash at compile time and runtime. + * + * HK 16-SEP-1998 v0.002 + * removed the PROM console as this is not a real serial + * device. Added support for PROM console in drivers/char/tty_io.c + * instead. Although it may work to enable more than one + * console device I strongly recommend to use only one. + */ + +#include +#include +#include + +#ifdef CONFIG_ZS +extern int zs_init(void); +#endif + +#ifdef CONFIG_DZ +extern int dz_init(void); +#endif + +#ifdef CONFIG_SERIAL_CONSOLE + +#ifdef CONFIG_ZS +extern long zs_serial_console_init(long, long); +#endif + +#ifdef CONFIG_DZ +extern long dz_serial_console_init(long, long); +#endif + +#endif + +/* rs_init - starts up the serial interface - + handle normal case of starting up the serial interface */ + +#ifdef CONFIG_SERIAL + +__initfunc(int rs_init(void)) +{ + +#if defined(CONFIG_ZS) && defined(CONFIG_DZ) + if (IOASIC) + return zs_init(); + else + return dz_init(); +#else + +#ifdef CONFIG_ZS + return zs_init(); +#endif + +#ifdef CONFIG_DZ + return dz_init(); +#endif + +#endif +} + +#endif + +#ifdef CONFIG_SERIAL_CONSOLE + +/* serial_console_init handles the special case of starting + * up the console on the serial port + */ +__initfunc(long serial_console_init(long kmem_start, long kmem_end)) +{ +#if defined(CONFIG_ZS) && defined(CONFIG_DZ) + if (IOASIC) + kmem_start = zs_serial_console_init(kmem_start, kmem_end); + else + kmem_start = dz_serial_console_init(kmem_start, kmem_end); +#else + +#ifdef CONFIG_ZS + kmem_start = zs_serial_console_init(kmem_start, kmem_end); +#endif + +#ifdef CONFIG_DZ + kmem_start = dz_serial_console_init(kmem_start, kmem_end); +#endif + +#endif + + return kmem_start; +} + +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/setup.c linux.pre11.3/arch/mips/dec/setup.c --- linux.vanilla/arch/mips/dec/setup.c Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/dec/setup.c Mon Jul 19 23:28:46 1999 @@ -0,0 +1,503 @@ +/* + * Setup the interrupt stuff. + * + * 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. + * + * Copyright (C) 1998 Harald Koerfgen + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +extern asmlinkage void decstation_handle_int(void); + +void dec_init_kn01(void); +void dec_init_kn230(void); +void dec_init_kn02(void); +void dec_init_kn02ba(void); +void dec_init_kn02ca(void); +void dec_init_kn03(void); + +char *dec_rtc_base = (char *) KN01_RTC_BASE; /* Assume DS2100/3100 initially */ + +decint_t dec_interrupt[NR_INTS]; + +/* + * Information regarding the IRQ Controller + * + * isr and imr are also hardcoded for different machines in int_handler.S + */ + +volatile unsigned int *isr = 0L; /* address of the interrupt status register */ +volatile unsigned int *imr = 0L; /* address of the interrupt mask register */ + +extern void dec_machine_restart(char *command); +extern void dec_machine_halt(void); +extern void dec_machine_power_off(void); + +extern void wbflush_setup(void); + +extern struct rtc_ops dec_rtc_ops; + +extern void intr_halt(void); + +extern int setup_dec_irq(int, struct irqaction *); + +void (*board_time_init) (struct irqaction * irq); + +__initfunc(static void dec_irq_setup(void)) +{ + switch (mips_machtype) { + case MACH_DS23100: + dec_init_kn01(); + break; + case MACH_DS5100: /* DS5100 MIPSMATE */ + dec_init_kn230(); + break; + case MACH_DS5000_200: /* DS5000 3max */ + dec_init_kn02(); + break; + case MACH_DS5000_1XX: /* DS5000/100 3min */ + dec_init_kn02ba(); + break; + case MACH_DS5000_2X0: /* DS5000/240 3max+ */ + dec_init_kn03(); + break; + case MACH_DS5000_XX: /* Personal DS5000/2x */ + dec_init_kn02ca(); + break; + case MACH_DS5800: /* DS5800 Isis */ + panic("Don't know how to set this up!"); + break; + case MACH_DS5400: /* DS5400 MIPSfair */ + panic("Don't know how to set this up!"); + break; + case MACH_DS5500: /* DS5500 MIPSfair-2 */ + panic("Don't know how to set this up!"); + break; + } + set_except_vector(0, decstation_handle_int); +} + +/* + * enable the periodic interrupts + */ +__initfunc(static void dec_time_init(struct irqaction *irq)) +{ + /* + * Here we go, enable periodic rtc interrupts. + */ + +#ifndef LOG_2_HZ +# define LOG_2_HZ 7 +#endif + + CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - LOG_2_HZ), RTC_REG_A); + CMOS_WRITE(CMOS_READ(RTC_REG_B) | RTC_PIE, RTC_REG_B); + setup_dec_irq(CLOCK, irq); +} + +__initfunc(void decstation_setup(void)) +{ + irq_setup = dec_irq_setup; + board_time_init = dec_time_init; + + wbflush_setup(); + + _machine_restart = dec_machine_restart; + _machine_halt = dec_machine_halt; + _machine_power_off = dec_machine_power_off; + + rtc_ops = &dec_rtc_ops; +} + +/* + * Machine-specific initialisation for kn01, aka Pmax, aka DS2100, DS3100, + * and possibly also the DS5100. + */ +__initfunc(void dec_init_kn01(void)) +{ + /* + * Setup some memory addresses. + */ + dec_rtc_base = (char *) KN01_RTC_BASE; + + /* + * Setup interrupt structure + */ + dec_interrupt[CLOCK].cpu_mask = IE_IRQ3; + dec_interrupt[CLOCK].iemask = 0; + cpu_mask_tbl[0] = IE_IRQ3; + cpu_irq_nr[0] = CLOCK; + + dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ0; + dec_interrupt[SCSI_INT].iemask = 0; + cpu_mask_tbl[1] = IE_IRQ0; + cpu_irq_nr[1] = SCSI_INT; + + dec_interrupt[ETHER].cpu_mask = IE_IRQ1; + dec_interrupt[ETHER].iemask = 0; + cpu_mask_tbl[2] = IE_IRQ1; + cpu_irq_nr[2] = ETHER; + + dec_interrupt[SERIAL].cpu_mask = IE_IRQ2; + dec_interrupt[SERIAL].iemask = 0; + cpu_mask_tbl[3] = IE_IRQ2; + cpu_irq_nr[3] = SERIAL; + + dec_interrupt[MEMORY].cpu_mask = IE_IRQ4; + dec_interrupt[MEMORY].iemask = 0; + cpu_mask_tbl[4] = IE_IRQ4; + cpu_irq_nr[4] = MEMORY; + + dec_interrupt[FPU].cpu_mask = IE_IRQ5; + dec_interrupt[FPU].iemask = 0; + cpu_mask_tbl[5] = IE_IRQ5; + cpu_irq_nr[5] = FPU; +} /* dec_init_kn01 */ + +/* + * Machine-specific initialisation for kn230, aka MIPSmate, aka DS5100 + * + * There are a lot of experiments to do, this is definitely incomplete. + */ +__initfunc(void dec_init_kn230(void)) +{ + /* + * Setup some memory addresses. + */ + dec_rtc_base = (char *) KN01_RTC_BASE; + + /* + * Setup interrupt structure + */ + dec_interrupt[CLOCK].cpu_mask = IE_IRQ2; + dec_interrupt[CLOCK].iemask = 0; + cpu_mask_tbl[0] = IE_IRQ2; + cpu_irq_nr[0] = CLOCK; + + dec_interrupt[FPU].cpu_mask = IE_IRQ5; + dec_interrupt[FPU].iemask = 0; + cpu_mask_tbl[5] = IE_IRQ5; + cpu_irq_nr[5] = FPU; +} /* dec_init_kn230 */ + +/* + * Machine-specific initialisation for kn02, aka 3max, aka DS5000/2xx. + */ +__initfunc(void dec_init_kn02(void)) +{ + /* + * Setup some memory addresses. FIXME: probably incomplete! + */ + dec_rtc_base = (char *) KN02_RTC_BASE; + isr = (volatile unsigned int *) KN02_CSR_ADDR; + imr = (volatile unsigned int *) KN02_CSR_ADDR; + + /* + * Setup IOASIC interrupt + */ + cpu_ivec_tbl[1] = kn02_io_int; + cpu_mask_tbl[1] = IE_IRQ0; + cpu_irq_nr[1] = -1; + *imr = *imr & 0xff00ff00; + + /* + * Setup interrupt structure + */ + dec_interrupt[CLOCK].cpu_mask = IE_IRQ1; + dec_interrupt[CLOCK].iemask = 0; + cpu_mask_tbl[0] = IE_IRQ1; + cpu_irq_nr[0] = CLOCK; + + dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ0; + dec_interrupt[SCSI_INT].iemask = KN02_SLOT5; + asic_mask_tbl[0] = KN02_SLOT5; + asic_irq_nr[0] = SCSI_INT; + + dec_interrupt[ETHER].cpu_mask = IE_IRQ0; + dec_interrupt[ETHER].iemask = KN02_SLOT6; + asic_mask_tbl[1] = KN02_SLOT6; + asic_irq_nr[1] = ETHER; + + dec_interrupt[SERIAL].cpu_mask = IE_IRQ0; + dec_interrupt[SERIAL].iemask = KN02_SLOT7; + asic_mask_tbl[2] = KN02_SLOT7; + asic_irq_nr[2] = SERIAL; + + dec_interrupt[TC0].cpu_mask = IE_IRQ0; + dec_interrupt[TC0].iemask = KN02_SLOT0; + asic_mask_tbl[3] = KN02_SLOT0; + asic_irq_nr[3] = TC0; + + dec_interrupt[TC1].cpu_mask = IE_IRQ0; + dec_interrupt[TC1].iemask = KN02_SLOT1; + asic_mask_tbl[4] = KN02_SLOT1; + asic_irq_nr[4] = TC1; + + dec_interrupt[TC2].cpu_mask = IE_IRQ0; + dec_interrupt[TC2].iemask = KN02_SLOT2; + asic_mask_tbl[5] = KN02_SLOT2; + asic_irq_nr[5] = TC2; + + dec_interrupt[MEMORY].cpu_mask = IE_IRQ3; + dec_interrupt[MEMORY].iemask = 0; + cpu_mask_tbl[2] = IE_IRQ3; + cpu_irq_nr[2] = MEMORY; + + dec_interrupt[FPU].cpu_mask = IE_IRQ5; + dec_interrupt[FPU].iemask = 0; + cpu_mask_tbl[3] = IE_IRQ5; + cpu_irq_nr[3] = FPU; + +} /* dec_init_kn02 */ + +/* + * Machine-specific initialisation for kn02ba, aka 3min, aka DS5000/1xx. + */ +__initfunc(void dec_init_kn02ba(void)) +{ + /* + * Setup some memory addresses. + */ + dec_rtc_base = (char *) KN02XA_RTC_BASE; + isr = (volatile unsigned int *) KN02XA_SIR_ADDR; + imr = (volatile unsigned int *) KN02XA_SIRM_ADDR; + + /* + * Setup IOASIC interrupt + */ + cpu_mask_tbl[0] = IE_IRQ3; + cpu_irq_nr[0] = -1; + cpu_ivec_tbl[0] = kn02ba_io_int; + *imr = 0; + + /* + * Setup interrupt structure + */ + dec_interrupt[CLOCK].cpu_mask = IE_IRQ3; + dec_interrupt[CLOCK].iemask = KMIN_CLOCK; + asic_mask_tbl[0] = KMIN_CLOCK; + asic_irq_nr[0] = CLOCK; + + dec_interrupt[SCSI_DMA_INT].cpu_mask = IE_IRQ3; + dec_interrupt[SCSI_DMA_INT].iemask = SCSI_DMA_INTS; + asic_mask_tbl[1] = SCSI_DMA_INTS; + asic_irq_nr[1] = SCSI_DMA_INT; + + dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ3; + dec_interrupt[SCSI_INT].iemask = SCSI_CHIP; + asic_mask_tbl[2] = SCSI_CHIP; + asic_irq_nr[2] = SCSI_INT; + + dec_interrupt[ETHER].cpu_mask = IE_IRQ3; + dec_interrupt[ETHER].iemask = LANCE_INTS; + asic_mask_tbl[3] = LANCE_INTS; + asic_irq_nr[3] = ETHER; + + dec_interrupt[SERIAL].cpu_mask = IE_IRQ3; + dec_interrupt[SERIAL].iemask = SERIAL_INTS; + asic_mask_tbl[4] = SERIAL_INTS; + asic_irq_nr[4] = SERIAL; + + dec_interrupt[MEMORY].cpu_mask = IE_IRQ3; + dec_interrupt[MEMORY].iemask = KMIN_TIMEOUT; + asic_mask_tbl[5] = KMIN_TIMEOUT; + asic_irq_nr[5] = MEMORY; + + dec_interrupt[TC0].cpu_mask = IE_IRQ0; + dec_interrupt[TC0].iemask = 0; + cpu_mask_tbl[1] = IE_IRQ0; + cpu_irq_nr[1] = TC0; + + dec_interrupt[TC1].cpu_mask = IE_IRQ1; + dec_interrupt[TC1].iemask = 0; + cpu_mask_tbl[2] = IE_IRQ1; + cpu_irq_nr[2] = TC1; + + dec_interrupt[TC2].cpu_mask = IE_IRQ2; + dec_interrupt[TC2].iemask = 0; + cpu_mask_tbl[3] = IE_IRQ2; + cpu_irq_nr[3] = TC2; + + dec_interrupt[HALT].cpu_mask = IE_IRQ4; + dec_interrupt[HALT].iemask = 0; + cpu_mask_tbl[4] = IE_IRQ4; + cpu_irq_nr[4] = HALT; + + dec_interrupt[FPU].cpu_mask = IE_IRQ5; + dec_interrupt[FPU].iemask = 0; + cpu_mask_tbl[5] = IE_IRQ5; + cpu_irq_nr[5] = FPU; + +} /* dec_init_kn02ba */ + +/* + * Machine-specific initialisation for kn02ca, aka maxine, aka DS5000/2x. + */ +__initfunc(void dec_init_kn02ca(void)) +{ + /* + * Setup some memory addresses. FIXME: probably incomplete! + */ + dec_rtc_base = (char *) KN02XA_RTC_BASE; + isr = (volatile unsigned int *) KN02XA_SIR_ADDR; + imr = (volatile unsigned int *) KN02XA_SIRM_ADDR; + + /* + * Setup IOASIC interrupt + */ + cpu_ivec_tbl[1] = kn02ba_io_int; + cpu_irq_nr[1] = -1; + cpu_mask_tbl[1] = IE_IRQ3; + *imr = 0; + + /* + * Setup interrupt structure + */ + dec_interrupt[CLOCK].cpu_mask = IE_IRQ1; + dec_interrupt[CLOCK].iemask = 0; + cpu_mask_tbl[0] = IE_IRQ1; + cpu_irq_nr[0] = CLOCK; + + dec_interrupt[SCSI_DMA_INT].cpu_mask = IE_IRQ3; + dec_interrupt[SCSI_DMA_INT].iemask = SCSI_DMA_INTS; + asic_mask_tbl[0] = SCSI_DMA_INTS; + asic_irq_nr[0] = SCSI_DMA_INT; + + dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ3; + dec_interrupt[SCSI_INT].iemask = SCSI_CHIP; + asic_mask_tbl[1] = SCSI_CHIP; + asic_irq_nr[1] = SCSI_INT; + + dec_interrupt[ETHER].cpu_mask = IE_IRQ3; + dec_interrupt[ETHER].iemask = LANCE_INTS; + asic_mask_tbl[2] = LANCE_INTS; + asic_irq_nr[2] = ETHER; + + dec_interrupt[SERIAL].cpu_mask = IE_IRQ3; + dec_interrupt[SERIAL].iemask = XINE_SERIAL_INTS; + asic_mask_tbl[3] = XINE_SERIAL_INTS; + asic_irq_nr[3] = SERIAL; + + dec_interrupt[TC0].cpu_mask = IE_IRQ3; + dec_interrupt[TC0].iemask = MAXINE_TC0; + asic_mask_tbl[4] = MAXINE_TC0; + asic_irq_nr[4] = TC0; + + dec_interrupt[TC1].cpu_mask = IE_IRQ3; + dec_interrupt[TC1].iemask = MAXINE_TC1; + asic_mask_tbl[5] = MAXINE_TC1; + asic_irq_nr[5] = TC1; + + dec_interrupt[MEMORY].cpu_mask = IE_IRQ2; + dec_interrupt[MEMORY].iemask = 0; + cpu_mask_tbl[2] = IE_IRQ2; + cpu_irq_nr[2] = MEMORY; + + dec_interrupt[HALT].cpu_mask = IE_IRQ4; + dec_interrupt[HALT].iemask = 0; + cpu_mask_tbl[3] = IE_IRQ4; + cpu_irq_nr[3] = HALT; + + dec_interrupt[FPU].cpu_mask = IE_IRQ5; + dec_interrupt[FPU].iemask = 0; + cpu_mask_tbl[4] = IE_IRQ5; + cpu_irq_nr[4] = FPU; + +} /* dec_init_kn02ca */ + +/* + * Machine-specific initialisation for kn03, aka 3max+, aka DS5000/240. + */ +__initfunc(void dec_init_kn03(void)) +{ + /* + * Setup some memory addresses. FIXME: probably incomplete! + */ + dec_rtc_base = (char *) KN03_RTC_BASE; + isr = (volatile unsigned int *) KN03_SIR_ADDR; + imr = (volatile unsigned int *) KN03_SIRM_ADDR; + + /* + * Setup IOASIC interrupt + */ + cpu_ivec_tbl[1] = kn03_io_int; + cpu_mask_tbl[1] = IE_IRQ0; + cpu_irq_nr[1] = -1; + *imr = 0; + + /* + * Setup interrupt structure + */ + dec_interrupt[CLOCK].cpu_mask = IE_IRQ1; + dec_interrupt[CLOCK].iemask = 0; + cpu_mask_tbl[0] = IE_IRQ1; + cpu_irq_nr[0] = CLOCK; + + dec_interrupt[SCSI_DMA_INT].cpu_mask = IE_IRQ0; + dec_interrupt[SCSI_DMA_INT].iemask = SCSI_DMA_INTS; + asic_mask_tbl[0] = SCSI_DMA_INTS; + asic_irq_nr[0] = SCSI_DMA_INT; + + dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ0; + dec_interrupt[SCSI_INT].iemask = SCSI_CHIP; + asic_mask_tbl[1] = SCSI_CHIP; + asic_irq_nr[1] = SCSI_INT; + + dec_interrupt[ETHER].cpu_mask = IE_IRQ0; + dec_interrupt[ETHER].iemask = LANCE_INTS; + asic_mask_tbl[2] = LANCE_INTS; + asic_irq_nr[2] = ETHER; + + dec_interrupt[SERIAL].cpu_mask = IE_IRQ0; + dec_interrupt[SERIAL].iemask = SERIAL_INTS; + asic_mask_tbl[3] = SERIAL_INTS; + asic_irq_nr[3] = SERIAL; + + dec_interrupt[TC0].cpu_mask = IE_IRQ0; + dec_interrupt[TC0].iemask = KN03_TC0; + asic_mask_tbl[4] = KN03_TC0; + asic_irq_nr[4] = TC0; + + dec_interrupt[TC1].cpu_mask = IE_IRQ0; + dec_interrupt[TC1].iemask = KN03_TC1; + asic_mask_tbl[5] = KN03_TC1; + asic_irq_nr[5] = TC1; + + dec_interrupt[TC2].cpu_mask = IE_IRQ0; + dec_interrupt[TC2].iemask = KN03_TC2; + asic_mask_tbl[6] = KN03_TC2; + asic_irq_nr[6] = TC2; + + dec_interrupt[MEMORY].cpu_mask = IE_IRQ3; + dec_interrupt[MEMORY].iemask = 0; + cpu_mask_tbl[2] = IE_IRQ3; + cpu_irq_nr[2] = MEMORY; + + dec_interrupt[HALT].cpu_mask = IE_IRQ4; + dec_interrupt[HALT].iemask = 0; + cpu_mask_tbl[3] = IE_IRQ4; + cpu_irq_nr[3] = HALT; + + dec_interrupt[FPU].cpu_mask = IE_IRQ5; + dec_interrupt[FPU].iemask = 0; + cpu_mask_tbl[4] = IE_IRQ5; + cpu_irq_nr[4] = FPU; + +} /* dec_init_kn03 */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/time.c linux.pre11.3/arch/mips/dec/time.c --- linux.vanilla/arch/mips/dec/time.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/dec/time.c Mon Jul 19 23:28:46 1999 @@ -0,0 +1,439 @@ + +/* + * linux/arch/mips/kernel/time.c + * + * Copyright (C) 1991, 1992, 1995 Linus Torvalds + * + * This file contains the time handling details for PC-style clocks as + * found in some MIPS systems. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +extern volatile unsigned long lost_ticks; + +/* + * Change this if you have some constant time drift + */ +/* This is the value for the PC-style PICs. */ +/* #define USECS_PER_JIFFY (1000020/HZ) */ + +/* This is for machines which generate the exact clock. */ +#define USECS_PER_JIFFY (1000000/HZ) + +/* Cycle counter value at the previous timer interrupt.. */ + +static unsigned int timerhi = 0, timerlo = 0; + +/* + * On MIPS only R4000 and better have a cycle counter. + * + * FIXME: Does playing with the RP bit in c0_status interfere with this code? + */ +static unsigned long do_fast_gettimeoffset(void) +{ + u32 count; + unsigned long res, tmp; + + /* Last jiffy when do_fast_gettimeoffset() was called. */ + static unsigned long last_jiffies = 0; + unsigned long quotient; + + /* + * Cached "1/(clocks per usec)*2^32" value. + * It has to be recalculated once each jiffy. + */ + static unsigned long cached_quotient = 0; + + tmp = jiffies; + + quotient = cached_quotient; + + if (last_jiffies != tmp) { + last_jiffies = tmp; + __asm__(".set\tnoreorder\n\t" + ".set\tnoat\n\t" + ".set\tmips3\n\t" + "lwu\t%0,%2\n\t" + "dsll32\t$1,%1,0\n\t" + "or\t$1,$1,%0\n\t" + "ddivu\t$0,$1,%3\n\t" + "mflo\t$1\n\t" + "dsll32\t%0,%4,0\n\t" + "nop\n\t" + "ddivu\t$0,%0,$1\n\t" + "mflo\t%0\n\t" + ".set\tmips0\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=&r"(quotient) + : "r"(timerhi), + "m"(timerlo), + "r"(tmp), + "r"(USECS_PER_JIFFY) + : "$1"); + cached_quotient = quotient; + } + /* Get last timer tick in absolute kernel time */ + count = read_32bit_cp0_register(CP0_COUNT); + + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; +//printk("count: %08lx, %08lx:%08lx\n", count, timerhi, timerlo); + + __asm__("multu\t%1,%2\n\t" + "mfhi\t%0" + : "=r"(res) + : "r"(count), + "r"(quotient)); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY - 1; + + return res; +} + +/* 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! + */ + +#define TICK_SIZE tick + +static unsigned long do_slow_gettimeoffset(void) +{ + /* + * This is a kludge until I find a way for the + * DECstations without bus cycle counter. HK + */ + return 0; +} + +static unsigned long (*do_gettimeoffset) (void) = do_slow_gettimeoffset; + +/* + * This version of gettimeofday has near microsecond resolution. + */ +void do_gettimeofday(struct timeval *tv) +{ + unsigned long flags; + + save_and_cli(flags); + *tv = xtime; + tv->tv_usec += do_gettimeoffset(); + + /* + * xtime is atomically updated in timer_bh. lost_ticks is + * nonzero if the timer bottom half hasnt executed yet. + */ + if (lost_ticks) + tv->tv_usec += USECS_PER_JIFFY; + + restore_flags(flags); + + if (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } +} + +void do_settimeofday(struct timeval *tv) +{ + cli(); + /* This is revolting. We need to set the xtime.tv_usec + * correctly. However, the value in this location is + * is value at the last tick. + * Discover what correction gettimeofday + * would have done, and then undo it! + */ + tv->tv_usec -= do_gettimeoffset(); + + if (tv->tv_usec < 0) { + tv->tv_usec += 1000000; + tv->tv_sec--; + } + xtime = *tv; + time_state = TIME_BAD; + time_maxerror = MAXPHASE; + time_esterror = MAXPHASE; + sti(); +} + +/* + * In order to set the CMOS clock precisely, set_rtc_mmss has to be + * called 500 ms after the second nowtime has started, because when + * nowtime is written into the registers of the CMOS clock, it will + * jump to the next second precisely 500 ms later. Check the Motorola + * MC146818A or Dallas DS12887 data sheet for details. + */ +static int set_rtc_mmss(unsigned long nowtime) +{ + int retval = 0; + int real_seconds, real_minutes, cmos_minutes; + unsigned char save_control, save_freq_select; + + save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ + CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); + + save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ + CMOS_WRITE((save_freq_select | RTC_DIV_RESET2), RTC_FREQ_SELECT); + + cmos_minutes = CMOS_READ(RTC_MINUTES); + if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + BCD_TO_BIN(cmos_minutes); + + /* + * since we're only adjusting minutes and seconds, + * don't interfere with hour overflow. This avoids + * messing with unknown time zones but requires your + * RTC not to be off by more than 15 minutes + */ + real_seconds = nowtime % 60; + real_minutes = nowtime / 60; + if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1) + real_minutes += 30; /* correct for half hour time zone */ + real_minutes %= 60; + + if (abs(real_minutes - cmos_minutes) < 30) { + if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BIN_TO_BCD(real_seconds); + BIN_TO_BCD(real_minutes); + } + CMOS_WRITE(real_seconds, RTC_SECONDS); + CMOS_WRITE(real_minutes, RTC_MINUTES); + } else + retval = -1; + + /* The following flags have to be released exactly in this order, + * otherwise the DS12887 (popular MC146818A clone with integrated + * battery and quartz) will not reset the oscillator and will not + * update precisely 500 ms later. You won't find this mentioned in + * the Dallas Semiconductor data sheets, but who believes data + * sheets anyway ... -- Markus Kuhn + */ + CMOS_WRITE(save_control, RTC_CONTROL); + CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + + return retval; +} + +/* last time the cmos clock got updated */ +static long last_rtc_update = 0; + +/* + * timer_interrupt() needs to keep up the real-time clock, + * as well as call the "do_timer()" routine every clocktick + */ +static void inline + timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + volatile unsigned char dummy; + + dummy = CMOS_READ(RTC_REG_C); /* ACK RTC Interrupt */ + do_timer(regs); + + /* + * If we have an externally synchronized Linux clock, then update + * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be + * called as close as possible to 500 ms before the new second starts. + */ + if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 && + xtime.tv_usec > 500000 - (tick >> 1) && + xtime.tv_usec < 500000 + (tick >> 1)) + if (set_rtc_mmss(xtime.tv_sec) == 0) + last_rtc_update = xtime.tv_sec; + else + last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ +} + +static void r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int count; + + /* + * The cycle counter is only 32 bit which is good for about + * a minute at current count rates of upto 150MHz or so. + */ + count = read_32bit_cp0_register(CP0_COUNT); + timerhi += (count < timerlo); /* Wrap around */ + timerlo = count; + + timer_interrupt(irq, dev_id, regs); +} + +/* Converts Gregorian date to seconds since 1970-01-01 00:00:00. + * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 + * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. + * + * [For the Julian calendar (which was used in Russia before 1917, + * Britain & colonies before 1752, anywhere else before 1582, + * and is still in use by some communities) leave out the + * -year/100+year/400 terms, and add 10.] + * + * This algorithm was first published by Gauss (I think). + * + * WARNING: this function will overflow on 2106-02-07 06:28:16 on + * machines were long is 32-bit! (However, as time_t is signed, we + * will already get problems at other places on 2038-01-19 03:14:08) + */ +static inline unsigned long mktime(unsigned int year, unsigned int mon, + unsigned int day, unsigned int hour, + unsigned int min, unsigned int sec) +{ + if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */ + mon += 12; /* Puts Feb last since it has leap day */ + year -= 1; + } + return ((( + (unsigned long) (year / 4 - year / 100 + year / 400 + 367 * mon / 12 + day) + + year * 365 - 719499 + ) * 24 + hour /* now have hours */ + ) * 60 + min /* now have minutes */ + ) * 60 + sec; /* finally seconds */ +} + +char cyclecounter_available; + +static inline void init_cycle_counter(void) +{ + switch (mips_cputype) { + case CPU_UNKNOWN: + case CPU_R2000: + case CPU_R3000: + case CPU_R3000A: + case CPU_R3041: + case CPU_R3051: + case CPU_R3052: + case CPU_R3081: + case CPU_R3081E: + case CPU_R6000: + case CPU_R6000A: + case CPU_R8000: /* Not shure about that one, play safe */ + cyclecounter_available = 0; + break; + case CPU_R4000PC: + case CPU_R4000SC: + case CPU_R4000MC: + case CPU_R4200: + case CPU_R4400PC: + case CPU_R4400SC: + case CPU_R4400MC: + case CPU_R4600: + case CPU_R10000: + case CPU_R4300: + case CPU_R4650: + case CPU_R4700: + case CPU_R5000: + case CPU_R5000A: + case CPU_R4640: + case CPU_NEVADA: + cyclecounter_available = 1; + break; + } +} + +struct irqaction irq0 = +{timer_interrupt, SA_INTERRUPT, 0, + "timer", NULL, NULL}; + + +void (*board_time_init) (struct irqaction * irq); + +__initfunc(void time_init(void)) +{ + unsigned int year, mon, day, hour, min, sec; + int i; + + /* The Linux interpretation of the CMOS clock register contents: + * When the Update-In-Progress (UIP) flag goes from 1 to 0, the + * RTC registers show the second which has precisely just started. + * Let's hope other operating systems interpret the RTC the same way. + */ + /* read RTC exactly on falling edge of update flag */ + for (i = 0; i < 1000000; i++) /* may take up to 1 second... */ + if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) + break; + for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */ + if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) + break; + do { /* Isn't this overkill ? UIP above should guarantee consistency */ + sec = CMOS_READ(RTC_SECONDS); + min = CMOS_READ(RTC_MINUTES); + hour = CMOS_READ(RTC_HOURS); + day = CMOS_READ(RTC_DAY_OF_MONTH); + mon = CMOS_READ(RTC_MONTH); + year = CMOS_READ(RTC_YEAR); + } while (sec != CMOS_READ(RTC_SECONDS)); + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); + } + /* + * The DECstation RTC is used as a TOY (Time Of Year). + * The PROM will reset the year to either '70, '71 or '72. + * This hack will only work until Dec 31 2001. + */ + year += 1927; + + xtime.tv_sec = mktime(year, mon, day, hour, min, sec); + xtime.tv_usec = 0; + + init_cycle_counter(); + + if (cyclecounter_available) { + write_32bit_cp0_register(CP0_COUNT, 0); + do_gettimeoffset = do_fast_gettimeoffset; + irq0.handler = r4k_timer_interrupt; + } + board_time_init(&irq0); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/wbflush.c linux.pre11.3/arch/mips/dec/wbflush.c --- linux.vanilla/arch/mips/dec/wbflush.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/dec/wbflush.c Mon Jul 19 23:28:46 1999 @@ -0,0 +1,104 @@ +/* + * Setup the right wbflush routine for the different DECstations. + * + * Created with information from: + * DECstation 3100 Desktop Workstation Functional Specification + * DECstation 5000/200 KN02 System Module Functional Specification + * mipsel-linux-objdump --disassemble vmunix | grep "wbflush" :-) + * + * 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. + * + * Copyright (C) 1998 Harald Koerfgen + */ + +#include +#include + +static void wbflush_kn01(void); +static void wbflush_kn210(void); +static void wbflush_kn02ba(void); +static void wbflush_kn03(void); + +void (*__wbflush) (void); + +__initfunc(void wbflush_setup(void)) +{ + switch (mips_machtype) { + case MACH_DS23100: + __wbflush = wbflush_kn01; + break; + case MACH_DS5100: /* DS5100 MIPSMATE */ + __wbflush = wbflush_kn210; + break; + case MACH_DS5000_200: /* DS5000 3max */ + __wbflush = wbflush_kn01; + break; + case MACH_DS5000_1XX: /* DS5000/100 3min */ + __wbflush = wbflush_kn02ba; + break; + case MACH_DS5000_2X0: /* DS5000/240 3max+ */ + __wbflush = wbflush_kn03; + break; + case MACH_DS5000_XX: /* Personal DS5000/2x */ + __wbflush = wbflush_kn02ba; + break; + } +} + +/* + * For the DS3100 and DS5000/200 the writeback buffer functions + * as part of Coprocessor 0. + */ +static void wbflush_kn01(void) +{ + asm(".set\tpush\n\t" + ".set\tnoreorder\n\t" + "1:\tbc0f\t1b\n\t" + "nop\n\t" + ".set\tpop"); +} + +/* + * For the DS5100 the writeback buffer seems to be a part of Coprocessor 3. + * But CP3 has to enabled first. + */ +static void wbflush_kn210(void) +{ + asm(".set\tpush\n\t" + ".set\tnoreorder\n\t" + "mfc0\t$2,$12\n\t" + "lui\t$3,0x8000\n\t" + "or\t$3,$2,$3\n\t" + "mtc0\t$3,$12\n\t" + "nop\n" + "1:\tbc3f\t1b\n\t" + "nop\n\t" + "mtc0\t$2,$12\n\t" + "nop\n\t" + ".set\tpop" + : : :"$2", "$3"); +} + +/* + * Looks like some magic with the System Interrupt Mask Register + * in the famous IOASIC for kmins and maxines. + */ +static void wbflush_kn02ba(void) +{ + asm(".set\tpush\n\t" + ".set\tnoreorder\n\t" + "lui\t$2,0xbc04\n\t" + "lw\t$3,0x120($2)\n\t" + "lw\t$3,0x120($2)\n\t" + ".set\tpop" + : : :"$2", "$3"); +} + +/* + * The DS500/2x0 doesnt need to write back the WB. + */ +static void wbflush_kn03(void) +{ +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/defconfig linux.pre11.3/arch/mips/defconfig --- linux.vanilla/arch/mips/defconfig Wed Mar 10 21:13:00 1999 +++ linux.pre11.3/arch/mips/defconfig Mon Jul 19 23:28:45 1999 @@ -10,13 +10,11 @@ # # Machine selection # -CONFIG_ACER_PICA_61=y +# CONFIG_ACER_PICA_61 is not set # CONFIG_MIPS_MAGNUM_4000 is not set # CONFIG_OLIVETTI_M700 is not set # CONFIG_SGI is not set CONFIG_SNI_RM200_PCI=y -CONFIG_MIPS_JAZZ=y -CONFIG_VGA_CONSOLE=y CONFIG_PCI=y # @@ -34,8 +32,10 @@ # # General setup # -CONFIG_ELF_KERNEL=y +CONFIG_PCI_QUIRKS=y +CONFIG_PCI_OLD_PROC=y CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_ELF_KERNEL=y # CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set @@ -49,21 +49,21 @@ # Loadable module support # CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set +CONFIG_MODVERSIONS=y CONFIG_KMOD=y # # Block devices # -CONFIG_BLK_DEV_FD=y -CONFIG_BLK_DEV_IDE=y +CONFIG_BLK_DEV_FD=m +CONFIG_BLK_DEV_IDE=m # # Please see Documentation/ide.txt for help/info on IDE drives # # CONFIG_BLK_DEV_HD_IDE is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_BLK_DEV_IDECD=y +CONFIG_BLK_DEV_IDEDISK=m +CONFIG_BLK_DEV_IDECD=m # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set @@ -75,10 +75,10 @@ # # Additional Block Devices # -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NBD=m # CONFIG_BLK_DEV_MD is not set -# CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_RAM=m # CONFIG_BLK_DEV_XD is not set CONFIG_PARIDE_PARPORT=y # CONFIG_PARIDE is not set @@ -106,7 +106,6 @@ # (it is safe to leave these untouched) # # CONFIG_INET_RARP is not set -CONFIG_IP_NOSR=y # CONFIG_SKB_LARGE is not set # @@ -124,8 +123,8 @@ # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_ST=y -CONFIG_BLK_DEV_SR=y +CONFIG_CHR_DEV_ST=m +CONFIG_BLK_DEV_SR=m # CONFIG_BLK_DEV_SR_VENDOR is not set # CONFIG_CHR_DEV_SG is not set @@ -134,12 +133,13 @@ # # CONFIG_SCSI_MULTI_LUN is not set CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y +# CONFIG_SCSI_LOGGING is not set # # SCSI low-level drivers # # 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 @@ -147,20 +147,25 @@ # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_BUSLOGIC 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_EATA 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_INITIO is not set +# CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_SYM53C416 is not set # CONFIG_SCSI_NCR53C7xx is not set CONFIG_SCSI_NCR53C8XX=y +# CONFIG_SCSI_SYM53C8XX is not set CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4 -CONFIG_SCSI_NCR53C8XX_SYNC=5 +CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 +CONFIG_SCSI_NCR53C8XX_SYNC=20 # CONFIG_SCSI_NCR53C8XX_PROFILE is not set # CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set # CONFIG_SCSI_PAS16 is not set @@ -169,13 +174,12 @@ # CONFIG_SCSI_PSI240I 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_SEAGATE 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_JAZZ_ESP=y -CONFIG_JAZZ_ESP=y # # Network device support @@ -185,7 +189,6 @@ # CONFIG_DUMMY is not set # CONFIG_EQUALIZER is not set CONFIG_NET_ETHERNET=y -CONFIG_MIPS_JAZZ_SONIC=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set @@ -211,6 +214,8 @@ # CONFIG_NET_RADIO is not set # CONFIG_TR is not set # CONFIG_HOSTESS_SV11 is not set +# CONFIG_COSA is not set +# CONFIG_RCPCI is not set # CONFIG_WAN_DRIVERS is not set # CONFIG_LAPBETHER is not set # CONFIG_X25_ASY is not set @@ -235,7 +240,7 @@ # CONFIG_ISDN is not set # -# CD-ROM drivers (not for SCSI or IDE/ATAPI drives) +# comment # # CONFIG_CD_NO_IDESCSI is not set @@ -244,18 +249,26 @@ # CONFIG_VT=y CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -# CONFIG_SERIAL_CONSOLE is not set +CONFIG_SERIAL=m # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_UNIX98_PTYS is not set # CONFIG_MOUSE is not set # CONFIG_QIC02_TAPE is not set # CONFIG_WATCHDOG is not set -# CONFIG_RTC is not set -# CONFIG_VIDEO_DEV is not set # CONFIG_NVRAM is not set +CONFIG_RTC=y + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set + +# +# Joystick support +# # CONFIG_JOYSTICK is not set +# CONFIG_DTLK is not set # # Ftape, the floppy tape device driver @@ -265,69 +278,85 @@ # # Filesystems # -# CONFIG_QUOTA is not set -# CONFIG_MINIX_FS is not set -CONFIG_EXT2_FS=y -CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -# CONFIG_UMSDOS_FS is not set -CONFIG_VFAT_FS=y -CONFIG_PROC_FS=y -CONFIG_NFS_FS=y -CONFIG_NFSD=y -CONFIG_SUNRPC=y -CONFIG_LOCKD=y -# CONFIG_CODA_FS is not set -# CONFIG_SMB_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_SYSV_FS is not set +CONFIG_QUOTA=y +CONFIG_AUTOFS_FS=m # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_AUTOFS_FS is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_UMSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_MINIX_FS=m +# CONFIG_NTFS_FS is not set +CONFIG_HPFS_FS=m +CONFIG_PROC_FS=y +CONFIG_ROMFS_FS=m +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=m +CONFIG_SUNRPC=m +CONFIG_LOCKD=m +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set + +# +# Partition Types +# # CONFIG_BSD_DISKLABEL is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_OSF_PARTITION is not set # CONFIG_SMD_DISKLABEL is not set # CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_MAC_PARTITION is not set CONFIG_NLS=y # # Native Language Support # -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -CONFIG_NLS_CODEPAGE_850=y -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -CONFIG_NLS_ISO8859_1=y -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_KOI8_R is not set +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m # # Console drivers # +CONFIG_VGA_CONSOLE=y +# CONFIG_FB is not set +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +# CONFIG_FBCON_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y # # Sound @@ -337,7 +366,7 @@ # # Kernel hacking # -CONFIG_CROSSCOMPILE=y +# CONFIG_CROSSCOMPILE is not set # CONFIG_MIPS_FPE_MODULE is not set # CONFIG_REMOTE_DEBUG is not set # CONFIG_MAGIC_SYSRQ is not set diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/jazz/Makefile linux.pre11.3/arch/mips/jazz/Makefile --- linux.vanilla/arch/mips/jazz/Makefile Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/jazz/Makefile Mon Jul 19 23:28:46 1999 @@ -1,3 +1,4 @@ +# $Id: Makefile,v 1.6 1999/02/25 21:57:01 tsbogend Exp $ # # Makefile for the Jazz family specific parts of the kernel # @@ -13,7 +14,8 @@ all: jazz.o O_TARGET := jazz.o -O_OBJS := hw-access.o int-handler.o jazzdma.o reset.o rtc-jazz.o setup.o +O_OBJS := int-handler.o jazzdma.o reset.o rtc-jazz.o setup.o floppy-jazz.o \ + kbd-jazz.o int-handler.o: int-handler.S diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/jazz/floppy-jazz.c linux.pre11.3/arch/mips/jazz/floppy-jazz.c --- linux.vanilla/arch/mips/jazz/floppy-jazz.c Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/jazz/floppy-jazz.c Mon Jul 19 23:28:46 1999 @@ -14,11 +14,11 @@ #include #include #include -#include #include #include #include #include +#include static unsigned char jazz_fd_inb(unsigned int port) { @@ -108,7 +108,7 @@ return order; } -extern inline unsigned long jazz_fd_dma_mem_alloc(unsigned long size) +static unsigned long jazz_fd_dma_mem_alloc(unsigned long size) { int order = __get_order(size); unsigned long mem; @@ -121,14 +121,14 @@ return mem; } -extern inline void jazz_fd_dma_mem_free(unsigned long addr, +static void jazz_fd_dma_mem_free(unsigned long addr, unsigned long size) { - vdma_free(PHYSADDR(addr)); + vdma_free(vdma_phys2log(PHYSADDR(addr))); free_pages(addr, __get_order(size)); } -static void std_fd_drive_type(unsigned long n) +static unsigned long jazz_fd_drive_type(unsigned long n) { /* XXX This is wrong for machines with ED 2.88mb disk drives like the Olivetti M700. Anyway, we should suck this from the ARC diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/jazz/hw-access.c linux.pre11.3/arch/mips/jazz/hw-access.c --- linux.vanilla/arch/mips/jazz/hw-access.c Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/jazz/hw-access.c Thu Jan 1 01:00:00 1970 @@ -1,90 +0,0 @@ -/* $Id: hw-access.c,v 1.11 1998/09/16 22:50:39 ralf Exp $ - * - * Low-level hardware access stuff for Jazz family machines. - * - * 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. - * - * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static volatile keyboard_hardware *jazz_kh = - (keyboard_hardware *) JAZZ_KEYBOARD_ADDRESS; - -#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ - -static unsigned char jazz_read_input(void) -{ - return jazz_kh->data; -} - -static void jazz_write_output(unsigned char val) -{ - int status; - - do { - status = jazz_kh->command; - } while (status & KBD_STAT_IBF); - jazz_kh->data = val; -} - -static void jazz_write_command(unsigned char val) -{ - int status; - - do { - status = jazz_kh->command; - } while (status & KBD_STAT_IBF); - jazz_kh->command = val; -} - -static unsigned char jazz_read_status(void) -{ - return jazz_kh->command; -} - -__initfunc(void jazz_keyboard_setup(void)) -{ - kbd_read_input = jazz_read_input; - kbd_write_output = jazz_write_output; - kbd_write_command = jazz_write_command; - kbd_read_status = jazz_read_status; - request_irq(JAZZ_KEYBOARD_IRQ, keyboard_interrupt, - 0, "keyboard", NULL); - request_region(0x60, 16, "keyboard"); - r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, - r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) - | JAZZ_IE_KEYBOARD); -} - -int jazz_ps2_request_irq(void) -{ - extern void aux_interrupt(int, void *, struct pt_regs *); - int ret; - - ret = request_irq(JAZZ_MOUSE_IRQ, aux_interrupt, 0, "PS/2 Mouse", NULL); - if (!ret) - r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, - r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | - JAZZ_IE_MOUSE); - return ret; -} - -void jazz_ps2_free_irq(void) -{ - r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, - r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | - JAZZ_IE_MOUSE); - free_irq(JAZZ_MOUSE_IRQ, NULL); -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/jazz/int-handler.S linux.pre11.3/arch/mips/jazz/int-handler.S --- linux.vanilla/arch/mips/jazz/int-handler.S Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/jazz/int-handler.S Mon Jul 19 23:28:46 1999 @@ -1,4 +1,4 @@ -/* $Id: int-handler.S,v 1.6 1998/08/28 15:55:19 ralf Exp $ +/* $Id: int-handler.S,v 1.14 1999/05/01 22:40:34 ralf Exp $ * * 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 @@ -91,51 +91,8 @@ * whistles and bells and we're aware of the problem. */ ll_isa_irq: lw a0,JAZZ_EISA_IRQ_ACK - lui s0,%hi(JAZZ_PORT_BASE) - li s1,1 - andi t0,a0,8 # which pic? - bnez t0,ack_second - andi a0,7 # delay slot - /* - * Acknowledge first pic - */ - lb t2,%lo(JAZZ_PORT_BASE)+0x21(s0) - lui s4,%hi(cache_21) - lb t0,%lo(cache_21)(s4) - sllv s1,s1,a0 - or t0,s1 - sb t0,%lo(cache_21)(s4) - sb t0,%lo(JAZZ_PORT_BASE)+0x21(s0) - li t2,0x20 - sb t2,%lo(JAZZ_PORT_BASE)+0x20(s0) - /* - * Now call the real handler - */ - jal do_IRQ - move a1,sp - j ret_from_irq - nop - - .align 5 -ack_second: /* - * Acknowledge second pic - */ - lbu t2,%lo(JAZZ_PORT_BASE)+0xa1(s0) - lui s4,%hi(cache_A1) - lb t3,%lo(cache_A1)(s4) - sllv s1,s1,a0 - or t3,s1 - sb t3,%lo(cache_A1)(s4) - sb t3,%lo(JAZZ_PORT_BASE)+0xa1(s0) - li t3,0x20 - sb t3,%lo(JAZZ_PORT_BASE)+0xa0(s0) - sb t3,%lo(JAZZ_PORT_BASE)+0x20(s0) - /* - * Now call the real handler - */ - or a0, 8 - jal do_IRQ + jal i8259_do_irq move a1,sp j ret_from_irq @@ -144,7 +101,7 @@ /* * Hmm... This is not just a plain PC clone so the question is * which devices on Jazz machines can generate an (E)ISA NMI? - * (Writing to nonexistant memory?) + * (Writing to nonexistent memory?) */ ll_isa_nmi: li s1,~IE_IRQ3 PANIC("Unimplemented isa_nmi handler") @@ -152,7 +109,7 @@ /* * Timer IRQ - remapped to be more similar to an IBM compatible. * - * The timer interrupt is handled specially to insure that the jiffies + * The timer interrupt is handled specially to ensure that the jiffies * variable is updated at all times. Specifically, the timer interrupt is * just like the complete handlers except that it is invoked with interrupts * disabled and should never re-enable them. If other interrupts were @@ -163,7 +120,7 @@ ll_timer: lw zero,JAZZ_TIMER_REGISTER # timer irq cleared on read li s1,~IE_IRQ4 - li a0,0 + li a0, JAZZ_TIMER_IRQ jal do_IRQ move a1,sp @@ -228,14 +185,14 @@ b loc_call /* - * Floppy IRQ, remapped to level 6 + * Floppy IRQ */ loc_floppy: li s1,~JAZZ_IE_FLOPPY li a0,JAZZ_FLOPPY_IRQ b loc_call /* - * Sound? What sound hardware (whistle) ??? + * Sound IRQ */ loc_sound: PANIC("Unimplemented loc_sound handler") loc_video: PANIC("Unimplemented loc_video handler") diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/jazz/jazzdma.c linux.pre11.3/arch/mips/jazz/jazzdma.c --- linux.vanilla/arch/mips/jazz/jazzdma.c Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/jazz/jazzdma.c Mon Jul 19 23:28:46 1999 @@ -97,6 +97,7 @@ unsigned int frame; unsigned long laddr; int i; + unsigned long flags; /* check arguments */ @@ -113,6 +114,7 @@ return VDMA_ERROR; /* invalid physical address */ } + save_and_cli (flags); /* * Find free chunk */ @@ -123,8 +125,10 @@ while (entry[first].owner != VDMA_PAGE_EMPTY && first < VDMA_PGTBL_ENTRIES) first++; - if (first+pages > VDMA_PGTBL_ENTRIES) /* nothing free */ + if (first+pages > VDMA_PGTBL_ENTRIES) { /* nothing free */ + restore_flags (flags); return VDMA_ERROR; + } last = first+1; while (entry[last].owner == VDMA_PAGE_EMPTY && last-first < pages) @@ -170,6 +174,7 @@ printk("\n"); } + restore_flags(flags); return laddr; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/jazz/kbd-jazz.c linux.pre11.3/arch/mips/jazz/kbd-jazz.c --- linux.vanilla/arch/mips/jazz/kbd-jazz.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/jazz/kbd-jazz.c Mon Jul 19 23:28:46 1999 @@ -0,0 +1,102 @@ +/* $Id: kbd-jazz.c,v 1.1 1998/10/28 12:38:10 ralf Exp $ + * + * Low-level hardware access stuff for Jazz family machines. + * + * 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. + * + * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle + */ +#include +#include +#include +#include + +#define jazz_kh ((keyboard_hardware *) JAZZ_KEYBOARD_ADDRESS) + +static void jazz_request_region(void) +{ + /* No I/O ports are being used on Jazz. */ +} + +static int jazz_request_irq(void (*handler)(int, void *, struct pt_regs *)) +{ + int res; + + res = request_irq(JAZZ_KEYBOARD_IRQ, handler, 0, "keyboard", NULL); + if (res != 0) + return res; + + /* jazz_request_irq() should do this ... */ + r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, + r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) + | JAZZ_IE_KEYBOARD); + + return 0; +} + +static int jazz_aux_request_irq(void (*handler)(int, void *, struct pt_regs *)) +{ + int ret; + + ret = request_irq(JAZZ_MOUSE_IRQ, handler, 0, "PS/2 Mouse", NULL); + if (ret != 0) + return ret; + + r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, + r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | + JAZZ_IE_MOUSE); + return 0; +} + +static void jazz_aux_free_irq(void) +{ + r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, + r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) + | JAZZ_IE_MOUSE); + free_irq(JAZZ_MOUSE_IRQ, NULL); +} + +static unsigned char jazz_read_input(void) +{ + return jazz_kh->data; +} + +static void jazz_write_output(unsigned char val) +{ + int status; + + do { + status = jazz_kh->command; + } while (status & KBD_STAT_IBF); + jazz_kh->data = val; +} + +static void jazz_write_command(unsigned char val) +{ + int status; + + do { + status = jazz_kh->command; + } while (status & KBD_STAT_IBF); + jazz_kh->command = val; +} + +static unsigned char jazz_read_status(void) +{ + return jazz_kh->command; +} + +struct kbd_ops jazz_kbd_ops = { + jazz_request_region, + jazz_request_irq, + + jazz_aux_request_irq, + jazz_aux_free_irq, + + jazz_read_input, + jazz_write_output, + jazz_write_command, + jazz_read_status +}; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/jazz/reset.c linux.pre11.3/arch/mips/jazz/reset.c --- linux.vanilla/arch/mips/jazz/reset.c Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/jazz/reset.c Mon Jul 19 23:28:46 1999 @@ -3,7 +3,7 @@ * * Reset a Jazz machine. * - * $Id: reset.c,v 1.2 1998/03/04 12:17:40 ralf Exp $ + * $Id: reset.c,v 1.3 1998/03/04 08:29:10 ralf Exp $ */ #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/jazz/rtc-jazz.c linux.pre11.3/arch/mips/jazz/rtc-jazz.c --- linux.vanilla/arch/mips/jazz/rtc-jazz.c Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/jazz/rtc-jazz.c Mon Jul 19 23:28:46 1999 @@ -1,4 +1,4 @@ -/* $Id: rtc-jazz.c,v 1.3 1998/08/28 15:55:19 ralf Exp $ +/* $Id: rtc-jazz.c,v 1.2 1998/06/25 20:19:14 ralf Exp $ * * 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 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/jazz/setup.c linux.pre11.3/arch/mips/jazz/setup.c --- linux.vanilla/arch/mips/jazz/setup.c Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/jazz/setup.c Mon Jul 19 23:28:46 1999 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.14 1998/09/16 22:50:40 ralf Exp $ +/* $Id: setup.c,v 1.20 1999/02/25 21:57:47 tsbogend Exp $ * * Setup pointers to hardware-dependent routines. * @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -40,7 +39,6 @@ static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL}; extern asmlinkage void jazz_handle_int(void); -extern void jazz_keyboard_setup(void); extern void jazz_machine_restart(char *command); extern void jazz_machine_halt(void); @@ -48,6 +46,9 @@ extern struct ide_ops std_ide_ops; extern struct rtc_ops jazz_rtc_ops; +extern struct kbd_ops jazz_kbd_ops; +extern struct fd_ops *fd_ops; +extern struct fd_ops jazz_fd_ops; void (*board_time_init)(struct irqaction *irq); @@ -55,7 +56,7 @@ { /* set the clock to 100 Hz */ r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9); - setup_x86_irq(0, irq); + i8259_setup_irq(JAZZ_TIMER_IRQ, irq); } __initfunc(static void jazz_irq_setup(void)) @@ -75,43 +76,16 @@ r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9); request_region(0x20, 0x20, "pic1"); request_region(0xa0, 0x20, "pic2"); - setup_x86_irq(2, &irq2); + i8259_setup_irq(2, &irq2); } __initfunc(void jazz_setup(void)) { - tag *atag; - - /* - * we just check if a tag_screen_info can be gathered - * in setup_arch(), if yes we don't proceed futher... - */ - atag = bi_TagFind(tag_screen_info); - if (!atag) { - /* - * If no, we try to find the tag_arc_displayinfo which is - * always created by Milo for an ARC box (for now Milo only - * works on ARC boxes :) -Stoned. - */ - atag = bi_TagFind(tag_arcdisplayinfo); - if (atag) { - screen_info.orig_x = - ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_x; - screen_info.orig_y = - ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_y; - screen_info.orig_video_cols = - ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->columns; - screen_info.orig_video_lines = - ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->lines; - } - } - add_wired_entry (0x02000017, 0x03c00017, 0xe0000000, PM_64K); add_wired_entry (0x02400017, 0x02440017, 0xe2000000, PM_16M); add_wired_entry (0x01800017, 0x01000017, 0xe4000000, PM_4M); irq_setup = jazz_irq_setup; - keyboard_setup = jazz_keyboard_setup; mips_io_port_base = JAZZ_PORT_BASE; isa_slot_offset = 0xe3000000; request_region(0x00,0x20,"dma1"); @@ -128,6 +102,8 @@ #ifdef CONFIG_BLK_DEV_IDE ide_ops = &std_ide_ops; #endif - conswitchp = &fb_con; + conswitchp = &dummy_con; rtc_ops = &jazz_rtc_ops; + kbd_ops = &jazz_kbd_ops; + fd_ops = &jazz_fd_ops; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/Makefile linux.pre11.3/arch/mips/kernel/Makefile --- linux.vanilla/arch/mips/kernel/Makefile Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/Makefile Mon Jul 19 23:28:37 1999 @@ -23,10 +23,14 @@ endif # -# SGI's have very different interrupt/timer hardware. +# SGIs have very different interrupt/timer hardware. # ifndef CONFIG_SGI -O_OBJS += irq.o time.o + ifndef CONFIG_DECSTATION + ifndef CONFIG_BAGET_MIPS + O_OBJS += irq.o time.o + endif + endif endif # diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/entry.S linux.pre11.3/arch/mips/kernel/entry.S --- linux.vanilla/arch/mips/kernel/entry.S Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/entry.S Mon Jul 19 23:28:37 1999 @@ -7,7 +7,7 @@ * * Copyright (C) 1994, 1995 by Ralf Baechle * - * $Id: entry.S,v 1.15 1998/10/14 20:26:26 ralf Exp $ + * $Id: entry.S,v 1.14 1999/04/12 19:13:21 harald Exp $ */ /* @@ -146,7 +146,7 @@ BUILD_HANDLER(adel,ade,ade,silent) /* #4 */ BUILD_HANDLER(ades,ade,ade,silent) /* #5 */ BUILD_HANDLER(ibe,ibe,cli,verbose) /* #6 */ - BUILD_HANDLER(dbe,dbe,cli,verbose) /* #7 */ + BUILD_HANDLER(dbe,dbe,cli,silent) /* #7 */ BUILD_HANDLER(bp,bp,sti,silent) /* #9 */ BUILD_HANDLER(ri,ri,sti,silent) /* #10 */ BUILD_HANDLER(cpu,cpu,sti,silent) /* #11 */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/fpe.c linux.pre11.3/arch/mips/kernel/fpe.c --- linux.vanilla/arch/mips/kernel/fpe.c Sun Nov 8 15:08:30 1998 +++ linux.pre11.3/arch/mips/kernel/fpe.c Mon Jul 19 23:28:45 1999 @@ -6,7 +6,7 @@ * * Copyright (C) 1997 Ralf Baechle * - * $Id: fpe.c,v 1.2 1998/03/27 08:53:39 ralf Exp $ + * $Id: fpe.c,v 1.4 1999/05/01 22:40:35 ralf Exp $ */ #include #include @@ -39,7 +39,7 @@ /* * For easier experimentation we never increment/decrement - * the module useable counter. + * the module usable counter. */ int register_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31)); int unregister_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31)); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/gdb-low.S linux.pre11.3/arch/mips/kernel/gdb-low.S --- linux.vanilla/arch/mips/kernel/gdb-low.S Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/gdb-low.S Mon Jul 19 23:28:38 1999 @@ -5,7 +5,7 @@ * * Copyright (C) 1995 Andreas Busse * - * $Id: gdb-low.S,v 1.3 1997/12/02 05:51:05 ralf Exp $ + * $Id: gdb-low.S,v 1.4 1997/12/01 17:57:26 ralf Exp $ */ #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/gdb-stub.c linux.pre11.3/arch/mips/kernel/gdb-stub.c --- linux.vanilla/arch/mips/kernel/gdb-stub.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/gdb-stub.c Mon Jul 19 23:28:38 1999 @@ -12,7 +12,7 @@ * * Copyright (C) 1995 Andreas Busse * - * $Id: gdb-stub.c,v 1.4 1997/12/02 05:51:06 ralf Exp $ + * $Id: gdb-stub.c,v 1.7 1999/06/12 18:39:28 ulfc Exp $ */ /* @@ -326,7 +326,7 @@ { 7, SIGBUS }, /* data bus error */ { 9, SIGTRAP }, /* break */ { 10, SIGILL }, /* reserved instruction */ -/* { 11, SIGILL }, */ /* cpu unusable */ +/* { 11, SIGILL }, */ /* CPU unusable */ { 12, SIGFPE }, /* overflow */ { 13, SIGTRAP }, /* trap */ { 14, SIGSEGV }, /* virtual instruction cache coherency */ @@ -362,8 +362,6 @@ initialized = 1; restore_flags(flags); - - breakpoint(); } @@ -379,7 +377,7 @@ } /* - * Convert the MIPS hardware trap type code to a unix signal number. + * Convert the MIPS hardware trap type code to a Unix signal number. */ static int computeSignal(int tt) { diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/head.S linux.pre11.3/arch/mips/kernel/head.S --- linux.vanilla/arch/mips/kernel/head.S Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/head.S Mon Jul 19 23:28:37 1999 @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.13 1998/10/14 20:26:27 ralf Exp $ +/* $Id: head.S,v 1.11 1998/10/18 13:27:12 tsbogend Exp $ * * arch/mips/kernel/head.S * @@ -408,15 +408,7 @@ probe_done: -#ifndef CONFIG_SGI - /* Get the memory upper limit the bootloader passed to us - * in a0 - */ - la t0, mips_memory_upper - nop - sw a0, (t0) -#else - /* On SGI's the firmware/bootloader passes argc/argp/envp + /* The firmware/bootloader passes argc/argp/envp * to us as arguments. But clear bss first because * the romvec and other important info is stored there * by prom_init(). @@ -431,6 +423,7 @@ jal prom_init /* prom_init(argc, argv, envp); */ nop +#ifdef CONFIG_SGI jal sgi_sysinit nop #endif @@ -440,18 +433,6 @@ nop #endif - /* Get the very one tags we need early in the boot process */ - nop - jal bi_EarlySnarf - nop -#ifndef CONFIG_SGI - /* Clear BSS first so that there are no surprises... */ - la t0, _edata - la t1, _end -1: addiu t0, 1 - bne t0, t1, 1b - sb zero, -1(t0) -#endif /* * Determine the mmu/cache attached to this machine, * then flush the tlb and caches. On the r4xx0 @@ -460,34 +441,10 @@ jal loadmmu nop - la t2, mips_cputype - lw t4, (t2) - li t1, CPU_R2000 - li t2, CPU_R3000 - li t3, CPU_R3000A - beq t4,t1,2f - nop - - beq t4,t2,2f - nop - - beq t4,t3,2f - nop - - jal wire_mappings_r4xx0 - nop - - b 9f - nop - -2: - jal wire_mappings_r3000 - nop - /* * Stack for kernel and init, current variable */ -9: la $28, init_task_union + la $28, init_task_union addiu t0, $28, KERNEL_STACK_SIZE-32 sw t0, kernelsp subu sp, t0, 4*SZREG @@ -509,81 +466,6 @@ nop # delay slot END(kernel_entry) -/* - * wire_mappings - used to map hardware registers, r4xx0 version. - */ -LEAF(wire_mappings_r4xx0) - mtc0 zero, CP0_WIRED - nop - nop - nop - j ra - nop - END(wire_mappings_r4xx0) - -/* - * R3000 version of wire_mappings. - */ -LEAF(wire_mappings_r3000) - /* - * Get base address of map0 table for the - * the board we're running on - */ - lw t1, mips_machtype - la t0, map0table - sll t1, PTRLOG # machtype used as index - addu t0, t1 - lw t0, (t0) # get base address - nop - /* Get number of wired TLB entries and - * loop over selected map0 table. - */ - lw t1, (t0) # number of wired TLB entries - move t2, zero # TLB entry counter - addiu t3, t1, 1 # wire one additional entry - beqz t1, 2f # null, exit - nop - - addiu t0, 8 -1: - lw t4, 24(t0) # PageMask - ld t5, 0(t0) # entryHi - ld t6, 8(t0) # entryLo0 - addiu t2, 1 # increment ctr - mtc0 t2, CP0_INDEX # set TLB entry - nop - mtc0 t5, CP0_ENTRYHI - nop - mtc0 t6, CP0_ENTRYLO0 - addiu t0, 32 - bne t1, t2, 1b # next TLB entry - tlbwi - - /* We use only 4k pages. Therefore the PageMask register - * is expected to be setup for 4k pages. - */ -2: - /* Now map the pagetables */ - mtc0 zero, CP0_INDEX - la t0, TLB_ROOT - mtc0 t0, CP0_ENTRYHI - nop - la t0, swapper_pg_dir - srl t0, 12 - ori t0, (0x00e0|0x0100) # uncachable, dirty, valid - mtc0 t0, CP0_ENTRYLO0 - nop - tlbwi # delayed - - /* Load the context register with zero. To see why, look - * at how the tlb refill code above works. - */ - mtc0 zero, CP0_CONTEXT - - jr ra - nop - END(wire_mappings_r3000) - /* CPU type probing code, called at Kernel entry. */ LEAF(cpu_probe) mfc0 t0, CP0_PRID @@ -707,115 +589,6 @@ b probe_done nop END(cpu_probe) - - .data -/* - * Build an entry for table of wired entries - */ -#define MAPDATA(q1,q2,q3,w1) \ - .quad q1; \ - .quad q2; \ - .quad q3; \ - .word w1; \ - .word 0 - -/* - * Initial mapping tables for supported Mips boards. - * First item is always the number of wired TLB entries, - * following by EntryHi/EntryLo pairs and page mask. - * Since everything must be quad-aligned (8) we insert - * some dummy zeros. - * - * Keep in mind that the PFN does not depend on the page size in the - * TLB page mask register. See milo's lib/dumptlb.c for how to decode - * and encode these entries. Don't see the same routine in the linux - * kernel distribution, since it is older and unreliable. - */ - -/* - * Address table of mapping tables for supported Mips boards. - * Add your own stuff here but don't forget to define your - * target system in bootinfo.h - */ - -map0table: PTR map0_dummy # machtype = unknown - PTR map0_rpc # Deskstation rPC44 - PTR map0_tyne # Deskstation Tyne - PTR map0_pica61 # Acer Pica-61 - PTR map0_magnum4000 # MIPS Magnum 4000PC (RC4030) - PTR map0_dummy - PTR map0_dummy # DEC Personal DECStation 5000/2x (for now) - PTR map0_sni_rm200_pci # SNI RM200 PCI - PTR map0_dummy # SGI INDY - -map0_dummy: .word 0 # 0 entries - - .align 3 -/* - * Deskstation rpc44 mappings. This machine has its EISA bus at physical - * address 0xa0000000 which we map for 32M, but that doesn't match EISA - * spec. Not sure what to do about this. Its I/O ports are memory mapped - * at physical memory location 0xb0000000. - */ -map0_rpc: .word 2 # no. of wired TLB entries - .word 0 # pad for alignment - -MAPDATA(0xffffffffe0000000, 0x02800017, 0x00000001, PM_16M) # ISA Memory space -MAPDATA(0xffffffffe2000000, 0x02c00017, 0x00000001, PM_64K) # ISA I/O Space - -/* - * Initial mappings for Deskstation Tyne boards. - */ -map0_tyne: .word 2 # no. of wired TLB entries - .word 0 # pad for alignment - -MAPDATA(0xffffffffe0000000, 0x04020017, 0x00000001, PM_1M) # VESA DMA cache -MAPDATA(0xffffffffe2000000, 0x24000017, 0x04000017, PM_16M) # VESA I/O and memory space - -/* - * Initial mapping for ACER PICA-61 boards. - * FIXME: These are rather preliminary since many drivers, such as serial, - * parallel, scsi and ethernet need some changes to distinguish between "local" - * (built-in) and "optional" (ISA/PCI) I/O hardware. Local video ram is mapped - * to the same location as the bios maps it to. Console driver has been changed - * accordingly (new video type: VIDEO_TYPE_PICA_S3). - * FIXME: Remove or merge some of the mappings. - */ -map0_pica61: .word 7 # no. wired TLB entries - .word 0 # dummy - -MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000001, PM_64K) # Local I/O space -MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000001, PM_4K) # Interrupt source register -MAPDATA(0xffffffffe0200000, 0x01800017, 0x01804017, PM_1M) # Local video control -MAPDATA(0xffffffffe0400000, 0x01808017, 0x0180c017, PM_1M) # Extended video control -MAPDATA(0xffffffffe0800000, 0x01000017, 0x01010017, PM_4M) # Local video memory (BIOS mapping) -MAPDATA(0xffffffffe2000000, 0x02400017, 0x02440017, PM_16M) # ISA I/O and ISA memory space (both 16M) -MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, PM_4K) # PCR (???) - -/* - * Initial mapping for Mips Magnum 4000PC systems. - * Do you believe me now that the Acer and Mips boxes are nearly the same ? :-) - * FIXME: Remove or merge some of the mappings. - */ -map0_magnum4000: - .word 8 # no. wired TLB entries - .word 0 # dummy - -MAPDATA(0xffffffffe1000000, 0x03ffc013, 0x00000001, PM_256K) # 0 -MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000001, PM_64K) # 1 local I/O -MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000001, PM_4K) # 2 IRQ source -MAPDATA(0xffffffffe0200000, 0x01800017, 0x01804017, PM_1M) # 3 local video ctrl -MAPDATA(0xffffffffe0400000, 0x01808017, 0x0180c017, PM_1M) # 4 ext. video ctrl -MAPDATA(0xffffffffe0800000, 0x01000017, 0x01010017, PM_4M) # 5 local video mem. -MAPDATA(0xffffffffe2000000, 0x02400017, 0x02440017, PM_16M) # 6 ISA I/O and mem. -MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, PM_4K) # 7 PCR - -/* - * The RM200 doesn't need any wired entries. - */ -map0_sni_rm200_pci: - .word 0 # no. wired TLB entries - .word 0 # dummy /* * This buffer is reserved for the use of the cache error handler. diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/init_task.c linux.pre11.3/arch/mips/kernel/init_task.c --- linux.vanilla/arch/mips/kernel/init_task.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/init_task.c Mon Jul 19 23:28:44 1999 @@ -6,7 +6,6 @@ static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; -static struct files * init_fd_array[NR_OPEN] = { NULL, }; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/ipc.c linux.pre11.3/arch/mips/kernel/ipc.c --- linux.vanilla/arch/mips/kernel/ipc.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/ipc.c Mon Jul 19 23:53:55 1999 @@ -1,5 +1,4 @@ -/* - * linux/arch/mips/kernel/ipc.c +/* $Id$ * * This file contains various random system calls that * have a non-standard calling sequence on the Linux/MIPS @@ -22,106 +21,92 @@ * * This is really horribly ugly. FIXME: Get rid of this wrapper. */ -asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth) +asmlinkage int sys_ipc (uint call, int first, int second, + int third, void *ptr, long fifth) { int version, ret; - lock_kernel(); version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; if (call <= SEMCTL) switch (call) { case SEMOP: - ret = sys_semop (first, (struct sembuf *)ptr, second); - goto out; + return sys_semop (first, (struct sembuf *)ptr, second); case SEMGET: - ret = sys_semget (first, second, third); - goto out; + return sys_semget (first, second, third); case SEMCTL: { union semun fourth; - ret = -EINVAL; if (!ptr) - goto out; - ret = -EFAULT; + return -EINVAL; if (get_user(fourth.__pad, (void **) ptr)) - goto out; - ret = sys_semctl (first, second, third, fourth); - goto out; + return -EFAULT; + return sys_semctl (first, second, third, fourth); } default: - ret = -EINVAL; - goto out; + return -EINVAL; } + if (call <= MSGCTL) switch (call) { case MSGSND: - ret = sys_msgsnd (first, (struct msgbuf *) ptr, + return sys_msgsnd (first, (struct msgbuf *) ptr, second, third); - goto out; case MSGRCV: switch (version) { case 0: { struct ipc_kludge tmp; - ret = -EINVAL; if (!ptr) - goto out; - ret = -EFAULT; - if (copy_from_user(&tmp,(struct ipc_kludge *) ptr, - sizeof (tmp))) - goto out; - ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third); - goto out; + return -EINVAL; + + if (copy_from_user(&tmp, + (struct ipc_kludge *) ptr, + sizeof (tmp))) + return -EFAULT; + return sys_msgrcv (first, tmp.msgp, second, + tmp.msgtyp, third); } - case 1: default: - ret = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third); - goto out; + default: + return sys_msgrcv (first, + (struct msgbuf *) ptr, + second, fifth, third); } case MSGGET: - ret = sys_msgget ((key_t) first, second); - goto out; + return sys_msgget ((key_t) first, second); case MSGCTL: - ret = sys_msgctl (first, second, (struct msqid_ds *) ptr); - goto out; + return sys_msgctl (first, second, + (struct msqid_ds *) ptr); default: - ret = -EINVAL; - goto out; + return -EINVAL; } if (call <= SHMCTL) switch (call) { case SHMAT: switch (version) { - case 0: default: { + default: { ulong raddr; - ret = sys_shmat (first, (char *) ptr, second, &raddr); + ret = sys_shmat (first, (char *) ptr, + second, &raddr); if (ret) - goto out; - ret = put_user (raddr, (ulong *) third); - goto out; + return ret; + return put_user (raddr, (ulong *) third); } case 1: /* iBCS2 emulator entry point */ - ret = -EINVAL; if (!segment_eq(get_fs(), get_ds())) - goto out; - ret = sys_shmat (first, (char *) ptr, second, (ulong *) third); - goto out; + return -EINVAL; + return sys_shmat (first, (char *) ptr, + second, (ulong *) third); } case SHMDT: - ret = sys_shmdt ((char *)ptr); - goto out; + return sys_shmdt ((char *)ptr); case SHMGET: - ret = sys_shmget (first, second, third); - goto out; + return sys_shmget (first, second, third); case SHMCTL: - ret = sys_shmctl (first, second, (struct shmid_ds *) ptr); - goto out; + return sys_shmctl (first, second, + (struct shmid_ds *) ptr); default: - ret = -EINVAL; - goto out; + return -EINVAL; } - else - ret = -EINVAL; -out: - unlock_kernel(); - return ret; + + return -EINVAL; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/irix5sys.h linux.pre11.3/arch/mips/kernel/irix5sys.h --- linux.vanilla/arch/mips/kernel/irix5sys.h Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/irix5sys.h Mon Jul 19 23:28:44 1999 @@ -1,4 +1,4 @@ -/* $Id: irix5sys.h,v 1.2 1998/08/17 10:16:25 ralf Exp $ +/* $Id: irix5sys.h,v 1.2 1998/08/25 09:14:39 ralf Exp $ * * irix5sys.h: 32-bit IRIX5 ABI system call table. * diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/irixelf.c linux.pre11.3/arch/mips/kernel/irixelf.c --- linux.vanilla/arch/mips/kernel/irixelf.c Fri Nov 13 01:37:10 1998 +++ linux.pre11.3/arch/mips/kernel/irixelf.c Mon Jul 19 23:28:38 1999 @@ -1,4 +1,5 @@ -/* +/* $Id: irixelf.c,v 1.17.2.2 1999/06/22 20:53:26 ralf Exp $ + * * irixelf.c: Code to load IRIX ELF executables which conform to * the MIPS ABI. * @@ -309,7 +310,7 @@ return 0xffffffff; } - file = current->files->fd[elf_exec_fileno]; + file = fget(elf_exec_fileno); eppnt = elf_phdata; for(i=0; ie_phnum; i++, eppnt++) { @@ -367,6 +368,7 @@ } /* Now use mmap to map the library into memory. */ + fput(file); sys_close(elf_exec_fileno); if(error < 0 && error > -1024) { #ifdef DEBUG_ELF @@ -617,8 +619,9 @@ unsigned int load_addr, elf_bss, elf_brk; unsigned int elf_entry, interp_load_addr = 0; unsigned int start_code, end_code, end_data, elf_stack; - int elf_exec_fileno, retval, has_interp, has_ephdr, i; + int elf_exec_fileno, retval, has_interp, has_ephdr, size, i; char *elf_interpreter; + struct file *file; mm_segment_t old_fs; load_addr = 0; @@ -634,17 +637,15 @@ #endif /* Now read in all of the header information */ - elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize * - elf_ex.e_phnum, GFP_KERNEL); + size = elf_ex.e_phentsize * elf_ex.e_phnum; + elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL); if (elf_phdata == NULL) return -ENOMEM; - retval = read_exec(bprm->dentry, elf_ex.e_phoff, (char *) elf_phdata, - elf_ex.e_phentsize * elf_ex.e_phnum, 1); - if (retval < 0) { - kfree (elf_phdata); - return retval; - } + retval = read_exec(bprm->dentry, elf_ex.e_phoff, + (char *) elf_phdata, size, 1); + if (retval < 0) + goto out_phdata; #ifdef DEBUG_ELF dump_phdrs(elf_phdata, elf_ex.e_phnum); @@ -669,12 +670,10 @@ elf_bss = 0; elf_brk = 0; - elf_exec_fileno = open_dentry(bprm->dentry, O_RDONLY); - - if (elf_exec_fileno < 0) { - kfree (elf_phdata); - return elf_exec_fileno; - } + retval = open_dentry(bprm->dentry, O_RDONLY); + if (retval < 0) + goto out_phdata; + file = fget(elf_exec_fileno = retval); elf_stack = 0xffffffff; elf_interpreter = NULL; @@ -686,40 +685,26 @@ &interpreter_dentry, &interp_elf_ex, elf_phdata, bprm, elf_ex.e_phnum); - if(retval) { - kfree(elf_phdata); - sys_close(elf_exec_fileno); - return retval; - } + if(retval) + goto out_file; if(elf_interpreter) { retval = verify_irix_interpreter(&interp_elf_ex); - if(retval) { - kfree(elf_interpreter); - kfree(elf_phdata); - sys_close(elf_exec_fileno); - return retval; - } + if(retval) + goto out_interp; } /* OK, we are done with that, now set up the arg stuff, * and then start this sucker up. */ - if (!bprm->sh_bang) { - if (!bprm->p) { - if(elf_interpreter) { - kfree(elf_interpreter); - } - kfree (elf_phdata); - sys_close(elf_exec_fileno); - return -E2BIG; - } - } + retval = -E2BIG; + if (!bprm->sh_bang && !bprm->p) + goto out_interp; /* Flush all traces of the currently running executable */ retval = flush_old_exec(bprm); if (retval) - return retval; + goto out_interp; /* OK, This is the point of no return */ current->mm->end_data = 0; @@ -741,8 +726,7 @@ old_fs = get_fs(); set_fs(get_ds()); - map_executable(current->files->fd[elf_exec_fileno], elf_phdata, - elf_ex.e_phnum, &elf_stack, &load_addr, + map_executable(file, elf_phdata, elf_ex.e_phnum, &elf_stack, &load_addr, &start_code, &elf_bss, &end_code, &end_data, &elf_brk); if(elf_interpreter) { @@ -762,6 +746,7 @@ set_fs(old_fs); kfree(elf_phdata); + fput(file); sys_close(elf_exec_fileno); current->personality = PER_IRIX32; @@ -824,6 +809,17 @@ if (current->flags & PF_PTRACED) send_sig(SIGTRAP, current, 0); return 0; + +out_interp: + if(elf_interpreter) { + kfree(elf_interpreter); + } +out_file: + fput(file); + sys_close(elf_exec_fileno); +out_phdata: + kfree (elf_phdata); + return retval; } static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs) @@ -839,9 +835,8 @@ /* This is really simpleminded and specialized - we are loading an * a.out library that is given an ELF header. */ -static inline int do_load_irix_library(int fd) +static inline int do_load_irix_library(struct file *file) { - struct file * file; struct elfhdr elf_ex; struct elf_phdr *elf_phdata = NULL; struct dentry *dentry; @@ -854,14 +849,12 @@ int i,j, k; len = 0; - file = current->files->fd[fd]; + if (!file->f_op) + return -EACCES; dentry = file->f_dentry; inode = dentry->d_inode; elf_bss = 0; - if (!file || !file->f_op) - return -EACCES; - /* Seek to the beginning of the file. */ if (file->f_op->llseek) { if ((error = file->f_op->llseek(file, 0, 0)) != 0) @@ -940,10 +933,15 @@ static int load_irix_library(int fd) { - int retval; + int retval = -EACCES; + struct file *file; MOD_INC_USE_COUNT; - retval = do_load_irix_library(fd); + file = fget(fd); + if (file) { + retval = do_load_irix_library(file); + fput(file); + } MOD_DEC_USE_COUNT; return retval; } @@ -984,9 +982,12 @@ return -ENOEXEC; } - filp = current->files->fd[fd]; - if(!filp || !filp->f_op) { + filp = fget(fd); + if (!filp) + return -EACCES; + if(!filp->f_op) { printk("irix_mapelf: Bogon filp!\n"); + fput(file); return -EACCES; } @@ -1004,6 +1005,7 @@ if(retval != (hp->p_vaddr & 0xfffff000)) { printk("irix_mapelf: do_mmap fails with %d!\n", retval); + fput(file); return retval; } } @@ -1011,6 +1013,7 @@ #ifdef DEBUG_ELF printk("irix_mapelf: Success, returning %08lx\n", user_phdrp->p_vaddr); #endif + fput(file); return user_phdrp->p_vaddr; } @@ -1026,7 +1029,13 @@ */ static int dump_write(struct file *file, const void *addr, int nr) { - return file->f_op->write(file, addr, nr, &file->f_pos) == nr; + int r; + + down(&file->f_dentry->d_inode->i_sem); + r = file->f_op->write(file, addr, nr, &file->f_pos) == nr; + up(&file->f_dentry->d_inode->i_sem); + + return r; } static int dump_seek(struct file *file, off_t off) @@ -1108,10 +1117,10 @@ #undef DUMP_SEEK #define DUMP_WRITE(addr, nr) \ - if (!dump_write(&file, (addr), (nr))) \ + if (!dump_write(file, (addr), (nr))) \ goto close_coredump; #define DUMP_SEEK(off) \ - if (!dump_seek(&file, (off))) \ + if (!dump_seek(file, (off))) \ goto close_coredump; /* Actual dumper. * @@ -1122,7 +1131,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs) { int has_dumped = 0; - struct file file; + struct file *file; struct dentry *dentry; struct inode *inode; mm_segment_t fs; @@ -1191,26 +1200,28 @@ fs = get_fs(); set_fs(KERNEL_DS); + memcpy(corefile,"core.", 5); #if 0 memcpy(corefile+5,current->comm,sizeof(current->comm)); #else corefile[4] = '\0'; #endif - dentry = open_namei(corefile, O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600); - if (IS_ERR(dentry)) { - inode = NULL; + file = filp_open(corefile, O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600); + if (IS_ERR(file)) goto end_coredump; - } + dentry = file->f_dentry; inode = dentry->d_inode; + if (inode->i_nlink > 1) + goto close_coredump; /* multiple links - don't dump */ + if (!S_ISREG(inode->i_mode)) - goto end_coredump; + goto close_coredump; if (!inode->i_op || !inode->i_op->default_file_ops) - goto end_coredump; - if (init_private_file(&file, dentry, 3)) - goto end_coredump; - if (!file.f_op->write) goto close_coredump; + if (!file->f_op->write) + goto close_coredump; + has_dumped = 1; current->flags |= PF_DUMPCORE; @@ -1346,7 +1357,7 @@ } for(i = 0; i < numnote; i++) - if (!writenote(¬es[i], &file)) + if (!writenote(¬es[i], file)) goto close_coredump; set_fs(fs); @@ -1368,19 +1379,17 @@ DUMP_WRITE((void *)addr, len); } - if ((off_t) file.f_pos != offset) { + if ((off_t) file->f_pos != offset) { /* Sanity check. */ - printk("elf_core_dump: file.f_pos (%ld) != offset (%ld)\n", - (off_t) file.f_pos, offset); + printk("elf_core_dump: file->f_pos (%ld) != offset (%ld)\n", + (off_t) file->f_pos, offset); } close_coredump: - if (file.f_op->release) - file.f_op->release(inode, &file); + filp_close(file, NULL); end_coredump: set_fs(fs); - dput(dentry); #ifndef CONFIG_BINFMT_ELF MOD_DEC_USE_COUNT; #endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/irixinv.c linux.pre11.3/arch/mips/kernel/irixinv.c --- linux.vanilla/arch/mips/kernel/irixinv.c Sun Nov 8 15:08:30 1998 +++ linux.pre11.3/arch/mips/kernel/irixinv.c Mon Jul 19 23:28:45 1999 @@ -5,7 +5,7 @@ * * Miguel de Icaza, 1997. * - * $Id: irixinv.c,v 1.3 1998/03/27 08:53:40 ralf Exp $ + * $Id: irixinv.c,v 1.3 1998/04/05 11:23:51 ralf Exp $ */ #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/irixioctl.c linux.pre11.3/arch/mips/kernel/irixioctl.c --- linux.vanilla/arch/mips/kernel/irixioctl.c Thu May 27 22:11:50 1999 +++ linux.pre11.3/arch/mips/kernel/irixioctl.c Mon Jul 19 23:28:45 1999 @@ -1,4 +1,4 @@ -/* $Id: irixioctl.c,v 1.4 1998/03/04 12:17:41 ralf Exp $ +/* $Id: irixioctl.c,v 1.6 1999/02/06 05:12:56 adevries Exp $ * irixioctl.c: A fucking mess... * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -33,15 +34,13 @@ { struct file *filp; - file = fcheck(fd); - if(!file) + if(!(filp = fcheck(fd))) return ((struct tty_struct *) 0); if(filp->private_data) { struct tty_struct *ttyp = (struct tty_struct *) filp->private_data; - if(ttyp->magic == TTY_MAGIC) { + if(ttyp->magic == TTY_MAGIC) return ttyp; - } } return ((struct tty_struct *) 0); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/irixsig.c linux.pre11.3/arch/mips/kernel/irixsig.c --- linux.vanilla/arch/mips/kernel/irixsig.c Sun Nov 8 15:10:06 1998 +++ linux.pre11.3/arch/mips/kernel/irixsig.c Mon Jul 19 23:28:45 1999 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: irixsig.c,v 1.11 1998/03/26 07:39:09 ralf Exp $ + * $Id: irixsig.c,v 1.10.2.2 1999/06/17 12:06:39 ralf Exp $ */ #include @@ -272,6 +272,7 @@ default: lock_kernel(); sigaddset(¤t->signal, signr); + recalc_sigpending(current); current->flags |= PF_SIGNALED; do_exit(exit_code); /* NOTREACHED */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/irq.c linux.pre11.3/arch/mips/kernel/irq.c --- linux.vanilla/arch/mips/kernel/irq.c Mon Dec 28 23:09:40 1998 +++ linux.pre11.3/arch/mips/kernel/irq.c Mon Jul 19 23:28:37 1999 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.13 1998/05/28 03:17:55 ralf Exp $ +/* $Id: irq.c,v 1.15 1999/02/25 21:50:49 tsbogend Exp $ * * 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 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -27,9 +28,21 @@ #include #include #include +#include -unsigned char cache_21 = 0xff; -unsigned char cache_A1 = 0xff; +/* + * This contains the irq mask for both 8259A irq controllers, it's an + * int so we can deal with the third PIC in some systems like the RM300. + * (XXX This is broken for big endian.) + */ +static unsigned int cached_irq_mask = 0xffff; + +#define __byte(x,y) (((unsigned char *)&(y))[x]) +#define __word(x,y) (((unsigned short *)&(y))[x]) +#define __long(x,y) (((unsigned int *)&(y))[x]) + +#define cached_21 (__byte(0,cached_irq_mask)) +#define cached_A1 (__byte(1,cached_irq_mask)) unsigned int local_bh_count[NR_CPUS]; unsigned int local_irq_count[NR_CPUS]; @@ -39,31 +52,23 @@ * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and * PCI devices. Other onboard hardware needs specific routines. */ -static inline void mask_irq(unsigned int irq_nr) +static inline void mask_irq(unsigned int irq) { - unsigned char mask; - - mask = 1 << (irq_nr & 7); - if (irq_nr < 8) { - cache_21 |= mask; - outb(cache_21,0x21); + cached_irq_mask |= 1 << irq; + if (irq & 8) { + outb(cached_A1, 0xa1); } else { - cache_A1 |= mask; - outb(cache_A1,0xA1); + outb(cached_21, 0x21); } } -static inline void unmask_irq(unsigned int irq_nr) +static inline void unmask_irq(unsigned int irq) { - unsigned char mask; - - mask = ~(1 << (irq_nr & 7)); - if (irq_nr < 8) { - cache_21 &= mask; - outb(cache_21,0x21); + cached_irq_mask &= ~(1 << irq); + if (irq & 8) { + outb(cached_A1, 0xa1); } else { - cache_A1 &= mask; - outb(cache_A1,0xA1); + outb(cached_21, 0x21); } } @@ -84,13 +89,11 @@ restore_flags(flags); } -/* - * Pointers to the low-level handlers: first the general ones, then the - * fast ones, then the bad ones. - */ -extern void interrupt(void); - -static struct irqaction *irq_action[32] = { +static struct irqaction *irq_action[NR_IRQS] = { + 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, 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, @@ -122,6 +125,59 @@ atomic_t __mips_bh_counter; +static inline void i8259_mask_and_ack_irq(int irq) +{ + cached_irq_mask |= 1 << irq; + + if (irq & 8) { + inb(0xa1); + outb(cached_A1, 0xa1); + outb(0x62, 0x20); /* Specific EOI to cascade */ + outb(0x20, 0xa0); + } else { + inb(0x21); + outb(cached_21, 0x21); + outb(0x20, 0x20); + } +} + +asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs) +{ + struct irqaction *action; + int do_random, cpu; + + cpu = smp_processor_id(); + hardirq_enter(cpu); + + if (irq >= 16) + goto out; + + i8259_mask_and_ack_irq(irq); + + kstat.irqs[cpu][irq]++; + + action = *(irq + irq_action); + if (!action) + goto out; + + if (!(action->flags & SA_INTERRUPT)) + __sti(); + action = *(irq + irq_action); + do_random = 0; + do { + do_random |= action->flags; + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + if (do_random & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + __cli(); + unmask_irq (irq); + +out: + hardirq_exit(cpu); +} + /* * do_IRQ handles IRQ's that have been installed without the * SA_INTERRUPT flag: it uses the full signal-handling return @@ -135,23 +191,9 @@ int do_random, cpu; cpu = smp_processor_id(); - irq_enter(cpu, irq); + hardirq_enter(cpu); kstat.irqs[cpu][irq]++; - /* - * mask and ack quickly, we don't want the irq controller - * thinking we're snobs just because some other CPU has - * disabled global interrupts (we have already done the - * INT_ACK cycles, it's too late to try to pretend to the - * controller that we aren't taking the interrupt). - * - * Commented out because we've already done this in the - * machinespecific part of the handler. It's reasonable to - * do this here in a highlevel language though because that way - * we could get rid of a good part of duplicated code ... - */ - /* mask_and_ack_irq(irq); */ - action = *(irq + irq_action); if (action) { if (!(action->flags & SA_INTERRUPT)) @@ -165,21 +207,14 @@ } while (action); if (do_random & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - unmask_irq (irq); __cli(); } - irq_exit(cpu, irq); + hardirq_exit(cpu); /* unmasking and bottom half handling is done magically for us. */ } -/* - * Used only for setup of PC style interrupts and therefore still - * called setup_x86_irq. Later on I'll provide a machine specific - * function with similar purpose. Idea is to put all interrupts - * in a single table and differenciate them just by number. - */ -int setup_x86_irq(int irq, struct irqaction * new) +int i8259_setup_irq(int irq, struct irqaction * new) { int shared = 0; struct irqaction *old, **p; @@ -216,11 +251,15 @@ return 0; } +/* + * Request_interrupt and free_interrupt ``sort of'' handle interrupts of + * non i8259 devices. They will have to be replaced by architecture + * specific variants. For now we still use this as broken as it is because + * it used to work ... + */ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, - const char * devname, - void *dev_id) + unsigned long irqflags, const char * devname, void *dev_id) { int retval; struct irqaction * action; @@ -241,7 +280,7 @@ action->next = NULL; action->dev_id = dev_id; - retval = setup_x86_irq(irq, action); + retval = i8259_setup_irq(irq, action); if (retval) kfree(action); @@ -275,7 +314,7 @@ unsigned long probe_irq_on (void) { - unsigned int i, irqs = 0, irqmask; + unsigned int i, irqs = 0; unsigned long delay; /* first, enable any unassigned (E)ISA irqs */ @@ -291,19 +330,17 @@ /* about 100ms delay */; /* now filter out any obviously spurious interrupts */ - irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21; - return irqs & ~irqmask; + return irqs & ~cached_irq_mask; } int probe_irq_off (unsigned long irqs) { - unsigned int i, irqmask; + unsigned int i; - irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21; #ifdef DEBUG printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask); #endif - irqs &= irqmask; + irqs &= cached_irq_mask; if (!irqs) return 0; i = ffz(~irqs); @@ -314,13 +351,36 @@ int (*irq_cannonicalize)(int irq); -static int i8259a_irq_cannonicalize(int irq) +static int i8259_irq_cannonicalize(int irq) { return ((irq == 2) ? 9 : irq); } +__initfunc(static void i8259_init(void)) +{ + /* Init master interrupt controller */ + outb(0x11, 0x20); /* Start init sequence */ + outb(0x00, 0x21); /* Vector base */ + outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */ + outb(0x01, 0x21); /* Select 8086 mode */ + outb(0xff, 0x21); /* Mask all */ + + /* Init slave interrupt controller */ + outb(0x11, 0xa0); /* Start init sequence */ + outb(0x08, 0xa1); /* Vector base */ + outb(0x02, 0xa1); /* edge triggered, Cascade (slave) on IRQ2 */ + outb(0x01, 0xa1); /* Select 8086 mode */ + outb(0xff, 0xa1); /* Mask all */ + + outb(cached_A1, 0xa1); + outb(cached_21, 0x21); +} + __initfunc(void init_IRQ(void)) { - irq_cannonicalize = i8259a_irq_cannonicalize; + irq_cannonicalize = i8259_irq_cannonicalize; + /* i8259_init(); */ irq_setup(); } + +EXPORT_SYMBOL(irq_cannonicalize); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/mips_ksyms.c linux.pre11.3/arch/mips/kernel/mips_ksyms.c --- linux.vanilla/arch/mips/kernel/mips_ksyms.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/mips_ksyms.c Mon Jul 19 23:28:45 1999 @@ -1,4 +1,4 @@ -/* $Id: mips_ksyms.c,v 1.12 1998/09/16 22:50:41 ralf Exp $ +/* $Id: mips_ksyms.c,v 1.19 1999/04/11 18:37:55 harald Exp $ * * Export MIPS-specific functions needed for loadable modules. * @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -50,23 +51,25 @@ EXPORT_SYMBOL_NOVERS(strnlen); EXPORT_SYMBOL_NOVERS(strrchr); EXPORT_SYMBOL_NOVERS(strtok); +EXPORT_SYMBOL_NOVERS(strpbrk); EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(__mips_bh_counter); EXPORT_SYMBOL(local_bh_count); EXPORT_SYMBOL(local_irq_count); -//EXPORT_SYMBOL(enable_irq); -//EXPORT_SYMBOL(disable_irq); +EXPORT_SYMBOL(enable_irq); +EXPORT_SYMBOL(disable_irq); +EXPORT_SYMBOL(kernel_thread); /* * Userspace access stuff. */ -EXPORT_SYMBOL(__copy_user); -EXPORT_SYMBOL(__bzero); -EXPORT_SYMBOL(__strncpy_from_user_nocheck_asm); -EXPORT_SYMBOL(__strncpy_from_user_asm); -EXPORT_SYMBOL(__strlen_user_nocheck_asm); -EXPORT_SYMBOL(__strlen_user_asm); +EXPORT_SYMBOL_NOVERS(__copy_user); +EXPORT_SYMBOL_NOVERS(__bzero); +EXPORT_SYMBOL_NOVERS(__strncpy_from_user_nocheck_asm); +EXPORT_SYMBOL_NOVERS(__strncpy_from_user_asm); +EXPORT_SYMBOL_NOVERS(__strlen_user_nocheck_asm); +EXPORT_SYMBOL_NOVERS(__strlen_user_asm); /* Networking helper routines. */ @@ -77,6 +80,10 @@ */ EXPORT_SYMBOL(flush_page_to_ram); EXPORT_SYMBOL(flush_cache_all); +EXPORT_SYMBOL(dma_cache_wback_inv); +EXPORT_SYMBOL(dma_cache_inv); + +EXPORT_SYMBOL(invalid_pte_table); /* * Base address of ports for Intel style I/O. @@ -106,12 +113,12 @@ int unregister_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31)); #ifdef CONFIG_MIPS_FPE_MODULE -EXPORT_SYMBOL(force_sig); EXPORT_SYMBOL(__compute_return_epc); EXPORT_SYMBOL(register_fpe); EXPORT_SYMBOL(unregister_fpe); #endif -#if CONFIG_PCI -EXPORT_SYMBOL(pci_devices); +#ifdef CONFIG_VT +EXPORT_SYMBOL(screen_info); #endif + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/pci.c linux.pre11.3/arch/mips/kernel/pci.c --- linux.vanilla/arch/mips/kernel/pci.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/pci.c Mon Jul 19 23:28:45 1999 @@ -1,4 +1,4 @@ -/* $Id: pci.c,v 1.6 1998/08/19 21:53:50 ralf Exp $ +/* $Id: pci.c,v 1.8 1999/05/01 22:40:36 ralf Exp $ * * 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 @@ -36,13 +36,13 @@ } /* - * The functions below are machine specific and must be reimplented for + * The functions below are machine specific and must be reimplimented for * each PCI chipset configuration. We just run the hook to the machine * specific implementation. */ void pcibios_fixup (void) { - return pci_ops->pcibios_fixup(); + pci_ops->pcibios_fixup(); } int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn, @@ -88,11 +88,6 @@ __initfunc(void pcibios_fixup_bus(struct pci_bus *bus)) { -} - -__initfunc(char *pcibios_setup(char *str)) -{ - return str; } #endif /* defined(CONFIG_PCI) */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/process.c linux.pre11.3/arch/mips/kernel/process.c --- linux.vanilla/arch/mips/kernel/process.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/process.c Mon Jul 19 23:28:37 1999 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.11 1998/08/17 12:14:53 ralf Exp $ +/* $Id: process.c,v 1.11 1999/01/03 17:50:51 ralf Exp $ * * 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 @@ -144,4 +144,41 @@ (current->mm->start_stack - dump->start_stack + PAGE_SIZE - 1) >> PAGE_SHIFT; memcpy(&dump->regs[0], regs, sizeof(struct pt_regs)); memcpy(&dump->regs[EF_SIZE/4], ¤t->tss.fpu, sizeof(current->tss.fpu)); +} + +/* + * Create a kernel thread + */ +pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + long retval; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + "move\t$6,$sp\n\t" + "move\t$4,%5\n\t" + "li\t$2,%1\n\t" + "syscall\n\t" + "beq\t$6,$sp,1f\n\t" + "subu\t$sp,32\n\t" /* delay slot */ + "jalr\t%4\n\t" + "move\t$4,%3\n\t" /* delay slot */ + "move\t$4,$2\n\t" + "li\t$2,%2\n\t" + "syscall\n" + "1:\taddiu\t$sp,32\n\t" + "move\t%0,$2\n\t" + ".set\treorder" + :"=r" (retval) + :"i" (__NR_clone), "i" (__NR_exit), + "r" (arg), "r" (fn), + "r" (flags | CLONE_VM) + /* + * The called subroutine might have destroyed any of the + * at, result, argument or temporary registers ... + */ + :"$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", + "$9","$10","$11","$12","$13","$14","$15","$24","$25"); + + return retval; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/ptrace.c linux.pre11.3/arch/mips/kernel/ptrace.c --- linux.vanilla/arch/mips/kernel/ptrace.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/ptrace.c Mon Jul 19 23:28:37 1999 @@ -1,4 +1,4 @@ -/* $Id: ptrace.c,v 1.11 1998/10/19 16:26:31 ralf Exp $ +/* $Id: ptrace.c,v 1.12 1999/06/13 16:30:32 ralf Exp $ * * 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 @@ -259,6 +259,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; + unsigned int flags; int res; lock_kernel(); @@ -297,22 +298,26 @@ (current->uid != child->uid) || (current->gid != child->egid) || (current->gid != child->sgid) || - (current->gid != child->gid)) && - !capable(CAP_SYS_PTRACE)) { + (current->gid != child->gid) || + (!cap_issubset(child->cap_permitted, + current->cap_permitted)) || + (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)){ res = -EPERM; goto out; } /* the same process cannot be attached many times */ - if (child->flags & PF_PTRACED) { - res = -EPERM; + if (child->flags & PF_PTRACED) goto out; - } child->flags |= PF_PTRACED; + + write_lock_irqsave(&tasklist_lock, flags); if (child->p_pptr != current) { REMOVE_LINKS(child); child->p_pptr = current; SET_LINKS(child); } + write_unlock_irqrestore(&tasklist_lock, flags); + send_sig(SIGSTOP, child, 1); res = 0; goto out; @@ -337,15 +342,16 @@ case PTRACE_PEEKDATA: { unsigned long tmp; + down(&child->mm->mmap_sem); res = read_long(child, addr, &tmp); + up(&child->mm->mmap_sem); if (res < 0) goto out; res = put_user(tmp,(unsigned long *) data); goto out; } - /* read the word at location addr in the USER area. */ -/* #define DEBUG_PEEKUSR */ + /* Read the word at location addr in the USER area. */ case PTRACE_PEEKUSR: { struct pt_regs *regs; unsigned long tmp; @@ -353,12 +359,15 @@ regs = (struct pt_regs *) ((unsigned long) child + KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); tmp = 0; /* Default return value. */ - if (addr < 32 && addr >= 0) - tmp = regs->regs[addr]; - else if (addr >= 32 && addr < 64) { - unsigned long long *fregs; + switch(addr) { + case 0 ... 31: + tmp = regs->regs[addr]; + break; + case FPR_BASE ... FPR_BASE + 31: if (child->used_math) { + unsigned long long *fregs; + if (last_task_used_math == child) { enable_cp1(); r4xx0_save_fp(child); @@ -371,35 +380,32 @@ } else { tmp = -1; /* FP not yet used */ } - } else { - addr -= 64; - switch(addr) { - case 0: - tmp = regs->cp0_epc; - break; - case 1: - tmp = regs->cp0_cause; - break; - case 2: - tmp = regs->cp0_badvaddr; - break; - case 3: - tmp = regs->lo; - break; - case 4: - tmp = regs->hi; - break; - case 5: - tmp = child->tss.fpu.hard.control; - break; - case 6: /* implementation / version register */ - tmp = 0; /* XXX */ - break; - default: - tmp = 0; - res = -EIO; - goto out; - } + break; + case PC: + tmp = regs->cp0_epc; + break; + case CAUSE: + tmp = regs->cp0_cause; + break; + case BADVADDR: + tmp = regs->cp0_badvaddr; + break; + case MMHI: + tmp = regs->hi; + break; + case MMLO: + tmp = regs->lo; + break; + case FPC_CSR: + tmp = child->tss.fpu.hard.control; + break; + case FPC_EIR: /* implementation / version register */ + tmp = 0; /* XXX */ + break; + default: + tmp = 0; + res = -EIO; + goto out; } res = put_user(tmp, (unsigned long *) data); goto out; @@ -407,20 +413,22 @@ case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA: + down(&child->mm->mmap_sem); res = write_long(child,addr,data); + up(&child->mm->mmap_sem); goto out; case PTRACE_POKEUSR: { + unsigned long long *fregs; struct pt_regs *regs; int res = 0; - regs = (struct pt_regs *) ((unsigned long) child + - KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); - if (addr < 32 && addr >= 0) - regs->regs[addr] = data; - else if (addr >= 32 && addr < 64) { - unsigned long long *fregs; - + switch (addr) { + case 0 ... 31: + regs = (struct pt_regs *) ((unsigned long) child + + KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); + break; + case FPR_BASE ... FPR_BASE + 31: if (child->used_math) { if (last_task_used_math == child) { enable_cp1(); @@ -437,26 +445,23 @@ fregs = (unsigned long long *) &child->tss.fpu.hard.fp_regs[0]; fregs[(addr - 32)] = (unsigned long long) data; - } else { - addr -= 64; - switch (addr) { - case 0: - regs->cp0_epc = data; - break; - case 3: - regs->lo = data; - break; - case 4: - regs->hi = data; - break; - case 5: - child->tss.fpu.hard.control = data; - break; - default: - /* The rest are not allowed. */ - res = -EIO; - break; - }; + break; + case PC: + regs->cp0_epc = data; + break; + case MMHI: + regs->hi = data; + break; + case MMLO: + regs->lo = data; + break; + case FPC_CSR: + child->tss.fpu.hard.control = data; + break; + default: + /* The rest are not allowed. */ + res = -EIO; + break; } goto out; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/r2300_fpu.S linux.pre11.3/arch/mips/kernel/r2300_fpu.S --- linux.vanilla/arch/mips/kernel/r2300_fpu.S Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/r2300_fpu.S Mon Jul 19 23:28:42 1999 @@ -1,16 +1,17 @@ -/* +/* $Id: r2300_fpu.S,v 1.5 1999/05/01 22:40:36 ralf Exp $ * r2300_fpu.S: Save/restore floating point context for signal handlers. * * 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. * - * Copyright (C) 1996 by Ralf Baechle + * Copyright (C) 1996, 1998 by Ralf Baechle * * Multi-arch abstraction and asm macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r2300_fpu.S,v 1.3 1997/12/01 16:54:20 ralf Exp $ + * Further modifications to make this work: + * Copyright (c) 1998 Harald Koerfgen */ #include #include @@ -18,123 +19,103 @@ #include #include - .set mips3 +#define EX(a,b) \ +9: a,##b; \ + .section __ex_table,"a"; \ + PTR 9b,bad_stack; \ + .previous + .set noreorder + .set mips1 /* Save floating point context */ - .align 5 - LEAF(r2300_save_fp_context) - mfc0 t0,CP0_STATUS - sll t0,t0,2 - - bgez t0,1f - nop - - cfc1 t0,fcr31 - /* Store the 32 single precision registers */ - swc1 $f0,(SC_FPREGS+0)(a0) - swc1 $f1,(SC_FPREGS+8)(a0) - swc1 $f2,(SC_FPREGS+16)(a0) - swc1 $f3,(SC_FPREGS+24)(a0) - swc1 $f4,(SC_FPREGS+32)(a0) - swc1 $f5,(SC_FPREGS+40)(a0) - swc1 $f6,(SC_FPREGS+48)(a0) - swc1 $f7,(SC_FPREGS+56)(a0) - swc1 $f8,(SC_FPREGS+64)(a0) - swc1 $f9,(SC_FPREGS+72)(a0) - swc1 $f10,(SC_FPREGS+80)(a0) - swc1 $f11,(SC_FPREGS+88)(a0) - swc1 $f12,(SC_FPREGS+96)(a0) - swc1 $f13,(SC_FPREGS+104)(a0) - swc1 $f14,(SC_FPREGS+112)(a0) - swc1 $f15,(SC_FPREGS+120)(a0) - swc1 $f16,(SC_FPREGS+128)(a0) - swc1 $f17,(SC_FPREGS+136)(a0) - swc1 $f18,(SC_FPREGS+144)(a0) - swc1 $f19,(SC_FPREGS+152)(a0) - swc1 $f20,(SC_FPREGS+160)(a0) - swc1 $f21,(SC_FPREGS+168)(a0) - swc1 $f22,(SC_FPREGS+176)(a0) - swc1 $f23,(SC_FPREGS+184)(a0) - swc1 $f24,(SC_FPREGS+192)(a0) - swc1 $f25,(SC_FPREGS+200)(a0) - swc1 $f26,(SC_FPREGS+208)(a0) - swc1 $f27,(SC_FPREGS+216)(a0) - swc1 $f28,(SC_FPREGS+224)(a0) - swc1 $f29,(SC_FPREGS+232)(a0) - swc1 $f30,(SC_FPREGS+240)(a0) - swc1 $f31,(SC_FPREGS+248)(a0) - sw t0,SC_FPC_CSR(a0) +LEAF(r2300_save_fp_context) + + cfc1 t1,fcr31 + EX(swc1 $f0,(SC_FPREGS+0)(a0)) + EX(swc1 $f1,(SC_FPREGS+8)(a0)) + EX(swc1 $f2,(SC_FPREGS+16)(a0)) + EX(swc1 $f3,(SC_FPREGS+24)(a0)) + EX(swc1 $f4,(SC_FPREGS+32)(a0)) + EX(swc1 $f5,(SC_FPREGS+40)(a0)) + EX(swc1 $f6,(SC_FPREGS+48)(a0)) + EX(swc1 $f7,(SC_FPREGS+56)(a0)) + EX(swc1 $f8,(SC_FPREGS+64)(a0)) + EX(swc1 $f9,(SC_FPREGS+72)(a0)) + EX(swc1 $f10,(SC_FPREGS+80)(a0)) + EX(swc1 $f11,(SC_FPREGS+88)(a0)) + EX(swc1 $f12,(SC_FPREGS+96)(a0)) + EX(swc1 $f13,(SC_FPREGS+104)(a0)) + EX(swc1 $f14,(SC_FPREGS+112)(a0)) + EX(swc1 $f15,(SC_FPREGS+120)(a0)) + EX(swc1 $f16,(SC_FPREGS+128)(a0)) + EX(swc1 $f17,(SC_FPREGS+136)(a0)) + EX(swc1 $f18,(SC_FPREGS+144)(a0)) + EX(swc1 $f19,(SC_FPREGS+152)(a0)) + EX(swc1 $f20,(SC_FPREGS+160)(a0)) + EX(swc1 $f21,(SC_FPREGS+168)(a0)) + EX(swc1 $f22,(SC_FPREGS+176)(a0)) + EX(swc1 $f23,(SC_FPREGS+184)(a0)) + EX(swc1 $f24,(SC_FPREGS+192)(a0)) + EX(swc1 $f25,(SC_FPREGS+200)(a0)) + EX(swc1 $f26,(SC_FPREGS+208)(a0)) + EX(swc1 $f27,(SC_FPREGS+216)(a0)) + EX(swc1 $f28,(SC_FPREGS+224)(a0)) + EX(swc1 $f29,(SC_FPREGS+232)(a0)) + EX(swc1 $f30,(SC_FPREGS+240)(a0)) + EX(swc1 $f31,(SC_FPREGS+248)(a0)) + EX(sw t1,SC_FPC_CSR(a0)) cfc1 t0,$0 # implementation/version jr ra .set nomacro - sw t0,SC_FPC_EIR(a0) - .set macro -1: - jr ra - .set nomacro - nop + EX(sw t0,SC_FPC_EIR(a0)) .set macro END(r2300_save_fp_context) /* - * Restore fpu state: + * Restore FPU state: * - fp gp registers * - cp1 status/control register * - * We base the decission which registers to restore from the signal stack + * We base the decision which registers to restore from the signal stack * frame on the current content of c0_status, not on the content of the * stack frame which might have been changed by the user. */ - LEAF(r2300_restore_fp_context) - mfc0 t0,CP0_STATUS - sll t0,t0,2 - - bgez t0,1f - nop - - lw t0,SC_FPC_CSR(a0) - /* Restore the 16 odd double precision registers only - * when enabled in the cp0 status register. - */ - ldc1 $f0,(SC_FPREGS+0)(a0) - ldc1 $f1,(SC_FPREGS+8)(a0) - ldc1 $f2,(SC_FPREGS+16)(a0) - ldc1 $f3,(SC_FPREGS+24)(a0) - ldc1 $f4,(SC_FPREGS+32)(a0) - ldc1 $f5,(SC_FPREGS+40)(a0) - ldc1 $f6,(SC_FPREGS+48)(a0) - ldc1 $f7,(SC_FPREGS+56)(a0) - ldc1 $f8,(SC_FPREGS+64)(a0) - ldc1 $f9,(SC_FPREGS+72)(a0) - ldc1 $f10,(SC_FPREGS+80)(a0) - ldc1 $f11,(SC_FPREGS+88)(a0) - ldc1 $f12,(SC_FPREGS+96)(a0) - ldc1 $f13,(SC_FPREGS+104)(a0) - ldc1 $f14,(SC_FPREGS+112)(a0) - ldc1 $f15,(SC_FPREGS+120)(a0) - ldc1 $f16,(SC_FPREGS+128)(a0) - ldc1 $f17,(SC_FPREGS+136)(a0) - ldc1 $f18,(SC_FPREGS+144)(a0) - ldc1 $f19,(SC_FPREGS+152)(a0) - ldc1 $f20,(SC_FPREGS+160)(a0) - ldc1 $f21,(SC_FPREGS+168)(a0) - ldc1 $f22,(SC_FPREGS+176)(a0) - ldc1 $f23,(SC_FPREGS+184)(a0) - ldc1 $f24,(SC_FPREGS+192)(a0) - ldc1 $f25,(SC_FPREGS+200)(a0) - ldc1 $f26,(SC_FPREGS+208)(a0) - ldc1 $f27,(SC_FPREGS+216)(a0) - ldc1 $f28,(SC_FPREGS+224)(a0) - ldc1 $f29,(SC_FPREGS+232)(a0) - ldc1 $f30,(SC_FPREGS+240)(a0) - ldc1 $f31,(SC_FPREGS+248)(a0) +LEAF(r2300_restore_fp_context) + EX(lw t0,SC_FPC_CSR(a0)) + EX(lwc1 $f0,(SC_FPREGS+0)(a0)) + EX(lwc1 $f1,(SC_FPREGS+8)(a0)) + EX(lwc1 $f2,(SC_FPREGS+16)(a0)) + EX(lwc1 $f3,(SC_FPREGS+24)(a0)) + EX(lwc1 $f4,(SC_FPREGS+32)(a0)) + EX(lwc1 $f5,(SC_FPREGS+40)(a0)) + EX(lwc1 $f6,(SC_FPREGS+48)(a0)) + EX(lwc1 $f7,(SC_FPREGS+56)(a0)) + EX(lwc1 $f8,(SC_FPREGS+64)(a0)) + EX(lwc1 $f9,(SC_FPREGS+72)(a0)) + EX(lwc1 $f10,(SC_FPREGS+80)(a0)) + EX(lwc1 $f11,(SC_FPREGS+88)(a0)) + EX(lwc1 $f12,(SC_FPREGS+96)(a0)) + EX(lwc1 $f13,(SC_FPREGS+104)(a0)) + EX(lwc1 $f14,(SC_FPREGS+112)(a0)) + EX(lwc1 $f15,(SC_FPREGS+120)(a0)) + EX(lwc1 $f16,(SC_FPREGS+128)(a0)) + EX(lwc1 $f17,(SC_FPREGS+136)(a0)) + EX(lwc1 $f18,(SC_FPREGS+144)(a0)) + EX(lwc1 $f19,(SC_FPREGS+152)(a0)) + EX(lwc1 $f20,(SC_FPREGS+160)(a0)) + EX(lwc1 $f21,(SC_FPREGS+168)(a0)) + EX(lwc1 $f22,(SC_FPREGS+176)(a0)) + EX(lwc1 $f23,(SC_FPREGS+184)(a0)) + EX(lwc1 $f24,(SC_FPREGS+192)(a0)) + EX(lwc1 $f25,(SC_FPREGS+200)(a0)) + EX(lwc1 $f26,(SC_FPREGS+208)(a0)) + EX(lwc1 $f27,(SC_FPREGS+216)(a0)) + EX(lwc1 $f28,(SC_FPREGS+224)(a0)) + EX(lwc1 $f29,(SC_FPREGS+232)(a0)) + EX(lwc1 $f30,(SC_FPREGS+240)(a0)) + EX(lwc1 $f31,(SC_FPREGS+248)(a0)) jr ra - .set nomacro ctc1 t0,fcr31 - .set macro -1: - jr ra - .set nomacro - nop - .set macro END(r2300_restore_fp_context) + + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/r2300_misc.S linux.pre11.3/arch/mips/kernel/r2300_misc.S --- linux.vanilla/arch/mips/kernel/r2300_misc.S Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/r2300_misc.S Mon Jul 19 23:53:55 1999 @@ -1,14 +1,17 @@ -/* $Id: r2300_misc.S,v 1.1.1.1 1997/06/01 03:16:42 ralf Exp $ +/* $Id: r2300_misc.S,v 1.3 1999/05/01 22:40:36 ralf Exp $ * r2300_misc.S: Misc. exception handling code for R3000/R2000. * * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse * - * Multi-cpu abstraction reworking: + * Multi-CPU abstraction reworking: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * Further modifications to make this work: + * Copyright (c) 1998 Harald Koerfgen + * Copyright (c) 1998 Gleb Raiko & Vladimir Roganov */ -#include - #include +#include #include #include #include @@ -18,380 +21,175 @@ #include #include #include +#include #include .text .set mips1 .set noreorder - .align 5 - NESTED(r2300_handle_tlbl, PT_SIZE, sp) - .set noat - /* Check whether this is a refill or an invalid exception */ - mfc0 k0,CP0_BADVADDR - mfc0 k1,CP0_ENTRYHI - ori k0,0xfff # clear ASID... - xori k0,0xfff # in BadVAddr - andi k1,0xfc0 # get current ASID - or k0,k1 # make new entryhi - mfc0 k1,CP0_ENTRYHI - mtc0 k0,CP0_ENTRYHI - nop # for pipeline - nop - nop - tlbp - nop # for pipeline - nop - mfc0 k0,CP0_INDEX - - bgez k0,invalid_tlbl # bad addr in c0_badvaddr - mtc0 k1,CP0_ENTRYHI - - /* Damn... The next nop is required on the R4400PC V5.0, but - * I don't know why - at least there is no documented - * reason as for the others :-( - * And I haven't tested it as being necessary on R3000 - PMA. - * (The R3000 pipeline has only 5 stages, so it's probably not - * required -- Ralf) - */ - nop - -#ifdef CONF_DEBUG_TLB - /* OK, this is a double fault. Let's see whether this is - * due to an invalid entry in the page_table. - */ - /* used to be dmfc0 */ - mfc0 k0,CP0_BADVADDR - /* FIXME: This srl/sll sequence is as it is for the R4xx0, - * and I suspect that it should be different for - * the R[23]000. PMA - * (No, it's the assembler way to do - * k0 = k0 / PAGE_SIZE; - * k0 = k0 * sizeof(pte_t) - * Acutally the R4xx0 code will have to change when - * switching to 64 bit ... -- Ralf) - */ - srl k0,12 # get PFN? - sll k0,2 - lui k1,%HI(TLBMAP) - addu k0,k1 - lw k1,(k0) - andi k1,(_PAGE_PRESENT|_PAGE_ACCESSED) - bnez k1,reload_pgd_entries - nop - - .set noat - SAVE_ALL - .set at - PRINT("Double fault caused by invalid entries in pgd:\n") - mfc0 a1,CP0_BADVADDR - PRINT("Double fault address : %08lx\n") - mfc0 a1,CP0_EPC - PRINT("c0_epc : %08lx\n") - - jal show_regs - move a0,sp +#undef NOTLB_OPTIMIZE /* If you are paranoid, define this. */ - jal dump_tlb_nonwired - nop + /* ABUSE of CPP macros 101. */ - mfc0 a0,CP0_BADVADDR + /* After this macro runs, the pte faulted on is + * in register PTE, a ptr into the table in which + * the pte belongs is in PTR. + */ +#define LOAD_PTE(pte, ptr) \ + mfc0 pte, CP0_BADVADDR; \ + _GET_CURRENT(ptr); \ + srl pte, pte, 22; \ + lw ptr, THREAD_PGDIR(ptr); \ + sll pte, pte, 2; \ + addu ptr, pte, ptr; \ + mfc0 pte, CP0_CONTEXT; \ + lw ptr, (ptr); \ + andi pte, pte, 0xffc; \ + addu ptr, ptr, pte; \ + lw pte, (ptr); \ + nop; + + /* This places the even/odd pte pair in the page + * table at PTR into ENTRYLO0 and ENTRYLO1 using + * TMP as a scratch register. + */ +#define PTE_RELOAD(ptr) \ + lw ptr, (ptr) ; \ + nop ; \ + mtc0 ptr, CP0_ENTRYLO0; \ + nop; + +#define DO_FAULT(write) \ + .set noat; \ + .set macro; \ + SAVE_ALL; \ + mfc0 a2, CP0_BADVADDR; \ + STI; \ + .set at; \ + move a0, sp; \ + jal do_page_fault; \ + li a1, write; \ + j ret_from_sys_call; \ + nop; \ + .set noat; \ + .set nomacro; + + /* Check is PTE is present, if not then jump to LABEL. + * PTR points to the page table where this PTE is located, + * when the macro is done executing PTE will be restored + * with it's original value. + */ +#define PTE_PRESENT(pte, ptr, label) \ + andi pte, pte, (_PAGE_PRESENT | _PAGE_READ); \ + xori pte, pte, (_PAGE_PRESENT | _PAGE_READ); \ + bnez pte, label; \ + .set push; \ + .set reorder; \ + lw pte, (ptr); \ + .set pop; + + /* Make PTE valid, store result in PTR. */ +#define PTE_MAKEVALID(pte, ptr) \ + ori pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \ + sw pte, (ptr); + + /* Check if PTE can be written to, if not branch to LABEL. + * Regardless restore PTE with value from PTR when done. + */ +#define PTE_WRITABLE(pte, ptr, label) \ + andi pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \ + xori pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \ + bnez pte, label; \ + .set push; \ + .set reorder; \ + lw pte, (ptr); \ + .set pop; + + + /* Make PTE writable, update software status bits as well, + * then store at PTR. + */ +#define PTE_MAKEWRITE(pte, ptr) \ + ori pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | \ + _PAGE_VALID | _PAGE_DIRTY); \ + sw pte, (ptr); - jal dump_list_current - nop + .set noreorder + .align 5 +NESTED(r2300_handle_tlbl, PT_SIZE, sp) .set noat - STI - .set at - PANIC("Corrupted pagedir") - .set noat - -reload_pgd_entries: -#endif /* CONF_DEBUG_TLB */ - /* Load missing pair of entries from the pgd and return. */ - mfc0 k1,CP0_CONTEXT - lw k0,(k1) # Never causes nested exception - mfc0 k1,CP0_EPC # get the return PC - srl k0,12 # Convert to EntryLo format - mtc0 k0,CP0_ENTRYLO0 - nop # for pipeline - tlbwr - nop # for pipeline +#ifndef NOTLB_OPTIMIZE + /* Test present bit in entry. */ + LOAD_PTE(k0, k1) + tlbp nop + PTE_PRESENT(k0, k1, nopage_tlbl) + PTE_MAKEVALID(k0, k1) + PTE_RELOAD(k1) + tlbwi nop - /* We don't know whether the original access was read or - * write, so return and see what happens... - */ - jr k1 - rfe - - /* Handle invalid exception - * - * There are two possible causes for an invalid (tlbl) - * exception: - * 1) pages with present bit set but the valid bit clear - * 2) nonexistant pages - * Case one needs fast handling, therefore don't save - * registers yet. - * - * k0 contains c0_index. - */ -invalid_tlbl: -#ifdef CONFIG_TLB_SHUTDOWN - /* Remove entry so we don't need to care later - * For sake of the pipeline the tlbwi insn has been moved down. - * Moving it around is juggling with explosives... - */ - /* FIXME: Why is Ralf setting bit 3 of k1? This may need to - * be changed for R[236]000! PMA - * (The new ENTRYHI value will then point represent a - * inique virtual address outside the 32 bit address - * limit. This is just paranoia to avoid a tlb - * shutdown. This whole part of the routine is probably - * no longer required and can be removed -- Ralf) - */ - lui k1,0x0008 - or k0,k1 - sll k0,12 # make it EntryHi format - mtc0 k0,CP0_ENTRYHI - mtc0 zero,CP0_ENTRYLO0 -#endif - /* Test present bit in entry */ - mfc0 k0,CP0_BADVADDR - /* FIXME: This srl/sll sequence is as it is for the R4xx0, - * and I suspect that it should be different for - * the R[23]000. PMA - * (No, it's the assembler way to do - * k0 = k0 / PAGE_SIZE; - * k0 = k0 * sizeof(pte_t) - * Acutally the R4xx0 code will have to change when - * switching to 64 bit ... -- Ralf) - */ - srl k0,12 - sll k0,2 -#ifdef CONFIG_TLB_SHUTDOWN - tlbwi # do not move! -#endif - lui k1,%HI(TLBMAP) - addu k0,k1 - lw k1,(k0) - andi k1,(_PAGE_PRESENT|_PAGE_READ) - xori k1,(_PAGE_PRESENT|_PAGE_READ) - - bnez k1,nopage_tlbl - lw k1,(k0) - - /* Present and read bits are set -> set valid and accessed bits */ - ori k1,(_PAGE_VALID|_PAGE_ACCESSED) - sw k1,(k0) - mfc0 k1,CP0_EPC + mfc0 k0, CP0_EPC nop - - jr k1 + jr k0 rfe - - /* Page doesn't exist. Lots of work which is less important - * for speed needs to be done, so hand it all over to the - * kernel memory management routines. - */ nopage_tlbl: - SAVE_ALL - mfc0 a2,CP0_BADVADDR - STI - .set at - /* a0 (struct pt_regs *) regs - * a1 (unsigned long) 0 for read access - * a2 (unsigned long) faulting virtual address - */ - move a0,sp - jal do_page_fault - li a1,0 - - j ret_from_sys_call - nop - END(r2300_handle_tlbl) +#endif + DO_FAULT(0) +END(r2300_handle_tlbl) - .text - .align 5 - NESTED(r2300_handle_tlbs, PT_SIZE, sp) +NESTED(r2300_handle_tlbs, PT_SIZE, sp) .set noat - /* It is impossible that is a nested reload exception. - * Therefore this must be a invalid exception. - * Two possible cases: - * 1) Page exists but not dirty. - * 2) Page doesn't exist yet. Hand over to the kernel. - * - * Test whether present bit in entry is set - */ - /* used to be dmfc0 */ - mfc0 k0,CP0_BADVADDR - /* FIXME: This srl/sll sequence is as it is for the R4xx0, - * and I suspect that it should be different for - * the R[23]000. PMA - */ - srl k0,12 - sll k0,2 - lui k1,%HI(TLBMAP) - addu k0,k1 - lw k1,(k0) - tlbp # find faulting entry - andi k1,(_PAGE_PRESENT|_PAGE_WRITE) - xori k1,(_PAGE_PRESENT|_PAGE_WRITE) - bnez k1,nopage_tlbs - lw k1,(k0) - - /* Present and writable bits set: set accessed and dirty bits. */ - ori k1,k1,(_PAGE_ACCESSED|_PAGE_MODIFIED| \ - _PAGE_VALID|_PAGE_DIRTY) - sw k1,(k0) - /* Now reload the entry into the TLB */ - /* FIXME: Why has Ralf set bit 2? Should it be different for - * R[23]000? PMA - * (The ori/xori combination actually _clears_ bit 2. - * This is required for the R4xx0 these CPUs always - * map page pairs; a page pair of 4k pages therfore - * has always an address with bit 2 set to zero. -- Ralf) - */ - ori k0,0x0004 - xori k0,0x0004 - lw k0,(k0) - srl k0,12 - mtc0 k0,CP0_ENTRYLO0 - mfc0 k1,CP0_EPC - nop # for pipeline +#ifndef NOTLB_OPTIMIZE + LOAD_PTE(k0, k1) + tlbp # find faulting entry + nop + PTE_WRITABLE(k0, k1, nopage_tlbs) + PTE_MAKEWRITE(k0, k1) + PTE_RELOAD(k1) tlbwi - nop # for pipeline nop + mfc0 k0, CP0_EPC nop - - jr k1 + jr k0 rfe - - /* Page doesn't exist. Lots of work which is less important - * for speed needs to be done, so hand it all over to the - * kernel memory management routines. - */ nopage_tlbs: -nowrite_mod: -#ifdef CONFIG_TLB_SHUTDOWN - /* Remove entry so we don't need to care later */ - mfc0 k0,CP0_INDEX -#ifdef CONF_DEBUG_TLB - bgez k0,2f - nop - /* We got a tlbs exception but found no matching entry in - * the tlb. This should never happen. Paranoia makes us - * check it, though. - */ - SAVE_ALL - jal show_regs - move a0,sp - .set at - mfc0 a1,CP0_BADVADDR - PRINT("c0_badvaddr == %08lx\n") - mfc0 a1,CP0_INDEX - PRINT("c0_index == %08x\n") - mfc0 a1,CP0_ENTRYHI - PRINT("c0_entryhi == %08x\n") - .set noat - STI - .set at - PANIC("Tlbs or tlbm exception with no matching entry in tlb") -1: - j 1b - nop -2: -#endif /* CONF_DEBUG_TLB */ - /* FIXME: Why is Ralf setting bit 3 of k1? This may need to - * be changed for R[236]000! PMA - * (The new ENTRYHI value will then point represent a - * inique virtual address outside the 32 bit address - * limit. This is just paranoia to avoid a tlb - * shutdown. This whole part of the routine is probably - * no longer required and can be removed -- Ralf) - */ - lui k1,0x0008 - or k0,k1 - sll k0,12 - mtc0 k0,CP0_ENTRYHI - mtc0 zero,CP0_ENTRYLO0 - nop # for pipeline - nop # R4000 V2.2 requires 4 NOPs - nop - nop - tlbwi -#endif /* CONFIG_TLB_SHUTDOWN */ - .set noat - SAVE_ALL - mfc0 a2,CP0_BADVADDR - STI - .set at - /* a0 (struct pt_regs *) regs - * a1 (unsigned long) 1 for write access - * a2 (unsigned long) faulting virtual address - */ - move a0,sp - jal do_page_fault - li a1,1 - - j ret_from_sys_call - nop - END(r2300_handle_tlbs) +#endif + DO_FAULT(1) +END(r2300_handle_tlbs) .align 5 - NESTED(r2300_handle_mod, PT_SIZE, sp) +NESTED(r2300_handle_mod, PT_SIZE, sp) .set noat - /* Two possible cases: - * 1) Page is writable but not dirty -> set dirty and return - * 2) Page is not writable -> call C handler - */ - /* used to be dmfc0 */ - mfc0 k0,CP0_BADVADDR - /* FIXME: This srl/sll sequence is as it is for the R4xx0, - * and I suspect that it should be different for - * the R[23]000. PMA - */ - srl k0,12 - sll k0,2 - lui k1,%HI(TLBMAP) - addu k0,k1 - lw k1,(k0) +#ifndef NOTLB_OPTIMIZE + LOAD_PTE(k0, k1) tlbp # find faulting entry - andi k1,_PAGE_WRITE + andi k0, k0, _PAGE_WRITE + beqz k0, nowrite_mod + .set push + .set reorder + lw k0, (k1) + .set pop - beqz k1,nowrite_mod - lw k1,(k0) + /* Present and writable bits set, set accessed and dirty bits. */ + PTE_MAKEWRITE(k0, k1) - /* Present and writable bits set: set accessed and dirty bits. */ - ori k1,(_PAGE_ACCESSED|_PAGE_DIRTY) - sw k1,(k0) - /* Now reload the entry into the tlb */ - /* FIXME: Why has Ralf set bit 2? Should it be different for - * R[23]000? PMA - * (The ori/xori combination actually _clears_ bit 2. - * This is required for the R4xx0 these CPUs always - * map page pairs; a page pair of 4k pages therfore - * has always an address with bit 2 set to zero. -- Ralf) - */ - ori k0,0x0004 - xori k0,0x0004 - lw k0,(k0) - srl k0,12 - mtc0 k0,CP0_ENTRYLO0 - mfc0 k1,CP0_EPC - nop # for pipeline - nop + /* Now reload the entry into the tlb. */ + PTE_RELOAD(k1) nop tlbwi - nop # for pipeline nop + mfc0 k0, CP0_EPC nop - - jr k1 + jr k0 rfe - END(r2300_handle_mod) - .set at +#endif + +nowrite_mod: + DO_FAULT(1) +END(r2300_handle_mod) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/r2300_switch.S linux.pre11.3/arch/mips/kernel/r2300_switch.S --- linux.vanilla/arch/mips/kernel/r2300_switch.S Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/r2300_switch.S Mon Jul 19 23:28:45 1999 @@ -1,12 +1,15 @@ -/* - * r2300_switch.S: R3000/R2000 specific task switching code. +/* $Id: r2300_switch.S,v 1.6 1999/06/13 16:30:32 ralf Exp $ + * + * r2300_switch.S: R2300 specific task switching code. * - * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse + * Copyright (C) 1994, 1995, 1996, 1999 by Ralf Baechle + * Copyright (C) 1994, 1995, 1996 by Andreas Busse * * Multi-cpu abstraction and macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r2300_switch.S,v 1.4 1998/04/04 13:59:38 ralf Exp $ + * Further modifications to make this work: + * Copyright (c) 1998 Harald Koerfgen */ #include #include @@ -15,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -23,68 +27,137 @@ #include -/* XXX The following is fucking losing... find a better way dave. */ -MODE_ALIAS = 0x00e0 # uncachable, dirty, valid - - .text .set mips1 - .set noreorder + .align 5 + /* - * Code necessary to switch tasks on an Linux/MIPS machine. - * FIXME: We don't need to disable interrupts anymore. + * task_struct *r4xx0_resume(task_struct *prev, + * task_struct *next) */ - .align 5 - LEAF(r2300_resume) - mfc0 t1,CP0_STATUS # Save status register - sw t1,THREAD_STATUS($28) - ori t2,t1,0x1f # Disable interrupts - xori t2,0x1e - mtc0 t2,CP0_STATUS - CPU_SAVE_NONSCRATCH($28) - sll t2,t1,2 # Save floating point state - bgez t2,1f - sw ra,THREAD_REG31($28) - FPU_SAVE($28, t0) -1: - move $28, a0 - lw t0,THREAD_PGDIR($28) # Switch the root pointer - li t1,TLB_ROOT # get PFN - mtc0 t1,CP0_ENTRYHI - mtc0 zero,CP0_INDEX - srl t0,12 # PFN is 12 bits west - ori t0,MODE_ALIAS # want uncachable, dirty, valid - mtc0 t0,CP0_ENTRYLO0 - lw a2,THREAD_STATUS($28) - tlbwi - - /* Flush TLB. */ - mfc0 t3,CP0_STATUS # disable interrupts... - ori t4,t3,1 - xori t4,1 - mtc0 t4,CP0_STATUS - lw t0,mips_tlb_entries - mtc0 zero,CP0_ENTRYLO0 -1: - subu t0,1 - mtc0 t0,CP0_INDEX - lui t1,0x0008 - or t1,t0,t1 - sll t1,12 - mtc0 t1,CP0_ENTRYHI - bne t2,t0,1b - tlbwi - - ori t1,a2,1 # Restore FPU, pipeline magic - xori t1,1 - mtc0 t1,CP0_STATUS - sll t0,a2,2 - bgez t0,1f - lw ra,THREAD_REG31($28) - FPU_RESTORE($28, t0) -1: +LEAF(r2300_resume) + .set reorder + mfc0 t1, CP0_STATUS + .set noreorder + sw t1, THREAD_STATUS(a0) + CPU_SAVE_NONSCRATCH(a0) + sw ra, THREAD_REG31(a0) + + /* + * The order of restoring the registers takes care of the race + * updating $28, $29 and kernelsp without disabling ints. + */ + move $28, a1 CPU_RESTORE_NONSCRATCH($28) addiu t0, $28, KERNEL_STACK_SIZE-32 - sw t0,kernelsp + sw t0, kernelsp + mfc0 t1, CP0_STATUS /* Do we really need this? */ + li a3, 0xff00 + and t1, a3 + lw a2, THREAD_STATUS($28) + nor a3, $0, a3 + and a2, a3 + lw a3, TASK_MM($28) + or a2, t1 + lw a3, MM_CONTEXT(a3) + mtc0 a2, CP0_STATUS + andi a3, 0xfc0 + mtc0 a3, CP0_ENTRYHI jr ra - mtc0 a2,CP0_STATUS # Restore status register + move v0, a0 END(r2300_resume) + +/* + * Do lazy fpu context switch. Saves FPU context to the process in a0 + * and loads the new context of the current process. + */ + +#define ST_OFF (KERNEL_STACK_SIZE - 32 - PT_SIZE + PT_STATUS) + +LEAF(r2300_lazy_fpu_switch) + mfc0 t0, CP0_STATUS # enable cp1 + li t3, 0x20000000 + or t0, t3 + mtc0 t0, CP0_STATUS + + beqz a0, 2f # Save floating point state + nor t3, zero, t3 + .set reorder + lw t1, ST_OFF(a0) # last thread looses fpu + .set noreorder + and t1, t3 + sw t1, ST_OFF(a0) + swc1 $f0, (THREAD_FPU + 0x00)(a0) + FPU_SAVE(a0, t1) # clobbers t1 + +2: + lwc1 $f0, (THREAD_FPU + 0x00)($28) + .set reorder + FPU_RESTORE($28, t0) # clobbers t0 + jr ra + END(r2300_lazy_fpu_switch) + +/* + * Save a thread's fp context. + */ + .set noreorder +LEAF(r2300_save_fp) + FPU_SAVE(a0, t1) # clobbers t1 + jr ra + swc1 $f0, (THREAD_FPU + 0x00)(a0) + END(r2300_save_fp) + +/* + * Load the FPU with signalling NANS. This bit pattern we're using has + * the property that no matter wether considered as single or as double + * precission represents signaling NANS. + * + * We initialize fcr31 to rounding to nearest, no exceptions. + */ + +#define FPU_DEFAULT 0x00000000 + +LEAF(r2300_init_fpu) + mfc0 t0, CP0_STATUS + li t1, 0x20000000 + or t0, t1 + mtc0 t0, CP0_STATUS + + li t1, FPU_DEFAULT + ctc1 t1, fcr31 + + li t0, -1 + + mtc1 t0, $f0 + mtc1 t0, $f1 + mtc1 t0, $f2 + mtc1 t0, $f3 + mtc1 t0, $f4 + mtc1 t0, $f5 + mtc1 t0, $f6 + mtc1 t0, $f7 + mtc1 t0, $f8 + mtc1 t0, $f9 + mtc1 t0, $f10 + mtc1 t0, $f11 + mtc1 t0, $f12 + mtc1 t0, $f13 + mtc1 t0, $f14 + mtc1 t0, $f15 + mtc1 t0, $f16 + mtc1 t0, $f17 + mtc1 t0, $f18 + mtc1 t0, $f19 + mtc1 t0, $f20 + mtc1 t0, $f21 + mtc1 t0, $f22 + mtc1 t0, $f23 + mtc1 t0, $f24 + mtc1 t0, $f25 + mtc1 t0, $f26 + mtc1 t0, $f27 + mtc1 t0, $f28 + mtc1 t0, $f29 + mtc1 t0, $f30 + jr ra + mtc1 t0, $f31 + END(r2300_init_fpu) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/r4k_fpu.S linux.pre11.3/arch/mips/kernel/r4k_fpu.S --- linux.vanilla/arch/mips/kernel/r4k_fpu.S Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/r4k_fpu.S Mon Jul 19 23:28:44 1999 @@ -10,7 +10,7 @@ * Multi-arch abstraction and asm macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r4k_fpu.S,v 1.4 1998/04/04 13:59:38 ralf Exp $ + * $Id: r4k_fpu.S,v 1.5 1999/05/01 22:40:36 ralf Exp $ */ #include #include @@ -79,11 +79,11 @@ END(r4k_save_fp_context) /* - * Restore fpu state: + * Restore FPU state: * - fp gp registers * - cp1 status/control register * - * We base the decission which registers to restore from the signal stack + * We base the decision which registers to restore from the signal stack * frame on the current content of c0_status, not on the content of the * stack frame which might have been changed by the user. */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/r4k_misc.S linux.pre11.3/arch/mips/kernel/r4k_misc.S --- linux.vanilla/arch/mips/kernel/r4k_misc.S Sun Nov 8 15:08:30 1998 +++ linux.pre11.3/arch/mips/kernel/r4k_misc.S Mon Jul 19 23:53:55 1999 @@ -6,14 +6,13 @@ * Multi-cpu abstraction and reworking: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r4k_misc.S,v 1.3 1997/09/07 04:51:07 ralf Exp $ + * $Id: r4k_misc.S,v 1.4 1997/12/01 17:57:30 ralf Exp $ */ #include #include #include #include #include -#include #include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/r4k_switch.S linux.pre11.3/arch/mips/kernel/r4k_switch.S --- linux.vanilla/arch/mips/kernel/r4k_switch.S Sun Nov 8 15:08:30 1998 +++ linux.pre11.3/arch/mips/kernel/r4k_switch.S Mon Jul 19 23:28:45 1999 @@ -1,10 +1,10 @@ -/* $Id: r4k_switch.S,v 1.4 1998/07/14 09:15:33 ralf Exp $ +/* $Id: r4k_switch.S,v 1.7 1999/06/13 16:30:32 ralf Exp $ * * 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. * - * Copyright (C) 1994, 1995, 1996, 1998 by Ralf Baechle + * Copyright (C) 1994, 1995, 1996, 1998, 1999 by Ralf Baechle * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * Copyright (C) 1994, 1995, 1996, by Andreas Busse */ @@ -24,30 +24,41 @@ #include +/* + * task_struct *r4xx0_resume(task_struct *prev, + * task_struct *next) + */ .set noreorder .set mips3 .align 5 LEAF(r4xx0_resume) mfc0 t1, CP0_STATUS - sw t1, THREAD_STATUS($28) - CPU_SAVE_NONSCRATCH($28) - sw ra, THREAD_REG31($28) + sw t1, THREAD_STATUS(a0) + CPU_SAVE_NONSCRATCH(a0) + sw ra, THREAD_REG31(a0) /* * The order of restoring the registers takes care of the race * updating $28, $29 and kernelsp without disabling ints. */ - move $28, a0 + move $28, a1 CPU_RESTORE_NONSCRATCH($28) addiu t0, $28, KERNEL_STACK_SIZE-32 sw t0, kernelsp - lw a3, TASK_MM($28) + mfc0 t1, CP0_STATUS /* Do we really need this? */ + li a3, 0xff00 + and t1, a3 lw a2, THREAD_STATUS($28) + nor a3, $0, a3 + and a2, a3 + lw a3, TASK_MM($28) + or a2, t1 lw a3, MM_CONTEXT(a3) mtc0 a2, CP0_STATUS andi a3, a3, 0xff + mtc0 a3, CP0_ENTRYHI jr ra - mtc0 a3, CP0_ENTRYHI + move v0, a0 END(r4xx0_resume) /* @@ -104,8 +115,8 @@ /* * Load the FPU with signalling NANS. This bit pattern we're using has - * the property that no matter wether considered as single or as double - * precission represents signaling NANS. + * the property that no matter whether considered as single or as double + * precision represents signaling NANS. * * We initialize fcr31 to rounding to nearest, no exceptions. */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/r6000_fpu.S linux.pre11.3/arch/mips/kernel/r6000_fpu.S --- linux.vanilla/arch/mips/kernel/r6000_fpu.S Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/r6000_fpu.S Mon Jul 19 23:28:44 1999 @@ -10,7 +10,7 @@ * Multi-arch abstraction and asm macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r6000_fpu.S,v 1.3 1997/12/01 16:56:56 ralf Exp $ + * $Id: r6000_fpu.S,v 1.5 1999/05/01 22:40:37 ralf Exp $ */ #include #include @@ -19,6 +19,7 @@ #include .set noreorder + .set mips2 /* Save floating point context */ LEAF(r6000_save_fp_context) mfc0 t0,CP0_STATUS @@ -50,11 +51,11 @@ nop END(r6000_save_fp_context) -/* Restore fpu state: +/* Restore FPU state: * - fp gp registers * - cp1 status/control register * - * We base the decission which registers to restore from the signal stack + * We base the decision which registers to restore from the signal stack * frame on the current content of c0_status, not on the content of the * stack frame which might have been changed by the user. */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/scall_o32.S linux.pre11.3/arch/mips/kernel/scall_o32.S --- linux.vanilla/arch/mips/kernel/scall_o32.S Sun Nov 8 15:08:30 1998 +++ linux.pre11.3/arch/mips/kernel/scall_o32.S Mon Jul 19 23:28:45 1999 @@ -1,4 +1,4 @@ -/* $Id: scall_o32.S,v 1.5 1998/08/19 21:53:50 ralf Exp $ +/* $Id: scall_o32.S,v 1.4 1998/06/25 20:01:01 ralf Exp $ * * 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 @@ -44,6 +44,7 @@ beqz t2, illegal_syscall; subu t0, t3, 5 # 5 or more arguments? + sw a3, PT_R26(sp) # save a3 for syscall restarting bgez t0, stackargs stack_done: diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/setup.c linux.pre11.3/arch/mips/kernel/setup.c --- linux.vanilla/arch/mips/kernel/setup.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/setup.c Mon Jul 19 23:53:55 1999 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.12 1998/08/18 20:45:06 ralf Exp $ +/* $Id: setup.c,v 1.15.2.2 1999/06/17 12:06:39 ralf Exp $ * * 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 @@ -29,7 +29,6 @@ #include #endif #ifdef CONFIG_RTC -#include #include #endif @@ -76,7 +75,6 @@ * information is being use to continue the screen output just below * the BIOS printed text and with the same text resolution. */ -struct drive_info_struct drive_info = DEFAULT_DRIVE_INFO; struct screen_info screen_info = DEFAULT_SCREEN_INFO; #ifdef CONFIG_BLK_DEV_FD @@ -92,39 +90,25 @@ extern struct rtc_ops no_rtc_ops; struct rtc_ops *rtc_ops; +extern struct kbd_ops no_kbd_ops; +struct kbd_ops *kbd_ops; + /* * Setup information * - * These are intialized so they are in the .data section + * These are initialized so they are in the .data section */ unsigned long mips_memory_upper = KSEG0; /* this is set by kernel_entry() */ unsigned long mips_cputype = CPU_UNKNOWN; unsigned long mips_machtype = MACH_UNKNOWN; unsigned long mips_machgroup = MACH_GROUP_UNKNOWN; -unsigned long mips_tlb_entries = 48; /* Guess which CPU I've got :) */ -unsigned long mips_vram_base = KSEG0; unsigned char aux_device_present; -extern int root_mountflags; extern int _end; -extern char empty_zero_page[PAGE_SIZE]; - -/* - * This is set up by the setup-routine at boot-time - */ -#define PARAM empty_zero_page -#if 0 -#define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC)) -#define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF)) -#endif -#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210)) -#define KERNEL_START (*(unsigned long *) (PARAM+0x214)) -#define INITRD_START (*(unsigned long *) (PARAM+0x218)) -#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c)) - static char command_line[CL_SIZE] = { 0, }; char saved_command_line[CL_SIZE]; +extern char arcs_cmdline[CL_SIZE]; /* * The board specific setup routine sets irq_setup to point to a board @@ -153,7 +137,11 @@ unsigned long * memory_start_p, unsigned long * memory_end_p)) { unsigned long memory_end; - tag* atag; +#ifdef CONFIG_BLK_DEV_INITRD + unsigned long tmp; + unsigned long *initrd_header; +#endif + void baget_setup(void); void cobalt_setup(void); void decstation_setup(void); void deskstation_setup(void); @@ -161,18 +149,6 @@ void sni_rm200_pci_setup(void); void sgi_setup(void); - /* Perhaps a lot of tags are not getting 'snarfed' - */ - /* please help yourself */ - - atag = bi_TagFind(tag_machtype); - memcpy(&mips_machtype, TAGVALPTR(atag), atag->size); - - atag = bi_TagFind(tag_machgroup); - memcpy(&mips_machgroup, TAGVALPTR(atag), atag->size); - - atag = bi_TagFind(tag_vram_base); - memcpy(&mips_vram_base, TAGVALPTR(atag), atag->size); - /* Save defaults for configuration-dependent routines. */ irq_setup = default_irq_setup; @@ -185,14 +161,25 @@ #endif rtc_ops = &no_rtc_ops; + kbd_ops = &no_kbd_ops; switch(mips_machgroup) { +#ifdef CONFIG_BAGET_MIPS + case MACH_GROUP_UNKNOWN: + baget_setup(); + break; +#endif #ifdef CONFIG_COBALT_MICRO_SERVER case MACH_GROUP_COBALT: cobalt_setup(); break; #endif +#ifdef CONFIG_DECSTATION + case MACH_GROUP_DEC: + decstation_setup(); + break; +#endif #ifdef CONFIG_MIPS_JAZZ case MACH_GROUP_JAZZ: jazz_setup(); @@ -212,9 +199,6 @@ panic("Unsupported architecture"); } - atag = bi_TagFind(tag_drive_info); - memcpy(&drive_info, TAGVALPTR(atag), atag->size); - memory_end = mips_memory_upper; /* * Due to prefetching and similar mechanism the CPU sometimes @@ -225,20 +209,7 @@ memory_end -= 128; memory_end &= PAGE_MASK; -#ifdef CONFIG_BLK_DEV_RAM - rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; - rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); - rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); -#endif - - atag = bi_TagFind(tag_mount_root_rdonly); - if (atag) - root_mountflags |= MS_RDONLY; - - atag = bi_TagFind(tag_command_line); - if (atag) - memcpy(&command_line, TAGVALPTR(atag), atag->size); - + strncpy (command_line, arcs_cmdline, CL_SIZE); memcpy(saved_command_line, command_line, CL_SIZE); saved_command_line[CL_SIZE-1] = '\0'; @@ -247,15 +218,21 @@ *memory_end_p = memory_end; #ifdef CONFIG_BLK_DEV_INITRD - if (LOADER_TYPE) { - initrd_start = INITRD_START; - initrd_end = INITRD_START+INITRD_SIZE; + tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8; + if (tmp < (unsigned long)&_end) + tmp += PAGE_SIZE; + initrd_header = (unsigned long *)tmp; + if (initrd_header[0] == 0x494E5244) { + initrd_start = (unsigned long)&initrd_header[2]; + initrd_end = initrd_start + initrd_header[1]; + initrd_below_start_ok = 1; if (initrd_end > memory_end) { printk("initrd extends beyond end of memory " "(0x%08lx > 0x%08lx)\ndisabling initrd\n", initrd_end,memory_end); - initrd_start = 0; - } + initrd_start = 0; + } else + *memory_start_p = initrd_end; } #endif } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/signal.c linux.pre11.3/arch/mips/kernel/signal.c --- linux.vanilla/arch/mips/kernel/signal.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/signal.c Mon Jul 19 23:28:37 1999 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.24 1998/09/16 22:50:42 ralf Exp $ +/* $Id: signal.c,v 1.18.2.1 1999/06/17 12:06:40 ralf Exp $ * * linux/arch/mips/kernel/signal.c * @@ -392,6 +392,7 @@ } /* fallthrough */ case ERESTARTNOINTR: /* Userland will reload $v0. */ + regs->regs[7] = regs->regs[26]; regs->cp0_epc -= 8; } @@ -491,6 +492,7 @@ case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: + case SIGBUS: lock_kernel(); if (current->binfmt && current->binfmt->core_dump @@ -502,6 +504,7 @@ default: lock_kernel(); sigaddset(¤t->signal, signr); + recalc_sigpending(current); current->flags |= PF_SIGNALED; do_exit(exit_code); /* NOTREACHED */ @@ -524,6 +527,7 @@ if (regs->regs[2] == ERESTARTNOHAND || regs->regs[2] == ERESTARTSYS || regs->regs[2] == ERESTARTNOINTR) { + regs->regs[7] = regs->regs[26]; regs->cp0_epc -= 8; } } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/softfp.S linux.pre11.3/arch/mips/kernel/softfp.S --- linux.vanilla/arch/mips/kernel/softfp.S Sun Nov 8 15:08:30 1998 +++ linux.pre11.3/arch/mips/kernel/softfp.S Mon Jul 19 23:28:45 1999 @@ -1,4 +1,4 @@ -/* $Id: softfp.S,v 1.1 1998/07/14 09:33:48 ralf Exp $ +/* $Id: softfp.S,v 1.1 1998/07/16 19:10:02 ralf Exp $ * * 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 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/syscall.c linux.pre11.3/arch/mips/kernel/syscall.c --- linux.vanilla/arch/mips/kernel/syscall.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/syscall.c Mon Jul 19 23:28:38 1999 @@ -1,10 +1,10 @@ -/* $Id: syscall.c,v 1.10 1998/08/20 14:38:40 ralf Exp $ +/* $Id: syscall.c,v 1.10 1999/02/15 02:16:52 ralf Exp $ * * 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. * - * Copyright (C) 1995 - 1998 by Ralf Baechle + * Copyright (C) 1995 - 1999 by Ralf Baechle * * TODO: Implement the compatibility syscalls. * Don't waste that much memory for empty entries in the syscall @@ -80,11 +80,10 @@ asmlinkage int sys_idle(void) { unsigned long start_idle = 0; - int ret = -EPERM; - lock_kernel(); if (current->pid != 0) - goto out; + return -EPERM; + /* endless idle loop with no priority at all */ current->priority = 0; current->counter = 0; @@ -110,10 +109,8 @@ start_idle = 0; schedule(); } - ret = 0; -out: - unlock_kernel(); - return ret; + + return 0; } asmlinkage int sys_fork(struct pt_regs regs) @@ -121,9 +118,7 @@ int res; save_static(®s); - lock_kernel(); res = do_fork(SIGCHLD, regs.regs[29], ®s); - unlock_kernel(); return res; } @@ -134,13 +129,11 @@ int res; save_static(®s); - lock_kernel(); clone_flags = regs.regs[4]; newsp = regs.regs[5]; if (!newsp) newsp = regs.regs[29]; res = do_fork(clone_flags, newsp, ®s); - unlock_kernel(); return res; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/syscalls.h linux.pre11.3/arch/mips/kernel/syscalls.h --- linux.vanilla/arch/mips/kernel/syscalls.h Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/syscalls.h Mon Jul 19 23:28:38 1999 @@ -1,4 +1,4 @@ -/* $Id: syscalls.h,v 1.16 1998/09/16 22:50:43 ralf Exp $ +/* $Id: syscalls.h,v 1.15 1998/09/19 19:16:17 ralf Exp $ * * 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 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/sysirix.c linux.pre11.3/arch/mips/kernel/sysirix.c --- linux.vanilla/arch/mips/kernel/sysirix.c Thu May 27 22:11:50 1999 +++ linux.pre11.3/arch/mips/kernel/sysirix.c Mon Jul 19 23:28:44 1999 @@ -1,4 +1,4 @@ -/* $Id: sysirix.c,v 1.12 1998/08/17 10:16:27 ralf Exp $ +/* $Id: sysirix.c,v 1.19 1999/06/13 16:30:33 ralf Exp $ * * sysirix.c: IRIX system call emulation. * @@ -172,7 +172,7 @@ case PR_RESIDENT: printk("irix_prctl[%s:%ld]: Wants PR_RESIDENT\n", current->comm, current->pid); - error = 0; /* Compatability indeed. */ + error = 0; /* Compatibility indeed. */ break; case PR_ATTACHADDR: @@ -734,8 +734,9 @@ struct statfs kbuf; int error, i; - /* We don't support this feature yet. */ lock_kernel(); + + /* We don't support this feature yet. */ if(fs_type) { error = -EINVAL; goto out; @@ -1622,8 +1623,7 @@ __put_user(0, &buf->f_basetype[i]); __put_user(0, &buf->f_flag); __put_user(kbuf.f_namelen, &buf->f_namemax); - for(i = 0; i < 32; i++) - __put_user(0, &buf->f_fstr[i]); + __clear_user(&buf->f_fstr, sizeof(buf->f_fstr)); out_f: fput(file); @@ -1917,8 +1917,8 @@ __put_user(0, &buf->f_basetype[i]); __put_user(0, &buf->f_flag); __put_user(kbuf.f_namelen, &buf->f_namemax); - for(i = 0; i < 32; i++) - __put_user(0, &buf->f_fstr[i]); + __clear_user(buf->f_fstr, sizeof(buf->f_fstr[i])); + out_f: fput(file); out: @@ -1983,22 +1983,21 @@ #define NAME_OFFSET32(de) ((int) ((de)->d_name - (char *) (de))) #define ROUND_UP32(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1)) -static int irix_filldir32(void *__buf, const char *name, int namlen, off_t offset, ino_t ino) +static int irix_filldir32(void *__buf, const char *name, int namlen, + off_t offset, ino_t ino) { struct irix_dirent32 *dirent; - struct irix_dirent32_callback *buf = (struct irix_dirent32_callback *)__buf; + struct irix_dirent32_callback *buf = + (struct irix_dirent32_callback *)__buf; unsigned short reclen = ROUND_UP32(NAME_OFFSET32(dirent) + namlen + 1); - int retval; #ifdef DEBUG_GETDENTS printk("\nirix_filldir32[reclen<%d>namlen<%d>count<%d>]", reclen, namlen, buf->count); #endif buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) { - retval = -EINVAL; - goto out; - } + if (reclen > buf->count) + return -EINVAL; dirent = buf->previous; if (dirent) __put_user(offset, &dirent->d_off); @@ -2012,10 +2011,7 @@ buf->current_dir = dirent; buf->count -= reclen; - retval = 0; - -out: - return retval; + return 0; } asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count, int *eob) @@ -2040,10 +2036,6 @@ if (!inode) goto out_putf; - inode = dentry->d_inode; - if (!inode) - goto out_putf; - buf.current_dir = (struct irix_dirent32 *) dirent; buf.previous = NULL; buf.count = count; @@ -2111,13 +2103,10 @@ struct irix_dirent64_callback * buf = (struct irix_dirent64_callback *) __buf; unsigned short reclen = ROUND_UP64(NAME_OFFSET64(dirent) + namlen + 1); - int retval; buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) { - retval = -EINVAL; - goto out; - } + if (reclen > buf->count) + return -EINVAL; dirent = buf->previous; if (dirent) __put_user(offset, &dirent->d_off); @@ -2125,15 +2114,13 @@ buf->previous = dirent; __put_user(ino, &dirent->d_ino); __put_user(reclen, &dirent->d_reclen); - copy_to_user(dirent->d_name, name, namlen); + __copy_to_user(dirent->d_name, name, namlen); __put_user(0, &dirent->d_name[namlen]); ((char *) dirent) += reclen; buf->curr = dirent; buf->count -= reclen; - retval = 0; -out: - return retval; + return 0; } asmlinkage int irix_getdents64(int fd, void *dirent, int cnt) @@ -2437,3 +2424,4 @@ return -ENOSYS; } + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/sysmips.c linux.pre11.3/arch/mips/kernel/sysmips.c --- linux.vanilla/arch/mips/kernel/sysmips.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/kernel/sysmips.c Mon Jul 19 23:28:41 1999 @@ -7,7 +7,7 @@ * * Copyright (C) 1995, 1996, 1997 by Ralf Baechle * - * $Id: sysmips.c,v 1.4 1998/05/07 15:20:05 ralf Exp $ + * $Id: sysmips.c,v 1.6 1998/08/25 09:14:42 ralf Exp $ */ #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/time.c linux.pre11.3/arch/mips/kernel/time.c --- linux.vanilla/arch/mips/kernel/time.c Wed Mar 24 10:55:10 1999 +++ linux.pre11.3/arch/mips/kernel/time.c Mon Jul 19 23:53:55 1999 @@ -1,16 +1,12 @@ -/* - * linux/arch/mips/kernel/time.c +/* $Id: time.c,v 1.12 1999/06/13 16:30:34 ralf Exp $ * * Copyright (C) 1991, 1992, 1995 Linus Torvalds + * Copyright (C) 1996, 1997, 1998 Ralf Baechle * * This file contains the time handling details for PC-style clocks as * found in some MIPS systems. - * - * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 - * "A Kernel Model for Precision Timekeeping" by Dave Mills - * - * $Id: time.c,v 1.6 1998/08/17 13:57:44 ralf Exp $ */ +#include #include #include #include @@ -67,7 +63,7 @@ quotient = cached_quotient; - if (last_jiffies != tmp) { + if (tmp && last_jiffies != tmp) { last_jiffies = tmp; __asm__(".set\tnoreorder\n\t" ".set\tnoat\n\t" @@ -340,6 +336,25 @@ static void inline timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) { +#ifdef CONFIG_PROFILE + if(!user_mode(regs)) { + if (prof_buffer && current->pid) { + extern int _stext; + unsigned long pc = regs->cp0_epc; + + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + /* + * Dont ignore out-of-bounds pc values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + if (pc > prof_len-1) + pc = prof_len-1; + atomic_inc((atomic_t *)&prof_buffer[pc]); + } + } +#endif do_timer(regs); /* @@ -375,6 +390,16 @@ timerlo = count; timer_interrupt(irq, dev_id, regs); + + if (!jiffies) + { + /* + * If jiffies has overflowed in this timer_interrupt we must + * update the timer[hi]/[lo] to make do_fast_gettimeoffset() + * quotient calc still valid. -arca + */ + timerhi = timerlo = 0; + } } /* Converts Gregorian date to seconds since 1970-01-01 00:00:00. @@ -456,7 +481,7 @@ __initfunc(void time_init(void)) { - unsigned int year, mon, day, hour, min, sec; + unsigned int epoch, year, mon, day, hour, min, sec; int i; /* The Linux interpretation of the CMOS clock register contents: @@ -488,13 +513,17 @@ BCD_TO_BIN(mon); BCD_TO_BIN(year); } -#if 0 /* the IBM way */ - if ((year += 1900) < 1970) - year += 100; -#else - /* Acer PICA clock starts from 1980. True for all MIPS machines? */ - year += 1980; -#endif + + /* Attempt to guess the epoch. This is the same heuristic as in rtc.c so + no stupid things will happen to timekeeping. Who knows, maybe Ultrix + also uses 1952 as epoch ... */ + if (year > 10 && year < 44) { + epoch = 1980; + } else if (year < 96) { + epoch = 1952; + } + year += epoch; + xtime.tv_sec = mktime(year, mon, day, hour, min, sec); xtime.tv_usec = 0; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/traps.c linux.pre11.3/arch/mips/kernel/traps.c --- linux.vanilla/arch/mips/kernel/traps.c Wed Jan 6 23:02:18 1999 +++ linux.pre11.3/arch/mips/kernel/traps.c Mon Jul 19 23:28:37 1999 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.20 1998/10/14 20:26:26 ralf Exp $ +/* $Id: traps.c,v 1.20 1999/06/13 16:30:34 ralf Exp $ * * 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 @@ -202,17 +202,16 @@ * Assume it would be too dangerous to continue ... */ force_sig(SIGBUS, current); +show_regs(regs); while(1); } void do_ibe(struct pt_regs *regs) { -show_regs(regs); while(1); ibe_board_handler(regs); } void do_dbe(struct pt_regs *regs) { -show_regs(regs); while(1); dbe_board_handler(regs); } @@ -325,7 +324,7 @@ /* * (A short test says that IRIX 5.3 sends SIGTRAP for all break * insns, even for break codes that indicate arithmetic failures. - * Wiered ...) + * Weird ...) */ force_sig(SIGTRAP, current); } @@ -341,7 +340,7 @@ /* * (A short test says that IRIX 5.3 sends SIGTRAP for all break * insns, even for break codes that indicate arithmetic failures. - * Wiered ...) + * Weird ...) */ force_sig(SIGTRAP, current); } @@ -465,8 +464,8 @@ extern asmlinkage void r2300_restore_fp_context(struct sigcontext *sc); extern asmlinkage void r6000_restore_fp_context(struct sigcontext *sc); -extern asmlinkage void r4xx0_resume(void *tsk); -extern asmlinkage void r2300_resume(void *tsk); +extern asmlinkage void *r4xx0_resume(void *last, void *next); +extern asmlinkage void *r2300_resume(void *last, void *next); __initfunc(void trap_init(void)) { diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/unaligned.c linux.pre11.3/arch/mips/kernel/unaligned.c --- linux.vanilla/arch/mips/kernel/unaligned.c Sun Nov 8 15:08:30 1998 +++ linux.pre11.3/arch/mips/kernel/unaligned.c Mon Jul 19 23:28:45 1999 @@ -7,7 +7,7 @@ * * Copyright (C) 1996, 1998 by Ralf Baechle * - * $Id: unaligned.c,v 1.5 1998/08/17 13:57:44 ralf Exp $ + * $Id: unaligned.c,v 1.5 1999/05/01 22:40:39 ralf Exp $ * * This file contains exception handler for address error exception with the * special capability to execute faulting instructions in software. The @@ -17,7 +17,7 @@ * Putting data to unaligned addresses is a bad practice even on Intel where * only the performance is affected. Much worse is that such code is non- * portable. Due to several programs that die on MIPS due to alignment - * problems I decieded to implement this handler anyway though I originally + * problems I decided to implement this handler anyway though I originally * didn't intend to do this at all for user code. * * For now I enable fixing of address errors by default to make life easier. @@ -140,7 +140,7 @@ goto sigbus; /* - * The remaining opcodes are the ones that are really of interrest. + * The remaining opcodes are the ones that are really of interest. */ case lh_op: check_axs(pc, addr, 2); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/Makefile linux.pre11.3/arch/mips/lib/Makefile --- linux.vanilla/arch/mips/lib/Makefile Sun Nov 8 15:08:30 1998 +++ linux.pre11.3/arch/mips/lib/Makefile Mon Jul 19 23:28:45 1999 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.12 1998/05/28 03:17:57 ralf Exp $ +# $Id: Makefile,v 1.9 1999/01/04 16:03:50 ralf Exp $ # # Makefile for MIPS-specific library files.. # @@ -10,7 +10,7 @@ L_TARGET = lib.a L_OBJS = csum_partial.o csum_partial_copy.o dump_tlb.o floppy-std.o \ - floppy-no.o ide-std.o ide-no.o rtc-std.o rtc-no.o memset.o memcpy.o \ - strlen_user.o strncpy_user.o tags.o watch.o + floppy-no.o ide-std.o ide-no.o kbd-std.o kbd-no.o rtc-std.o \ + rtc-no.o memset.o memcpy.o strlen_user.o strncpy_user.o watch.o include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/csum_partial.S linux.pre11.3/arch/mips/lib/csum_partial.S --- linux.vanilla/arch/mips/lib/csum_partial.S Sun Nov 8 15:08:30 1998 +++ linux.pre11.3/arch/mips/lib/csum_partial.S Mon Jul 19 23:28:45 1999 @@ -1,4 +1,4 @@ -/* $Id: csum_partial.S,v 1.3 1998/05/07 14:17:45 ralf Exp $ +/* $Id: csum_partial.S,v 1.2 1998/05/07 23:44:01 ralf Exp $ * * 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 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/csum_partial_copy.c linux.pre11.3/arch/mips/lib/csum_partial_copy.c --- linux.vanilla/arch/mips/lib/csum_partial_copy.c Sun Nov 8 15:08:30 1998 +++ linux.pre11.3/arch/mips/lib/csum_partial_copy.c Mon Jul 19 23:28:45 1999 @@ -14,7 +14,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * $Id: csum_partial_copy.c,v 1.2 1998/09/16 13:29:32 ralf Exp $ + * $Id: csum_partial_copy.c,v 1.2 1998/09/19 19:16:17 ralf Exp $ */ #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/floppy-std.c linux.pre11.3/arch/mips/lib/floppy-std.c --- linux.vanilla/arch/mips/lib/floppy-std.c Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/lib/floppy-std.c Mon Jul 19 23:28:45 1999 @@ -1,4 +1,4 @@ -/* $Id: floppy-std.c,v 1.2 1998/05/28 03:17:57 ralf Exp $ +/* $Id: floppy-std.c,v 1.3 1998/10/28 12:38:13 ralf Exp $ * * 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 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/ide-no.c linux.pre11.3/arch/mips/lib/ide-no.c --- linux.vanilla/arch/mips/lib/ide-no.c Sun Nov 8 15:08:30 1998 +++ linux.pre11.3/arch/mips/lib/ide-no.c Mon Jul 19 23:28:45 1999 @@ -1,4 +1,4 @@ -/* $Id: ide-no.c,v 1.2 1998/05/28 03:17:57 ralf Exp $ +/* $Id: ide-no.c,v 1.2.2.2 1999/06/17 12:06:40 ralf Exp $ * * 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 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/ide-std.c linux.pre11.3/arch/mips/lib/ide-std.c --- linux.vanilla/arch/mips/lib/ide-std.c Sun Nov 8 15:08:30 1998 +++ linux.pre11.3/arch/mips/lib/ide-std.c Mon Jul 19 23:28:45 1999 @@ -1,5 +1,4 @@ -/* - * include/asm-mips/types.h +/* $Id: ide-std.c,v 1.3.2.2 1999/06/17 12:06:41 ralf Exp $ * * 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 @@ -9,6 +8,8 @@ * * Copyright (C) 1998 by Ralf Baechle */ +#include +#include #include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/kbd-no.c linux.pre11.3/arch/mips/lib/kbd-no.c --- linux.vanilla/arch/mips/lib/kbd-no.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/lib/kbd-no.c Mon Jul 19 23:28:45 1999 @@ -0,0 +1,63 @@ +/* $Id: kbd-no.c,v 1.1 1998/10/28 12:38:14 ralf Exp $ + * + * 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. + * + * Stub keyboard and psaux routines to keep Linux from crashing on machines + * without a keyboard. + * + * Copyright (C) 1998 by Ralf Baechle + */ +#include +#include + +static void no_kbd_request_region(void) +{ + /* No I/O ports are being used on the Indy. */ +} + +static int no_kbd_request_irq(void (*handler)(int, void *, struct pt_regs *)) +{ + return -ENODEV; +} + +static int no_aux_request_irq(void (*handler)(int, void *, struct pt_regs *)) +{ + return -ENODEV; +} + +static void no_aux_free_irq(void) +{ +} + +static unsigned char no_kbd_read_input(void) +{ + return 0; +} + +static void no_kbd_write_output(unsigned char val) +{ +} + +static void no_kbd_write_command(unsigned char val) +{ +} + +static unsigned char no_kbd_read_status(void) +{ + return 0; +} + +struct kbd_ops no_kbd_ops = { + no_kbd_request_region, + no_kbd_request_irq, + + no_aux_request_irq, + no_aux_free_irq, + + no_kbd_read_input, + no_kbd_write_output, + no_kbd_write_command, + no_kbd_read_status +}; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/kbd-std.c linux.pre11.3/arch/mips/lib/kbd-std.c --- linux.vanilla/arch/mips/lib/kbd-std.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/lib/kbd-std.c Mon Jul 19 23:28:45 1999 @@ -0,0 +1,81 @@ +/* $Id: kbd-std.c,v 1.1 1998/10/28 12:38:14 ralf Exp $ + * + * 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. + * + * Routines for standard PC style keyboards accessible via I/O ports. + * + * Copyright (C) 1998 by Ralf Baechle + */ +#include +#include +#include +#include +#include + +#define KEYBOARD_IRQ 1 +#define AUX_IRQ 12 + +static void std_kbd_request_region(void) +{ + request_region(0x60, 16, "keyboard"); +} + +static int std_kbd_request_irq(void (*handler)(int, void *, struct pt_regs *)) +{ + return request_irq(KEYBOARD_IRQ, handler, 0, "keyboard", NULL); +} + +static int std_aux_request_irq(void (*handler)(int, void *, struct pt_regs *)) +{ + return request_irq(AUX_IRQ, handler, 0, "PS/2 Mouse", NULL); +} + +static void std_aux_free_irq(void) +{ + free_irq(AUX_IRQ, NULL); +} + +static unsigned char std_kbd_read_input(void) +{ + return inb(KBD_DATA_REG); +} + +static void std_kbd_write_output(unsigned char val) +{ + int status; + + do { + status = inb(KBD_CNTL_REG); + } while (status & KBD_STAT_IBF); + outb(val, KBD_DATA_REG); +} + +static void std_kbd_write_command(unsigned char val) +{ + int status; + + do { + status = inb(KBD_CNTL_REG); + } while (status & KBD_STAT_IBF); + outb(val, KBD_CNTL_REG); +} + +static unsigned char std_kbd_read_status(void) +{ + return inb(KBD_STATUS_REG); +} + +struct kbd_ops std_kbd_ops = { + std_kbd_request_region, + std_kbd_request_irq, + + std_aux_request_irq, + std_aux_free_irq, + + std_kbd_read_input, + std_kbd_write_output, + std_kbd_write_command, + std_kbd_read_status +}; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/memcpy.S linux.pre11.3/arch/mips/lib/memcpy.S --- linux.vanilla/arch/mips/lib/memcpy.S Sun Nov 8 15:08:30 1998 +++ linux.pre11.3/arch/mips/lib/memcpy.S Mon Jul 19 23:28:45 1999 @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * $Id: memcpy.S,v 1.4 1998/07/03 14:05:33 ralf Exp $ + * $Id: memcpy.S,v 1.3 1998/07/10 01:14:49 ralf Exp $ * * Unified implementation of memcpy, memmove and the __copy_user backend. * For __rmemcpy and memmove an exception is always a kernel bug, therefore diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/memset.S linux.pre11.3/arch/mips/lib/memset.S --- linux.vanilla/arch/mips/lib/memset.S Sun Nov 8 15:08:30 1998 +++ linux.pre11.3/arch/mips/lib/memset.S Mon Jul 19 23:28:45 1999 @@ -7,7 +7,7 @@ * * Copyright (C) 1998 by Ralf Baechle * - * $Id: memset.S,v 1.2 1998/04/25 17:01:45 ralf Exp $ + * $Id: memset.S,v 1.1 1998/05/04 09:12:54 ralf Exp $ */ #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/strlen_user.S linux.pre11.3/arch/mips/lib/strlen_user.S --- linux.vanilla/arch/mips/lib/strlen_user.S Sun Nov 8 15:08:30 1998 +++ linux.pre11.3/arch/mips/lib/strlen_user.S Mon Jul 19 23:28:45 1999 @@ -7,7 +7,7 @@ * * Copyright (c) 1996, 1998 by Ralf Baechle * - * $Id: strlen_user.S,v 1.3 1998/05/03 11:13:45 ralf Exp $ + * $Id: strlen_user.S,v 1.2 1998/05/04 09:12:54 ralf Exp $ */ #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/strncpy_user.S linux.pre11.3/arch/mips/lib/strncpy_user.S --- linux.vanilla/arch/mips/lib/strncpy_user.S Sun Nov 8 15:08:30 1998 +++ linux.pre11.3/arch/mips/lib/strncpy_user.S Mon Jul 19 23:28:45 1999 @@ -7,7 +7,7 @@ * * Copyright (c) 1996 by Ralf Baechle * - * $Id: strncpy_user.S,v 1.3 1998/05/03 11:13:45 ralf Exp $ + * $Id: strncpy_user.S,v 1.2 1998/05/04 09:12:54 ralf Exp $ */ #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/tags.c linux.pre11.3/arch/mips/lib/tags.c --- linux.vanilla/arch/mips/lib/tags.c Sun Nov 8 15:08:30 1998 +++ linux.pre11.3/arch/mips/lib/tags.c Thu Jan 1 01:00:00 1970 @@ -1,75 +0,0 @@ -/* - * linux/arch/mips/lib/tags.c - * - * Copyright (C) 1996 Stoned Elipot - */ -#include -#include -#include -#include -#include - -/* - * Parse the tags present in upper memory to find out - * a pecular one. - * - * Parameter: type - tag type to find - * - * returns : NULL - failure - * !NULL - pointer on the tag structure found - */ -tag * -bi_TagFind(enum bi_tag type) -{ - tag* t = (tag*)(mips_memory_upper - sizeof(tag)); - - while((t->tag != tag_dummy) && (t->tag != type)) - t = (tag*)(NEXTTAGPTR(t)); - - if (t->tag == tag_dummy) /* tag not found */ - return (tag*)NULL; - - return t; -} - -/* - * Snarf from the tag list in memory end some tags needed - * before the kernel reachs setup_arch() - * - * add yours here if you want to, but *beware*: the kernel var - * that will hold the values you want to snarf have to be - * in .data section of the kernel, so initialized in to whatever - * value in the kernel's sources. - */ -void bi_EarlySnarf(void) -{ - tag* atag; - - /* for wire_mappings() */ - atag = bi_TagFind(tag_machgroup); - if (atag) - memcpy(&mips_machgroup, TAGVALPTR(atag), atag->size); - else { - /* useless for boxes without text video mode but....*/ - panic("machine group not specified by bootloader"); - } - - atag = bi_TagFind(tag_machtype); - if (atag) - memcpy(&mips_machtype, TAGVALPTR(atag), atag->size); - else { - /* useless for boxes without text video mode but....*/ - panic("machine type not specified by bootloader"); - } - - /* for tlbflush() */ - atag = bi_TagFind(tag_tlb_entries); - if (atag) - memcpy(&mips_tlb_entries, TAGVALPTR(atag), atag->size); - else { - /* useless for boxes without text video mode but....*/ - panic("number of TLB entries not specified by bootloader"); - } - - return; -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/watch.S linux.pre11.3/arch/mips/lib/watch.S --- linux.vanilla/arch/mips/lib/watch.S Sun Nov 8 15:08:30 1998 +++ linux.pre11.3/arch/mips/lib/watch.S Mon Jul 19 23:28:45 1999 @@ -1,6 +1,6 @@ /* * Kernel debug stuff to use the Watch registers. - * Usefull to find stack overflows, dangeling pointers etc. + * Useful to find stack overflows, dangling pointers etc. * * 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 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/mm/Makefile linux.pre11.3/arch/mips/mm/Makefile --- linux.vanilla/arch/mips/mm/Makefile Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/mm/Makefile Mon Jul 19 23:28:37 1999 @@ -15,4 +15,8 @@ O_OBJS += umap.o endif +ifdef CONFIG_BAGET_MIPS +O_OBJS += umap.o +endif + include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/mm/andes.c linux.pre11.3/arch/mips/mm/andes.c --- linux.vanilla/arch/mips/mm/andes.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/mm/andes.c Mon Jul 19 23:28:37 1999 @@ -1,4 +1,4 @@ -/* $Id: andes.c,v 1.6 1998/10/16 19:22:42 ralf Exp $ +/* $Id: andes.c,v 1.6 1999/01/04 16:03:52 ralf Exp $ * * andes.c: MMU and cache operations for the R10000 (ANDES). * diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/mm/fault.c linux.pre11.3/arch/mips/mm/fault.c --- linux.vanilla/arch/mips/mm/fault.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/mm/fault.c Mon Jul 19 23:28:37 1999 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.12 1998/10/19 21:27:37 ralf Exp $ +/* $Id: fault.c,v 1.9 1999/01/04 16:03:53 ralf Exp $ * * 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 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/mm/init.c linux.pre11.3/arch/mips/mm/init.c --- linux.vanilla/arch/mips/mm/init.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/mm/init.c Mon Jul 19 23:28:37 1999 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.13 1998/10/16 19:22:42 ralf Exp $ +/* $Id: init.c,v 1.13 1999/05/01 22:40:40 ralf Exp $ * * 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 @@ -35,12 +35,6 @@ #endif #include -/* - * Define this to effectivly disable the userpage colouring shit. - */ -#define CONF_GIVE_A_SHIT_ABOUT_COLOURS - -extern void deskstation_tyne_dma_init(void); extern void show_net_buffers(void); void __bad_pte_kernel(pmd_t *pmd) @@ -59,7 +53,7 @@ { pte_t *page; - page = (pte_t *) __get_free_page(GFP_KERNEL); + page = (pte_t *) __get_free_page(GFP_USER); if (pmd_none(*pmd)) { if (page) { clear_page((unsigned long)page); @@ -126,6 +120,7 @@ case CPU_R4400SC: case CPU_R4400MC: order = 3; + break; default: order = 0; } @@ -137,6 +132,7 @@ pg = MAP_NR(empty_zero_page); while(pg < MAP_NR(empty_zero_page) + (1 << order)) { set_bit(PG_reserved, &mem_map[pg].flags); + atomic_set(&mem_map[pg].count, 0); pg++; } @@ -243,83 +239,6 @@ return pte_mkdirty(mk_pte(page, PAGE_SHARED)); } -#ifdef __SMP__ -spinlock_t user_page_lock = SPIN_LOCK_UNLOCKED; -#endif -struct upcache user_page_cache[8] __attribute__((aligned(32))); -static unsigned long user_page_order; -unsigned long user_page_colours; - -unsigned long get_user_page_slow(int which) -{ - unsigned long chunk; - struct upcache *up = &user_page_cache[0]; - struct page *p, *res; - int i; - - do { - chunk = __get_free_pages(GFP_KERNEL, user_page_order); - } while(chunk==0); - - p = mem_map + MAP_NR(chunk); - res = p + which; - spin_lock(&user_page_lock); - for (i=user_page_colours; i>=0; i--,p++,up++,chunk+=PAGE_SIZE) { - atomic_set(&p->count, 1); - p->age = PAGE_INITIAL_AGE; - - if (p != res) { - if(up->count < USER_PAGE_WATER) { - p->next = up->list; - up->list = p; - up->count++; - } else - free_pages(chunk, 0); - } - } - spin_unlock(&user_page_lock); - - return page_address(res); -} - -static inline void user_page_setup(void) -{ - unsigned long assoc = 0; - unsigned long dcache_log, icache_log, cache_log; - unsigned long config = read_32bit_cp0_register(CP0_CONFIG); - - switch(mips_cputype) { - case CPU_R4000SC: - case CPU_R4000MC: - case CPU_R4400SC: - case CPU_R4400MC: - cache_log = 3; /* => 32k, sucks */ - break; - - case CPU_R4600: /* two way set associative caches? */ - case CPU_R4700: - case CPU_R5000: - case CPU_NEVADA: - assoc = 1; - /* fall through */ - default: - /* use bigger cache */ - icache_log = (config >> 9) & 7; - dcache_log = (config >> 6) & 7; - if (dcache_log > icache_log) - cache_log = dcache_log; - else - cache_log = icache_log; - } - -#ifdef CONF_GIVE_A_SHIT_ABOUT_COLOURS - cache_log = assoc = 0; -#endif - - user_page_order = cache_log - assoc; - user_page_colours = (1 << (cache_log - assoc)) - 1; -} - void show_mem(void) { int i, free = 0, total = 0, reserved = 0; @@ -375,8 +294,9 @@ #endif end_mem &= PAGE_MASK; - max_mapnr = num_physpages = MAP_NR(end_mem); + max_mapnr = MAP_NR(end_mem); high_memory = (void *)end_mem; + num_physpages = 0; /* mark usable pages in the mem_map[] */ start_mem = PAGE_ALIGN(start_mem); @@ -384,15 +304,12 @@ for(tmp = MAP_NR(start_mem);tmp < max_mapnr;tmp++) clear_bit(PG_reserved, &mem_map[tmp].flags); - -#ifdef CONFIG_SGI prom_fixup_mem_map(start_mem, (unsigned long)high_memory); -#endif for (tmp = PAGE_OFFSET; tmp < end_mem; tmp += PAGE_SIZE) { /* * This is only for PC-style DMA. The onboard DMA - * of Jazz and Tyne machines is completly different and + * of Jazz and Tyne machines is completely different and * not handled via a flag in mem_map_t. */ if (tmp >= MAX_DMA_ADDRESS) @@ -406,6 +323,7 @@ datapages++; continue; } + num_physpages++; atomic_set(&mem_map[MAP_NR(tmp)].count, 1); #ifdef CONFIG_BLK_DEV_INITRD if (!initrd_start || (tmp < initrd_start || tmp >= @@ -423,9 +341,6 @@ max_mapnr << (PAGE_SHIFT-10), codepages << (PAGE_SHIFT-10), datapages << (PAGE_SHIFT-10)); - - /* Initialize allocator for colour matched mapped pages. */ - user_page_setup(); } extern char __init_begin, __init_end; @@ -433,7 +348,9 @@ void free_initmem(void) { unsigned long addr; - + + prom_free_prom_memory (); + addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/mm/loadmmu.c linux.pre11.3/arch/mips/mm/loadmmu.c --- linux.vanilla/arch/mips/mm/loadmmu.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/mm/loadmmu.c Mon Jul 19 23:28:37 1999 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: loadmmu.c,v 1.7 1998/03/27 08:53:41 ralf Exp $ + * $Id: loadmmu.c,v 1.9.2.2 1999/06/17 12:06:42 ralf Exp $ */ #include #include @@ -53,7 +53,7 @@ int (*user_mode)(struct pt_regs *); -asmlinkage void (*resume)(void *tsk); +asmlinkage void *(*resume)(void *last, void *next); extern void ld_mmu_r2300(void); extern void ld_mmu_r4xx0(void); @@ -66,6 +66,7 @@ switch(mips_cputype) { case CPU_R2000: case CPU_R3000: + case CPU_R3000A: printk("Loading R[23]00 MMU routines.\n"); ld_mmu_r2300(); break; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/mm/r2300.c linux.pre11.3/arch/mips/mm/r2300.c --- linux.vanilla/arch/mips/mm/r2300.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/mm/r2300.c Mon Jul 19 23:28:37 1999 @@ -1,8 +1,13 @@ -/* $Id: r2300.c,v 1.7 1998/10/16 19:22:43 ralf Exp $ - * +/* * r2300.c: R2000 and R3000 specific mmu/cache code. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * with a lot of changes to make this thing work for R3000s + * Copyright (C) 1998 Harald Koerfgen + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + * + * $Id: r2300.c,v 1.8 1999/04/11 17:13:56 harald Exp $ */ #include #include @@ -11,12 +16,40 @@ #include #include +#include #include #include -#include +#include +#include +/* + * Temporarily disabled + * +#include + */ + +/* + * According to the paper written by D. Miller about Linux cache & TLB + * flush implementation, DMA/Driver coherence should be done at the + * driver layer. Thus, normally, we don't need flush dcache for R3000. + * Define this if driver does not handle cache consistency during DMA ops. + */ +#undef DO_DCACHE_FLUSH + +/* + * Unified cache space description structure + */ +static struct cache_space { + unsigned long ca_flags; /* Cache space access flags */ + int size; /* Cache space size */ +} icache, dcache; + +#undef DEBUG_TLB +#undef DEBUG_CACHE extern unsigned long mips_tlb_entries; +#define NTLB_ENTRIES 64 /* Fixed on all R23000 variants... */ + /* page functions */ void r2300_clear_page(unsigned long page) { @@ -94,80 +127,425 @@ "I" (PAGE_SIZE)); } -/* Cache operations. */ -static inline void r2300_flush_cache_all(void) { } -static void r2300_flush_cache_mm(struct mm_struct *mm) { } +__initfunc(static unsigned long size_cache(unsigned long ca_flags)) +{ + unsigned long flags, status, dummy, size; + volatile unsigned long *p; + + p = (volatile unsigned long *) KSEG0; + + save_and_cli(flags); + + /* isolate cache space */ + write_32bit_cp0_register(CP0_STATUS, (ca_flags|flags)&~ST0_IEC); + + *p = 0xa5a55a5a; + dummy = *p; + status = read_32bit_cp0_register(CP0_STATUS); + + if (dummy != 0xa5a55a5a || (status & (1<<19))) { + size = 0; + } else { + for (size = 512; size <= 0x40000; size <<= 1) + *(p + size) = 0; + *p = -1; + for (size = 512; + (size <= 0x40000) && (*(p + size) == 0); + size <<= 1) + ; + if (size > 0x40000) + size = 0; + } + restore_flags(flags); + + return size * sizeof(*p); +} + +__initfunc(static void probe_dcache(void)) +{ + dcache.size = size_cache(dcache.ca_flags = ST0_DE); + printk("Data cache %dkb\n", dcache.size >> 10); +} + +__initfunc(static void probe_icache(void)) +{ + icache.size = size_cache(icache.ca_flags = ST0_DE|ST0_CE); + printk("Instruction cache %dkb\n", icache.size >> 10); +} + +static inline unsigned long get_phys_page (unsigned long page, + struct mm_struct *mm) +{ + page &= PAGE_MASK; + if (page >= KSEG0 && page < KSEG1) { + /* + * We already have physical address + */ + return page; + } else { + if (!mm) { + printk ("get_phys_page: vaddr without mm\n"); + return 0; + } else { + /* + * Find a physical page using mm_struct + */ + pgd_t *page_dir; + pmd_t *page_middle; + pte_t *page_table, pte; + + unsigned long address = page; + + page_dir = pgd_offset(mm, address); + if (pgd_none(*page_dir)) + return 0; + page_middle = pmd_offset(page_dir, address); + if (pmd_none(*page_middle)) + return 0; + page_table = pte_offset(page_middle, address); + pte = *page_table; + if (!pte_present(pte)) + return 0; + return pte_page(pte); + } + } +} + +static inline void flush_cache_space_page(struct cache_space *space, + unsigned long page) +{ + register unsigned long i, flags, size = space->size; + register volatile unsigned char *p = (volatile unsigned char*) page; + +#ifndef DO_DCACHE_FLUSH + if (space == &dcache) + return; +#endif + if (size > PAGE_SIZE) + size = PAGE_SIZE; + + save_and_cli(flags); + + /* isolate cache space */ + write_32bit_cp0_register(CP0_STATUS, (space->ca_flags|flags)&~ST0_IEC); + + for (i = 0; i < size; i += 64) { + asm ( "sb\t$0,(%0)\n\t" + "sb\t$0,4(%0)\n\t" + "sb\t$0,8(%0)\n\t" + "sb\t$0,12(%0)\n\t" + "sb\t$0,16(%0)\n\t" + "sb\t$0,20(%0)\n\t" + "sb\t$0,24(%0)\n\t" + "sb\t$0,28(%0)\n\t" + "sb\t$0,32(%0)\n\t" + "sb\t$0,36(%0)\n\t" + "sb\t$0,40(%0)\n\t" + "sb\t$0,44(%0)\n\t" + "sb\t$0,48(%0)\n\t" + "sb\t$0,52(%0)\n\t" + "sb\t$0,56(%0)\n\t" + "sb\t$0,60(%0)\n\t" + : : "r" (p) ); + p += 64; + } + + restore_flags(flags); +} + +static inline void flush_cache_space_all(struct cache_space *space) +{ + unsigned long page = KSEG0; + int size = space->size; + +#ifndef DO_DCACHE_FLUSH + if (space == &dcache) + return; +#endif + while(size > 0) { + flush_cache_space_page(space, page); + page += PAGE_SIZE; size -= PAGE_SIZE; + } +} + +static inline void r2300_flush_cache_all(void) +{ + flush_cache_space_all(&dcache); + flush_cache_space_all(&icache); +} + +static void r2300_flush_cache_mm(struct mm_struct *mm) +{ + if(mm->context == 0) + return; +#ifdef DEBUG_CACHE + printk("cmm[%d]", (int)mm->context); +#endif + /* + * This function is called not offen, so it looks + * enough good to flush all caches than scan mm_struct, + * count pages to flush (and, very probably, flush more + * than cache space size :-) + */ + flush_cache_all(); +} + static void r2300_flush_cache_range(struct mm_struct *mm, unsigned long start, unsigned long end) { + /* + * In general, we need to flush both i- & d- caches here. + * Optimization: if cache space is less than given range, + * it is more quickly to flush all cache than all pages in range. + */ + + unsigned long page; + int icache_done = 0, dcache_done = 0; + + if(mm->context == 0) + return; +#ifdef DEBUG_CACHE + printk("crange[%d]", (int)mm->context); +#endif + if (end - start >= icache.size) { + flush_cache_space_all(&icache); + icache_done = 1; + } + if (end - start >= dcache.size) { + flush_cache_space_all(&dcache); + dcache_done = 1; + } + if (icache_done && dcache_done) + return; + + for (page = start; page < end; page += PAGE_SIZE) { + unsigned long phys_page = get_phys_page(page, mm); + + if (phys_page) { + if (!icache_done) + flush_cache_space_page(&icache, phys_page); + if (!dcache_done) + flush_cache_space_page(&dcache, phys_page); + } + } } static void r2300_flush_cache_page(struct vm_area_struct *vma, unsigned long page) { + struct mm_struct *mm = vma->vm_mm; + + if(mm->context == 0) + return; +#ifdef DEBUG_CACHE + printk("cpage[%d,%08lx]", (int)mm->context, page); +#endif + /* + * User changes page, so we need to check: + * is icache page flush needed ? + * It looks we don't need to flush dcache, + * due it is write-transparent on R3000 + */ + if (vma->vm_flags & VM_EXEC) { + unsigned long phys_page = get_phys_page(page, vma->vm_mm); + if (phys_page) + flush_cache_space_page(&icache, phys_page); + } } static void r2300_flush_page_to_ram(unsigned long page) { - /* XXX What we want to do here is perform a displacement - * XXX flush because there are circumstances where you do - * XXX indeed want to remove stale data from the cache. - * XXX (DMA operations for example, where the cache cannot - * XXX "see" this data get changed.) + /* + * We need to flush both i- & d- caches :-( */ + unsigned long phys_page = get_phys_page(page, NULL); +#ifdef DEBUG_CACHE + printk("cram[%08lx]", page); +#endif + if (phys_page) { + flush_cache_space_page(&icache, phys_page); + flush_cache_space_page(&dcache, phys_page); + } +} + +static void r3k_dma_cache_wback_inv(unsigned long start, unsigned long size) +{ + register unsigned long i, flags; + register volatile unsigned char *p = (volatile unsigned char*) start; + +/* + * Temporarily disabled + wbflush(); + */ + + /* + * Invalidate dcache + */ + if (size < 64) + size = 64; + + if (size > dcache.size) + size = dcache.size; + + save_and_cli(flags); + + /* isolate cache space */ + write_32bit_cp0_register(CP0_STATUS, (ST0_DE|flags)&~ST0_IEC); + + for (i = 0; i < size; i += 64) { + asm ( "sb\t$0,(%0)\n\t" + "sb\t$0,4(%0)\n\t" + "sb\t$0,8(%0)\n\t" + "sb\t$0,12(%0)\n\t" + "sb\t$0,16(%0)\n\t" + "sb\t$0,20(%0)\n\t" + "sb\t$0,24(%0)\n\t" + "sb\t$0,28(%0)\n\t" + "sb\t$0,32(%0)\n\t" + "sb\t$0,36(%0)\n\t" + "sb\t$0,40(%0)\n\t" + "sb\t$0,44(%0)\n\t" + "sb\t$0,48(%0)\n\t" + "sb\t$0,52(%0)\n\t" + "sb\t$0,56(%0)\n\t" + "sb\t$0,60(%0)\n\t" + : : "r" (p) ); + p += 64; + } + + restore_flags(flags); } static void r2300_flush_cache_sigtramp(unsigned long page) { + /* + * We need only flush i-cache here + * + * This function receives virtual address (from signal.c), + * but this moment we have needed mm_struct in 'current' + */ + unsigned long phys_page = get_phys_page(page, current->mm); +#ifdef DEBUG_CACHE + printk("csigtramp[%08lx]", page); +#endif + if (phys_page) + flush_cache_space_page(&icache, phys_page); } /* TLB operations. */ static inline void r2300_flush_tlb_all(void) { unsigned long flags; + unsigned long old_ctx; int entry; +#ifdef DEBUG_TLB + printk("[tlball]"); +#endif + save_and_cli(flags); + old_ctx = (get_entryhi() & 0xfc0); write_32bit_cp0_register(CP0_ENTRYLO0, 0); - for(entry = 0; entry < mips_tlb_entries; entry++) { - write_32bit_cp0_register(CP0_INDEX, entry); - write_32bit_cp0_register(CP0_ENTRYHI, ((entry | 0x8) << 12)); + for(entry = 0; entry < NTLB_ENTRIES; entry++) { + write_32bit_cp0_register(CP0_INDEX, entry << 8); + write_32bit_cp0_register(CP0_ENTRYHI, ((entry | 0x80000) << 12)); __asm__ __volatile__("tlbwi"); } + set_entryhi(old_ctx); restore_flags(flags); } static void r2300_flush_tlb_mm(struct mm_struct *mm) { + if(mm->context != 0) { + unsigned long flags; + +#ifdef DEBUG_TLB + printk("[tlbmm<%d>]", mm->context); +#endif + save_and_cli(flags); + get_new_mmu_context(mm, asid_cache); if(mm == current->mm) - r2300_flush_tlb_all(); + set_entryhi(mm->context & 0xfc0); + restore_flags(flags); + } } static void r2300_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { + if(mm->context != 0) { + unsigned long flags; + int size; + +#ifdef DEBUG_TLB + printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xfc0), + start, end); +#endif + save_and_cli(flags); + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + if(size <= NTLB_ENTRIES) { + int oldpid = (get_entryhi() & 0xfc0); + int newpid = (mm->context & 0xfc0); + + start &= PAGE_MASK; + end += (PAGE_SIZE - 1); + end &= PAGE_MASK; + while(start < end) { + int idx; + + set_entryhi(start | newpid); + start += PAGE_SIZE; + tlb_probe(); + idx = get_index(); + set_entrylo0(0); + set_entryhi(KSEG0); + if(idx < 0) + continue; + tlb_write_indexed(); + } + set_entryhi(oldpid); + } else { + get_new_mmu_context(mm, asid_cache); if(mm == current->mm) - r2300_flush_tlb_all(); + set_entryhi(mm->context & 0xfc0); + } + restore_flags(flags); + } } static void r2300_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) { - if(vma->vm_mm == current->mm) - r2300_flush_tlb_all(); + if(vma->vm_mm->context != 0) { + unsigned long flags; + int oldpid, newpid, idx; + +#ifdef DEBUG_TLB + printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page); +#endif + newpid = (vma->vm_mm->context & 0xfc0); + page &= PAGE_MASK; + save_and_cli(flags); + oldpid = (get_entryhi() & 0xfc0); + set_entryhi(page | newpid); + tlb_probe(); + idx = get_index(); + set_entrylo0(0); + set_entryhi(KSEG0); + if(idx < 0) + goto finish; + tlb_write_indexed(); + +finish: + set_entryhi(oldpid); + restore_flags(flags); + } } /* Load a new root pointer into the TLB. */ static void r2300_load_pgd(unsigned long pg_dir) { - unsigned long flags; - - save_and_cli(flags); - write_32bit_cp0_register(CP0_ENTRYHI, TLB_ROOT); - write_32bit_cp0_register(CP0_INDEX, 0); - write_32bit_cp0_register(CP0_ENTRYLO0, ((pg_dir >> 6) | 0x00e0)); - __asm__ __volatile__("tlbwi"); - restore_flags(flags); } /* @@ -199,17 +577,63 @@ "=r" (dummy2) :"r" ((unsigned long) invalid_pte_table), "0" (page), - "1" (USER_PTRS_PER_PGD/8)); + "1" (PAGE_SIZE/(sizeof(pmd_t)*8))); } static void r2300_update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t pte) { - r2300_flush_tlb_page(vma, address); - /* - * FIXME: We should also reload a new entry into the TLB to - * avoid unnecessary exceptions. - */ + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int idx, pid; + + pid = (get_entryhi() & 0xfc0); + +#ifdef DEBUG_TLB + if((pid != (vma->vm_mm->context & 0xfc0)) || (vma->vm_mm->context == 0)) { + printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n", + (int) (vma->vm_mm->context & 0xfc0), pid); + } +#endif + + save_and_cli(flags); + address &= PAGE_MASK; + set_entryhi(address | (pid)); + pgdp = pgd_offset(vma->vm_mm, address); + tlb_probe(); + pmdp = pmd_offset(pgdp, address); + idx = get_index(); + ptep = pte_offset(pmdp, address); + set_entrylo0(pte_val(*ptep)); + set_entryhi(address | (pid)); + if(idx < 0) { + tlb_write_random(); +#if 0 + printk("[MISS]"); +#endif + } else { + tlb_write_indexed(); +#if 0 + printk("[HIT]"); +#endif + } +#if 0 + if(!strcmp(current->comm, "args")) { + printk("<"); + for(idx = 0; idx < NTLB_ENTRIES; idx++) { + set_index(idx); + tlb_read(); + address = get_entryhi(); + if((address & 0xfc0) != 0) + printk("[%08lx]", address); + } + printk(">\n"); + } +#endif + set_entryhi(pid); + restore_flags(flags); } static void r2300_show_regs(struct pt_regs * regs) @@ -248,6 +672,7 @@ static void r2300_add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask) { +printk("r2300_add_wired_entry"); /* * FIXME, to be done */ @@ -255,14 +680,19 @@ static int r2300_user_mode(struct pt_regs *regs) { - return !(regs->cp0_status & 0x4); + return !(regs->cp0_status & ST0_KUP); } __initfunc(void ld_mmu_r2300(void)) { + printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID)); + clear_page = r2300_clear_page; copy_page = r2300_copy_page; + probe_icache(); + probe_dcache(); + flush_cache_all = r2300_flush_cache_all; flush_cache_mm = r2300_flush_cache_mm; flush_cache_range = r2300_flush_cache_range; @@ -274,16 +704,19 @@ flush_tlb_mm = r2300_flush_tlb_mm; flush_tlb_range = r2300_flush_tlb_range; flush_tlb_page = r2300_flush_tlb_page; - r3000_asid_setup(); + + dma_cache_wback_inv = r3k_dma_cache_wback_inv; load_pgd = r2300_load_pgd; pgd_init = r2300_pgd_init; update_mmu_cache = r2300_update_mmu_cache; + r3000_asid_setup(); show_regs = r2300_show_regs; add_wired_entry = r2300_add_wired_entry; user_mode = r2300_user_mode; + flush_tlb_all(); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/mm/r4xx0.c linux.pre11.3/arch/mips/mm/r4xx0.c --- linux.vanilla/arch/mips/mm/r4xx0.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/mm/r4xx0.c Mon Jul 19 23:28:37 1999 @@ -1,4 +1,4 @@ -/* $Id: r4xx0.c,v 1.30 1998/10/16 19:22:43 ralf Exp $ +/* $Id: r4xx0.c,v 1.21.2.2 1999/06/17 12:06:42 ralf Exp $ * * 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 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/mm/r6000.c linux.pre11.3/arch/mips/mm/r6000.c --- linux.vanilla/arch/mips/mm/r6000.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/mm/r6000.c Mon Jul 19 23:28:37 1999 @@ -1,4 +1,4 @@ -/* $Id: r6000.c,v 1.6 1998/10/16 19:22:44 ralf Exp $ +/* $Id: r6000.c,v 1.6 1999/01/04 16:03:54 ralf Exp $ * * r6000.c: MMU and cache routines for the R6000 processors. * diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/mm/tfp.c linux.pre11.3/arch/mips/mm/tfp.c --- linux.vanilla/arch/mips/mm/tfp.c Sun Nov 8 15:08:29 1998 +++ linux.pre11.3/arch/mips/mm/tfp.c Mon Jul 19 23:28:37 1999 @@ -1,4 +1,4 @@ -/* $Id: tfp.c,v 1.6 1998/10/16 19:22:44 ralf Exp $ +/* $Id: tfp.c,v 1.6 1999/01/04 16:03:55 ralf Exp $ * * tfp.c: MMU and cache routines specific to the r8000 (TFP). * diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/Makefile linux.pre11.3/arch/mips/sgi/kernel/Makefile --- linux.vanilla/arch/mips/sgi/kernel/Makefile Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/sgi/kernel/Makefile Mon Jul 19 23:28:46 1999 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.3 1998/06/25 20:19:17 ralf Exp $ +# $Id: Makefile,v 1.7 1999/05/07 18:00:16 ulfc Exp $ # Makefile for the SGI specific kernel interface routines # under Linux. # @@ -13,8 +13,11 @@ .S.o: $(CC) $(CFLAGS) -c $< -o $*.o -OBJS = indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o system.o \ - indy_timer.o indyIRQ.o reset.o setup.o time.o +OBJS = indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o \ + system.o indy_timer.o indyIRQ.o reset.o setup.o time.o +ifdef CONFIG_SGI_PROM_CONSOLE +OBJS += promcon.o +endif all: sgikern.a diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/indyIRQ.S linux.pre11.3/arch/mips/sgi/kernel/indyIRQ.S --- linux.vanilla/arch/mips/sgi/kernel/indyIRQ.S Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/sgi/kernel/indyIRQ.S Mon Jul 19 23:28:46 1999 @@ -1,4 +1,4 @@ -/* $Id: indyIRQ.S,v 1.3 1998/03/21 22:39:53 ralf Exp $ +/* $Id: indyIRQ.S,v 1.3 1998/03/22 23:27:17 ralf Exp $ * indyIRQ.S: Interrupt exception dispatch code for FullHouse and * Guiness. * diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/indy_hpc.c linux.pre11.3/arch/mips/sgi/kernel/indy_hpc.c --- linux.vanilla/arch/mips/sgi/kernel/indy_hpc.c Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/sgi/kernel/indy_hpc.c Mon Jul 19 23:28:46 1999 @@ -1,4 +1,4 @@ -/* $Id: indy_hpc.c,v 1.4 1998/07/14 09:12:27 ralf Exp $ +/* $Id: indy_hpc.c,v 1.6 1999/05/07 22:34:31 ulfc Exp $ * * indy_hpc.c: Routines for generic manipulation of the HPC controllers. * @@ -43,7 +43,8 @@ prom_printf("sgihpc_init: "); #endif - if(sid & 1) { + /* This test works now thanks to William J. Earl */ + if ((sid & 1) == 0 ) { #ifdef DEBUG_SGIHPC prom_printf("GUINESS "); #endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/indy_int.c linux.pre11.3/arch/mips/sgi/kernel/indy_int.c --- linux.vanilla/arch/mips/sgi/kernel/indy_int.c Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/sgi/kernel/indy_int.c Mon Jul 19 23:53:55 1999 @@ -1,12 +1,14 @@ -/* $Id: indy_int.c,v 1.9 1998/05/28 03:18:00 ralf Exp $ +/* $Id: indy_int.c,v 1.13 1999/06/12 17:26:15 ulfc Exp $ * * indy_int.c: Routines for generic manipulation of the INT[23] ASIC * found on INDY workstations.. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * Copyright (C) 1997, 1998 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) + * - Indigo2 changes + * - Interrupt handling fixes */ -#include #include #include @@ -35,6 +37,7 @@ #include #include #include +#include /* #define DEBUG_SGINT */ @@ -51,10 +54,6 @@ extern asmlinkage void indyIRQ(void); -#ifdef CONFIG_REMOTE_DEBUG -extern void rs_kgdb_hook(int); -#endif - unsigned int local_bh_count[NR_CPUS]; unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; @@ -274,7 +273,7 @@ int do_random, cpu; cpu = smp_processor_id(); - irq_enter(cpu, irq); + hardirq_enter(cpu); kstat.irqs[0][irq]++; printk("Got irq %d, press a key.", irq); @@ -310,7 +309,7 @@ add_interrupt_randomness(irq); __cli(); } - irq_exit(cpu, irq); + hardirq_exit(cpu); /* unmasking and bottom half handling is done magically for us. */ } @@ -448,10 +447,23 @@ action = local_irq_action[irq]; } - irq_enter(cpu, irq); + /* if irq == 0, then the interrupt has already been cleared */ + if ( irq == 0 ) { goto end; } + /* if action == NULL, then we do have a handler for the irq */ + if ( action == NULL ) { goto no_handler; } + + hardirq_enter(cpu); kstat.irqs[0][irq + 16]++; action->handler(irq, action->dev_id, regs); - irq_exit(cpu, irq); + hardirq_exit(cpu); + goto end; + +no_handler: + printk("No handler for local0 irq: %i\n", irq); + +end: + return; + } void indy_local1_irqdispatch(struct pt_regs *regs) @@ -472,10 +484,23 @@ irq = lc1msk_to_irqnr[mask]; action = local_irq_action[irq]; } - irq_enter(cpu, irq); + /* if irq == 0, then the interrupt has already been cleared */ + /* not sure if it is needed here, but it is needed for local0 */ + if ( irq == 0 ) { goto end; } + /* if action == NULL, then we do have a handler for the irq */ + if ( action == NULL ) { goto no_handler; } + + hardirq_enter(cpu); kstat.irqs[0][irq + 24]++; action->handler(irq, action->dev_id, regs); - irq_exit(cpu, irq); + hardirq_exit(cpu); + goto end; + +no_handler: + printk("No handler for local1 irq: %i\n", irq); + +end: + return; } void indy_buserror_irq(struct pt_regs *regs) @@ -483,13 +508,13 @@ int cpu = smp_processor_id(); int irq = 6; - irq_enter(cpu, irq); + hardirq_enter(cpu); kstat.irqs[0][irq]++; printk("Got a bus error IRQ, shouldn't happen yet\n"); show_regs(regs); printk("Spinning...\n"); while(1); - irq_exit(cpu, irq); + hardirq_exit(cpu); } /* Misc. crap just to keep the kernel linking... */ @@ -506,9 +531,6 @@ __initfunc(void sgint_init(void)) { int i; -#ifdef CONFIG_REMOTE_DEBUG - char *ctype; -#endif sgi_i2regs = (struct sgi_int2_regs *) (KSEG1 + SGI_INT2_BASE); sgi_i3regs = (struct sgi_int3_regs *) (KSEG1 + SGI_INT3_BASE); @@ -563,9 +585,16 @@ } } - ioc_icontrol = &sgi_i3regs->ints; - ioc_timers = &sgi_i3regs->timers; - ioc_tclear = &sgi_i3regs->tclear; + /* Indy uses an INT3, Indigo2 uses an INT2 */ + if (sgi_guiness) { + ioc_icontrol = &sgi_i3regs->ints; + ioc_timers = &sgi_i3regs->timers; + ioc_tclear = &sgi_i3regs->tclear; + } else { + ioc_icontrol = &sgi_i2regs->ints; + ioc_timers = &sgi_i2regs->timers; + ioc_tclear = &sgi_i2regs->tclear; + } /* Mask out all interrupts. */ ioc_icontrol->imask0 = 0; @@ -575,28 +604,4 @@ /* Now safe to set the exception vector. */ set_except_vector(0, indyIRQ); - -#ifdef CONFIG_REMOTE_DEBUG - ctype = prom_getcmdline(); - for(i = 0; i < strlen(ctype); i++) { - if(ctype[i]=='k' && ctype[i+1]=='g' && - ctype[i+2]=='d' && ctype[i+3]=='b' && - ctype[i+4]=='=' && ctype[i+5]=='t' && - ctype[i+6]=='t' && ctype[i+7]=='y' && - ctype[i+8]=='d' && - (ctype[i+9] == '1' || ctype[i+9] == '2')) { - printk("KGDB: Using serial line /dev/ttyd%d for " - "session\n", (ctype[i+9] - '0')); - if(ctype[i+9]=='1') - rs_kgdb_hook(1); - else if(ctype[i+9]=='2') - rs_kgdb_hook(0); - else { - printk("KGDB: whoops bogon tty line " - "requested, disabling session\n"); - } - - } - } -#endif } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/indy_mc.c linux.pre11.3/arch/mips/sgi/kernel/indy_mc.c --- linux.vanilla/arch/mips/sgi/kernel/indy_mc.c Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/sgi/kernel/indy_mc.c Mon Jul 19 23:28:46 1999 @@ -2,8 +2,9 @@ * indy_mc.c: Routines for manipulating the INDY memory controller. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - Indigo2 changes * - * $Id: indy_mc.c,v 1.3 1998/04/25 15:43:32 ralf Exp $ + * $Id: indy_mc.c,v 1.4 1999/05/07 22:34:32 ulfc Exp $ */ #include #include @@ -150,6 +151,8 @@ tmpreg |= SGIMC_GIOPARM_PLINEEXP0; /* exp[01] pipelined */ tmpreg |= SGIMC_GIOPARM_PLINEEXP1; tmpreg |= SGIMC_GIOPARM_MASTEREISA;/* EISA masters */ + /* someone forgot this poor little guy... */ + tmpreg |= SGIMC_GIOPARM_GFX64; /* GFX at 64 bits */ } } mcmisc_regs->gioparm = tmpreg; /* poof */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/indy_sc.c linux.pre11.3/arch/mips/sgi/kernel/indy_sc.c --- linux.vanilla/arch/mips/sgi/kernel/indy_sc.c Sun Nov 8 15:10:06 1998 +++ linux.pre11.3/arch/mips/sgi/kernel/indy_sc.c Mon Jul 19 23:53:55 1999 @@ -1,4 +1,4 @@ -/* $Id: indy_sc.c,v 1.9 1998/08/17 12:14:55 ralf Exp $ +/* $Id: indy_sc.c,v 1.9 1999/05/12 21:57:49 ulfc Exp $ * * indy_sc.c: Indy cache managment functions. * @@ -9,7 +9,6 @@ #include #include #include -#include #include #include @@ -38,6 +37,7 @@ .set noreorder .set mips3 .set noat + mfc0 $2, $12 li $1, 0x80 # Go 64 bit mtc0 $1, $12 @@ -50,12 +50,12 @@ bne %0, %1, 1b daddu %0, 32 - mtc0 $0, $12 # Back to 32 bit + mtc0 $2, $12 # Back to 32 bit nop; nop; nop; nop; .set mips0 .set reorder" - : "=r" (first), "=r" (last) - : "0" (first), "1" (last) + : /* no output */ + : "r" (first), "r" (last) : "$1"); } @@ -69,7 +69,10 @@ #endif /* Which lines to flush? */ first_line = SC_INDEX(addr); - last_line = SC_INDEX(SC_ROUND(addr + size)); + if (size <= SC_LINE) + last_line = SC_INDEX(addr); + else + last_line = SC_INDEX(addr + size - 1); __save_and_cli(flags); if (first_line <= last_line) { @@ -80,8 +83,8 @@ /* Cache index wrap around. Due to the way the buddy system works this case should not happen. We're prepared to handle it, though. */ - indy_sc_wipe(last_line, SC_SIZE); - indy_sc_wipe(0, first_line); + indy_sc_wipe(first_line, SC_SIZE - SC_LINE); + indy_sc_wipe(0, last_line); out: __restore_flags(flags); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/indy_timer.c linux.pre11.3/arch/mips/sgi/kernel/indy_timer.c --- linux.vanilla/arch/mips/sgi/kernel/indy_timer.c Wed Mar 24 10:55:10 1999 +++ linux.pre11.3/arch/mips/sgi/kernel/indy_timer.c Mon Jul 19 23:28:46 1999 @@ -1,4 +1,4 @@ -/* $Id: indy_timer.c,v 1.9 1998/06/25 20:15:02 ralf Exp $ +/* $Id: indy_timer.c,v 1.12 1999/06/13 16:30:36 ralf Exp $ * * indy_timer.c: Setting up the clock on the INDY 8254 controller. * @@ -262,12 +262,12 @@ int cpu = smp_processor_id(); int irq = 4; - irq_enter(cpu, irq); + hardirq_enter(cpu); kstat.irqs[0][irq]++; printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n"); prom_getchar(); prom_imode(); - irq_exit(cpu, irq); + hardirq_exit(cpu); } void do_gettimeofday(struct timeval *tv) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/promcon.c linux.pre11.3/arch/mips/sgi/kernel/promcon.c --- linux.vanilla/arch/mips/sgi/kernel/promcon.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/arch/mips/sgi/kernel/promcon.c Mon Jul 19 23:28:46 1999 @@ -0,0 +1,73 @@ +/* + * Wrap-around code for a console using the + * SGI PROM io-routines. + * + * Copyright (c) 1999 Ulf Carlsson + * + * Derived from DECstation promcon.c + * Copyright (c) 1998 Harald Koerfgen + */ + +#include +#include +#include +#include +#include +#include + +#include + +static void prom_console_write(struct console *co, const char *s, + unsigned count) +{ + unsigned i; + + /* + * Now, do each character + */ + for (i = 0; i < count; i++) { + if (*s == 10) + prom_printf("%c", 13); + prom_printf("%c", *s++); + } +} + +static int prom_console_wait_key(struct console *co) +{ + return prom_getchar(); +} + +__initfunc(static int prom_console_setup(struct console *co, char *options)) +{ + return 0; +} + +static kdev_t prom_console_device(struct console *c) +{ + return MKDEV(TTY_MAJOR, 64 + c->index); +} + +static struct console sercons = +{ + "ttyS", + prom_console_write, + NULL, + prom_console_device, + prom_console_wait_key, + NULL, + prom_console_setup, + CON_PRINTBUFFER, + -1, + 0, + NULL +}; + +/* + * Register console. + */ + +__initfunc(long sgi_prom_console_init(long kmem_start, long kmem_end)) +{ + register_console(&sercons); + return kmem_start; +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/reset.c linux.pre11.3/arch/mips/sgi/kernel/reset.c --- linux.vanilla/arch/mips/sgi/kernel/reset.c Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/sgi/kernel/reset.c Mon Jul 19 23:28:46 1999 @@ -1,4 +1,4 @@ -/* $Id: reset.c,v 1.6 1998/07/09 19:57:47 ralf Exp $ +/* $Id: reset.c,v 1.6 1999/04/10 12:21:30 ulfc Exp $ * * Reset a SGI. * @@ -33,7 +33,9 @@ #define POWERDOWN_FREQ (HZ / 4) #define PANIC_FREQ (HZ / 8) -static struct timer_list power_timer, blink_timer, debounce_timer; +static unsigned char sgi_volume; + +static struct timer_list power_timer, blink_timer, debounce_timer, volume_timer; static int shuting_down, has_paniced; static void sgi_machine_restart(char *command) __attribute__((noreturn)); @@ -129,14 +131,50 @@ add_timer(&power_timer); } -static inline void volume_up_button(void) +void inline sgi_volume_set(unsigned char volume) +{ + sgi_volume = volume; + + hpc3c0->pbus_extregs[2][0] = sgi_volume; + hpc3c0->pbus_extregs[2][1] = sgi_volume; +} + +void inline sgi_volume_get(unsigned char *volume) { - /* Later when we have sound support ... */ + *volume = sgi_volume; } -static inline void volume_down_button(void) +static inline void volume_up_button(unsigned long data) { - /* Later when we have sound support ... */ + del_timer(&volume_timer); + + if (sgi_volume < 0xff) + sgi_volume++; + + hpc3c0->pbus_extregs[2][0] = sgi_volume; + hpc3c0->pbus_extregs[2][1] = sgi_volume; + + if (ioc_icontrol->istat1 & 2) { + volume_timer.expires = jiffies + 1; + add_timer(&volume_timer); + } + +} + +static inline void volume_down_button(unsigned long data) +{ + del_timer(&volume_timer); + + if (sgi_volume > 0) + sgi_volume--; + + hpc3c0->pbus_extregs[2][0] = sgi_volume; + hpc3c0->pbus_extregs[2][1] = sgi_volume; + + if (ioc_icontrol->istat1 & 2) { + volume_timer.expires = jiffies + 1; + add_timer(&volume_timer); + } } static void panel_int(int irq, void *dev_id, struct pt_regs *regs) @@ -156,10 +194,18 @@ if (!(buttons & 2)) /* Power button was pressed */ power_button(); - if (!(buttons & 0x40)) /* Volume up button was pressed */ - volume_up_button(); - if (!(buttons & 0x10)) /* Volume down button was pressed */ - volume_down_button(); + if (!(buttons & 0x40)) { /* Volume up button was pressed */ + init_timer(&volume_timer); + volume_timer.function = volume_up_button; + volume_timer.expires = jiffies + 1; + add_timer(&volume_timer); + } + if (!(buttons & 0x10)) { /* Volume down button was pressed */ + init_timer(&volume_timer); + volume_timer.function = volume_down_button; + volume_timer.expires = jiffies + 1; + add_timer(&volume_timer); + } } static int panic_event(struct notifier_block *this, unsigned long event, diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/setup.c linux.pre11.3/arch/mips/sgi/kernel/setup.c --- linux.vanilla/arch/mips/sgi/kernel/setup.c Sun Nov 8 15:10:06 1998 +++ linux.pre11.3/arch/mips/sgi/kernel/setup.c Mon Jul 19 23:28:46 1999 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.13 1998/09/16 22:50:46 ralf Exp $ +/* $Id: setup.c,v 1.24 1999/06/12 17:26:15 ulfc Exp $ * * setup.c: SGI specific setup, including init of the feature struct. * @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -25,16 +26,55 @@ #include #include #include +#include -extern int serial_console; /* in sgiserial.c */ +#ifdef CONFIG_REMOTE_DEBUG +extern void rs_kgdb_hook(int); +extern void breakpoint(void); +#endif + +#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE) +extern void console_setup(char *, int *); +#endif extern struct rtc_ops indy_rtc_ops; void indy_reboot_setup(void); +void sgi_volume_set(unsigned char); -static volatile struct hpc_keyb *sgi_kh = (struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64); +static int remote_debug = 0; + +#define sgi_kh ((struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64)) #define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ +static void sgi_request_region(void) +{ + /* No I/O ports are being used on the Indy. */ +} + +static int sgi_request_irq(void (*handler)(int, void *, struct pt_regs *)) +{ + /* Dirty hack, this get's called as a callback from the keyboard + driver. We piggyback the initialization of the front panel + button handling on it even though they're technically not + related with the keyboard driver in any way. Doing it from + indy_setup wouldn't work since kmalloc isn't initialized yet. */ + indy_reboot_setup(); + + return request_irq(SGI_KEYBOARD_IRQ, handler, 0, "keyboard", NULL); +} + +static int sgi_aux_request_irq(void (*handler)(int, void *, struct pt_regs *)) +{ + /* Nothing to do, interrupt is shared with the keyboard hw */ + return 0; +} + +static void sgi_aux_free_irq(void) +{ + /* Nothing to do, interrupt is shared with the keyboard hw */ +} + static unsigned char sgi_read_input(void) { return sgi_kh->data; @@ -65,27 +105,28 @@ return sgi_kh->command; } -__initfunc(static void sgi_keyboard_setup(void)) -{ - kbd_read_input = sgi_read_input; - kbd_write_output = sgi_write_output; - kbd_write_command = sgi_write_command; - kbd_read_status = sgi_read_status; - - request_irq(SGI_KEYBOARD_IRQ, keyboard_interrupt, - 0, "keyboard", NULL); - - /* Dirty hack, this get's called as a callback from the keyboard - driver. We piggyback the initialization of the front panel - button handling on it even though they're technically not - related with the keyboard driver in any way. Doing it from - indy_setup wouldn't work since kmalloc isn't initialized yet. */ - indy_reboot_setup(); -} +struct kbd_ops sgi_kbd_ops = { + sgi_request_region, + sgi_request_irq, + + sgi_aux_request_irq, + sgi_aux_free_irq, + + sgi_read_input, + sgi_write_output, + sgi_write_command, + sgi_read_status +}; __initfunc(static void sgi_irq_setup(void)) { sgint_init(); + +#ifdef CONFIG_REMOTE_DEBUG + if (remote_debug) + set_debug_traps(); + breakpoint(); /* you may move this line to whereever you want :-) */ +#endif } __initfunc(void sgi_setup(void)) @@ -93,9 +134,12 @@ #ifdef CONFIG_SERIAL_CONSOLE char *ctype; #endif +#ifdef CONFIG_REMOTE_DEBUG + char *kgdb_ttyd; +#endif + irq_setup = sgi_irq_setup; - keyboard_setup = sgi_keyboard_setup; /* Init the INDY HPC I/O controller. Need to call this before * fucking with the memory controller because it needs to know the @@ -115,23 +159,55 @@ * line and "d2" for the second serial line. */ ctype = prom_getenv("console"); - serial_console = 0; if(*ctype == 'd') { if(*(ctype+1)=='2') - serial_console = 1; + console_setup ("ttyS1", NULL); else - serial_console = 2; - if(!serial_console) { - prom_printf("Weird console env setting %s\n", ctype); - prom_printf("Press a key to reboot.\n"); - prom_getchar(); - prom_imode(); - } + console_setup ("ttyS0", NULL); + } +#endif + +#ifdef CONFIG_REMOTE_DEBUG + kgdb_ttyd = prom_getcmdline(); + if ((kgdb_ttyd = strstr(kgdb_ttyd, "kgdb=ttyd")) != NULL) { + int line; + kgdb_ttyd += strlen("kgdb=ttyd"); + if (*kgdb_ttyd != '1' && *kgdb_ttyd != '2') + printk("KGDB: Uknown serial line /dev/ttyd%c, " + "falling back to /dev/ttyd1\n", *kgdb_ttyd); + line = *kgdb_ttyd == '2' ? 0 : 1; + printk("KGDB: Using serial line /dev/ttyd%d for session\n", + line ? 1 : 2); + rs_kgdb_hook(line); + + prom_printf("KGDB: Using serial line /dev/ttyd%d for session, " + "please connect your debugger\n", line ? 1 : 2); + + remote_debug = 1; + /* Breakpoints and stuff are in sgi_irq_setup() */ } #endif +#ifdef CONFIG_SGI_PROM_CONSOLE + console_setup("ttyS0", NULL); +#endif + + sgi_volume_set(simple_strtoul(prom_getenv("volume"), NULL, 10)); + #ifdef CONFIG_VT +#ifdef CONFIG_SGI_NEWPORT_CONSOLE conswitchp = &newport_con; +#else + conswitchp = &dummy_con; +#endif #endif + rtc_ops = &indy_rtc_ops; + kbd_ops = &sgi_kbd_ops; +#ifdef CONFIG_PSMOUSE + aux_device_present = 0xaa; +#endif +#ifdef CONFIG_VIDEO_VINO + init_vino(); +#endif } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/system.c linux.pre11.3/arch/mips/sgi/kernel/system.c --- linux.vanilla/arch/mips/sgi/kernel/system.c Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/sgi/kernel/system.c Mon Jul 19 23:28:46 1999 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: system.c,v 1.4 1998/03/27 08:53:45 ralf Exp $ + * $Id: system.c,v 1.7 1998/10/18 22:55:34 tsbogend Exp $ */ #include #include @@ -21,28 +21,6 @@ int type; }; -static struct smatch sgi_mtable[] = { - { "SGI-IP4", ip4 }, - { "SGI-IP5", ip5 }, - { "SGI-IP6", ip6 }, - { "SGI-IP7", ip7 }, - { "SGI-IP9", ip9 }, - { "SGI-IP12", ip12 }, - { "SGI-IP15", ip15 }, - { "SGI-IP17", ip17 }, - { "SGI-IP19", ip19 }, - { "SGI-IP20", ip20 }, - { "SGI-IP21", ip21 }, - { "SGI-IP22", ip22 }, - { "SGI-IP25", ip25 }, - { "SGI-IP26", ip26 }, - { "SGI-IP28", ip28 }, - { "SGI-IP30", ip30 }, - { "SGI-IP32", ip32 } -}; - -#define NUM_MACHS 17 /* for now */ - static struct smatch sgi_cputable[] = { { "MIPS-R2000", CPU_R2000 }, { "MIPS-R3000", CPU_R3000 }, @@ -57,28 +35,13 @@ #define NUM_CPUS 9 /* for now */ -__initfunc(static enum sgi_mach string_to_mach(char *s)) -{ - int i; - - for(i = 0; i < NUM_MACHS; i++) { - if(!strcmp(s, sgi_mtable[i].name)) - return (enum sgi_mach) sgi_mtable[i].type; - } - prom_printf("\nYeee, could not determine SGI architecture type <%s>\n", s); - prom_printf("press a key to reboot\n"); - prom_getchar(); - romvec->imode(); - return (enum sgi_mach) 0; -} - __initfunc(static int string_to_cpu(char *s)) { int i; for(i = 0; i < NUM_CPUS; i++) { if(!strcmp(s, sgi_cputable[i].name)) - return sgi_mtable[i].type; + return sgi_cputable[i].type; } prom_printf("\nYeee, could not determine MIPS cpu type <%s>\n", s); prom_printf("press a key to reboot\n"); @@ -101,8 +64,6 @@ * have here. */ p = prom_getchild(PROM_NULL_COMPONENT); - printk("ARCH: %s\n", p->iname); - sgimach = string_to_mach(p->iname); /* Now scan for cpu(s). */ toplev = p = prom_getchild(p); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/time.c linux.pre11.3/arch/mips/sgi/kernel/time.c --- linux.vanilla/arch/mips/sgi/kernel/time.c Sun Nov 8 15:08:31 1998 +++ linux.pre11.3/arch/mips/sgi/kernel/time.c Mon Jul 19 23:28:46 1999 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.2 1998/03/27 08:53:45 ralf Exp $ +/* $Id: time.c,v 1.2 1998/04/05 11:24:00 ralf Exp $ * time.c: Generic SGI time_init() code, this will dispatch to the * appropriate per-architecture time/counter init code. * diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/Makefile linux.pre11.3/arch/mips/sgi/prom/Makefile --- linux.vanilla/arch/mips/sgi/prom/Makefile Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sgi/prom/Makefile Thu Jan 1 01:00:00 1970 @@ -1,23 +0,0 @@ -# $Id: Makefile,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $ -# Makefile for the SGI arcs prom monitor library routines -# under Linux. -# -# 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... - -OBJS = console.o init.o printf.o memory.o tree.o tags.o env.o \ - cmdline.o misc.o time.o file.o - -all: promlib.a - -promlib.a: $(OBJS) - $(AR) rcs promlib.a $(OBJS) - sync - -dep: - $(CPP) -M *.c > .depend - -include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/cmdline.c linux.pre11.3/arch/mips/sgi/prom/cmdline.c --- linux.vanilla/arch/mips/sgi/prom/cmdline.c Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sgi/prom/cmdline.c Thu Jan 1 01:00:00 1970 @@ -1,64 +0,0 @@ -/* - * cmdline.c: Kernel command line creation using ARCS argc/argv. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: cmdline.c,v 1.3 1998/03/27 08:53:46 ralf Exp $ - */ -#include -#include -#include - -#include -#include - -/* #define DEBUG_CMDLINE */ - -extern char arcs_cmdline[CL_SIZE]; - -__initfunc(char *prom_getcmdline(void)) -{ - return &(arcs_cmdline[0]); -} - -static char *ignored[] = { - "ConsoleIn=", - "ConsoleOut=", - "SystemPartition=", - "OSLoader=", - "OSLoadPartition=", - "OSLoadFilename=" -}; -#define NENTS(foo) ((sizeof((foo)) / (sizeof((foo[0]))))) - -__initfunc(void prom_init_cmdline(void)) -{ - char *cp; - int actr, i; - - actr = 1; /* Always ignore argv[0] */ - - cp = &(arcs_cmdline[0]); - while(actr < prom_argc) { - for(i = 0; i < NENTS(ignored); i++) { - int len = strlen(ignored[i]); - - if(!strncmp(prom_argv[actr], ignored[i], len)) - goto pic_cont; - } - /* Ok, we want it. */ - strcpy(cp, prom_argv[actr]); - cp += strlen(prom_argv[actr]); - *cp++ = ' '; - - pic_cont: - actr++; - } - if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ - --cp; - *cp = '\0'; - -#ifdef DEBUG_CMDLINE - prom_printf("prom_init_cmdline: %s\n", &(arcs_cmdline[0])); -#endif -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/console.c linux.pre11.3/arch/mips/sgi/prom/console.c --- linux.vanilla/arch/mips/sgi/prom/console.c Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sgi/prom/console.c Thu Jan 1 01:00:00 1970 @@ -1,26 +0,0 @@ -/* - * console.c: SGI arcs console code. - * - * Copyright (C) 1996 David S. Miller (dm@sgi.com) - * - * $Id: console.c,v 1.2 1998/03/27 08:53:46 ralf Exp $ - */ -#include -#include - -__initfunc(void prom_putchar(char c)) -{ - long cnt; - char it = c; - - romvec->write(1, &it, 1, &cnt); -} - -__initfunc(char prom_getchar(void)) -{ - long cnt; - char c; - - romvec->read(0, &c, 1, &cnt); - return c; -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/env.c linux.pre11.3/arch/mips/sgi/prom/env.c --- linux.vanilla/arch/mips/sgi/prom/env.c Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sgi/prom/env.c Thu Jan 1 01:00:00 1970 @@ -1,22 +0,0 @@ -/* - * env.c: ARCS environment variable routines. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: env.c,v 1.2 1998/03/27 08:53:46 ralf Exp $ - */ -#include -#include -#include - -#include - -__initfunc(char *prom_getenv(char *name)) -{ - return romvec->get_evar(name); -} - -__initfunc(long prom_setenv(char *name, char *value)) -{ - return romvec->set_evar(name, value); -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/file.c linux.pre11.3/arch/mips/sgi/prom/file.c --- linux.vanilla/arch/mips/sgi/prom/file.c Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sgi/prom/file.c Thu Jan 1 01:00:00 1970 @@ -1,59 +0,0 @@ -/* - * file.c: ARCS firmware interface to files. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: file.c,v 1.2 1998/03/27 08:53:47 ralf Exp $ - */ -#include -#include - -__initfunc(long prom_getvdirent(unsigned long fd, struct linux_vdirent *ent, unsigned long num, unsigned long *cnt)) -{ - return romvec->get_vdirent(fd, ent, num, cnt); -} - -__initfunc(long prom_open(char *name, enum linux_omode md, unsigned long *fd)) -{ - return romvec->open(name, md, fd); -} - -__initfunc(long prom_close(unsigned long fd)) -{ - return romvec->close(fd); -} - -__initfunc(long prom_read(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt)) -{ - return romvec->read(fd, buf, num, cnt); -} - -__initfunc(long prom_getrstatus(unsigned long fd)) -{ - return romvec->get_rstatus(fd); -} - -__initfunc(long prom_write(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt)) -{ - return romvec->write(fd, buf, num, cnt); -} - -__initfunc(long prom_seek(unsigned long fd, struct linux_bigint *off, enum linux_seekmode sm)) -{ - return romvec->seek(fd, off, sm); -} - -__initfunc(long prom_mount(char *name, enum linux_mountops op)) -{ - return romvec->mount(name, op); -} - -__initfunc(long prom_getfinfo(unsigned long fd, struct linux_finfo *buf)) -{ - return romvec->get_finfo(fd, buf); -} - -__initfunc(long prom_setfinfo(unsigned long fd, unsigned long flags, unsigned long msk)) -{ - return romvec->set_finfo(fd, flags, msk); -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/init.c linux.pre11.3/arch/mips/sgi/prom/init.c --- linux.vanilla/arch/mips/sgi/prom/init.c Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sgi/prom/init.c Thu Jan 1 01:00:00 1970 @@ -1,61 +0,0 @@ -/* - * init.c: PROM library initialisation code. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: init.c,v 1.2 1998/03/27 08:53:47 ralf Exp $ - */ -#include -#include - -#include - -/* #define DEBUG_PROM_INIT */ - -/* Master romvec interface. */ -struct linux_romvec *romvec; -struct linux_promblock *sgi_pblock; -int prom_argc; -char **prom_argv, **prom_envp; -unsigned short prom_vers, prom_rev; - -extern void prom_testtree(void); - -__initfunc(int prom_init(int argc, char **argv, char **envp)) -{ - struct linux_promblock *pb; - - romvec = ROMVECTOR; - pb = sgi_pblock = PROMBLOCK; - prom_argc = argc; - prom_argv = argv; - prom_envp = envp; - - if(pb->magic != 0x53435241) { - prom_printf("Aieee, bad prom vector magic %08lx\n", pb->magic); - while(1) - ; - } - - prom_init_cmdline(); - - prom_vers = pb->ver; - prom_rev = pb->rev; - printk("PROMLIB: SGI ARCS firmware Version %d Revision %d\n", - prom_vers, prom_rev); - prom_meminit(); - prom_setup_archtags(); - -#if 0 - prom_testtree(); -#endif - -#ifdef DEBUG_PROM_INIT - { - prom_printf("Press a key to reboot\n"); - (void) prom_getchar(); - romvec->imode(); - } -#endif - return 0; -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/memory.c linux.pre11.3/arch/mips/sgi/prom/memory.c --- linux.vanilla/arch/mips/sgi/prom/memory.c Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sgi/prom/memory.c Thu Jan 1 01:00:00 1970 @@ -1,131 +0,0 @@ -/* - * memory.c: PROM library functions for acquiring/using memory descriptors - * given to us from the ARCS firmware. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: memory.c,v 1.2 1998/03/27 08:53:47 ralf Exp $ - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* #define DEBUG */ - -__initfunc(struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr)) -{ - return romvec->get_mdesc(curr); -} - -#ifdef DEBUG /* convenient for debugging */ -static char *mtypes[8] = { - "Exception Block", - "ARCS Romvec Page", - "Free/Contig RAM", - "Generic Free RAM", - "Bad Memory", - "Standlong Program Pages", - "ARCS Temp Storage Area", - "ARCS Permanent Storage Area" -}; -#endif - -static struct prom_pmemblock prom_pblocks[PROM_MAX_PMEMBLOCKS]; - -__initfunc(struct prom_pmemblock *prom_getpblock_array(void)) -{ - return &prom_pblocks[0]; -} - -__initfunc(static void prom_setup_memupper(void)) -{ - struct prom_pmemblock *p, *highest; - - for(p = prom_getpblock_array(), highest = 0; p->size != 0; p++) { - if(p->base == 0xdeadbeef) - prom_printf("WHEEE, bogus pmemblock\n"); - if(!highest || p->base > highest->base) - highest = p; - } - mips_memory_upper = highest->base + highest->size; -#ifdef DEBUG - prom_printf("prom_setup_memupper: mips_memory_upper = %08lx\n", - mips_memory_upper); -#endif -} - -__initfunc(void prom_meminit(void)) -{ - struct linux_mdesc *p; - int totram; - int i = 0; - - p = prom_getmdesc(PROM_NULL_MDESC); -#ifdef DEBUG - prom_printf("ARCS MEMORY DESCRIPTOR dump:\n"); - while(p) { - prom_printf("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n", - i, p, p->base, p->pages, mtypes[p->type]); - p = prom_getmdesc(p); - i++; - } -#endif - p = prom_getmdesc(PROM_NULL_MDESC); - totram = 0; - i = 0; - while(p) { - if(p->type == free || p->type == fcontig) { - prom_pblocks[i].base = - ((p->base<pages << PAGE_SHIFT; - totram += prom_pblocks[i].size; -#ifdef DEBUG - prom_printf("free_chunk[%d]: base=%08lx size=%d\n", - i, prom_pblocks[i].base, - prom_pblocks[i].size); -#endif - i++; - } - p = prom_getmdesc(p); - } - prom_pblocks[i].base = 0xdeadbeef; - prom_pblocks[i].size = 0; /* indicates last elem. of array */ - printk("PROMLIB: Total free ram %d bytes (%dK,%dMB)\n", - totram, (totram/1024), (totram/1024/1024)); - - /* Setup upper physical memory bound. */ - prom_setup_memupper(); -} - -/* Called from mem_init() to fixup the mem_map page settings. */ -__initfunc(void prom_fixup_mem_map(unsigned long start, unsigned long end)) -{ - struct prom_pmemblock *p; - int i, nents; - - /* Determine number of pblockarray entries. */ - p = prom_getpblock_array(); - for(i = 0; p[i].size; i++) - ; - nents = i; - while(start < end) { - for(i = 0; i < nents; i++) { - if((start >= (p[i].base)) && - (start < (p[i].base + p[i].size))) { - start = p[i].base + p[i].size; - start &= PAGE_MASK; - continue; - } - } - set_bit(PG_reserved, &mem_map[MAP_NR(start)].flags); - start += PAGE_SIZE; - } -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/misc.c linux.pre11.3/arch/mips/sgi/prom/misc.c --- linux.vanilla/arch/mips/sgi/prom/misc.c Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sgi/prom/misc.c Thu Jan 1 01:00:00 1970 @@ -1,84 +0,0 @@ -/* $Id: misc.c,v 1.6 1998/07/08 15:59:13 ralf Exp $ - * - * misc.c: Miscellaneous ARCS PROM routines. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ -#include -#include -#include - -#include -#include -#include -#include - -extern unsigned long mips_cputype; -extern void *sgiwd93_host; -extern void reset_wd33c93(void *instance); - -void prom_halt(void) -{ - bcops->bc_disable(); - cli(); -#if CONFIG_SCSI_SGIWD93 - reset_wd33c93(sgiwd93_host); -#endif - romvec->halt(); -} - -void prom_powerdown(void) -{ - bcops->bc_disable(); - cli(); -#if CONFIG_SCSI_SGIWD93 - reset_wd33c93(sgiwd93_host); -#endif - romvec->pdown(); -} - -/* XXX is this a soft reset basically? XXX */ -void prom_restart(void) -{ - bcops->bc_disable(); - cli(); -#if CONFIG_SCSI_SGIWD93 - reset_wd33c93(sgiwd93_host); -#endif - romvec->restart(); -} - -void prom_reboot(void) -{ - bcops->bc_disable(); - cli(); -#if CONFIG_SCSI_SGIWD93 - reset_wd33c93(sgiwd93_host); -#endif - romvec->reboot(); -} - -void prom_imode(void) -{ - bcops->bc_disable(); - cli(); -#if CONFIG_SCSI_SGIWD93 - reset_wd33c93(sgiwd93_host); -#endif - romvec->imode(); -} - -long prom_cfgsave(void) -{ - return romvec->cfg_save(); -} - -struct linux_sysid *prom_getsysid(void) -{ - return romvec->get_sysid(); -} - -__initfunc(void prom_cacheflush(void)) -{ - romvec->cache_flush(); -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/printf.c linux.pre11.3/arch/mips/sgi/prom/printf.c --- linux.vanilla/arch/mips/sgi/prom/printf.c Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sgi/prom/printf.c Thu Jan 1 01:00:00 1970 @@ -1,35 +0,0 @@ -/* - * printf.c: Putting things on the screen using SGI arcs - * PROM facilities. - * - * Copyright (C) 1996 David S. Miller (dm@sgi.com) - * - * $Id: printf.c,v 1.2 1998/03/27 08:53:48 ralf Exp $ - */ -#include -#include - -#include - -static char ppbuf[1024]; - -__initfunc(void prom_printf(char *fmt, ...)) -{ - va_list args; - char ch, *bptr; - int i; - - va_start(args, fmt); - i = vsprintf(ppbuf, fmt, args); - - bptr = ppbuf; - - while((ch = *(bptr++)) != 0) { - if(ch == '\n') - prom_putchar('\r'); - - prom_putchar(ch); - } - va_end(args); - return; -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/salone.c linux.pre11.3/arch/mips/sgi/prom/salone.c --- linux.vanilla/arch/mips/sgi/prom/salone.c Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sgi/prom/salone.c Thu Jan 1 01:00:00 1970 @@ -1,25 +0,0 @@ -/* - * salone.c: Routines to load into memory and execute stand-along - * program images using ARCS PROM firmware. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: salone.c,v 1.2 1998/03/27 08:53:48 ralf Exp $ - */ -#include -#include - -__initfunc(long prom_load(char *name, unsigned long end, unsigned long *pc, unsigned long *eaddr)) -{ - return romvec->load(name, end, pc, eaddr); -} - -__initfunc(long prom_invoke(unsigned long pc, unsigned long sp, long argc, char **argv, char **envp)) -{ - return romvec->invoke(pc, sp, argc, argv, envp); -} - -__initfunc(long prom_exec(char *name, long argc, char **argv, char **envp)) -{ - return romvec->exec(name, argc, argv, envp); -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/tags.c linux.pre11.3/arch/mips/sgi/prom/tags.c --- linux.vanilla/arch/mips/sgi/prom/tags.c Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sgi/prom/tags.c Thu Jan 1 01:00:00 1970 @@ -1,69 +0,0 @@ -/* - * tags.c: Initialize the arch tags the way the MIPS kernel setup - * expects. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: tags.c,v 1.2 1998/03/27 08:53:48 ralf Exp $ - */ -#include -#include -#include - -#include -#include -#include -#include - -/* XXX This tag thing is a fucking rats nest, I'm very inclined to completely - * XXX rework the MIPS people's multi-arch code _NOW_. - */ - -static unsigned long machtype_SGI_INDY = MACH_SGI_INDY; -static unsigned long machgroup_SGI = MACH_GROUP_SGI; -static unsigned long memlower_SGI_INDY = (KSEG0 + SGIMC_SEG0_BADDR); -static unsigned long cputype_SGI_INDY = CPU_R4400SC; -static unsigned long tlb_entries_SGI_INDY = 48; -static unsigned long dummy_SGI_INDY = 0; -static struct drive_info_struct dummy_dinfo_SGI_INDY = { { 0, }, }; -char arcs_cmdline[CL_SIZE]; - -#define TAG(t,l) {tag_##t,(l)} /* XXX RATS NEST CODE!!! XXX */ -#define TAGVAL(v) (void*)&(v) /* XXX FUCKING LOSING!!! XXX */ - -tag_def taglist_sgi_indy[] = { - {TAG(machtype, ULONGSIZE), TAGVAL(machtype_SGI_INDY)}, - {TAG(machgroup, ULONGSIZE), TAGVAL(machgroup_SGI)}, - {TAG(memlower, ULONGSIZE), TAGVAL(memlower_SGI_INDY)}, - {TAG(cputype, ULONGSIZE), TAGVAL(cputype_SGI_INDY)}, - {TAG(tlb_entries, ULONGSIZE), TAGVAL(tlb_entries_SGI_INDY)}, - {TAG(vram_base, ULONGSIZE), TAGVAL(dummy_SGI_INDY)}, - {TAG(drive_info, DRVINFOSIZE), TAGVAL(dummy_dinfo_SGI_INDY)}, - {TAG(mount_root_rdonly, ULONGSIZE), TAGVAL(dummy_SGI_INDY)}, - {TAG(command_line, CL_SIZE), TAGVAL(arcs_cmdline[0])}, - {TAG(dummy, 0), NULL} - /* XXX COLOSTOMY BAG!!!! XXX */ -}; - -__initfunc(void prom_setup_archtags(void)) -{ - tag_def *tdp = &taglist_sgi_indy[0]; - tag *tp; - - tp = (tag *) (mips_memory_upper - sizeof(tag)); - while(tdp->t.tag != tag_dummy) { - unsigned long size; - char *d; - - *tp = tdp->t; - size = tp->size; - d = (char *) tdp->d; - tp = (tag *)(((unsigned long)tp) - (tp->size)); - if(size) - memcpy(tp, d, size); - - tp--; - tdp++; - } - *tp = tdp->t; /* copy last dummy element over */ -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/time.c linux.pre11.3/arch/mips/sgi/prom/time.c --- linux.vanilla/arch/mips/sgi/prom/time.c Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sgi/prom/time.c Thu Jan 1 01:00:00 1970 @@ -1,19 +0,0 @@ -/* - * time.c: Extracting time information from ARCS prom. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: time.c,v 1.2 1998/03/27 08:53:49 ralf Exp $ - */ -#include -#include - -__initfunc(struct linux_tinfo *prom_gettinfo(void)) -{ - return romvec->get_tinfo(); -} - -__initfunc(unsigned long prom_getrtime(void)) -{ - return romvec->get_rtime(); -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/tree.c linux.pre11.3/arch/mips/sgi/prom/tree.c --- linux.vanilla/arch/mips/sgi/prom/tree.c Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sgi/prom/tree.c Thu Jan 1 01:00:00 1970 @@ -1,109 +0,0 @@ -/* - * tree.c: PROM component device tree code. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: tree.c,v 1.2 1998/03/27 08:53:49 ralf Exp $ - */ -#include -#include - -#define DEBUG_PROM_TREE - -__initfunc(pcomponent *prom_getsibling(pcomponent *this)) -{ - if(this == PROM_NULL_COMPONENT) - return PROM_NULL_COMPONENT; - return romvec->next_component(this); -} - -__initfunc(pcomponent *prom_getchild(pcomponent *this)) -{ - return romvec->child_component(this); -} - -__initfunc(pcomponent *prom_getparent(pcomponent *child)) -{ - if(child == PROM_NULL_COMPONENT) - return PROM_NULL_COMPONENT; - return romvec->parent_component(child); -} - -__initfunc(long prom_getcdata(void *buffer, pcomponent *this)) -{ - return romvec->component_data(buffer, this); -} - -__initfunc(pcomponent *prom_childadd(pcomponent *this, pcomponent *tmp, void *data)) -{ - return romvec->child_add(this, tmp, data); -} - -__initfunc(long prom_delcomponent(pcomponent *this)) -{ - return romvec->comp_del(this); -} - -__initfunc(pcomponent *prom_componentbypath(char *path)) -{ - return romvec->component_by_path(path); -} - -#ifdef DEBUG_PROM_TREE -static char *classes[] = { - "system", "processor", "cache", "adapter", "controller", "peripheral", - "memory" -}; - -static char *types[] = { - "arc", "cpu", "fpu", "picache", "pdcache", "sicache", "sdcache", "sccache", - "memdev", "eisa adapter", "tc adapter", "scsi adapter", "dti adapter", - "multi-func adapter", "disk controller", "tp controller", - "cdrom controller", "worm controller", "serial controller", - "net controller", "display controller", "parallel controller", - "pointer controller", "keyboard controller", "audio controller", - "misc controller", "disk peripheral", "floppy peripheral", - "tp peripheral", "modem peripheral", "monitor peripheral", - "printer peripheral", "pointer peripheral", "keyboard peripheral", - "terminal peripheral", "line peripheral", "net peripheral", - "misc peripheral", "anonymous" -}; - -static char *iflags[] = { - "bogus", "read only", "removable", "console in", "console out", - "input", "output" -}; - -__initfunc(static void dump_component(pcomponent *p)) -{ - prom_printf("[%p]:class<%s>type<%s>flags<%s>ver<%d>rev<%d>", - p, classes[p->class], types[p->type], - iflags[p->iflags], p->vers, p->rev); - prom_printf("key<%08lx>\n\tamask<%08lx>cdsize<%d>ilen<%d>iname<%s>\n", - p->key, p->amask, (int)p->cdsize, (int)p->ilen, p->iname); -} - -__initfunc(static void traverse(pcomponent *p, int op)) -{ - dump_component(p); - if(prom_getchild(p)) - traverse(prom_getchild(p), 1); - if(prom_getsibling(p) && op) - traverse(prom_getsibling(p), 1); -} - -__initfunc(void prom_testtree(void)) -{ - pcomponent *p; - - p = prom_getchild(PROM_NULL_COMPONENT); - dump_component(p); - p = prom_getchild(p); - while(p) { - dump_component(p); - p = prom_getsibling(p); - } - prom_printf("press a key\n"); - prom_getchar(); -} -#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sni/Makefile linux.pre11.3/arch/mips/sni/Makefile --- linux.vanilla/arch/mips/sni/Makefile Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sni/Makefile Mon Jul 19 23:28:46 1999 @@ -1,3 +1,4 @@ +# $Id: Makefile,v 1.3 1999/01/04 16:03:57 ralf Exp $ # # Makefile for the SNI specific part of the kernel # @@ -5,8 +6,6 @@ # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). # -# $Id: Makefile,v 1.2 1997/12/20 13:27:14 ralf Exp $ -# .S.s: $(CPP) $(CFLAGS) $< -o $*.s @@ -15,7 +14,7 @@ all: sni.o O_TARGET := sni.o -O_OBJS := hw-access.o int-handler.o io.o pci.o pcimt_scache.o reset.o setup.o +O_OBJS := int-handler.o io.o pci.o pcimt_scache.o reset.o setup.o int-handler.o: int-handler.S diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sni/hw-access.c linux.pre11.3/arch/mips/sni/hw-access.c --- linux.vanilla/arch/mips/sni/hw-access.c Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sni/hw-access.c Thu Jan 1 01:00:00 1970 @@ -1,70 +0,0 @@ -/* $Id: hw-access.c,v 1.8 1998/09/16 22:50:46 ralf Exp $ - * - * Low-level hardware access stuff for SNI RM200 PCI - * - * 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. - * - * Copyright (C) 1996, 1997, 1998 by Ralf Baechle - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ - -static unsigned char sni_read_input(void) -{ - return inb(KBD_DATA_REG); -} - -static void sni_write_output(unsigned char val) -{ - int status; - - do { - status = inb(KBD_CNTL_REG); - } while (status & KBD_STAT_IBF); - outb(val, KBD_DATA_REG); -} - -static void sni_write_command(unsigned char val) -{ - int status; - - do { - status = inb(KBD_CNTL_REG); - } while (status & KBD_STAT_IBF); - outb(val, KBD_CNTL_REG); -} - -static unsigned char sni_read_status(void) -{ - return inb(KBD_STATUS_REG); -} - -__initfunc(void sni_rm200_keyboard_setup(void)) -{ - kbd_read_input = sni_read_input; - kbd_write_output = sni_write_output; - kbd_write_command = sni_write_command; - kbd_read_status = sni_read_status; - request_irq(PCIMT_KEYBOARD_IRQ, keyboard_interrupt, - 0, "keyboard", NULL); - request_region(0x60, 16, "keyboard"); -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sni/int-handler.S linux.pre11.3/arch/mips/sni/int-handler.S --- linux.vanilla/arch/mips/sni/int-handler.S Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sni/int-handler.S Mon Jul 19 23:28:46 1999 @@ -1,17 +1,22 @@ -/* $Id: int-handler.S,v 1.4 1998/05/07 14:17:47 ralf Exp $ +/* $Id: int-handler.S,v 1.4 1999/01/04 16:03:58 ralf Exp $ * * SNI RM200 PCI specific interrupt handler code. * * Copyright (C) 1994 - 1997 by Ralf Baechle */ #include -#include #include #include #include #include #include +/* The PCI ASIC has the nasty property that it may delay writes if it is busy. + As a consequence from writes that have not graduated when we exit from the + interrupt handler we might catch a spurious interrupt. To avoid this we + force the PCI ASIC to graduate all writes by executing a read from the + PCI bus. */ + .set noreorder .set noat .align 5 @@ -20,34 +25,38 @@ CLI .set at - lb t0,led_cache - addiu t0,1 - sb t0,led_cache - sb t0,PCIMT_CSLED + /* Blinken light ... */ + lb t0, led_cache + addiu t0, 1 + sb t0, led_cache + sb t0, PCIMT_CSLED # write only register .data led_cache: .byte 0 .text - mfc0 t0,CP0_STATUS - mfc0 t1,CP0_CAUSE - and t0,t1 - - andi t1,t0,0x0800 # hardware interrupt 1 - bnez t1,hwint1 - andi t1,t0,0x4000 # hardware interrupt 4 - bnez t1,eth_int - - andi t1,t0,0x1000 # hardware interrupt 2 - bnez t1,hwint2 - andi t1,t0,0x2000 # hardware interrupt 3 - bnez t1,hwint3 - andi t1,t0,0x8000 # hardware interrupt 5 - bnez t1,hwint5 - andi t1,t0,0x0400 # hardware interrupt 0 - bnez t1,hwint0 + mfc0 t0, CP0_STATUS + mfc0 t1, CP0_CAUSE + and t0, t1 + + /* The following interrupt dispatch tests for hwint 1 / + EISA bridge first such that the timer interrupt get the + highest priority. */ + andi t1, t0, 0x0800 # hardware interrupt 1 + bnez t1, hwint1 + andi t1, t0, 0x4000 # hardware interrupt 4 + bnez t1, hwint4 + + andi t1, t0, 0x1000 # hardware interrupt 2 + bnez t1, hwint2 + andi t1, t0, 0x2000 # hardware interrupt 3 + bnez t1, hwint3 + andi t1, t0, 0x8000 # hardware interrupt 5 + bnez t1, hwint5 + andi t1, t0, 0x0400 # hardware interrupt 0 + bnez t1, hwint0 nop - j spurious_interrupt # Nothing up ... + j return # spurious interrupt nop ############################################################################## @@ -57,146 +66,61 @@ /* ------------------------------------------------------------------------ */ -hwint1: lbu t0,PCIMT_CSITPEND - - andi t1,t0,0x20 - bnez t1,eisa_int - -#ifdef CONFIG_SCSI_NCR53C8XX - andi t1,t0,0x40 - beqz t1,scsi_int -#endif - nop - - j spurious_interrupt - nop - - /* ------------------------------------------------------------------------ */ - -hwint0: lbu t0,PCIMT_CSITPEND - - andi t1,t0,0x01 - beqz t1,int2 +/* hwint1 deals with EISA and SCSI interrupts. */ +hwint1: lbu s0, PCIMT_CSITPEND -go_spurious: j spurious_interrupt # we got fooled + andi t1, s0, 0x20 + beqz t1, 1f + andi s1, s0, 0x40 + lbu a0, PCIMT_INT_ACKNOWLEDGE # IACK cycle + xori t0, a0, 0xff + beqz t0, 1f # spurious interrupt? nop + jal i8259_do_irq # call real handler + move a1, sp -eisa_int: lui s0,%hi(SNI_PORT_BASE) - li a0,0x0f - sb a0,%lo(SNI_PORT_BASE+0x20)(s0) # poll command - lb a0,%lo(SNI_PORT_BASE+0x20)(s0) # read result - bgtz a0,poll_second - andi a0,7 - beq a0,2,poll_second # cascade? - li s1,1 - /* - * Acknowledge first pic - */ - lb t2,%lo(SNI_PORT_BASE+0x21)(s0) - lui s4,%hi(cache_21) - lb t0,%lo(cache_21)(s4) - sllv s1,s1,a0 - or t0,s1 - sb t0,%lo(cache_21)(s4) - sb t0,%lo(SNI_PORT_BASE+0x21)(s0) - li t2,0x20 - sb t2,%lo(SNI_PORT_BASE+0x20)(s0) - /* - * Now call the real handler - */ +1: bnez s1, 1f + li a0, PCIMT_IRQ_SCSI jal do_IRQ - move a1,sp - /* - * Unblock first pic - */ - lbu t1,%lo(SNI_PORT_BASE+0x21)(s0) - lb t1,%lo(cache_21)(s4) - nor s1,zero,s1 - and t1,s1 - sb t1,%lo(cache_21)(s4) - j ret_from_irq - sb t1,%lo(SNI_PORT_BASE+0x21)(s0) + move a1, sp - /* - * Cascade interrupt from second PIC - */ - .align 5 -poll_second: li a0,0x0f - sb a0,%lo(SNI_PORT_BASE+0xa0)(s0) # poll command - lb a0,%lo(SNI_PORT_BASE+0xa0)(s0) # read result - bgtz a0,go_spurious - andi a0,7 - /* - * Acknowledge second pic - */ - lbu t2,%lo(SNI_PORT_BASE+0xa1)(s0) - lui s4,%hi(cache_A1) - lb t3,%lo(cache_A1)(s4) - sllv s1,s1,a0 - or t3,s1 - sb t3,%lo(cache_A1)(s4) - sb t3,%lo(SNI_PORT_BASE+0xa1)(s0) - li t3,0x20 - sb t3,%lo(SNI_PORT_BASE+0xa0)(s0) - sb t3,%lo(SNI_PORT_BASE+0x20)(s0) - /* - * Now call the real handler - */ - addiu a0,8 - jal do_IRQ - move a1,sp - /* - * Unblock second pic - */ - lb t1,%lo(SNI_PORT_BASE+0xa1)(s0) - lb t1,%lo(cache_A1)(s4) - subu t0,1 - nor s1,zero,s1 - and t1,t1,s1 - sb t1,%lo(cache_A1)(s4) +1: lui t0, %hi(PCIMT_CSITPEND) j ret_from_irq - sb t1,%lo(SNI_PORT_BASE+0xa1)(s0) - -/* - * ... check if we were interrupted by the Lance ... - */ -eth_int: mfc0 s0,CP0_STATUS - ori t0,s0,0x4000 - xori t0,0x4000 - mtc0 t0,CP0_STATUS + lbu zero, %lo(PCIMT_CSITPEND)(t0) - li a0,PCIMT_IRQ_ETHERNET - jal do_IRQ - move a1,sp + /* ------------------------------------------------------------------------ */ - mtc0 s0,CP0_STATUS +/* hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug + button interrupts. */ +hwint0: PANIC("Received int0 but no handler yet ...\n") +1: j 1b + nop - j ret_from_irq +go_spurious: j spurious_interrupt # we got fooled nop -#ifdef CONFIG_SCSI_NCR53C8XX +/* hwint4 is used for only the onboard PCnet 32. */ +hwint4: mfc0 s0, CP0_STATUS + ori t0, s0, 0x4000 + xori t0, 0x4000 + mtc0 t0, CP0_STATUS -/* - * ... check if we were interrupted by the NCR ... - */ -scsi_int: li a0,PCIMT_IRQ_SCSI + li a0, PCIMT_IRQ_ETHERNET jal do_IRQ - move a1,sp - j ret_from_irq - nop - -#endif /* CONFIG_SCSI_NCR53C8XX */ + move a1, sp -pci_int: PANIC("Received PCI interrupt but no handler yet ...\n") -1: j 1b - nop + mtc0 s0, CP0_STATUS -int2: PANIC("Received int2 but no handler yet ...\n") -1: j 1b + j ret_from_irq nop +/* This interrupt was used for the com1 console on the first prototypes. */ hwint2: PANIC("hwint2 and no handler yet") + +/* hwint3 should deal with the PCI A - D interrupts. */ hwint3: PANIC("hwint3 and no handler yet") + +/* hwint5 is the r4k count / compare interrupt */ hwint5: PANIC("hwint5 and no handler yet") END(sni_rm200_pci_handle_int) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sni/io.c linux.pre11.3/arch/mips/sni/io.c --- linux.vanilla/arch/mips/sni/io.c Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sni/io.c Mon Jul 19 23:28:46 1999 @@ -1,11 +1,10 @@ -/* +/* $Id: io.c,v 1.3 1999/01/04 16:03:58 ralf Exp $ + * * 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. * * Low level I/O functions for SNI. - * - * $Id: io.c,v 1.2 1998/03/27 08:53:50 ralf Exp $ */ #include #include @@ -14,46 +13,42 @@ #include #include -unsigned char sni_map_isa_cache; - -#define unused __attribute__((unused)) - -/* - * The PCIMT_CSMAPISA is shared by all processors; we need locking. - * - * XXX It's legal to use all the I/O memory access functions in interrupt - * code, so we need to use the _irq locking stuff which may result in - * significant IRQ latencies. - */ -static spinlock_t csmapisa_lock unused = SPIN_LOCK_UNLOCKED; - /* * Urgs... We only can see a 16mb window of the 4gb EISA address space * at PCIMT_EISA_BASE. Maladia segmentitis ... * - * XXX Check out if accessing PCIMT_CSMAPISA really is slow. - * For now assume so. + * To avoid locking and all the related headacke we implement this such + * that accessing the bus address space nests, so we're treating this + * correctly even for interrupts. This is going to suck seriously for + * the SMP members of the RM family. + * + * Making things worse the PCIMT_CSMAPISA register resides on the X bus with + * it's unbeatable 1.4 mb/s transfer rate. */ -static inline void update_isa_cache(unsigned long address) + +static inline void eisa_map(unsigned long address) { unsigned char upper; upper = address >> 24; - if (sni_map_isa_cache != upper) { - sni_map_isa_cache = upper; - *(volatile unsigned char *)PCIMT_CSMAPISA = ~upper; - } + *(volatile unsigned char *)PCIMT_CSMAPISA = ~upper; } +#define save_eisa_map() \ + (*(volatile unsigned char *)PCIMT_CSMAPISA) +#define restore_eisa_map(val) \ + do { (*(volatile unsigned char *)PCIMT_CSMAPISA) = val; } while(0) + static unsigned char sni_readb(unsigned long addr) { unsigned char res; + unsigned int save_map; - spin_lock_irq(&csmapisa_lock); - update_isa_cache(addr); + save_map = save_eisa_map(); + eisa_map(addr); addr &= 0xffffff; res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr); - spin_unlock_irq(&csmapisa_lock); + restore_eisa_map(save_map); return res; } @@ -61,12 +56,13 @@ static unsigned short sni_readw(unsigned long addr) { unsigned short res; + unsigned int save_map; - spin_lock_irq(&csmapisa_lock); - update_isa_cache(addr); + save_map = save_eisa_map(); + eisa_map(addr); addr &= 0xffffff; res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr); - spin_unlock_irq(&csmapisa_lock); + restore_eisa_map(save_map); return res; } @@ -74,101 +70,111 @@ static unsigned int sni_readl(unsigned long addr) { unsigned int res; + unsigned int save_map; - spin_lock_irq(&csmapisa_lock); - update_isa_cache(addr); + save_map = save_eisa_map(); + eisa_map(addr); addr &= 0xffffff; res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr); - spin_unlock_irq(&csmapisa_lock); + restore_eisa_map(save_map); return res; } static void sni_writeb(unsigned char val, unsigned long addr) { - spin_lock_irq(&csmapisa_lock); - update_isa_cache(addr); + unsigned int save_map; + + save_map = save_eisa_map(); + eisa_map(addr); addr &= 0xffffff; *(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val; - spin_unlock_irq(&csmapisa_lock); + restore_eisa_map(save_map); } static void sni_writew(unsigned short val, unsigned long addr) { - spin_lock_irq(&csmapisa_lock); - update_isa_cache(addr); + unsigned int save_map; + + save_map = save_eisa_map(); + eisa_map(addr); addr &= 0xffffff; *(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val; - spin_unlock_irq(&csmapisa_lock); + restore_eisa_map(save_map); } static void sni_writel(unsigned int val, unsigned long addr) { - spin_lock_irq(&csmapisa_lock); - update_isa_cache(addr); + unsigned int save_map; + + save_map = save_eisa_map(); + eisa_map(addr); addr &= 0xffffff; *(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val; - spin_unlock_irq(&csmapisa_lock); + restore_eisa_map(save_map); } static void sni_memset_io(unsigned long addr, int val, unsigned long len) { unsigned long waddr; + unsigned int save_map; + save_map = save_eisa_map(); waddr = PCIMT_EISA_BASE | (addr & 0xffffff); - spin_lock_irq(&csmapisa_lock); while(len) { unsigned long fraglen; fraglen = (~addr + 1) & 0xffffff; fraglen = (fraglen < len) ? fraglen : len; - update_isa_cache(addr); + eisa_map(addr); memset((char *)waddr, val, fraglen); addr += fraglen; waddr = waddr + fraglen - 0x1000000; len -= fraglen; } - spin_unlock_irq(&csmapisa_lock); + restore_eisa_map(save_map); } static void sni_memcpy_fromio(unsigned long to, unsigned long from, unsigned long len) { unsigned long waddr; + unsigned int save_map; + save_map = save_eisa_map(); waddr = PCIMT_EISA_BASE | (from & 0xffffff); - spin_lock_irq(&csmapisa_lock); while(len) { unsigned long fraglen; fraglen = (~from + 1) & 0xffffff; fraglen = (fraglen < len) ? fraglen : len; - update_isa_cache(from); + eisa_map(from); memcpy((void *)to, (void *)waddr, fraglen); to += fraglen; from += fraglen; waddr = waddr + fraglen - 0x1000000; len -= fraglen; } - spin_unlock_irq(&csmapisa_lock); + restore_eisa_map(save_map); } static void sni_memcpy_toio(unsigned long to, unsigned long from, unsigned long len) { unsigned long waddr; + unsigned int save_map; + save_map = save_eisa_map(); waddr = PCIMT_EISA_BASE | (to & 0xffffff); - spin_lock_irq(&csmapisa_lock); while(len) { unsigned long fraglen; fraglen = (~to + 1) & 0xffffff; fraglen = (fraglen < len) ? fraglen : len; - update_isa_cache(to); + eisa_map(to); memcpy((char *)to + PCIMT_EISA_BASE, (void *)from, fraglen); to += fraglen; from += fraglen; waddr = waddr + fraglen - 0x1000000; len -= fraglen; } - spin_unlock_irq(&csmapisa_lock); + restore_eisa_map(save_map); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sni/pci.c linux.pre11.3/arch/mips/sni/pci.c --- linux.vanilla/arch/mips/sni/pci.c Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sni/pci.c Mon Jul 19 23:28:46 1999 @@ -1,4 +1,4 @@ -/* $Id: pci.c,v 1.6 1998/05/07 14:17:48 ralf Exp $ +/* $Id: pci.c,v 1.7 1999/01/04 16:03:58 ralf Exp $ * * 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 @@ -9,6 +9,7 @@ * Copyright (C) 1997, 1998 Ralf Baechle */ #include +#include #include #include #include @@ -28,13 +29,37 @@ static void sni_rm200_pcibios_fixup (void) { - /* - * TODO: Fix PCI_INTERRUPT_LINE register for onboard cards. - * Take care of RM300 revision D boards for where the network - * slot became an ordinary PCI slot. - */ - pcibios_write_config_byte(0, PCI_DEVFN(1, 0), PCI_INTERRUPT_LINE, - PCIMT_IRQ_SCSI); + struct pci_dev *dev; + + for (dev=pci_devices; dev; dev=dev->next) { + /* + * TODO: Take care of RM300 revision D boards for where the + * network slot became an ordinary PCI slot. + */ + if (dev->devfn == PCI_DEVFN(1, 0)) { + /* Evil hack ... */ + set_cp0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_NO_WA); + dev->irq = PCIMT_IRQ_SCSI; + continue; + } + if (dev->devfn == PCI_DEVFN(2, 0)) { + dev->irq = PCIMT_IRQ_ETHERNET; + continue; + } + + switch(dev->irq) { + case 1 ... 4: + dev->irq += PCIMT_IRQ_INTA - 1; + break; + case 0: + break; + default: + printk("PCI device on bus %d, dev %d, function %d " + "impossible interrupt configured.\n", + dev->bus->number, PCI_SLOT(dev->devfn), + PCI_SLOT(dev->devfn)); + } + } } /* diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sni/pcimt_scache.c linux.pre11.3/arch/mips/sni/pcimt_scache.c --- linux.vanilla/arch/mips/sni/pcimt_scache.c Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sni/pcimt_scache.c Mon Jul 19 23:28:46 1999 @@ -1,35 +1,38 @@ -/* +/* $Id: pcimt_scache.c,v 1.4 1999/01/04 16:03:59 ralf Exp $ + * * arch/mips/sni/pcimt_scache.c * * 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. * - * Copyright (c) 1997 by Ralf Baechle - * - * $Id: pcimt_scache.c,v 1.2 1998/05/28 03:18:02 ralf Exp $ + * Copyright (c) 1997, 1998 by Ralf Baechle */ #include #include #include #include +#define cacheconf (*(volatile unsigned int *)PCIMT_CACHECONF) +#define invspace (*(volatile unsigned int *)PCIMT_INVSPACE) + __initfunc(void sni_pcimt_sc_init(void)) { - unsigned int cacheconf, sc_size; + unsigned int scsiz, sc_size; - cacheconf = *(volatile unsigned int *)PCIMT_CACHECONF; - if ((cacheconf & 7) == 0) { - printk("No second level cache detected\n"); - printk("WARNING: not activating second level cache, " - "tell ralf@gnu.org\n"); + scsiz = cacheconf & 7; + if (scsiz == 0) { + printk("Second level cache is deactived.\n"); return; } - if ((cacheconf & 7) >= 6) { - printk("Invalid second level cache size detected\n"); + if (scsiz >= 6) { + printk("Invalid second level cache size configured, " + "deactivating second level cache.\n"); + cacheconf = 0; return; } - - sc_size = 128 << (cacheconf & 7); - printk("%dkb second level cache detected.\n", sc_size); + + sc_size = 128 << scsiz; + printk("%dkb second level cache detected, deactivating.\n", sc_size); + cacheconf = 0; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sni/setup.c linux.pre11.3/arch/mips/sni/setup.c --- linux.vanilla/arch/mips/sni/setup.c Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/sni/setup.c Mon Jul 19 23:28:46 1999 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.13 1998/08/17 13:57:45 ralf Exp $ +/* $Id: setup.c,v 1.10 1999/01/04 16:03:59 ralf Exp $ * * Setup pointers to hardware-dependent routines. * @@ -17,6 +17,11 @@ #include #include #include +#include +#include +#include +#include + #include #include #include @@ -39,7 +44,6 @@ static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL}; extern asmlinkage void sni_rm200_pci_handle_int(void); -extern void sni_rm200_keyboard_setup(void); extern void sni_machine_restart(char *command); extern void sni_machine_halt(void); @@ -47,19 +51,20 @@ extern struct ide_ops std_ide_ops; extern struct rtc_ops std_rtc_ops; +extern struct kbd_ops std_kbd_ops; __initfunc(static void sni_irq_setup(void)) { set_except_vector(0, sni_rm200_pci_handle_int); request_region(0x20,0x20, "pic1"); request_region(0xa0,0x20, "pic2"); - setup_x86_irq(2, &irq2); + i8259_setup_irq(2, &irq2); /* * IRQ0 seems to be the irq for PC style stuff. * I don't know how to handle the debug button interrupt, so * don't use this button yet or bad things happen ... */ - set_cp0_status(ST0_IM, IE_IRQ1 | IE_IRQ4); + set_cp0_status(ST0_IM, IE_IRQ1 | IE_IRQ3 | IE_IRQ4); } void (*board_time_init)(struct irqaction *irq); @@ -70,7 +75,7 @@ outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */ outb_p(LATCH & 0xff , 0x40); /* LSB */ outb(LATCH >> 8 , 0x40); /* MSB */ - setup_x86_irq(0, irq); + i8259_setup_irq(0, irq); } unsigned char aux_device_present; @@ -132,7 +137,6 @@ irq_setup = sni_irq_setup; mips_io_port_base = SNI_PORT_BASE; - keyboard_setup = sni_rm200_keyboard_setup; /* * Setup (E)ISA I/O memory access stuff @@ -165,6 +169,10 @@ #ifdef CONFIG_BLK_DEV_IDE ide_ops = &std_ide_ops; #endif - + conswitchp = &vga_con; rtc_ops = &std_rtc_ops; + kbd_ops = &std_kbd_ops; +#ifdef CONFIG_PSMOUSE + aux_device_present = 0xaa; +#endif } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/tools/Makefile linux.pre11.3/arch/mips/tools/Makefile --- linux.vanilla/arch/mips/tools/Makefile Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/tools/Makefile Mon Jul 19 23:28:47 1999 @@ -3,7 +3,7 @@ # Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) # Copyright (C) 1997 Ralf Baechle (ralf@gnu.ai.mit.edu) # -# $Id: Makefile,v 1.2 1997/09/23 06:23:49 ralf Exp $ +# $Id: Makefile,v 1.2 1997/12/01 17:57:41 ralf Exp $ # TARGET := $(TOPDIR)/include/asm-$(ARCH)/offset.h diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/tools/offset.c linux.pre11.3/arch/mips/tools/offset.c --- linux.vanilla/arch/mips/tools/offset.c Sun Nov 8 15:08:32 1998 +++ linux.pre11.3/arch/mips/tools/offset.c Mon Jul 19 23:28:47 1999 @@ -1,4 +1,4 @@ -/* $Id: offset.c,v 1.10 1998/08/19 21:53:53 ralf Exp $ +/* $Id: offset.c,v 1.9 1998/08/25 09:14:52 ralf Exp $ * * offset.c: Calculate pt_regs and task_struct offsets. * diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/amiga/amiints.c linux.pre11.3/arch/ppc/amiga/amiints.c --- linux.vanilla/arch/ppc/amiga/amiints.c Sat Jan 9 21:50:36 1999 +++ linux.pre11.3/arch/ppc/amiga/amiints.c Mon Jul 19 23:28:50 1999 @@ -108,7 +108,7 @@ custom.intreq = 0x7fff; #ifdef CONFIG_APUS - /* Clear any inter-CPU interupt requests. Circumvents bug in + /* Clear any inter-CPU interrupt requests. Circumvents bug in Blizzard IPL emulation HW (or so it appears). */ APUS_WRITE(APUS_INT_LVL, INTLVL_SETRESET | INTLVL_MASK); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/amiga/config.c linux.pre11.3/arch/ppc/amiga/config.c --- linux.vanilla/arch/ppc/amiga/config.c Tue Dec 22 23:19:31 1998 +++ linux.pre11.3/arch/ppc/amiga/config.c Mon Jul 19 23:53:55 1999 @@ -30,7 +30,6 @@ #include #include #include -#include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/kernel/irq.c linux.pre11.3/arch/ppc/kernel/irq.c --- linux.vanilla/arch/ppc/kernel/irq.c Tue Jun 15 16:49:46 1999 +++ linux.pre11.3/arch/ppc/kernel/irq.c Mon Jul 19 23:53:55 1999 @@ -50,7 +50,6 @@ #include #include #include -#include #include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/kernel/pci.c linux.pre11.3/arch/ppc/kernel/pci.c --- linux.vanilla/arch/ppc/kernel/pci.c Thu May 27 22:11:50 1999 +++ linux.pre11.3/arch/ppc/kernel/pci.c Mon Jul 19 23:53:55 1999 @@ -9,7 +9,6 @@ #include #include #include -#include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/kernel/pmac_setup.c linux.pre11.3/arch/ppc/kernel/pmac_setup.c --- linux.vanilla/arch/ppc/kernel/pmac_setup.c Thu May 27 22:11:50 1999 +++ linux.pre11.3/arch/ppc/kernel/pmac_setup.c Mon Jul 19 23:28:48 1999 @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/kernel/ppc-stub.c linux.pre11.3/arch/ppc/kernel/ppc-stub.c --- linux.vanilla/arch/ppc/kernel/ppc-stub.c Sun Nov 8 15:08:33 1998 +++ linux.pre11.3/arch/ppc/kernel/ppc-stub.c Mon Jul 19 23:53:55 1999 @@ -107,7 +107,6 @@ #include #include -#include #include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/kernel/process.c linux.pre11.3/arch/ppc/kernel/process.c --- linux.vanilla/arch/ppc/kernel/process.c Thu May 27 22:11:50 1999 +++ linux.pre11.3/arch/ppc/kernel/process.c Mon Jul 19 23:53:55 1999 @@ -31,7 +31,6 @@ #include #include #include -#include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/kernel/setup.c linux.pre11.3/arch/ppc/kernel/setup.c --- linux.vanilla/arch/ppc/kernel/setup.c Tue Jun 15 16:49:47 1999 +++ linux.pre11.3/arch/ppc/kernel/setup.c Mon Jul 19 23:53:55 1999 @@ -31,7 +31,6 @@ #endif #include #include -#include extern void pmac_init(unsigned long r3, unsigned long r4, diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/kernel/syscalls.c linux.pre11.3/arch/ppc/kernel/syscalls.c --- linux.vanilla/arch/ppc/kernel/syscalls.c Tue Jun 15 16:49:47 1999 +++ linux.pre11.3/arch/ppc/kernel/syscalls.c Mon Jul 19 23:53:55 1999 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/ap1000/aplib.c linux.pre11.3/arch/sparc/ap1000/aplib.c --- linux.vanilla/arch/sparc/ap1000/aplib.c Sun Nov 8 15:08:28 1998 +++ linux.pre11.3/arch/sparc/ap1000/aplib.c Mon Jul 19 23:53:56 1999 @@ -27,7 +27,6 @@ #include #include #include -#include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/defconfig linux.pre11.3/arch/sparc/defconfig --- linux.vanilla/arch/sparc/defconfig Tue Jun 15 16:49:47 1999 +++ linux.pre11.3/arch/sparc/defconfig Mon Jul 19 23:28:34 1999 @@ -254,7 +254,6 @@ CONFIG_SUNRPC=y CONFIG_LOCKD=y CONFIG_SMB_FS=m -CONFIG_SMB_WIN95=y CONFIG_NCP_FS=m # CONFIG_NCPFS_PACKET_SIGNING is not set # CONFIG_NCPFS_IOCTL_LOCKING is not set diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/kernel/pcic.c linux.pre11.3/arch/sparc/kernel/pcic.c --- linux.vanilla/arch/sparc/kernel/pcic.c Wed Mar 24 10:55:12 1999 +++ linux.pre11.3/arch/sparc/kernel/pcic.c Mon Jul 19 23:53:56 1999 @@ -35,7 +35,6 @@ #include #include -#include #include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/kernel/process.c linux.pre11.3/arch/sparc/kernel/process.c --- linux.vanilla/arch/sparc/kernel/process.c Thu May 27 22:11:51 1999 +++ linux.pre11.3/arch/sparc/kernel/process.c Mon Jul 19 23:53:56 1999 @@ -37,7 +37,6 @@ #include #include #include -#include #include extern void fpsave(unsigned long *, unsigned long *, void *, unsigned long *); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/kernel/sparc-stub.c linux.pre11.3/arch/sparc/kernel/sparc-stub.c --- linux.vanilla/arch/sparc/kernel/sparc-stub.c Sun Nov 8 15:08:26 1998 +++ linux.pre11.3/arch/sparc/kernel/sparc-stub.c Mon Jul 19 23:53:56 1999 @@ -105,7 +105,6 @@ #include #include #include -#include #include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/kernel/sparc_ksyms.c linux.pre11.3/arch/sparc/kernel/sparc_ksyms.c --- linux.vanilla/arch/sparc/kernel/sparc_ksyms.c Wed Mar 24 10:55:12 1999 +++ linux.pre11.3/arch/sparc/kernel/sparc_ksyms.c Mon Jul 19 23:54:04 1999 @@ -40,7 +40,6 @@ #include #endif #include -#include #include struct poll { diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/kernel/sys_sunos.c linux.pre11.3/arch/sparc/kernel/sys_sunos.c --- linux.vanilla/arch/sparc/kernel/sys_sunos.c Tue Jun 15 16:49:47 1999 +++ linux.pre11.3/arch/sparc/kernel/sys_sunos.c Mon Jul 19 23:54:04 1999 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/mm/fault.c linux.pre11.3/arch/sparc/mm/fault.c --- linux.vanilla/arch/sparc/mm/fault.c Wed Mar 24 10:55:12 1999 +++ linux.pre11.3/arch/sparc/mm/fault.c Mon Jul 19 23:54:04 1999 @@ -17,7 +17,6 @@ #include #include #include -#include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/mm/init.c linux.pre11.3/arch/sparc/mm/init.c --- linux.vanilla/arch/sparc/mm/init.c Wed Apr 28 19:14:25 1999 +++ linux.pre11.3/arch/sparc/mm/init.c Mon Jul 19 23:28:35 1999 @@ -245,7 +245,7 @@ struct page *page, *end; /* Saves us work later. */ - memset((void *) ZERO_PAGE, 0, PAGE_SIZE); + memset((void *) ZERO_PAGE(0), 0, PAGE_SIZE); end_mem &= PAGE_MASK; max_mapnr = MAP_NR(end_mem); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/config.in linux.pre11.3/arch/sparc64/config.in --- linux.vanilla/arch/sparc64/config.in Wed Apr 28 19:14:25 1999 +++ linux.pre11.3/arch/sparc64/config.in Mon Jul 19 23:28:53 1999 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.66 1999/03/29 05:08:42 davem Exp $ +# $Id: config.in,v 1.67 1999/05/01 09:17:37 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -235,6 +235,16 @@ bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 +fi +endmenu + +mainmenu_option next_comment +comment 'Video For Linux' +tristate 'Video For Linux' CONFIG_VIDEO_DEV +if [ "$CONFIG_VIDEO_DEV" != "n" ]; then + if [ "$CONFIG_PCI" != "n" ]; then + dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV + fi fi endmenu diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/defconfig linux.pre11.3/arch/sparc64/defconfig --- linux.vanilla/arch/sparc64/defconfig Tue Jun 15 16:49:47 1999 +++ linux.pre11.3/arch/sparc64/defconfig Mon Jul 19 23:28:53 1999 @@ -257,6 +257,12 @@ CONFIG_UNIX98_PTY_COUNT=256 # +# Video For Linux +# +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_BT848=y + +# # Filesystems # # CONFIG_QUOTA is not set @@ -292,7 +298,6 @@ CONFIG_SUNRPC=y CONFIG_LOCKD=y CONFIG_SMB_FS=m -CONFIG_SMB_WIN95=y CONFIG_NCP_FS=m # CONFIG_NCPFS_PACKET_SIGNING is not set # CONFIG_NCPFS_IOCTL_LOCKING is not set diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/kernel/binfmt_aout32.c linux.pre11.3/arch/sparc64/kernel/binfmt_aout32.c --- linux.vanilla/arch/sparc64/kernel/binfmt_aout32.c Wed Mar 24 10:55:13 1999 +++ linux.pre11.3/arch/sparc64/kernel/binfmt_aout32.c Mon Jul 19 23:28:53 1999 @@ -57,8 +57,19 @@ * These are the only things you should do on a core-file: use only these * macros to write out all the necessary info. */ -#define DUMP_WRITE(addr,nr) \ -while (file->f_op->write(file,(char *)(addr),(nr),&file->f_pos) != (nr)) goto close_coredump + +static int dump_write(struct file *file, const void *addr, int nr) +{ + int r; + down(&file->f_dentry->d_inode->i_sem); + r = file->f_op->write(file, addr, nr, &file->f_pos) == nr; + up(&file->f_dentry->d_inode->i_sem); + return r; +} + +#define DUMP_WRITE(addr, nr) \ + if (!dump_write(file, (void *)(addr), (nr))) \ + goto close_coredump; #define DUMP_SEEK(offset) \ if (file->f_op->llseek) { \ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/kernel/psycho.c linux.pre11.3/arch/sparc64/kernel/psycho.c --- linux.vanilla/arch/sparc64/kernel/psycho.c Wed Apr 28 19:14:25 1999 +++ linux.pre11.3/arch/sparc64/kernel/psycho.c Mon Jul 19 23:28:53 1999 @@ -1,4 +1,4 @@ -/* $Id: psycho.c,v 1.85 1999/04/02 14:54:28 davem Exp $ +/* $Id: psycho.c,v 1.85.2.1 1999/07/01 10:41:16 davem Exp $ * psycho.c: Ultra/AX U2P PCI controller support. * * Copyright (C) 1997 David S. Miller (davem@caipfs.rutgers.edu) @@ -757,13 +757,15 @@ unsigned short stmp; unsigned int itmp; +#if 0 for(pdev = pci_devices; pdev; pdev = pdev->next) { if(pdev->vendor == PCI_VENDOR_ID_SUN && pdev->device == PCI_DEVICE_ID_SUN_SABRE) { - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 128); + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); break; } } +#endif for (pdev = sabre->pci_bus->devices; pdev; pdev = pdev->sibling) { if (pdev->vendor == PCI_VENDOR_ID_SUN && pdev->device == PCI_DEVICE_ID_SUN_SIMBA) { @@ -795,13 +797,14 @@ pci_read_config_dword(pdev, APB_PCI_CONTROL_LOW, &itmp); itmp = APB_PCI_CTL_LOW_ERRINT_EN | 0x0f; pci_write_config_dword(pdev, APB_PCI_CONTROL_LOW, itmp); - +#if 0 /* Don't mess with the retry limit and PIO/DMA latency * timer settings. But do set primary and secondary * latency timers. */ - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 128); - pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 128); + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); + pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 64); +#endif } } } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/kernel/sparc64_ksyms.c linux.pre11.3/arch/sparc64/kernel/sparc64_ksyms.c --- linux.vanilla/arch/sparc64/kernel/sparc64_ksyms.c Thu May 27 22:11:51 1999 +++ linux.pre11.3/arch/sparc64/kernel/sparc64_ksyms.c Mon Jul 19 23:28:53 1999 @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.58 1999/05/08 03:00:31 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.58.2.1 1999/06/28 11:27:57 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -206,6 +206,7 @@ /* Kernel thread creation. */ EXPORT_SYMBOL(kernel_thread); +EXPORT_SYMBOL(init_mm); /* prom symbols */ EXPORT_SYMBOL(idprom); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/kernel/sys_sunos32.c linux.pre11.3/arch/sparc64/kernel/sys_sunos32.c --- linux.vanilla/arch/sparc64/kernel/sys_sunos32.c Tue Jun 15 16:49:47 1999 +++ linux.pre11.3/arch/sparc64/kernel/sys_sunos32.c Mon Jul 19 23:54:30 1999 @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/mm/init.c linux.pre11.3/arch/sparc64/mm/init.c --- linux.vanilla/arch/sparc64/mm/init.c Thu May 27 22:11:51 1999 +++ linux.pre11.3/arch/sparc64/mm/init.c Mon Jul 19 23:28:55 1999 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.127 1999/05/08 03:00:38 davem Exp $ +/* $Id: init.c,v 1.127.2.1 1999/06/25 10:42:10 davem Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu) @@ -418,10 +418,12 @@ } if (iommu->strbuf_enabled) { + volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush; + spin_lock_irqsave(&iommu->iommu_lock, flags); iommu->flushflag = 0; while(start < end) { - sregs->sbuf_pflush = start; + *sbuf_pflush = start; start += PAGE_SIZE; } sregs->sbuf_fsync = __pa(&(iommu->flushflag)); @@ -446,6 +448,8 @@ start &= PAGE_MASK; if (iommu->strbuf_enabled) { + volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush; + spin_lock_irqsave(&iommu->iommu_lock, flags); /* 1) Clear the flush flag word */ @@ -455,7 +459,7 @@ * we want flushed. */ while(start < end) { - sregs->sbuf_pflush = start; + *sbuf_pflush = start; start += PAGE_SIZE; } @@ -483,6 +487,8 @@ volatile u64 *sbctrl = (volatile u64 *) &sregs->sbus_control; if (iommu->strbuf_enabled) { + volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush; + spin_lock_irqsave(&iommu->iommu_lock, flags); iommu->flushflag = 0; @@ -499,7 +505,7 @@ sg[sz--].dvma_addr = sbus_dvma_addr(start); start &= PAGE_MASK; while(start < end) { - sregs->sbuf_pflush = start; + *sbuf_pflush = start; start += PAGE_SIZE; } } @@ -534,6 +540,8 @@ unsigned long flags, tmp; if (iommu->strbuf_enabled) { + volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush; + spin_lock_irqsave(&iommu->iommu_lock, flags); /* 1) Clear the flush flag word */ @@ -548,7 +556,7 @@ start &= PAGE_MASK; while(start < end) { - sregs->sbuf_pflush = start; + *sbuf_pflush = start; start += PAGE_SIZE; } sz--; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/solaris/socksys.c linux.pre11.3/arch/sparc64/solaris/socksys.c --- linux.vanilla/arch/sparc64/solaris/socksys.c Sun Nov 8 15:08:42 1998 +++ linux.pre11.3/arch/sparc64/solaris/socksys.c Mon Jul 19 23:54:30 1999 @@ -16,7 +16,6 @@ #include #include #include -#include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/Makefile linux.pre11.3/drivers/Makefile --- linux.vanilla/drivers/Makefile Thu May 27 22:11:52 1999 +++ linux.pre11.3/drivers/Makefile Mon Jul 19 23:54:40 1999 @@ -9,8 +9,8 @@ SUB_DIRS := block char net misc sound MOD_SUB_DIRS := $(SUB_DIRS) -ALL_SUB_DIRS := $(SUB_DIRS) pci scsi sbus cdrom isdn pnp \ - macintosh video dio zorro fc4 usb +ALL_SUB_DIRS := $(SUB_DIRS) pci sgi scsi sbus cdrom isdn pnp \ + macintosh video dio zorro fc4 usb ifdef CONFIG_DIO SUB_DIRS += dio @@ -34,6 +34,10 @@ SUB_DIRS += nubus endif +ifdef CONFIG_TC +SUB_DIRS += tc +endif + ifdef CONFIG_VT SUB_DIRS += video MOD_SUB_DIRS += video @@ -52,6 +56,11 @@ MOD_SUB_DIRS += usb endif endif + +ifdef CONFIG_SGI +SUB_DIRS += sgi +MOD_SUB_DIRS += sgi +endif # If CONFIG_SCSI is set, the core of SCSI support will be added to the kernel, # but some of the low-level things may also be modules. diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/ap1000/bif.c linux.pre11.3/drivers/ap1000/bif.c --- linux.vanilla/drivers/ap1000/bif.c Sun Nov 8 15:08:12 1998 +++ linux.pre11.3/drivers/ap1000/bif.c Mon Jul 19 23:54:46 1999 @@ -30,7 +30,6 @@ #include #include -#include #include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/Config.in linux.pre11.3/drivers/block/Config.in --- linux.vanilla/drivers/block/Config.in Thu May 27 22:11:52 1999 +++ linux.pre11.3/drivers/block/Config.in Tue Jul 20 00:27:46 1999 @@ -114,6 +114,9 @@ bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD fi tristate 'XT hard disk support' CONFIG_BLK_DEV_XD +if [ "$CONFIG_PCI" = "y" ]; then + tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960 +fi # PARIDE doesn't need PARPORT, but if PARPORT is configured as a module, # PARIDE must also be a module. The bogus CONFIG_PARIDE_PARPORT option @@ -128,6 +131,7 @@ if [ "$CONFIG_PARIDE" = "y" -o "$CONFIG_PARIDE" = "m" ]; then source drivers/block/paride/Config.in fi +tristate 'Compaq SMART2 support' CONFIG_BLK_CPQ_DA if [ "$CONFIG_BLK_DEV_HD_IDE" = "y" -o "$CONFIG_BLK_DEV_HD_ONLY" = "y" ]; then define_bool CONFIG_BLK_DEV_HD y diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/DAC960.c linux.pre11.3/drivers/block/DAC960.c --- linux.vanilla/drivers/block/DAC960.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/block/DAC960.c Tue Jul 20 00:27:58 1999 @@ -0,0 +1,3320 @@ +/* + + Linux Driver for Mylex DAC960 and DAC1100 PCI RAID Controllers + + Copyright 1998-1999 by Leonard N. Zubkoff + + This program is free software; you may redistribute 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 complete details. + + The author respectfully requests that any modifications to this software be + sent directly to him for evaluation and testing. + +*/ + + +#define DAC960_DriverVersion "2.2.2" +#define DAC960_DriverDate "3 July 1999" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "DAC960.h" + + +/* + DAC960_ControllerCount is the number of DAC960 Controllers detected. +*/ + +static int + DAC960_ControllerCount = 0; + + +/* + DAC960_ActiveControllerCount is the number of Active DAC960 Controllers + detected. +*/ + +static int + DAC960_ActiveControllerCount = 0; + + +/* + DAC960_Controllers is an array of pointers to the DAC960 Controller + structures. +*/ + +static DAC960_Controller_T + *DAC960_Controllers[DAC960_MaxControllers] = { NULL }; + + +/* + DAC960_FileOperations is the File Operations structure for DAC960 Logical + Disk Devices. +*/ + +static FileOperations_T + DAC960_FileOperations = + { llseek: NULL, + read: block_read, + write: block_write, + readdir: NULL, + poll: NULL, + ioctl: DAC960_IOCTL, + mmap: NULL, + open: DAC960_Open, + release: DAC960_Release, + fsync: block_fsync, + fasync: NULL, + check_media_change: NULL, + revalidate: NULL }; + + +/* + DAC960_ProcDirectoryEntry is the DAC960 /proc/rd directory entry. +*/ + +static PROC_DirectoryEntry_T + DAC960_ProcDirectoryEntry; + + +/* + DAC960_NotifierBlock is the Notifier Block structure for DAC960 Driver. +*/ + +static NotifierBlock_T + DAC960_NotifierBlock = { DAC960_Finalize, NULL, 0 }; + + +/* + DAC960_AnnounceDriver announces the Driver Version and Date, Author's Name, + Copyright Notice, and Electronic Mail Address. +*/ + +static void DAC960_AnnounceDriver(DAC960_Controller_T *Controller) +{ + DAC960_Announce("***** DAC960 RAID Driver Version " + DAC960_DriverVersion " of " + DAC960_DriverDate " *****\n", Controller); + DAC960_Announce("Copyright 1998-1999 by Leonard N. Zubkoff " + "\n", Controller); +} + + +/* + DAC960_Failure prints a standardized error message, and then returns false. +*/ + +static boolean DAC960_Failure(DAC960_Controller_T *Controller, + char *ErrorMessage) +{ + DAC960_Error("While configuring DAC960 PCI RAID Controller at\n", + Controller); + 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, + 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, + Controller->Bus, Controller->Device, + Controller->Function, Controller->IO_Address, + Controller->PCI_Address); + DAC960_Error("%s FAILED - DETACHING\n", Controller, ErrorMessage); + return false; +} + + +/* + DAC960_ClearCommand clears critical fields of Command. +*/ + +static inline void DAC960_ClearCommand(DAC960_Command_T *Command) +{ + DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; + CommandMailbox->Words[0] = 0; + CommandMailbox->Words[1] = 0; + CommandMailbox->Words[2] = 0; + CommandMailbox->Words[3] = 0; + Command->CommandStatus = 0; +} + + +/* + DAC960_AllocateCommand allocates a Command structure from Controller's + free list. +*/ + +static inline DAC960_Command_T *DAC960_AllocateCommand(DAC960_Controller_T + *Controller) +{ + DAC960_Command_T *Command = Controller->FreeCommands; + if (Command == NULL) return NULL; + Controller->FreeCommands = Command->Next; + Command->Next = NULL; + return Command; +} + + +/* + DAC960_DeallocateCommand deallocates Command, returning it to Controller's + free list. +*/ + +static inline void DAC960_DeallocateCommand(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + Command->Next = Controller->FreeCommands; + Controller->FreeCommands = Command; +} + + +/* + DAC960_QueueCommand queues Command. +*/ + +static void DAC960_QueueCommand(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; + DAC960_CommandMailbox_T *NextCommandMailbox; + CommandMailbox->Common.CommandIdentifier = Command - Controller->Commands; + switch (Controller->ControllerType) + { + case DAC960_V5_Controller: + NextCommandMailbox = Controller->NextCommandMailbox; + DAC960_V5_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); + if (Controller->PreviousCommandMailbox1->Words[0] == 0 || + Controller->PreviousCommandMailbox2->Words[0] == 0) + { + if (Controller->DualModeMemoryMailboxInterface) + DAC960_V5_MemoryMailboxNewCommand(ControllerBaseAddress); + else DAC960_V5_HardwareMailboxNewCommand(ControllerBaseAddress); + } + Controller->PreviousCommandMailbox2 = Controller->PreviousCommandMailbox1; + Controller->PreviousCommandMailbox1 = NextCommandMailbox; + if (++NextCommandMailbox > Controller->LastCommandMailbox) + NextCommandMailbox = Controller->FirstCommandMailbox; + Controller->NextCommandMailbox = NextCommandMailbox; + break; + case DAC960_V4_Controller: + NextCommandMailbox = Controller->NextCommandMailbox; + DAC960_V4_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); + if (Controller->PreviousCommandMailbox1->Words[0] == 0 || + Controller->PreviousCommandMailbox2->Words[0] == 0) + { + if (Controller->DualModeMemoryMailboxInterface) + DAC960_V4_MemoryMailboxNewCommand(ControllerBaseAddress); + else DAC960_V4_HardwareMailboxNewCommand(ControllerBaseAddress); + } + Controller->PreviousCommandMailbox2 = Controller->PreviousCommandMailbox1; + Controller->PreviousCommandMailbox1 = NextCommandMailbox; + if (++NextCommandMailbox > Controller->LastCommandMailbox) + NextCommandMailbox = Controller->FirstCommandMailbox; + Controller->NextCommandMailbox = NextCommandMailbox; + break; + case DAC960_V3_Controller: + while (DAC960_V3_MailboxFullP(ControllerBaseAddress)) + udelay(1); + DAC960_V3_WriteCommandMailbox(ControllerBaseAddress, CommandMailbox); + DAC960_V3_NewCommand(ControllerBaseAddress); + break; + } +} + + +/* + DAC960_ExecuteCommand executes Command and waits for completion. It + returns true on success and false on failure. +*/ + +static boolean DAC960_ExecuteCommand(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + Semaphore_T Semaphore = MUTEX_LOCKED; + unsigned long ProcessorFlags; + Command->Semaphore = &Semaphore; + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + DAC960_QueueCommand(Command); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + if (!in_interrupt()) + down(&Semaphore); + return Command->CommandStatus == DAC960_NormalCompletion; +} + + +/* + DAC960_ExecuteType3 executes a DAC960 Type 3 Command and waits for + completion. It returns true on success and false on failure. +*/ + +static boolean DAC960_ExecuteType3(DAC960_Controller_T *Controller, + DAC960_CommandOpcode_T CommandOpcode, + void *DataPointer) +{ + DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); + DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; + boolean Result; + DAC960_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox->Type3.CommandOpcode = CommandOpcode; + CommandMailbox->Type3.BusAddress = Virtual_to_Bus(DataPointer); + Result = DAC960_ExecuteCommand(Command); + DAC960_DeallocateCommand(Command); + return Result; +} + + +/* + DAC960_ExecuteType3D executes a DAC960 Type 3D Command and waits for + completion. It returns true on success and false on failure. +*/ + +static boolean DAC960_ExecuteType3D(DAC960_Controller_T *Controller, + DAC960_CommandOpcode_T CommandOpcode, + unsigned char Channel, + unsigned char TargetID, + void *DataPointer) +{ + DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); + DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; + boolean Result; + DAC960_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox->Type3D.CommandOpcode = CommandOpcode; + CommandMailbox->Type3D.Channel = Channel; + CommandMailbox->Type3D.TargetID = TargetID; + CommandMailbox->Type3D.BusAddress = Virtual_to_Bus(DataPointer); + Result = DAC960_ExecuteCommand(Command); + DAC960_DeallocateCommand(Command); + return Result; +} + + +/* + DAC960_EnableMemoryMailboxInterface enables the Memory Mailbox Interface. +*/ + +static boolean DAC960_EnableMemoryMailboxInterface(DAC960_Controller_T + *Controller) +{ + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_CommandMailbox_T *CommandMailboxesMemory; + DAC960_StatusMailbox_T *StatusMailboxesMemory; + DAC960_CommandMailbox_T CommandMailbox; + DAC960_CommandStatus_T CommandStatus; + void *SavedMemoryMailboxesAddress = NULL; + short NextCommandMailboxIndex = 0; + short NextStatusMailboxIndex = 0; + int TimeoutCounter = 1000000, i; + if (Controller->ControllerType == DAC960_V5_Controller) + DAC960_V5_RestoreMemoryMailboxInfo(Controller, + &SavedMemoryMailboxesAddress, + &NextCommandMailboxIndex, + &NextStatusMailboxIndex); + else DAC960_V4_RestoreMemoryMailboxInfo(Controller, + &SavedMemoryMailboxesAddress, + &NextCommandMailboxIndex, + &NextStatusMailboxIndex); + if (SavedMemoryMailboxesAddress == NULL) + CommandMailboxesMemory = + (DAC960_CommandMailbox_T *) __get_free_pages(GFP_KERNEL, 1); + else CommandMailboxesMemory = SavedMemoryMailboxesAddress; + memset(CommandMailboxesMemory, 0, PAGE_SIZE << 1); + Controller->FirstCommandMailbox = CommandMailboxesMemory; + CommandMailboxesMemory += DAC960_CommandMailboxCount - 1; + Controller->LastCommandMailbox = CommandMailboxesMemory; + Controller->NextCommandMailbox = + &Controller->FirstCommandMailbox[NextCommandMailboxIndex]; + if (--NextCommandMailboxIndex < 0) + NextCommandMailboxIndex = DAC960_CommandMailboxCount - 1; + Controller->PreviousCommandMailbox1 = + &Controller->FirstCommandMailbox[NextCommandMailboxIndex]; + if (--NextCommandMailboxIndex < 0) + NextCommandMailboxIndex = DAC960_CommandMailboxCount - 1; + Controller->PreviousCommandMailbox2 = + &Controller->FirstCommandMailbox[NextCommandMailboxIndex]; + StatusMailboxesMemory = + (DAC960_StatusMailbox_T *) (CommandMailboxesMemory + 1); + Controller->FirstStatusMailbox = StatusMailboxesMemory; + StatusMailboxesMemory += DAC960_StatusMailboxCount - 1; + Controller->LastStatusMailbox = StatusMailboxesMemory; + Controller->NextStatusMailbox = + &Controller->FirstStatusMailbox[NextStatusMailboxIndex]; + if (SavedMemoryMailboxesAddress != NULL) return true; + /* Enable the Memory Mailbox Interface. */ + Controller->DualModeMemoryMailboxInterface = true; + CommandMailbox.TypeX.CommandOpcode = 0x2B; + CommandMailbox.TypeX.CommandIdentifier = 0; + CommandMailbox.TypeX.CommandOpcode2 = 0x14; + CommandMailbox.TypeX.CommandMailboxesBusAddress = + Virtual_to_Bus(Controller->FirstCommandMailbox); + CommandMailbox.TypeX.StatusMailboxesBusAddress = + Virtual_to_Bus(Controller->FirstStatusMailbox); + for (i = 0; i < 2; i++) + switch (Controller->ControllerType) + { + case DAC960_V5_Controller: + while (--TimeoutCounter >= 0) + { + if (DAC960_V5_HardwareMailboxEmptyP(ControllerBaseAddress)) + break; + udelay(10); + } + if (TimeoutCounter < 0) return false; + DAC960_V5_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); + DAC960_V5_HardwareMailboxNewCommand(ControllerBaseAddress); + while (--TimeoutCounter >= 0) + { + if (DAC960_V5_HardwareMailboxStatusAvailableP( + ControllerBaseAddress)) + break; + udelay(10); + } + if (TimeoutCounter < 0) return false; + CommandStatus = DAC960_V5_ReadStatusRegister(ControllerBaseAddress); + DAC960_V5_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress); + DAC960_V5_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress); + if (CommandStatus == DAC960_NormalCompletion) return true; + Controller->DualModeMemoryMailboxInterface = false; + CommandMailbox.TypeX.CommandOpcode2 = 0x10; + break; + case DAC960_V4_Controller: + while (--TimeoutCounter >= 0) + { + if (!DAC960_V4_HardwareMailboxFullP(ControllerBaseAddress)) + break; + udelay(10); + } + if (TimeoutCounter < 0) return false; + DAC960_V4_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); + DAC960_V4_HardwareMailboxNewCommand(ControllerBaseAddress); + while (--TimeoutCounter >= 0) + { + if (DAC960_V4_HardwareMailboxStatusAvailableP( + ControllerBaseAddress)) + break; + udelay(10); + } + if (TimeoutCounter < 0) return false; + CommandStatus = DAC960_V4_ReadStatusRegister(ControllerBaseAddress); + DAC960_V4_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress); + DAC960_V4_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress); + if (CommandStatus == DAC960_NormalCompletion) return true; + Controller->DualModeMemoryMailboxInterface = false; + CommandMailbox.TypeX.CommandOpcode2 = 0x10; + break; + default: + break; + } + return false; +} + + +/* + DAC960_DetectControllers detects DAC960 PCI RAID Controllers by interrogating + the PCI Configuration Space for Controller Type. +*/ + +static void DAC960_DetectControllers(DAC960_ControllerType_T ControllerType) +{ + unsigned short VendorID = 0, DeviceID = 0; + unsigned int MemoryWindowSize = 0; + PCI_Device_T *PCI_Device = NULL; + switch (ControllerType) + { + case DAC960_V5_Controller: + VendorID = PCI_VENDOR_ID_DEC; + DeviceID = PCI_DEVICE_ID_DEC_21285; + MemoryWindowSize = DAC960_V5_RegisterWindowSize; + break; + case DAC960_V4_Controller: + VendorID = PCI_VENDOR_ID_MYLEX; + DeviceID = PCI_DEVICE_ID_MYLEX_DAC960P_V4; + MemoryWindowSize = DAC960_V4_RegisterWindowSize; + break; + case DAC960_V3_Controller: + VendorID = PCI_VENDOR_ID_MYLEX; + DeviceID = PCI_DEVICE_ID_MYLEX_DAC960P_V3; + MemoryWindowSize = DAC960_V3_RegisterWindowSize; + break; + } + while ((PCI_Device = pci_find_device(VendorID, DeviceID, PCI_Device)) != NULL) + { + DAC960_Controller_T *Controller = (DAC960_Controller_T *) + kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC); + 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 int IRQ_Channel = PCI_Device->irq; + unsigned long BaseAddress0 = PCI_Device->base_address[0]; + unsigned long BaseAddress1 = PCI_Device->base_address[1]; + unsigned short SubsystemVendorID, SubsystemDeviceID; + pci_read_config_word(PCI_Device, PCI_SUBSYSTEM_VENDOR_ID, + &SubsystemVendorID); + pci_read_config_word(PCI_Device, PCI_SUBSYSTEM_ID, + &SubsystemDeviceID); + switch (ControllerType) + { + case DAC960_V5_Controller: + if (!(SubsystemVendorID == PCI_VENDOR_ID_MYLEX && + SubsystemDeviceID == PCI_DEVICE_ID_MYLEX_DAC960P_V5)) + goto Ignore; + PCI_Address = BaseAddress0 & PCI_BASE_ADDRESS_MEM_MASK; + break; + case DAC960_V4_Controller: + PCI_Address = BaseAddress0 & PCI_BASE_ADDRESS_MEM_MASK; + break; + case DAC960_V3_Controller: + IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK; + PCI_Address = BaseAddress1 & PCI_BASE_ADDRESS_MEM_MASK; + break; + } + if (DAC960_ControllerCount == DAC960_MaxControllers) + { + DAC960_Error("More than %d DAC960 Controllers detected - " + "ignoring from Controller at\n", + NULL, DAC960_MaxControllers); + goto Ignore; + } + if (Controller == NULL) + { + DAC960_Error("Unable to allocate Controller structure for " + "Controller at\n", NULL); + goto Ignore; + } + memset(Controller, 0, sizeof(DAC960_Controller_T)); + Controller->ControllerNumber = DAC960_ControllerCount; + DAC960_Controllers[DAC960_ControllerCount++] = Controller; + DAC960_AnnounceDriver(Controller); + Controller->ControllerType = ControllerType; + Controller->IO_Address = IO_Address; + Controller->PCI_Address = PCI_Address; + Controller->Bus = Bus; + Controller->Device = Device; + Controller->Function = Function; + sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber); + /* + 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 Failure; + } + strcpy(Controller->FullModelName, "DAC960"); + if (request_irq(IRQ_Channel, DAC960_InterruptHandler, + SA_SHIRQ, Controller->FullModelName, Controller) < 0) + { + DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n", + Controller, IRQ_Channel); + goto Failure; + } + Controller->IRQ_Channel = IRQ_Channel; + /* + 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) + { + DAC960_Error("Unable to map Controller Register Window for " + "Controller at\n", Controller); + goto Failure; + } + switch (ControllerType) + { + case DAC960_V5_Controller: + DAC960_V5_DisableInterrupts(Controller->BaseAddress); + if (!DAC960_EnableMemoryMailboxInterface(Controller)) + { + DAC960_Error("Unable to Enable Memory Mailbox Interface " + "for Controller at\n", Controller); + goto Failure; + } + DAC960_V5_EnableInterrupts(Controller->BaseAddress); + break; + case DAC960_V4_Controller: + DAC960_V4_DisableInterrupts(Controller->BaseAddress); + if (!DAC960_EnableMemoryMailboxInterface(Controller)) + { + DAC960_Error("Unable to Enable Memory Mailbox Interface " + "for Controller at\n", Controller); + goto Failure; + } + DAC960_V4_EnableInterrupts(Controller->BaseAddress); + break; + case DAC960_V3_Controller: + request_region(Controller->IO_Address, 0x80, + Controller->FullModelName); + DAC960_V3_EnableInterrupts(Controller->BaseAddress); + break; + } + DAC960_ActiveControllerCount++; + Controller->Commands[0].Controller = Controller; + Controller->Commands[0].Next = NULL; + Controller->FreeCommands = &Controller->Commands[0]; + continue; + Failure: + if (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 " + "0x%X PCI Address 0x%X\n", Controller, + Bus, Device, Function, IO_Address, PCI_Address); + if (Controller == NULL) break; + if (Controller->IRQ_Channel > 0) + free_irq(IRQ_Channel, Controller); + if (Controller->MemoryMappedAddress != NULL) + iounmap(Controller->MemoryMappedAddress); + DAC960_Controllers[Controller->ControllerNumber] = NULL; + Ignore: + kfree(Controller); + } +} + + +/* + DAC960_ReadControllerConfiguration reads the Configuration Information + from Controller and initializes the Controller structure. +*/ + +static boolean DAC960_ReadControllerConfiguration(DAC960_Controller_T + *Controller) +{ + DAC960_Enquiry2_T Enquiry2; + DAC960_Config2_T Config2; + int LogicalDriveNumber, Channel, TargetID; + if (!DAC960_ExecuteType3(Controller, DAC960_Enquiry, + &Controller->Enquiry[0])) + return DAC960_Failure(Controller, "ENQUIRY"); + if (!DAC960_ExecuteType3(Controller, DAC960_Enquiry2, &Enquiry2)) + return DAC960_Failure(Controller, "ENQUIRY2"); + if (!DAC960_ExecuteType3(Controller, DAC960_ReadConfig2, &Config2)) + return DAC960_Failure(Controller, "READ CONFIG2"); + if (!DAC960_ExecuteType3(Controller, DAC960_GetLogicalDriveInformation, + &Controller->LogicalDriveInformation[0])) + return DAC960_Failure(Controller, "GET LOGICAL DRIVE INFORMATION"); + for (Channel = 0; Channel < Enquiry2.ActualChannels; Channel++) + for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++) + if (!DAC960_ExecuteType3D(Controller, DAC960_GetDeviceState, + Channel, TargetID, + &Controller->DeviceState[0][Channel][TargetID])) + return DAC960_Failure(Controller, "GET DEVICE STATE"); + /* + Initialize the Controller Model Name and Full Model Name fields. + */ + switch (Enquiry2.HardwareID.SubModel) + { + case DAC960_P_PD_PU: + if (Enquiry2.SCSICapability.BusSpeed == DAC960_Ultra) + strcpy(Controller->ModelName, "DAC960PU"); + else strcpy(Controller->ModelName, "DAC960PD"); + break; + case DAC960_PL: + strcpy(Controller->ModelName, "DAC960PL"); + break; + case DAC960_PG: + strcpy(Controller->ModelName, "DAC960PG"); + break; + case DAC960_PJ: + strcpy(Controller->ModelName, "DAC960PJ"); + break; + case DAC960_PR: + strcpy(Controller->ModelName, "DAC960PR"); + break; + case DAC960_PT: + strcpy(Controller->ModelName, "DAC960PT"); + break; + case DAC960_PTL0: + strcpy(Controller->ModelName, "DAC960PTL0"); + break; + case DAC960_PRL: + strcpy(Controller->ModelName, "DAC960PRL"); + break; + case DAC960_PTL1: + strcpy(Controller->ModelName, "DAC960PTL1"); + break; + case DAC1164_P: + strcpy(Controller->ModelName, "DAC1164P"); + break; + default: + return DAC960_Failure(Controller, "MODEL VERIFICATION"); + } + strcpy(Controller->FullModelName, "Mylex "); + strcat(Controller->FullModelName, Controller->ModelName); + /* + Initialize the Controller Firmware Version field and verify that it + is a supported firmware version. The supported firmware versions are: + + DAC1164P 5.06 and above + DAC960PTL/PRL/PJ/PG 4.06 and above + DAC960PU/PD/PL 3.51 and above + */ + sprintf(Controller->FirmwareVersion, "%d.%02d-%c-%02d", + 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' && + strcmp(Controller->FirmwareVersion, "4.06") >= 0) || + (Controller->FirmwareVersion[0] == '3' && + strcmp(Controller->FirmwareVersion, "3.51") >= 0))) + { + DAC960_Failure(Controller, "FIRMWARE VERSION VERIFICATION"); + DAC960_Error("Firmware Version = '%s'\n", Controller, + Controller->FirmwareVersion); + return false; + } + /* + Initialize the Controller Channels, Memory Size, and SAF-TE Enclosure + Management Enabled fields. + */ + Controller->Channels = Enquiry2.ActualChannels; + Controller->MemorySize = Enquiry2.MemorySize >> 20; + Controller->SAFTE_EnclosureManagementEnabled = + Enquiry2.FaultManagementType == DAC960_SAFTE; + /* + Initialize the Controller Queue Depth, Driver Queue Depth, Logical Drive + Count, Maximum Blocks per Command, and Maximum Scatter/Gather Segments. + The Driver Queue Depth must be at most one less than the Controller Queue + Depth to allow for an automatic drive rebuild operation. + */ + Controller->ControllerQueueDepth = Controller->Enquiry[0].MaxCommands; + Controller->DriverQueueDepth = Controller->ControllerQueueDepth - 1; + Controller->LogicalDriveCount = Controller->Enquiry[0].NumberOfLogicalDrives; + Controller->MaxBlocksPerCommand = Enquiry2.MaxBlocksPerCommand; + Controller->MaxScatterGatherSegments = Enquiry2.MaxScatterGatherEntries; + /* + Initialize the Stripe Size, Segment Size, and Geometry Translation. + */ + Controller->StripeSize = Config2.BlocksPerStripe * Config2.BlockFactor + >> (10 - DAC960_BlockSizeBits); + Controller->SegmentSize = Config2.BlocksPerCacheLine * Config2.BlockFactor + >> (10 - DAC960_BlockSizeBits); + switch (Config2.DriveGeometry) + { + case DAC960_Geometry_128_32: + Controller->GeometryTranslationHeads = 128; + Controller->GeometryTranslationSectors = 32; + break; + case DAC960_Geometry_255_63: + Controller->GeometryTranslationHeads = 255; + Controller->GeometryTranslationSectors = 63; + break; + default: + return DAC960_Failure(Controller, "CONFIG2 DRIVE GEOMETRY"); + } + /* + Initialize the Logical Drive Initial State. + */ + for (LogicalDriveNumber = 0; + LogicalDriveNumber < Controller->LogicalDriveCount; + LogicalDriveNumber++) + Controller->LogicalDriveInitialState[LogicalDriveNumber] = + Controller->LogicalDriveInformation[0] + [LogicalDriveNumber].LogicalDriveState; + Controller->LastRebuildStatus = DAC960_NoRebuildOrCheckInProgress; + return true; +} + + +/* + DAC960_ReportControllerConfiguration reports the configuration of + Controller. +*/ + +static boolean DAC960_ReportControllerConfiguration(DAC960_Controller_T + *Controller) +{ + int LogicalDriveNumber, Channel, TargetID; + DAC960_Info("Configuring Mylex %s PCI RAID Controller\n", + Controller, Controller->ModelName); + DAC960_Info(" Firmware Version: %s, Channels: %d, Memory Size: %dMB\n", + Controller, Controller->FirmwareVersion, + Controller->Channels, Controller->MemorySize); + DAC960_Info(" PCI Bus: %d, Device: %d, Function: %d, I/O Address: ", + Controller, Controller->Bus, + Controller->Device, Controller->Function); + if (Controller->IO_Address == 0) + DAC960_Info("Unassigned\n", Controller); + else DAC960_Info("0x%X\n", Controller, Controller->IO_Address); + DAC960_Info(" PCI Address: 0x%X mapped at 0x%lX, IRQ Channel: %d\n", + Controller, Controller->PCI_Address, + (unsigned long) Controller->BaseAddress, + Controller->IRQ_Channel); + DAC960_Info(" Controller Queue Depth: %d, " + "Maximum Blocks per Command: %d\n", + Controller, Controller->ControllerQueueDepth, + Controller->MaxBlocksPerCommand); + DAC960_Info(" Driver Queue Depth: %d, " + "Maximum Scatter/Gather Segments: %d\n", + Controller, Controller->DriverQueueDepth, + Controller->MaxScatterGatherSegments); + DAC960_Info(" Stripe Size: %dKB, Segment Size: %dKB, " + "BIOS Geometry: %d/%d\n", Controller, + Controller->StripeSize, + Controller->SegmentSize, + Controller->GeometryTranslationHeads, + Controller->GeometryTranslationSectors); + if (Controller->SAFTE_EnclosureManagementEnabled) + DAC960_Info(" SAF-TE Enclosure Management Enabled\n", Controller); + DAC960_Info(" Physical Devices:\n", Controller); + for (Channel = 0; Channel < Controller->Channels; Channel++) + for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++) + { + DAC960_DeviceState_T *DeviceState = + &Controller->DeviceState[Controller->DeviceStateIndex] + [Channel][TargetID]; + if (!DeviceState->Present) continue; + switch (DeviceState->DeviceType) + { + case DAC960_OtherType: + DAC960_Info(" %d:%d - Other\n", Controller, Channel, TargetID); + break; + case DAC960_DiskType: + DAC960_Info(" %d:%d - Disk: %s, %d blocks\n", Controller, + Channel, TargetID, + (DeviceState->DeviceState == DAC960_Device_Dead + ? "Dead" + : DeviceState->DeviceState == DAC960_Device_WriteOnly + ? "Write-Only" + : DeviceState->DeviceState == DAC960_Device_Online + ? "Online" : "Standby"), + DeviceState->DiskSize); + break; + case DAC960_SequentialType: + DAC960_Info(" %d:%d - Sequential\n", Controller, + Channel, TargetID); + break; + case DAC960_CDROM_or_WORM_Type: + DAC960_Info(" %d:%d - CD-ROM or WORM\n", Controller, + Channel, TargetID); + break; + } + + } + DAC960_Info(" Logical Drives:\n", Controller); + for (LogicalDriveNumber = 0; + LogicalDriveNumber < Controller->LogicalDriveCount; + LogicalDriveNumber++) + { + DAC960_LogicalDriveInformation_T *LogicalDriveInformation = + &Controller->LogicalDriveInformation + [Controller->LogicalDriveInformationIndex][LogicalDriveNumber]; + DAC960_Info(" /dev/rd/c%dd%d: RAID-%d, %s, %d blocks, %s\n", + Controller, Controller->ControllerNumber, LogicalDriveNumber, + LogicalDriveInformation->RAIDLevel, + (LogicalDriveInformation->LogicalDriveState == + DAC960_LogicalDrive_Online + ? "Online" + : LogicalDriveInformation->LogicalDriveState == + DAC960_LogicalDrive_Critical + ? "Critical" : "Offline"), + LogicalDriveInformation->LogicalDriveSize, + (LogicalDriveInformation->WriteBack + ? "Write Back" : "Write Thru")); + } + return true; +} + + +/* + DAC960_RegisterBlockDevice registers the Block Device structures + associated with Controller. +*/ + +static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller) +{ + static void (*RequestFunctions[DAC960_MaxControllers])(void) = + { DAC960_RequestFunction0, DAC960_RequestFunction1, + DAC960_RequestFunction2, DAC960_RequestFunction3, + DAC960_RequestFunction4, DAC960_RequestFunction5, + DAC960_RequestFunction6, DAC960_RequestFunction7 }; + int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber; + GenericDiskInfo_T *GenericDiskInfo; + int MinorNumber; + /* + Register the Block Device Major Number for this DAC960 Controller. + */ + if (register_blkdev(MajorNumber, "rd", &DAC960_FileOperations) < 0) + { + DAC960_Error("UNABLE TO ACQUIRE MAJOR NUMBER %d - DETACHING\n", + Controller, MajorNumber); + return false; + } + /* + Initialize the I/O Request Function. + */ + blk_dev[MajorNumber].request_fn = + RequestFunctions[Controller->ControllerNumber]; + /* + Initialize the Disk Partitions array, Partition Sizes array, Block Sizes + array, Max Sectors per Request array, and Max Segments per Request array. + */ + for (MinorNumber = 0; MinorNumber < DAC960_MinorCount; MinorNumber++) + { + Controller->BlockSizes[MinorNumber] = BLOCK_SIZE; + Controller->MaxSectorsPerRequest[MinorNumber] = + Controller->MaxBlocksPerCommand; + Controller->MaxSegmentsPerRequest[MinorNumber] = + Controller->MaxScatterGatherSegments; + } + Controller->GenericDiskInfo.part = Controller->DiskPartitions; + Controller->GenericDiskInfo.sizes = Controller->PartitionSizes; + blksize_size[MajorNumber] = Controller->BlockSizes; + max_sectors[MajorNumber] = Controller->MaxSectorsPerRequest; + max_segments[MajorNumber] = Controller->MaxSegmentsPerRequest; + /* + Initialize Read Ahead to 128 sectors. + */ + read_ahead[MajorNumber] = 128; + /* + Complete initialization of the Generic Disk Information structure. + */ + Controller->GenericDiskInfo.major = MajorNumber; + Controller->GenericDiskInfo.major_name = "rd"; + Controller->GenericDiskInfo.minor_shift = DAC960_MaxPartitionsBits; + Controller->GenericDiskInfo.max_p = DAC960_MaxPartitions; + Controller->GenericDiskInfo.max_nr = DAC960_MaxLogicalDrives; + Controller->GenericDiskInfo.init = DAC960_InitializeGenericDiskInfo; + Controller->GenericDiskInfo.nr_real = Controller->LogicalDriveCount; + Controller->GenericDiskInfo.real_devices = Controller; + Controller->GenericDiskInfo.next = NULL; + /* + Install the Generic Disk Information structure at the end of the list. + */ + if ((GenericDiskInfo = gendisk_head) != NULL) + { + while (GenericDiskInfo->next != NULL) + GenericDiskInfo = GenericDiskInfo->next; + GenericDiskInfo->next = &Controller->GenericDiskInfo; + } + else gendisk_head = &Controller->GenericDiskInfo; + /* + Indicate the Block Device Registration completed successfully, + */ + return true; +} + + +/* + DAC960_UnregisterBlockDevice unregisters the Block Device structures + associated with Controller. +*/ + +static void DAC960_UnregisterBlockDevice(DAC960_Controller_T *Controller) +{ + int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber; + /* + Unregister the Block Device Major Number for this DAC960 Controller. + */ + unregister_blkdev(MajorNumber, "rd"); + /* + Remove the I/O Request Function. + */ + blk_dev[MajorNumber].request_fn = NULL; + /* + Remove the Disk Partitions array, Partition Sizes array, Block Sizes + array, Max Sectors per Request array, and Max Segments per Request array. + */ + Controller->GenericDiskInfo.part = NULL; + Controller->GenericDiskInfo.sizes = NULL; + blk_size[MajorNumber] = NULL; + blksize_size[MajorNumber] = NULL; + max_sectors[MajorNumber] = NULL; + max_segments[MajorNumber] = NULL; + /* + Remove the Generic Disk Information structure from the list. + */ + if (gendisk_head != &Controller->GenericDiskInfo) + { + GenericDiskInfo_T *GenericDiskInfo = gendisk_head; + while (GenericDiskInfo != NULL && + GenericDiskInfo->next != &Controller->GenericDiskInfo) + GenericDiskInfo = GenericDiskInfo->next; + if (GenericDiskInfo != NULL) + GenericDiskInfo->next = GenericDiskInfo->next->next; + } + else gendisk_head = Controller->GenericDiskInfo.next; +} + + +/* + DAC960_InitializeController initializes Controller. +*/ + +static void DAC960_InitializeController(DAC960_Controller_T *Controller) +{ + if (DAC960_ReadControllerConfiguration(Controller) && + DAC960_ReportControllerConfiguration(Controller) && + DAC960_RegisterBlockDevice(Controller)) + { + /* + Initialize the Command structures. + */ + DAC960_Command_T *Commands = Controller->Commands; + int CommandIdentifier; + Controller->FreeCommands = NULL; + for (CommandIdentifier = 0; + CommandIdentifier < Controller->DriverQueueDepth; + CommandIdentifier++) + { + Commands[CommandIdentifier].Controller = Controller; + Commands[CommandIdentifier].Next = Controller->FreeCommands; + Controller->FreeCommands = &Commands[CommandIdentifier]; + } + /* + Initialize the Monitoring Timer. + */ + init_timer(&Controller->MonitoringTimer); + Controller->MonitoringTimer.expires = + jiffies + DAC960_MonitoringTimerInterval; + Controller->MonitoringTimer.data = (unsigned long) Controller; + Controller->MonitoringTimer.function = DAC960_MonitoringTimerFunction; + add_timer(&Controller->MonitoringTimer); + Controller->ControllerInitialized = true; + } + else DAC960_FinalizeController(Controller); +} + + +/* + DAC960_FinalizeController finalizes Controller. +*/ + +static void DAC960_FinalizeController(DAC960_Controller_T *Controller) +{ + if (Controller->ControllerInitialized) + { + del_timer(&Controller->MonitoringTimer); + DAC960_Notice("Flushing Cache...", Controller); + DAC960_ExecuteType3(Controller, DAC960_Flush, NULL); + DAC960_Notice("done\n", Controller); + switch (Controller->ControllerType) + { + case DAC960_V5_Controller: + if (!Controller->DualModeMemoryMailboxInterface) + DAC960_V5_SaveMemoryMailboxInfo(Controller); + break; + case DAC960_V4_Controller: + if (!Controller->DualModeMemoryMailboxInterface) + DAC960_V4_SaveMemoryMailboxInfo(Controller); + break; + case DAC960_V3_Controller: + break; + } + } + free_irq(Controller->IRQ_Channel, Controller); + iounmap(Controller->MemoryMappedAddress); + if (Controller->IO_Address > 0) + release_region(Controller->IO_Address, 0x80); + DAC960_UnregisterBlockDevice(Controller); + DAC960_Controllers[Controller->ControllerNumber] = NULL; + kfree(Controller); +} + + +/* + DAC960_Initialize initializes the DAC960 Driver. +*/ + +void DAC960_Initialize(void) +{ + int ControllerNumber; + DAC960_DetectControllers(DAC960_V5_Controller); + DAC960_DetectControllers(DAC960_V4_Controller); + DAC960_DetectControllers(DAC960_V3_Controller); + if (DAC960_ActiveControllerCount == 0) return; + for (ControllerNumber = 0; + ControllerNumber < DAC960_ControllerCount; + ControllerNumber++) + if (DAC960_Controllers[ControllerNumber] != NULL) + DAC960_InitializeController(DAC960_Controllers[ControllerNumber]); + DAC960_CreateProcEntries(); + register_reboot_notifier(&DAC960_NotifierBlock); +} + + +/* + DAC960_Finalize finalizes the DAC960 Driver. +*/ + +static int DAC960_Finalize(NotifierBlock_T *NotifierBlock, + unsigned long Event, + void *Buffer) +{ + int ControllerNumber; + if (!(Event == SYS_RESTART || Event == SYS_HALT || Event == SYS_POWER_OFF)) + return NOTIFY_DONE; + if (DAC960_ActiveControllerCount == 0) return NOTIFY_OK; + for (ControllerNumber = 0; + ControllerNumber < DAC960_ControllerCount; + ControllerNumber++) + if (DAC960_Controllers[ControllerNumber] != NULL) + DAC960_FinalizeController(DAC960_Controllers[ControllerNumber]); + DAC960_DestroyProcEntries(); + unregister_reboot_notifier(&DAC960_NotifierBlock); + return NOTIFY_OK; +} + + +/* + DAC960_ProcessRequest attempts to remove one I/O Request from Controller's + I/O Request Queue and queues it to the Controller. WaitForCommand is true if + this function should wait for a Command to become available if necessary. + This function returns true if an I/O Request was queued and false otherwise. +*/ + +static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller, + boolean WaitForCommand) +{ + IO_Request_T **RequestQueuePointer = + &blk_dev[DAC960_MAJOR + Controller->ControllerNumber].current_request; + IO_Request_T *Request; + DAC960_Command_T *Command; + char *RequestBuffer; + while (true) + { + Request = *RequestQueuePointer; + if (Request == NULL || Request->rq_status == RQ_INACTIVE) return false; + Command = DAC960_AllocateCommand(Controller); + if (Command != NULL) break; + if (!WaitForCommand) return false; + spin_unlock(&io_request_lock); + sleep_on(&Controller->CommandWaitQueue); + spin_lock_irq(&io_request_lock); + } + DAC960_ClearCommand(Command); + if (Request->cmd == READ) + Command->CommandType = DAC960_ReadCommand; + else Command->CommandType = DAC960_WriteCommand; + Command->Semaphore = Request->sem; + Command->LogicalDriveNumber = DAC960_LogicalDriveNumber(Request->rq_dev); + Command->BlockNumber = + Request->sector + + Controller->GenericDiskInfo.part[MINOR(Request->rq_dev)].start_sect; + Command->BlockCount = Request->nr_sectors; + Command->SegmentCount = Request->nr_segments; + Command->BufferHeader = Request->bh; + RequestBuffer = Request->buffer; + Request->rq_status = RQ_INACTIVE; + *RequestQueuePointer = Request->next; + wake_up(&wait_for_request); + if (Command->SegmentCount == 1) + { + DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; + if (Command->CommandType == DAC960_ReadCommand) + CommandMailbox->Type5.CommandOpcode = DAC960_Read; + else CommandMailbox->Type5.CommandOpcode = DAC960_Write; + CommandMailbox->Type5.LD.TransferLength = Command->BlockCount; + CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber; + CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber; + CommandMailbox->Type5.BusAddress = Virtual_to_Bus(RequestBuffer); + } + else + { + DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; + DAC960_ScatterGatherSegment_T + *ScatterGatherList = Command->ScatterGatherList; + BufferHeader_T *BufferHeader = Command->BufferHeader; + char *LastDataEndPointer = NULL; + int SegmentNumber = 0; + if (Command->CommandType == DAC960_ReadCommand) + CommandMailbox->Type5.CommandOpcode = DAC960_ReadWithOldScatterGather; + else + CommandMailbox->Type5.CommandOpcode = DAC960_WriteWithOldScatterGather; + CommandMailbox->Type5.LD.TransferLength = Command->BlockCount; + CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber; + CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber; + CommandMailbox->Type5.BusAddress = Virtual_to_Bus(ScatterGatherList); + 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_Bus(BufferHeader->b_data); + ScatterGatherList[SegmentNumber].SegmentByteCount = + BufferHeader->b_size; + LastDataEndPointer = BufferHeader->b_data + BufferHeader->b_size; + if (SegmentNumber++ > Controller->MaxScatterGatherSegments) + panic("DAC960: Scatter/Gather Segment Overflow\n"); + } + BufferHeader = BufferHeader->b_reqnext; + } + if (SegmentNumber != Command->SegmentCount) + panic("DAC960: SegmentNumber != SegmentCount\n"); + } + DAC960_QueueCommand(Command); + return true; +} + + +/* + DAC960_ProcessRequests attempts to remove as many I/O Requests as possible + from Controller's I/O Request Queue and queue them to the Controller. +*/ + +static inline void DAC960_ProcessRequests(DAC960_Controller_T *Controller) +{ + int Counter = 0; + while (DAC960_ProcessRequest(Controller, Counter++ == 0)) ; +} + + +/* + DAC960_RequestFunction0 is the I/O Request Function for DAC960 Controller 0. +*/ + +static void DAC960_RequestFunction0(void) +{ + DAC960_Controller_T *Controller = DAC960_Controllers[0]; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); + /* + Process I/O Requests for Controller. + */ + DAC960_ProcessRequests(Controller); + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); +} + + +/* + DAC960_RequestFunction1 is the I/O Request Function for DAC960 Controller 1. +*/ + +static void DAC960_RequestFunction1(void) +{ + DAC960_Controller_T *Controller = DAC960_Controllers[1]; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); + /* + Process I/O Requests for Controller. + */ + DAC960_ProcessRequests(Controller); + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); +} + + +/* + DAC960_RequestFunction2 is the I/O Request Function for DAC960 Controller 2. +*/ + +static void DAC960_RequestFunction2(void) +{ + DAC960_Controller_T *Controller = DAC960_Controllers[2]; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); + /* + Process I/O Requests for Controller. + */ + DAC960_ProcessRequests(Controller); + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); +} + + +/* + DAC960_RequestFunction3 is the I/O Request Function for DAC960 Controller 3. +*/ + +static void DAC960_RequestFunction3(void) +{ + DAC960_Controller_T *Controller = DAC960_Controllers[3]; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); + /* + Process I/O Requests for Controller. + */ + DAC960_ProcessRequests(Controller); + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); +} + + +/* + DAC960_RequestFunction4 is the I/O Request Function for DAC960 Controller 4. +*/ + +static void DAC960_RequestFunction4(void) +{ + DAC960_Controller_T *Controller = DAC960_Controllers[4]; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); + /* + Process I/O Requests for Controller. + */ + DAC960_ProcessRequests(Controller); + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); +} + + +/* + DAC960_RequestFunction5 is the I/O Request Function for DAC960 Controller 5. +*/ + +static void DAC960_RequestFunction5(void) +{ + DAC960_Controller_T *Controller = DAC960_Controllers[5]; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); + /* + Process I/O Requests for Controller. + */ + DAC960_ProcessRequests(Controller); + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); +} + + +/* + DAC960_RequestFunction6 is the I/O Request Function for DAC960 Controller 6. +*/ + +static void DAC960_RequestFunction6(void) +{ + DAC960_Controller_T *Controller = DAC960_Controllers[6]; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); + /* + Process I/O Requests for Controller. + */ + DAC960_ProcessRequests(Controller); + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); +} + + +/* + DAC960_RequestFunction7 is the I/O Request Function for DAC960 Controller 7. +*/ + +static void DAC960_RequestFunction7(void) +{ + DAC960_Controller_T *Controller = DAC960_Controllers[7]; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); + /* + Process I/O Requests for Controller. + */ + DAC960_ProcessRequests(Controller); + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); +} + + +/* + DAC960_ReadWriteError prints an appropriate error message for Command when + an error occurs on a Read or Write operation. +*/ + +static void DAC960_ReadWriteError(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + char *CommandName = "UNKNOWN"; + switch (Command->CommandType) + { + case DAC960_ReadCommand: + case DAC960_ReadRetryCommand: + CommandName = "READ"; + break; + case DAC960_WriteCommand: + case DAC960_WriteRetryCommand: + CommandName = "WRITE"; + break; + case DAC960_MonitoringCommand: + case DAC960_ImmediateCommand: + case DAC960_QueuedCommand: + break; + } + switch (Command->CommandStatus) + { + case DAC960_IrrecoverableDataError: + DAC960_Error("Irrecoverable Data Error on %s:\n", + Controller, CommandName); + break; + case DAC960_LogicalDriveNonexistentOrOffline: + DAC960_Error("Logical Drive Nonexistent or Offline on %s:\n", + Controller, CommandName); + break; + case DAC960_AccessBeyondEndOfLogicalDrive: + DAC960_Error("Attempt to Access Beyond End of Logical Drive " + "on %s:\n", Controller, CommandName); + break; + case DAC960_BadDataEncountered: + DAC960_Error("Bad Data Encountered on %s:\n", Controller, CommandName); + break; + default: + DAC960_Error("Unexpected Error Status %04X on %s:\n", + Controller, Command->CommandStatus, CommandName); + break; + } + DAC960_Error(" /dev/rd/c%dd%d: absolute blocks %d..%d\n", + Controller, Controller->ControllerNumber, + Command->LogicalDriveNumber, Command->BlockNumber, + Command->BlockNumber + Command->BlockCount - 1); + if (DAC960_PartitionNumber(Command->BufferHeader->b_rdev) > 0) + DAC960_Error(" /dev/rd/c%dd%dp%d: relative blocks %d..%d\n", + Controller, Controller->ControllerNumber, + Command->LogicalDriveNumber, + DAC960_PartitionNumber(Command->BufferHeader->b_rdev), + Command->BufferHeader->b_rsector, + Command->BufferHeader->b_rsector + Command->BlockCount - 1); +} + + +/* + DAC960_ProcessCompletedBuffer performs completion processing for an + individual Buffer. +*/ + +static inline void DAC960_ProcessCompletedBuffer(BufferHeader_T *BufferHeader, + boolean SuccessfulIO) +{ + BufferHeader->b_end_io(BufferHeader, SuccessfulIO); +} + + +/* + DAC960_ProcessCompletedCommand performs completion processing for Command. +*/ + +static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + DAC960_CommandType_T CommandType = Command->CommandType; + DAC960_CommandOpcode_T CommandOpcode = + Command->CommandMailbox.Common.CommandOpcode; + DAC960_CommandStatus_T CommandStatus = Command->CommandStatus; + BufferHeader_T *BufferHeader = Command->BufferHeader; + if (CommandType == DAC960_ReadCommand || + CommandType == DAC960_WriteCommand) + { + if (CommandStatus == DAC960_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; + } + /* + Wake up requestor for swap file paging requests. + */ + if (Command->Semaphore != NULL) + { + up(Command->Semaphore); + Command->Semaphore = NULL; + } + add_blkdev_randomness(DAC960_MAJOR + Controller->ControllerNumber); + } + else if ((CommandStatus == DAC960_IrrecoverableDataError || + CommandStatus == DAC960_BadDataEncountered) && + BufferHeader != NULL && + BufferHeader->b_reqnext != NULL) + { + DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; + if (CommandType == DAC960_ReadCommand) + { + Command->CommandType = DAC960_ReadRetryCommand; + CommandMailbox->Type5.CommandOpcode = DAC960_Read; + } + else + { + Command->CommandType = DAC960_WriteRetryCommand; + CommandMailbox->Type5.CommandOpcode = DAC960_Write; + } + Command->BlockCount = BufferHeader->b_size >> DAC960_BlockSizeBits; + CommandMailbox->Type5.LD.TransferLength = Command->BlockCount; + CommandMailbox->Type5.BusAddress = + Virtual_to_Bus(BufferHeader->b_data); + DAC960_QueueCommand(Command); + return; + } + else + { + if (CommandStatus != DAC960_LogicalDriveNonexistentOrOffline) + DAC960_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; + } + /* + Wake up requestor for swap file paging requests. + */ + if (Command->Semaphore != NULL) + { + up(Command->Semaphore); + Command->Semaphore = NULL; + } + } + } + else if (CommandType == DAC960_ReadRetryCommand || + CommandType == DAC960_WriteRetryCommand) + { + BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext; + BufferHeader->b_reqnext = NULL; + /* + Perform completion processing for this single buffer. + */ + if (CommandStatus == DAC960_NormalCompletion) + DAC960_ProcessCompletedBuffer(BufferHeader, true); + else + { + if (CommandStatus != DAC960_LogicalDriveNonexistentOrOffline) + DAC960_ReadWriteError(Command); + DAC960_ProcessCompletedBuffer(BufferHeader, false); + } + if (NextBufferHeader != NULL) + { + DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; + Command->BlockNumber += + BufferHeader->b_size >> DAC960_BlockSizeBits; + Command->BlockCount = + NextBufferHeader->b_size >> DAC960_BlockSizeBits; + Command->BufferHeader = NextBufferHeader; + CommandMailbox->Type5.LD.TransferLength = Command->BlockCount; + CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber; + CommandMailbox->Type5.BusAddress = + Virtual_to_Bus(NextBufferHeader->b_data); + DAC960_QueueCommand(Command); + return; + } + } + else if (CommandType == DAC960_MonitoringCommand || + CommandOpcode == DAC960_Enquiry || + CommandOpcode == DAC960_GetRebuildProgress) + { + if (CommandType != DAC960_MonitoringCommand) + { + if (CommandOpcode == DAC960_Enquiry) + memcpy(&Controller->Enquiry[Controller->EnquiryIndex ^ 1], + Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress), + sizeof(DAC960_Enquiry_T)); + else if (CommandOpcode == DAC960_GetRebuildProgress) + memcpy(&Controller->RebuildProgress, + Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress), + sizeof(DAC960_RebuildProgress_T)); + } + if (CommandOpcode == DAC960_Enquiry) + { + DAC960_Enquiry_T *OldEnquiry = + &Controller->Enquiry[Controller->EnquiryIndex]; + DAC960_Enquiry_T *NewEnquiry = + &Controller->Enquiry[Controller->EnquiryIndex ^= 1]; + unsigned int OldCriticalLogicalDriveCount = + OldEnquiry->CriticalLogicalDriveCount; + unsigned int NewCriticalLogicalDriveCount = + NewEnquiry->CriticalLogicalDriveCount; + if (NewEnquiry->StatusFlags.DeferredWriteError != + OldEnquiry->StatusFlags.DeferredWriteError) + DAC960_Critical("Deferred Write Error Flag is now %s\n", Controller, + (NewEnquiry->StatusFlags.DeferredWriteError + ? "TRUE" : "FALSE")); + if ((NewCriticalLogicalDriveCount > 0 || + NewCriticalLogicalDriveCount != OldCriticalLogicalDriveCount) || + (NewEnquiry->OfflineLogicalDriveCount > 0 || + NewEnquiry->OfflineLogicalDriveCount != + OldEnquiry->OfflineLogicalDriveCount) || + (NewEnquiry->DeadDriveCount > 0 || + NewEnquiry->DeadDriveCount != + OldEnquiry->DeadDriveCount) || + (NewEnquiry->EventLogSequenceNumber != + OldEnquiry->EventLogSequenceNumber) || + Controller->MonitoringTimerCount == 0 || + (jiffies - Controller->SecondaryMonitoringTime + >= DAC960_SecondaryMonitoringInterval)) + { + Controller->NeedLogicalDriveInformation = true; + Controller->NewEventLogSequenceNumber = + NewEnquiry->EventLogSequenceNumber; + Controller->NeedErrorTableInformation = true; + Controller->NeedDeviceStateInformation = true; + Controller->DeviceStateChannel = 0; + Controller->DeviceStateTargetID = 0; + Controller->SecondaryMonitoringTime = jiffies; + } + if (NewEnquiry->RebuildFlag == DAC960_StandbyRebuildInProgress || + NewEnquiry->RebuildFlag == DAC960_BackgroundRebuildInProgress || + OldEnquiry->RebuildFlag == DAC960_StandbyRebuildInProgress || + OldEnquiry->RebuildFlag == DAC960_BackgroundRebuildInProgress) + Controller->NeedRebuildProgress = true; + if (OldEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress) + switch (NewEnquiry->RebuildFlag) + { + case DAC960_NoStandbyRebuildOrCheckInProgress: + DAC960_Progress("Consistency Check Completed Successfully\n", + Controller); + break; + case DAC960_StandbyRebuildInProgress: + case DAC960_BackgroundRebuildInProgress: + break; + case DAC960_BackgroundCheckInProgress: + Controller->NeedConsistencyCheckProgress = true; + break; + case DAC960_StandbyRebuildCompletedWithError: + DAC960_Progress("Consistency Check Completed with Error\n", + Controller); + break; + case DAC960_BackgroundRebuildOrCheckFailed_DriveFailed: + DAC960_Progress("Consistency Check Failed - " + "Physical Drive Failed\n", Controller); + break; + case DAC960_BackgroundRebuildOrCheckFailed_LogicalDriveFailed: + DAC960_Progress("Consistency Check Failed - " + "Logical Drive Failed\n", Controller); + break; + case DAC960_BackgroundRebuildOrCheckFailed_OtherCauses: + DAC960_Progress("Consistency Check Failed - Other Causes\n", + Controller); + break; + case DAC960_BackgroundRebuildOrCheckSuccessfullyTerminated: + DAC960_Progress("Consistency Check Successfully Terminated\n", + Controller); + break; + } + else if (NewEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress) + Controller->NeedConsistencyCheckProgress = true; + } + else if (CommandOpcode == DAC960_PerformEventLogOperation) + { + static char + *DAC960_EventMessages[] = + { "killed because write recovery failed", + "killed because of SCSI bus reset failure", + "killed because of double check condition", + "killed because it was removed", + "killed because of gross error on SCSI chip", + "killed because of bad tag returned from drive", + "killed because of timeout on SCSI command", + "killed because of reset SCSI command issued from system", + "killed because busy or parity error count exceeded limit", + "killed because of 'kill drive' command from system", + "killed because of selection timeout", + "killed due to SCSI phase sequence error", + "killed due to unknown status" }; + DAC960_EventLogEntry_T *EventLogEntry = &Controller->EventLogEntry; + if (EventLogEntry->SequenceNumber == + Controller->OldEventLogSequenceNumber) + { + unsigned char SenseKey = EventLogEntry->SenseKey; + unsigned char AdditionalSenseCode = + EventLogEntry->AdditionalSenseCode; + unsigned char AdditionalSenseCodeQualifier = + EventLogEntry->AdditionalSenseCodeQualifier; + if (SenseKey == 9 && + AdditionalSenseCode == 0x80 && + AdditionalSenseCodeQualifier < + sizeof(DAC960_EventMessages) / sizeof(char *)) + DAC960_Critical("Physical Drive %d:%d %s\n", Controller, + EventLogEntry->Channel, + EventLogEntry->TargetID, + DAC960_EventMessages[ + AdditionalSenseCodeQualifier]); + else if (!(SenseKey == 0 || + (SenseKey == 2 && + AdditionalSenseCode == 0x04 && + (AdditionalSenseCodeQualifier == 0x01 || + AdditionalSenseCodeQualifier == 0x02)) || + (SenseKey == 6 && AdditionalSenseCode == 0x29 && + Controller->MonitoringTimerCount == 0))) + { + DAC960_Critical("Physical Drive %d:%d Error Log: " + "Sense Key = %d, ASC = %02X, ASCQ = %02X\n", + Controller, + EventLogEntry->Channel, + EventLogEntry->TargetID, + SenseKey, + AdditionalSenseCode, + AdditionalSenseCodeQualifier); + DAC960_Critical("Physical Drive %d:%d Error Log: " + "Information = %02X%02X%02X%02X " + "%02X%02X%02X%02X\n", + Controller, + EventLogEntry->Channel, + EventLogEntry->TargetID, + EventLogEntry->Information[0], + EventLogEntry->Information[1], + EventLogEntry->Information[2], + EventLogEntry->Information[3], + EventLogEntry->CommandSpecificInformation[0], + EventLogEntry->CommandSpecificInformation[1], + EventLogEntry->CommandSpecificInformation[2], + EventLogEntry->CommandSpecificInformation[3]); + } + } + Controller->OldEventLogSequenceNumber++; + } + else if (CommandOpcode == DAC960_GetErrorTable) + { + DAC960_ErrorTable_T *OldErrorTable = + &Controller->ErrorTable[Controller->ErrorTableIndex]; + DAC960_ErrorTable_T *NewErrorTable = + &Controller->ErrorTable[Controller->ErrorTableIndex ^= 1]; + int Channel, TargetID; + for (Channel = 0; Channel < Controller->Channels; Channel++) + for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++) + { + DAC960_ErrorTableEntry_T *NewErrorEntry = + &NewErrorTable->ErrorTableEntries[Channel][TargetID]; + DAC960_ErrorTableEntry_T *OldErrorEntry = + &OldErrorTable->ErrorTableEntries[Channel][TargetID]; + if ((NewErrorEntry->ParityErrorCount != + OldErrorEntry->ParityErrorCount) || + (NewErrorEntry->SoftErrorCount != + OldErrorEntry->SoftErrorCount) || + (NewErrorEntry->HardErrorCount != + OldErrorEntry->HardErrorCount) || + (NewErrorEntry->MiscErrorCount != + OldErrorEntry->MiscErrorCount)) + DAC960_Critical("Physical Drive %d:%d Errors: " + "Parity = %d, Soft = %d, " + "Hard = %d, Misc = %d\n", + Controller, Channel, TargetID, + NewErrorEntry->ParityErrorCount, + NewErrorEntry->SoftErrorCount, + NewErrorEntry->HardErrorCount, + NewErrorEntry->MiscErrorCount); + } + } + else if (CommandOpcode == DAC960_GetDeviceState) + { + DAC960_DeviceState_T *OldDeviceState = + &Controller->DeviceState[Controller->DeviceStateIndex] + [Controller->DeviceStateChannel] + [Controller->DeviceStateTargetID]; + DAC960_DeviceState_T *NewDeviceState = + &Controller->DeviceState[Controller->DeviceStateIndex ^ 1] + [Controller->DeviceStateChannel] + [Controller->DeviceStateTargetID]; + if (NewDeviceState->DeviceState != OldDeviceState->DeviceState) + DAC960_Critical("Physical Drive %d:%d is now %s\n", Controller, + Controller->DeviceStateChannel, + Controller->DeviceStateTargetID, + (NewDeviceState->DeviceState == DAC960_Device_Dead + ? "DEAD" + : NewDeviceState->DeviceState + == DAC960_Device_WriteOnly + ? "WRITE-ONLY" + : NewDeviceState->DeviceState + == DAC960_Device_Online + ? "ONLINE" : "STANDBY")); + if (++Controller->DeviceStateTargetID == DAC960_MaxTargets) + { + Controller->DeviceStateChannel++; + Controller->DeviceStateTargetID = 0; + } + } + else if (CommandOpcode == DAC960_GetLogicalDriveInformation) + { + int LogicalDriveNumber; + for (LogicalDriveNumber = 0; + LogicalDriveNumber < Controller->LogicalDriveCount; + LogicalDriveNumber++) + { + DAC960_LogicalDriveInformation_T *OldLogicalDriveInformation = + &Controller->LogicalDriveInformation + [Controller->LogicalDriveInformationIndex] + [LogicalDriveNumber]; + DAC960_LogicalDriveInformation_T *NewLogicalDriveInformation = + &Controller->LogicalDriveInformation + [Controller->LogicalDriveInformationIndex ^ 1] + [LogicalDriveNumber]; + if (NewLogicalDriveInformation->LogicalDriveState != + OldLogicalDriveInformation->LogicalDriveState) + DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) " + "is now %s\n", Controller, + LogicalDriveNumber, + Controller->ControllerNumber, + LogicalDriveNumber, + (NewLogicalDriveInformation->LogicalDriveState + == DAC960_LogicalDrive_Online + ? "ONLINE" + : NewLogicalDriveInformation->LogicalDriveState + == DAC960_LogicalDrive_Critical + ? "CRITICAL" : "OFFLINE")); + if (NewLogicalDriveInformation->WriteBack != + OldLogicalDriveInformation->WriteBack) + DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) " + "is now %s\n", Controller, + LogicalDriveNumber, + Controller->ControllerNumber, + LogicalDriveNumber, + (NewLogicalDriveInformation->WriteBack + ? "WRITE BACK" : "WRITE THRU")); + } + Controller->LogicalDriveInformationIndex ^= 1; + } + else if (CommandOpcode == DAC960_GetRebuildProgress) + { + unsigned int LogicalDriveNumber = + Controller->RebuildProgress.LogicalDriveNumber; + unsigned int LogicalDriveSize = + Controller->RebuildProgress.LogicalDriveSize; + unsigned int BlocksCompleted = + LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks; + switch (CommandStatus) + { + case DAC960_NormalCompletion: + Controller->EphemeralProgressMessage = true; + DAC960_Progress("Rebuild in Progress: " + "Logical Drive %d (/dev/rd/c%dd%d) " + "%d%% completed\n", + Controller, LogicalDriveNumber, + Controller->ControllerNumber, + LogicalDriveNumber, + (100 * (BlocksCompleted >> 7)) + / (LogicalDriveSize >> 7)); + Controller->EphemeralProgressMessage = false; + break; + case DAC960_RebuildFailed_LogicalDriveFailure: + DAC960_Progress("Rebuild Failed due to " + "Logical Drive Failure\n", Controller); + break; + case DAC960_RebuildFailed_BadBlocksOnOther: + DAC960_Progress("Rebuild Failed due to " + "Bad Blocks on Other Drives\n", Controller); + break; + case DAC960_RebuildFailed_NewDriveFailed: + DAC960_Progress("Rebuild Failed due to " + "Failure of Drive Being Rebuilt\n", Controller); + break; + case DAC960_NoRebuildOrCheckInProgress: + if (Controller->LastRebuildStatus != DAC960_NormalCompletion) + break; + case DAC960_RebuildSuccessful: + DAC960_Progress("Rebuild Completed Successfully\n", Controller); + break; + } + Controller->LastRebuildStatus = CommandStatus; + } + else if (CommandOpcode == DAC960_RebuildStat) + { + unsigned int LogicalDriveNumber = + Controller->RebuildProgress.LogicalDriveNumber; + unsigned int LogicalDriveSize = + Controller->RebuildProgress.LogicalDriveSize; + unsigned int BlocksCompleted = + LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks; + if (CommandStatus == DAC960_NormalCompletion) + { + Controller->EphemeralProgressMessage = true; + DAC960_Progress("Consistency Check in Progress: " + "Logical Drive %d (/dev/rd/c%dd%d) " + "%d%% completed\n", + Controller, LogicalDriveNumber, + Controller->ControllerNumber, + LogicalDriveNumber, + (100 * (BlocksCompleted >> 7)) + / (LogicalDriveSize >> 7)); + Controller->EphemeralProgressMessage = false; + } + } + } + if (CommandType == DAC960_MonitoringCommand) + { + if (Controller->NewEventLogSequenceNumber + - Controller->OldEventLogSequenceNumber > 0) + { + Command->CommandMailbox.Type3E.CommandOpcode = + DAC960_PerformEventLogOperation; + Command->CommandMailbox.Type3E.OperationType = + DAC960_GetEventLogEntry; + Command->CommandMailbox.Type3E.OperationQualifier = 1; + Command->CommandMailbox.Type3E.SequenceNumber = + Controller->OldEventLogSequenceNumber; + Command->CommandMailbox.Type3E.BusAddress = + Virtual_to_Bus(&Controller->EventLogEntry); + DAC960_QueueCommand(Command); + return; + } + if (Controller->NeedErrorTableInformation) + { + Controller->NeedErrorTableInformation = false; + Command->CommandMailbox.Type3.CommandOpcode = DAC960_GetErrorTable; + Command->CommandMailbox.Type3.BusAddress = + Virtual_to_Bus( + &Controller->ErrorTable[Controller->ErrorTableIndex ^ 1]); + DAC960_QueueCommand(Command); + return; + } + if (Controller->NeedRebuildProgress && + Controller->Enquiry[Controller->EnquiryIndex] + .CriticalLogicalDriveCount < + Controller->Enquiry[Controller->EnquiryIndex ^ 1] + .CriticalLogicalDriveCount) + { + Controller->NeedRebuildProgress = false; + Command->CommandMailbox.Type3.CommandOpcode = + DAC960_GetRebuildProgress; + Command->CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&Controller->RebuildProgress); + DAC960_QueueCommand(Command); + return; + } + if (Controller->NeedDeviceStateInformation) + { + while (Controller->DeviceStateChannel < Controller->Channels) + { + DAC960_DeviceState_T *OldDeviceState = + &Controller->DeviceState[Controller->DeviceStateIndex] + [Controller->DeviceStateChannel] + [Controller->DeviceStateTargetID]; + if (OldDeviceState->Present && + OldDeviceState->DeviceType == DAC960_DiskType) + { + Command->CommandMailbox.Type3D.CommandOpcode = + DAC960_GetDeviceState; + Command->CommandMailbox.Type3D.Channel = + Controller->DeviceStateChannel; + Command->CommandMailbox.Type3D.TargetID = + Controller->DeviceStateTargetID; + Command->CommandMailbox.Type3D.BusAddress = + Virtual_to_Bus(&Controller->DeviceState + [Controller->DeviceStateIndex ^ 1] + [Controller->DeviceStateChannel] + [Controller->DeviceStateTargetID]); + DAC960_QueueCommand(Command); + return; + } + if (++Controller->DeviceStateTargetID == DAC960_MaxTargets) + { + Controller->DeviceStateChannel++; + Controller->DeviceStateTargetID = 0; + } + } + Controller->NeedDeviceStateInformation = false; + Controller->DeviceStateIndex ^= 1; + } + if (Controller->NeedLogicalDriveInformation) + { + Controller->NeedLogicalDriveInformation = false; + Command->CommandMailbox.Type3.CommandOpcode = + DAC960_GetLogicalDriveInformation; + Command->CommandMailbox.Type3.BusAddress = + Virtual_to_Bus( + &Controller->LogicalDriveInformation + [Controller->LogicalDriveInformationIndex ^ 1]); + DAC960_QueueCommand(Command); + return; + } + if (Controller->NeedRebuildProgress) + { + Controller->NeedRebuildProgress = false; + Command->CommandMailbox.Type3.CommandOpcode = + DAC960_GetRebuildProgress; + Command->CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&Controller->RebuildProgress); + DAC960_QueueCommand(Command); + return; + } + if (Controller->NeedConsistencyCheckProgress) + { + Controller->NeedConsistencyCheckProgress = false; + Command->CommandMailbox.Type3.CommandOpcode = DAC960_RebuildStat; + Command->CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&Controller->RebuildProgress); + DAC960_QueueCommand(Command); + return; + } + Controller->MonitoringTimerCount++; + Controller->MonitoringTimer.expires = + jiffies + DAC960_MonitoringTimerInterval; + add_timer(&Controller->MonitoringTimer); + } + if (CommandType == DAC960_ImmediateCommand) + { + up(Command->Semaphore); + Command->Semaphore = NULL; + return; + } + if (CommandType == DAC960_QueuedCommand) + { + DAC960_KernelCommand_T *KernelCommand = Command->KernelCommand; + KernelCommand->CommandStatus = CommandStatus; + Command->KernelCommand = NULL; + if (CommandOpcode == DAC960_DCDB) + Controller->DirectCommandActive[KernelCommand->DCDB->Channel] + [KernelCommand->DCDB->TargetID] = false; + DAC960_DeallocateCommand(Command); + KernelCommand->CompletionFunction(KernelCommand); + return; + } + /* + Queue a Status Monitoring Command to the Controller using the just + completed Command if one was deferred previously due to lack of a + free Command when the Monitoring Timer Function was called. + */ + if (Controller->MonitoringCommandDeferred) + { + Controller->MonitoringCommandDeferred = false; + DAC960_QueueMonitoringCommand(Command); + return; + } + /* + Deallocate the Command, and wake up any processes waiting on a free Command. + */ + DAC960_DeallocateCommand(Command); + wake_up(&Controller->CommandWaitQueue); +} + + +/* + DAC960_InterruptHandler handles hardware interrupts from DAC960 Controllers. +*/ + +static void DAC960_InterruptHandler(int IRQ_Channel, + void *DeviceIdentifier, + Registers_T *InterruptRegisters) +{ + DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_StatusMailbox_T *NextStatusMailbox; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); + /* + Process Hardware Interrupts for Controller. + */ + switch (Controller->ControllerType) + { + case DAC960_V5_Controller: + DAC960_V5_AcknowledgeInterrupt(ControllerBaseAddress); + NextStatusMailbox = Controller->NextStatusMailbox; + while (NextStatusMailbox->Fields.Valid) + { + DAC960_CommandIdentifier_T CommandIdentifier = + NextStatusMailbox->Fields.CommandIdentifier; + DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier]; + Command->CommandStatus = NextStatusMailbox->Fields.CommandStatus; + NextStatusMailbox->Word = 0; + if (++NextStatusMailbox > Controller->LastStatusMailbox) + NextStatusMailbox = Controller->FirstStatusMailbox; + DAC960_ProcessCompletedCommand(Command); + } + Controller->NextStatusMailbox = NextStatusMailbox; + break; + case DAC960_V4_Controller: + DAC960_V4_AcknowledgeInterrupt(ControllerBaseAddress); + NextStatusMailbox = Controller->NextStatusMailbox; + while (NextStatusMailbox->Fields.Valid) + { + DAC960_CommandIdentifier_T CommandIdentifier = + NextStatusMailbox->Fields.CommandIdentifier; + DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier]; + Command->CommandStatus = NextStatusMailbox->Fields.CommandStatus; + NextStatusMailbox->Word = 0; + if (++NextStatusMailbox > Controller->LastStatusMailbox) + NextStatusMailbox = Controller->FirstStatusMailbox; + DAC960_ProcessCompletedCommand(Command); + } + Controller->NextStatusMailbox = NextStatusMailbox; + break; + case DAC960_V3_Controller: + while (DAC960_V3_StatusAvailableP(ControllerBaseAddress)) + { + DAC960_CommandIdentifier_T CommandIdentifier = + DAC960_V3_ReadStatusCommandIdentifier(ControllerBaseAddress); + DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier]; + Command->CommandStatus = + DAC960_V3_ReadStatusRegister(ControllerBaseAddress); + DAC960_V3_AcknowledgeInterrupt(ControllerBaseAddress); + DAC960_V3_AcknowledgeStatus(ControllerBaseAddress); + DAC960_ProcessCompletedCommand(Command); + } + break; + } + /* + Attempt to remove additional I/O Requests from the Controller's + I/O Request Queue and queue them to the Controller. + */ + while (DAC960_ProcessRequest(Controller, false)) ; + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); +} + + +/* + DAC960_QueueMonitoringCommand queues a Monitoring Command to Controller. +*/ + +static void DAC960_QueueMonitoringCommand(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; + DAC960_ClearCommand(Command); + Command->CommandType = DAC960_MonitoringCommand; + CommandMailbox->Type3.CommandOpcode = DAC960_Enquiry; + CommandMailbox->Type3.BusAddress = + Virtual_to_Bus(&Controller->Enquiry[Controller->EnquiryIndex ^ 1]); + DAC960_QueueCommand(Command); +} + + +/* + DAC960_MonitoringTimerFunction is the timer function for monitoring + the status of DAC960 Controllers. +*/ + +static void DAC960_MonitoringTimerFunction(unsigned long TimerData) +{ + DAC960_Controller_T *Controller = (DAC960_Controller_T *) TimerData; + DAC960_Command_T *Command; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + /* + Queue a Status Monitoring Command to Controller. + */ + Command = DAC960_AllocateCommand(Controller); + if (Command != NULL) + DAC960_QueueMonitoringCommand(Command); + else Controller->MonitoringCommandDeferred = true; + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); +} + + +/* + DAC960_Open is the Device Open Function for the DAC960 Driver. +*/ + +static int DAC960_Open(Inode_T *Inode, File_T *File) +{ + int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev); + int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev); + DAC960_Controller_T *Controller; + if (ControllerNumber == 0 && LogicalDriveNumber == 0 && + (File->f_flags & O_NONBLOCK)) + goto ModuleOnly; + if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1) + return -ENXIO; + Controller = DAC960_Controllers[ControllerNumber]; + if (Controller == NULL || + LogicalDriveNumber > Controller->LogicalDriveCount - 1) + return -ENXIO; + if (Controller->LogicalDriveInformation + [Controller->LogicalDriveInformationIndex] + [LogicalDriveNumber].LogicalDriveState + == DAC960_LogicalDrive_Offline) + return -ENXIO; + if (Controller->LogicalDriveInitialState[LogicalDriveNumber] + == DAC960_LogicalDrive_Offline) + { + Controller->LogicalDriveInitialState[LogicalDriveNumber] = + DAC960_LogicalDrive_Online; + DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo); + resetup_one_dev(&Controller->GenericDiskInfo, LogicalDriveNumber); + } + if (Controller->GenericDiskInfo.sizes[MINOR(Inode->i_rdev)] == 0) + return -ENXIO; + /* + Increment Controller and Logical Drive Usage Counts. + */ + Controller->ControllerUsageCount++; + Controller->LogicalDriveUsageCount[LogicalDriveNumber]++; + ModuleOnly: + MOD_INC_USE_COUNT; + return 0; +} + + +/* + DAC960_Release is the Device Release Function for the DAC960 Driver. +*/ + +static int DAC960_Release(Inode_T *Inode, File_T *File) +{ + int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev); + int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev); + DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; + if (ControllerNumber == 0 && LogicalDriveNumber == 0 && + File != NULL && (File->f_flags & O_NONBLOCK)) + goto ModuleOnly; + /* + Force any buffered data to be written. + */ + fsync_dev(Inode->i_rdev); + /* + Decrement the Logical Drive and Controller Usage Counts. + */ + Controller->LogicalDriveUsageCount[LogicalDriveNumber]--; + Controller->ControllerUsageCount--; + ModuleOnly: + MOD_DEC_USE_COUNT; + return 0; +} + + +/* + DAC960_IOCTL is the Device IOCTL Function for the DAC960 Driver. +*/ + +static int DAC960_IOCTL(Inode_T *Inode, File_T *File, + unsigned int Request, unsigned long Argument) +{ + int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev); + int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev); + DiskGeometry_T Geometry, *UserGeometry; + DAC960_Controller_T *Controller; + int PartitionNumber; + if (File->f_flags & O_NONBLOCK) + return DAC960_UserIOCTL(Inode, File, Request, Argument); + if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1) + return -ENXIO; + Controller = DAC960_Controllers[ControllerNumber]; + if (Controller == NULL || + LogicalDriveNumber > Controller->LogicalDriveCount - 1) + return -ENXIO; + switch (Request) + { + case HDIO_GETGEO: + /* Get BIOS Disk Geometry. */ + UserGeometry = (DiskGeometry_T *) Argument; + if (UserGeometry == NULL) return -EINVAL; + Geometry.heads = Controller->GeometryTranslationHeads; + Geometry.sectors = Controller->GeometryTranslationSectors; + Geometry.cylinders = + Controller->LogicalDriveInformation + [Controller->LogicalDriveInformationIndex] + [LogicalDriveNumber].LogicalDriveSize + / (Controller->GeometryTranslationHeads * + Controller->GeometryTranslationSectors); + Geometry.start = Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)] + .start_sect; + return copy_to_user(UserGeometry, &Geometry, sizeof(DiskGeometry_T)); + case BLKGETSIZE: + /* Get Device Size. */ + if ((long *) Argument == NULL) return -EINVAL; + return put_user(Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)] + .nr_sects, + (long *) Argument); + case BLKRAGET: + /* Get Read-Ahead. */ + if ((int *) Argument == NULL) return -EINVAL; + return put_user(read_ahead[MAJOR(Inode->i_rdev)], (int *) Argument); + case BLKRASET: + /* Set Read-Ahead. */ + if (!capable(CAP_SYS_ADMIN)) return -EACCES; + if (Argument > 256) return -EINVAL; + read_ahead[MAJOR(Inode->i_rdev)] = Argument; + return 0; + case BLKFLSBUF: + /* Flush Buffers. */ + if (!capable(CAP_SYS_ADMIN)) return -EACCES; + fsync_dev(Inode->i_rdev); + invalidate_buffers(Inode->i_rdev); + return 0; + case BLKRRPART: + /* Re-Read Partition Table. */ + if (!capable(CAP_SYS_ADMIN)) return -EACCES; + if (Controller->LogicalDriveUsageCount[LogicalDriveNumber] > 1) + return -EBUSY; + for (PartitionNumber = 0; + PartitionNumber < DAC960_MaxPartitions; + PartitionNumber++) + { + KernelDevice_T Device = DAC960_KernelDevice(ControllerNumber, + LogicalDriveNumber, + PartitionNumber); + int MinorNumber = DAC960_MinorNumber(LogicalDriveNumber, + PartitionNumber); + SuperBlock_T *SuperBlock = get_super(Device); + if (Controller->GenericDiskInfo.part[MinorNumber].nr_sects == 0) + continue; + /* + Flush all changes and invalidate buffered state. + */ + sync_dev(Device); + if (SuperBlock != NULL) + invalidate_inodes(SuperBlock); + invalidate_buffers(Device); + /* + Clear existing partition sizes. + */ + if (PartitionNumber > 0) + { + Controller->GenericDiskInfo.part[MinorNumber].start_sect = 0; + Controller->GenericDiskInfo.part[MinorNumber].nr_sects = 0; + } + /* + Reset the Block Size so that the partition table can be read. + */ + set_blocksize(Device, BLOCK_SIZE); + } + resetup_one_dev(&Controller->GenericDiskInfo, LogicalDriveNumber); + return 0; + } + return -EINVAL; +} + + +/* + DAC960_UserIOCTL is the User IOCTL Function for the DAC960 Driver. +*/ + +static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File, + unsigned int Request, unsigned long Argument) +{ + int ErrorCode; + if (!capable(CAP_SYS_ADMIN)) return -EACCES; + switch (Request) + { + case DAC960_IOCTL_GET_CONTROLLER_COUNT: + return DAC960_ControllerCount; + case DAC960_IOCTL_GET_CONTROLLER_INFO: + { + DAC960_ControllerInfo_T *UserSpaceControllerInfo = + (DAC960_ControllerInfo_T *) Argument; + DAC960_ControllerInfo_T ControllerInfo; + DAC960_Controller_T *Controller; + int ControllerNumber; + if (UserSpaceControllerInfo == NULL) return -EINVAL; + ErrorCode = get_user(ControllerNumber, + &UserSpaceControllerInfo->ControllerNumber); + if (ErrorCode != 0) return ErrorCode; + 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.PCI_Bus = Controller->Bus; + ControllerInfo.PCI_Device = Controller->Device; + ControllerInfo.PCI_Function = Controller->Function; + ControllerInfo.IRQ_Channel = Controller->IRQ_Channel; + ControllerInfo.Channels = Controller->Channels; + ControllerInfo.PCI_Address = Controller->PCI_Address; + strcpy(ControllerInfo.ModelName, Controller->ModelName); + strcpy(ControllerInfo.FirmwareVersion, Controller->FirmwareVersion); + return copy_to_user(UserSpaceControllerInfo, &ControllerInfo, + sizeof(DAC960_ControllerInfo_T)); + } + case DAC960_IOCTL_EXECUTE_COMMAND: + { + DAC960_UserCommand_T *UserSpaceUserCommand = + (DAC960_UserCommand_T *) Argument; + DAC960_UserCommand_T UserCommand; + DAC960_Controller_T *Controller; + DAC960_Command_T *Command = NULL; + DAC960_CommandOpcode_T CommandOpcode; + DAC960_CommandStatus_T CommandStatus; + DAC960_DCDB_T DCDB; + ProcessorFlags_T ProcessorFlags; + int ControllerNumber, DataTransferLength; + unsigned char *DataTransferBuffer = NULL; + if (UserSpaceUserCommand == NULL) return -EINVAL; + ErrorCode = copy_from_user(&UserCommand, UserSpaceUserCommand, + sizeof(DAC960_UserCommand_T)); + if (ErrorCode != 0) goto Failure; + ControllerNumber = UserCommand.ControllerNumber; + if (ControllerNumber < 0 || + ControllerNumber > DAC960_ControllerCount - 1) + return -ENXIO; + Controller = DAC960_Controllers[ControllerNumber]; + if (Controller == NULL) + return -ENXIO; + CommandOpcode = UserCommand.CommandMailbox.Common.CommandOpcode; + DataTransferLength = UserCommand.DataTransferLength; + if (CommandOpcode & 0x80) return -EINVAL; + if (CommandOpcode == DAC960_DCDB) + { + ErrorCode = + copy_from_user(&DCDB, UserCommand.DCDB, sizeof(DAC960_DCDB_T)); + if (ErrorCode != 0) goto Failure; + if (!((DataTransferLength == 0 && + DCDB.Direction == DAC960_DCDB_NoDataTransfer) || + (DataTransferLength > 0 && + DCDB.Direction == DAC960_DCDB_DataTransferDeviceToSystem) || + (DataTransferLength < 0 && + DCDB.Direction == DAC960_DCDB_DataTransferSystemToDevice))) + return -EINVAL; + if (((DCDB.TransferLengthHigh4 << 16) | DCDB.TransferLength) + != abs(DataTransferLength)) + return -EINVAL; + } + if (DataTransferLength > 0) + { + DataTransferBuffer = kmalloc(DataTransferLength, GFP_KERNEL); + if (DataTransferBuffer == NULL) return -ENOMEM; + memset(DataTransferBuffer, 0, DataTransferLength); + } + else if (DataTransferLength < 0) + { + DataTransferBuffer = kmalloc(-DataTransferLength, GFP_KERNEL); + if (DataTransferBuffer == NULL) return -ENOMEM; + ErrorCode = copy_from_user(DataTransferBuffer, + UserCommand.DataTransferBuffer, + -DataTransferLength); + if (ErrorCode != 0) goto Failure; + } + if (CommandOpcode == DAC960_DCDB) + { + while (true) + { + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + if (!Controller->DirectCommandActive[DCDB.Channel] + [DCDB.TargetID]) + Command = DAC960_AllocateCommand(Controller); + if (Command != NULL) + Controller->DirectCommandActive[DCDB.Channel] + [DCDB.TargetID] = true; + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + if (Command != NULL) break; + sleep_on(&Controller->CommandWaitQueue); + } + DAC960_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox, + sizeof(DAC960_CommandMailbox_T)); + Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(&DCDB); + DCDB.BusAddress = Virtual_to_Bus(DataTransferBuffer); + } + else + { + while (true) + { + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + Command = DAC960_AllocateCommand(Controller); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + if (Command != NULL) break; + sleep_on(&Controller->CommandWaitQueue); + } + DAC960_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox, + sizeof(DAC960_CommandMailbox_T)); + if (DataTransferBuffer != NULL) + Command->CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(DataTransferBuffer); + } + DAC960_ExecuteCommand(Command); + CommandStatus = Command->CommandStatus; + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + DAC960_DeallocateCommand(Command); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + if (CommandStatus == DAC960_NormalCompletion && + DataTransferLength > 0) + { + ErrorCode = copy_to_user(UserCommand.DataTransferBuffer, + DataTransferBuffer, DataTransferLength); + if (ErrorCode != 0) goto Failure; + } + if (CommandOpcode == DAC960_DCDB) + { + Controller->DirectCommandActive[DCDB.Channel] + [DCDB.TargetID] = false; + ErrorCode = + copy_to_user(UserCommand.DCDB, &DCDB, sizeof(DAC960_DCDB_T)); + if (ErrorCode != 0) goto Failure; + } + ErrorCode = CommandStatus; + Failure: + if (DataTransferBuffer != NULL) + kfree(DataTransferBuffer); + return ErrorCode; + } + } + 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->PCI_Bus = Controller->Bus; + ControllerInfo->PCI_Device = Controller->Device; + ControllerInfo->PCI_Function = Controller->Function; + ControllerInfo->IRQ_Channel = Controller->IRQ_Channel; + ControllerInfo->Channels = Controller->Channels; + ControllerInfo->PCI_Address = Controller->PCI_Address; + strcpy(ControllerInfo->ModelName, Controller->ModelName); + strcpy(ControllerInfo->FirmwareVersion, Controller->FirmwareVersion); + return 0; + } + case DAC960_IOCTL_EXECUTE_COMMAND: + { + DAC960_KernelCommand_T *KernelCommand = + (DAC960_KernelCommand_T *) Argument; + DAC960_Controller_T *Controller; + DAC960_Command_T *Command = NULL; + DAC960_CommandOpcode_T CommandOpcode; + DAC960_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; + CommandOpcode = KernelCommand->CommandMailbox.Common.CommandOpcode; + DataTransferLength = KernelCommand->DataTransferLength; + DataTransferBuffer = KernelCommand->DataTransferBuffer; + if (CommandOpcode & 0x80) return -EINVAL; + if (CommandOpcode == DAC960_DCDB) + { + DCDB = KernelCommand->DCDB; + if (!((DataTransferLength == 0 && + DCDB->Direction == DAC960_DCDB_NoDataTransfer) || + (DataTransferLength > 0 && + DCDB->Direction == DAC960_DCDB_DataTransferDeviceToSystem) || + (DataTransferLength < 0 && + DCDB->Direction == DAC960_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_DCDB) + { + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + if (!Controller->DirectCommandActive[DCDB->Channel] + [DCDB->TargetID]) + Command = DAC960_AllocateCommand(Controller); + if (Command == NULL) + { + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + return -EBUSY; + } + else Controller->DirectCommandActive[DCDB->Channel] + [DCDB->TargetID] = true; + DAC960_ClearCommand(Command); + Command->CommandType = DAC960_QueuedCommand; + memcpy(&Command->CommandMailbox, &KernelCommand->CommandMailbox, + sizeof(DAC960_CommandMailbox_T)); + Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB); + Command->KernelCommand = KernelCommand; + DCDB->BusAddress = Virtual_to_Bus(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_ClearCommand(Command); + Command->CommandType = DAC960_QueuedCommand; + memcpy(&Command->CommandMailbox, &KernelCommand->CommandMailbox, + sizeof(DAC960_CommandMailbox_T)); + if (DataTransferBuffer != NULL) + Command->CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(DataTransferBuffer); + Command->KernelCommand = KernelCommand; + DAC960_QueueCommand(Command); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + } + return 0; + } + } + return -EINVAL; +} + + +/* + DAC960_GenericDiskInit is the Generic Disk Information Initialization + Function for the DAC960 Driver. +*/ + +static void DAC960_InitializeGenericDiskInfo(GenericDiskInfo_T *GenericDiskInfo) +{ + DAC960_Controller_T *Controller = + (DAC960_Controller_T *) GenericDiskInfo->real_devices; + DAC960_LogicalDriveInformation_T *LogicalDriveInformation = + Controller->LogicalDriveInformation + [Controller->LogicalDriveInformationIndex]; + int LogicalDriveNumber; + for (LogicalDriveNumber = 0; + LogicalDriveNumber < Controller->LogicalDriveCount; + LogicalDriveNumber++) + GenericDiskInfo->part[DAC960_MinorNumber(LogicalDriveNumber, 0)].nr_sects = + LogicalDriveInformation[LogicalDriveNumber].LogicalDriveSize; +} + + +/* + DAC960_Message prints Driver Messages. +*/ + +static void DAC960_Message(DAC960_MessageLevel_T MessageLevel, + char *Format, + DAC960_Controller_T *Controller, + ...) +{ + static char Buffer[DAC960_LineBufferSize]; + static boolean BeginningOfLine = true; + va_list Arguments; + int Length = 0; + va_start(Arguments, Controller); + Length = vsprintf(Buffer, Format, Arguments); + va_end(Arguments); + if (Controller == NULL) + printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel], + DAC960_ControllerCount, Buffer); + else if (MessageLevel == DAC960_AnnounceLevel || + MessageLevel == DAC960_InfoLevel) + { + if (!Controller->ControllerInitialized) + { + strcpy(&Controller->InitialStatusBuffer[ + Controller->InitialStatusLength], Buffer); + Controller->InitialStatusLength += Length; + if (MessageLevel == DAC960_AnnounceLevel) + { + static int AnnouncementLines = 0; + if (++AnnouncementLines <= 2) + printk("%sDAC960: %s", DAC960_MessageLevelMap[MessageLevel], + Buffer); + } + else + { + if (BeginningOfLine) + { + if (Buffer[0] != '\n' || Length > 1) + printk("%sDAC960#%d: %s", + DAC960_MessageLevelMap[MessageLevel], + Controller->ControllerNumber, Buffer); + } + else printk("%s", Buffer); + } + } + else + { + strcpy(&Controller->CurrentStatusBuffer[ + Controller->CurrentStatusLength], Buffer); + Controller->CurrentStatusLength += Length; + } + } + else if (MessageLevel == DAC960_ProgressLevel) + { + strcpy(Controller->RebuildProgressBuffer, Buffer); + Controller->RebuildProgressLength = Length; + if (Controller->EphemeralProgressMessage) + { + if (jiffies - Controller->LastProgressReportTime + >= DAC960_ProgressReportingInterval) + { + printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel], + Controller->ControllerNumber, Buffer); + Controller->LastProgressReportTime = jiffies; + } + } + else printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel], + Controller->ControllerNumber, Buffer); + } + else if (MessageLevel == DAC960_UserCriticalLevel) + { + strcpy(&Controller->UserStatusBuffer[Controller->UserStatusLength], + Buffer); + Controller->UserStatusLength += Length; + if (Buffer[0] != '\n' || Length > 1) + printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel], + Controller->ControllerNumber, Buffer); + } + else + { + if (BeginningOfLine) + printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel], + Controller->ControllerNumber, Buffer); + else printk("%s", Buffer); + } + BeginningOfLine = (Buffer[Length-1] == '\n'); +} + + +/* + DAC960_ParsePhysicalDrive parses spaces followed by a Physical Drive + Channel:TargetID specification from a User Command string. It updates + Channel and TargetID and returns true on success and returns false otherwise. +*/ + +static boolean DAC960_ParsePhysicalDrive(DAC960_Controller_T *Controller, + char *UserCommandString, + unsigned char *Channel, + unsigned char *TargetID) +{ + char *NewUserCommandString = UserCommandString; + unsigned long XChannel, XTargetID; + while (*UserCommandString == ' ') UserCommandString++; + if (UserCommandString == NewUserCommandString) + return false; + XChannel = simple_strtoul(UserCommandString, &NewUserCommandString, 10); + if (NewUserCommandString == UserCommandString || + *NewUserCommandString != ':' || + XChannel >= Controller->Channels) + return false; + UserCommandString = ++NewUserCommandString; + XTargetID = simple_strtoul(UserCommandString, &NewUserCommandString, 10); + if (NewUserCommandString == UserCommandString || + *NewUserCommandString != '\0' || + XTargetID >= DAC960_MaxTargets) + return false; + *Channel = XChannel; + *TargetID = XTargetID; + return true; +} + + +/* + DAC960_ParseLogicalDrive parses spaces followed by a Logical Drive Number + specification from a User Command string. It updates LogicalDriveNumber and + returns true on success and returns false otherwise. +*/ + +static boolean DAC960_ParseLogicalDrive(DAC960_Controller_T *Controller, + char *UserCommandString, + unsigned char *LogicalDriveNumber) +{ + char *NewUserCommandString = UserCommandString; + unsigned long XLogicalDriveNumber; + while (*UserCommandString == ' ') UserCommandString++; + if (UserCommandString == NewUserCommandString) + return false; + XLogicalDriveNumber = + simple_strtoul(UserCommandString, &NewUserCommandString, 10); + if (NewUserCommandString == UserCommandString || + *NewUserCommandString != '\0' || + XLogicalDriveNumber >= Controller->LogicalDriveCount) + return false; + *LogicalDriveNumber = XLogicalDriveNumber; + return true; +} + + +/* + DAC960_SetDeviceState sets the Device State for a Physical Drive. +*/ + +static void DAC960_SetDeviceState(DAC960_Controller_T *Controller, + DAC960_Command_T *Command, + unsigned char Channel, + unsigned char TargetID, + DAC960_PhysicalDeviceState_T DeviceState, + const char *DeviceStateString) +{ + DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; + CommandMailbox->Type3D.CommandOpcode = DAC960_StartDevice; + CommandMailbox->Type3D.Channel = Channel; + CommandMailbox->Type3D.TargetID = TargetID; + CommandMailbox->Type3D.DeviceState = DeviceState; + CommandMailbox->Type3D.Modifier = 0; + DAC960_ExecuteCommand(Command); + switch (Command->CommandStatus) + { + case DAC960_NormalCompletion: + DAC960_UserCritical("%s of Physical Drive %d:%d Succeeded\n", Controller, + DeviceStateString, Channel, TargetID); + break; + case DAC960_UnableToStartDevice: + DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + "Unable to Start Device\n", Controller, + DeviceStateString, Channel, TargetID); + break; + case DAC960_NoDeviceAtAddress: + DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + "No Device at Address\n", Controller, + DeviceStateString, Channel, TargetID); + break; + case DAC960_InvalidChannelOrTargetOrModifier: + DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + "Invalid Channel or Target or Modifier\n", + Controller, DeviceStateString, Channel, TargetID); + break; + case DAC960_ChannelBusy: + DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + "Channel Busy\n", Controller, + DeviceStateString, Channel, TargetID); + break; + default: + DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + "Unexpected Status %04X\n", Controller, + DeviceStateString, Channel, TargetID, + Command->CommandStatus); + break; + } +} + + +/* + DAC960_ExecuteUserCommand executes a User Command. +*/ + +static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller, + char *UserCommand) +{ + DAC960_Command_T *Command; + DAC960_CommandMailbox_T *CommandMailbox; + ProcessorFlags_T ProcessorFlags; + unsigned char Channel, TargetID, LogicalDriveNumber; + while (true) + { + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + Command = DAC960_AllocateCommand(Controller); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + if (Command != NULL) break; + sleep_on(&Controller->CommandWaitQueue); + } + Controller->UserStatusLength = 0; + DAC960_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox = &Command->CommandMailbox; + if (strcmp(UserCommand, "flush-cache") == 0) + { + CommandMailbox->Type3.CommandOpcode = DAC960_Flush; + DAC960_ExecuteCommand(Command); + DAC960_UserCritical("Cache Flush Completed\n", Controller); + } + else if (strncmp(UserCommand, "kill", 4) == 0 && + DAC960_ParsePhysicalDrive(Controller, &UserCommand[4], + &Channel, &TargetID)) + { + DAC960_DeviceState_T *DeviceState = + &Controller->DeviceState[Controller->DeviceStateIndex] + [Channel][TargetID]; + if (DeviceState->Present && + DeviceState->DeviceType == DAC960_DiskType && + DeviceState->DeviceState != DAC960_Device_Dead) + DAC960_SetDeviceState(Controller, Command, Channel, TargetID, + DAC960_Device_Dead, "Kill"); + else DAC960_UserCritical("Kill of Physical Drive %d:%d Illegal\n", + Controller, Channel, TargetID); + } + else if (strncmp(UserCommand, "make-online", 11) == 0 && + DAC960_ParsePhysicalDrive(Controller, &UserCommand[11], + &Channel, &TargetID)) + { + DAC960_DeviceState_T *DeviceState = + &Controller->DeviceState[Controller->DeviceStateIndex] + [Channel][TargetID]; + if (DeviceState->Present && + DeviceState->DeviceType == DAC960_DiskType && + DeviceState->DeviceState == DAC960_Device_Dead) + DAC960_SetDeviceState(Controller, Command, Channel, TargetID, + DAC960_Device_Online, "Make Online"); + else DAC960_UserCritical("Make Online of Physical Drive %d:%d Illegal\n", + Controller, Channel, TargetID); + + } + else if (strncmp(UserCommand, "make-standby", 12) == 0 && + DAC960_ParsePhysicalDrive(Controller, &UserCommand[12], + &Channel, &TargetID)) + { + DAC960_DeviceState_T *DeviceState = + &Controller->DeviceState[Controller->DeviceStateIndex] + [Channel][TargetID]; + if (DeviceState->Present && + DeviceState->DeviceType == DAC960_DiskType && + DeviceState->DeviceState == DAC960_Device_Dead) + DAC960_SetDeviceState(Controller, Command, Channel, TargetID, + DAC960_Device_Standby, "Make Standby"); + else DAC960_UserCritical("Make Standby of Physical Drive %d:%d Illegal\n", + Controller, Channel, TargetID); + } + else if (strncmp(UserCommand, "rebuild", 7) == 0 && + DAC960_ParsePhysicalDrive(Controller, &UserCommand[7], + &Channel, &TargetID)) + { + CommandMailbox->Type3D.CommandOpcode = DAC960_RebuildAsync; + CommandMailbox->Type3D.Channel = Channel; + CommandMailbox->Type3D.TargetID = TargetID; + DAC960_ExecuteCommand(Command); + switch (Command->CommandStatus) + { + case DAC960_NormalCompletion: + DAC960_UserCritical("Rebuild of Physical Drive %d:%d Initiated\n", + Controller, Channel, TargetID); + break; + case DAC960_AttemptToRebuildOnlineDrive: + DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + "Attempt to Rebuild Online or " + "Unresponsive Drive\n", + Controller, Channel, TargetID); + break; + case DAC960_NewDiskFailedDuringRebuild: + DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + "New Disk Failed During Rebuild\n", + Controller, Channel, TargetID); + break; + case DAC960_InvalidDeviceAddress: + DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + "Invalid Device Address\n", + Controller, Channel, TargetID); + break; + case DAC960_RebuildOrCheckAlreadyInProgress: + DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + "Rebuild or Consistency Check Already " + "in Progress\n", Controller, Channel, TargetID); + break; + default: + DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + "Unexpected Status %04X\n", Controller, + Channel, TargetID, Command->CommandStatus); + break; + } + } + else if (strncmp(UserCommand, "check-consistency", 17) == 0 && + DAC960_ParseLogicalDrive(Controller, &UserCommand[17], + &LogicalDriveNumber)) + { + CommandMailbox->Type3C.CommandOpcode = DAC960_CheckConsistencyAsync; + CommandMailbox->Type3C.LogicalDriveNumber = LogicalDriveNumber; + CommandMailbox->Type3C.AutoRestore = true; + DAC960_ExecuteCommand(Command); + switch (Command->CommandStatus) + { + case DAC960_NormalCompletion: + DAC960_UserCritical("Consistency Check of Logical Drive %d " + "(/dev/rd/c%dd%d) Initiated\n", + Controller, LogicalDriveNumber, + Controller->ControllerNumber, + LogicalDriveNumber); + break; + case DAC960_DependentDiskIsDead: + DAC960_UserCritical("Consistency Check of Logical Drive %d " + "(/dev/rd/c%dd%d) Failed - " + "Dependent Physical Drive is DEAD\n", + Controller, LogicalDriveNumber, + Controller->ControllerNumber, + LogicalDriveNumber); + break; + case DAC960_InvalidOrNonredundantLogicalDrive: + DAC960_UserCritical("Consistency Check of Logical Drive %d " + "(/dev/rd/c%dd%d) Failed - " + "Invalid or Nonredundant Logical Drive\n", + Controller, LogicalDriveNumber, + Controller->ControllerNumber, + LogicalDriveNumber); + break; + case DAC960_RebuildOrCheckAlreadyInProgress: + DAC960_UserCritical("Consistency Check of Logical Drive %d " + "(/dev/rd/c%dd%d) Failed - Rebuild or " + "Consistency Check Already in Progress\n", + Controller, LogicalDriveNumber, + Controller->ControllerNumber, + LogicalDriveNumber); + break; + default: + DAC960_UserCritical("Consistency Check of Logical Drive %d " + "(/dev/rd/c%dd%d) Failed - " + "Unexpected Status %04X\n", + Controller, LogicalDriveNumber, + Controller->ControllerNumber, + LogicalDriveNumber, Command->CommandStatus); + break; + } + } + else if (strcmp(UserCommand, "cancel-rebuild") == 0 || + strcmp(UserCommand, "cancel-consistency-check") == 0) + { + unsigned char OldRebuildRateConstant; + CommandMailbox->Type3R.CommandOpcode = DAC960_RebuildControl; + CommandMailbox->Type3R.RebuildRateConstant = 0xFF; + CommandMailbox->Type3R.BusAddress = + Virtual_to_Bus(&OldRebuildRateConstant); + DAC960_ExecuteCommand(Command); + switch (Command->CommandStatus) + { + case DAC960_NormalCompletion: + DAC960_UserCritical("Rebuild or Consistency Check Cancelled\n", + Controller); + break; + default: + DAC960_UserCritical("Cancellation of Rebuild or " + "Consistency Check Failed - " + "Unexpected Status %04X\n", + Controller, Command->CommandStatus); + break; + } + } + else DAC960_UserCritical("Illegal User Command: '%s'\n", + Controller, UserCommand); + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + DAC960_DeallocateCommand(Command); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + return true; +} + + +/* + DAC960_ProcReadStatus implements reading /proc/rd/status. +*/ + +static ssize_t DAC960_ProcReadStatus(char *Page, char **Start, + off_t Offset, int Count, + int *EOF, void *Data) +{ + char *StatusMessage = "OK\n"; + int ControllerNumber, BytesAvailable; + for (ControllerNumber = 0; + ControllerNumber < DAC960_ControllerCount; + ControllerNumber++) + { + DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; + DAC960_Enquiry_T *Enquiry; + if (Controller == NULL) continue; + Enquiry = &Controller->Enquiry[Controller->EnquiryIndex]; + if (Enquiry->CriticalLogicalDriveCount > 0 || + Enquiry->OfflineLogicalDriveCount > 0 || + Enquiry->DeadDriveCount > 0) + { + StatusMessage = "ALERT\n"; + break; + } + } + BytesAvailable = strlen(StatusMessage) - Offset; + if (Count >= BytesAvailable) + { + Count = BytesAvailable; + *EOF = true; + } + if (Count <= 0) return 0; + memcpy(Page, &StatusMessage[Offset], Count); + return Count; +} + + +/* + DAC960_ProcReadInitialStatus implements reading /proc/rd/cN/initial_status. +*/ + +static ssize_t DAC960_ProcReadInitialStatus(char *Page, char **Start, + off_t Offset, int Count, + int *EOF, void *Data) +{ + DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data; + int BytesAvailable = Controller->InitialStatusLength - Offset; + if (Count >= BytesAvailable) + { + Count = BytesAvailable; + *EOF = true; + } + if (Count <= 0) return 0; + memcpy(Page, &Controller->InitialStatusBuffer[Offset], Count); + return Count; +} + + +/* + DAC960_ProcReadCurrentStatus implements reading /proc/rd/cN/current_status. +*/ + +static ssize_t DAC960_ProcReadCurrentStatus(char *Page, char **Start, + off_t Offset, int Count, + int *EOF, void *Data) +{ + DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data; + int BytesAvailable; + Controller->CurrentStatusLength = 0; + DAC960_AnnounceDriver(Controller); + DAC960_ReportControllerConfiguration(Controller); + Controller->CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' '; + Controller->CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' '; + if (Controller->RebuildProgressLength > 0) + { + strcpy(&Controller->CurrentStatusBuffer[Controller->CurrentStatusLength], + Controller->RebuildProgressBuffer); + Controller->CurrentStatusLength += Controller->RebuildProgressLength; + } + else + { + char *StatusMessage = "No Rebuild or Consistency Check in Progress\n"; + strcpy(&Controller->CurrentStatusBuffer[Controller->CurrentStatusLength], + StatusMessage); + Controller->CurrentStatusLength += strlen(StatusMessage); + } + BytesAvailable = Controller->CurrentStatusLength - Offset; + if (Count >= BytesAvailable) + { + Count = BytesAvailable; + *EOF = true; + } + if (Count <= 0) return 0; + memcpy(Page, &Controller->CurrentStatusBuffer[Offset], Count); + return Count; +} + + +/* + DAC960_ProcReadUserCommand implements reading /proc/rd/cN/user_command. +*/ + +static ssize_t DAC960_ProcReadUserCommand(char *Page, char **Start, + off_t Offset, int Count, + int *EOF, void *Data) +{ + DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data; + int BytesAvailable = Controller->UserStatusLength - Offset; + if (Count >= BytesAvailable) + { + Count = BytesAvailable; + *EOF = true; + } + if (Count <= 0) return 0; + memcpy(Page, &Controller->UserStatusBuffer[Offset], Count); + return Count; +} + + +/* + DAC960_ProcWriteUserCommand implements writing /proc/rd/cN/user_command. +*/ + +static ssize_t DAC960_ProcWriteUserCommand(File_T *File, const char *Buffer, + unsigned long Count, void *Data) +{ + DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data; + char CommandBuffer[80]; + int Length; + if (Count > sizeof(CommandBuffer)-1) return -EINVAL; + copy_from_user(CommandBuffer, Buffer, Count); + CommandBuffer[Count] = '\0'; + Length = strlen(CommandBuffer); + if (CommandBuffer[Length-1] == '\n') + CommandBuffer[--Length] = '\0'; + return (DAC960_ExecuteUserCommand(Controller, CommandBuffer) + ? Count : -EBUSY); +} + + +/* + DAC960_CreateProcEntries creates the /proc/rd/... entries for the DAC960 + Driver. +*/ + +static void DAC960_CreateProcEntries(void) +{ + static PROC_DirectoryEntry_T StatusProcEntry; + int ControllerNumber; + DAC960_ProcDirectoryEntry.name = "rd"; + DAC960_ProcDirectoryEntry.namelen = strlen(DAC960_ProcDirectoryEntry.name); + DAC960_ProcDirectoryEntry.mode = S_IFDIR | S_IRUGO | S_IXUGO; + proc_register(&proc_root, &DAC960_ProcDirectoryEntry); + StatusProcEntry.name = "status"; + StatusProcEntry.namelen = strlen(StatusProcEntry.name); + StatusProcEntry.mode = S_IFREG | S_IRUGO; + StatusProcEntry.read_proc = DAC960_ProcReadStatus; + proc_register(&DAC960_ProcDirectoryEntry, &StatusProcEntry); + for (ControllerNumber = 0; + ControllerNumber < DAC960_ControllerCount; + ControllerNumber++) + { + DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; + PROC_DirectoryEntry_T *ControllerProcEntry, *InitialStatusProcEntry; + PROC_DirectoryEntry_T *CurrentStatusProcEntry, *UserCommandProcEntry; + if (Controller == NULL) continue; + ControllerProcEntry = &Controller->ControllerProcEntry; + ControllerProcEntry->name = Controller->ControllerName; + ControllerProcEntry->namelen = strlen(ControllerProcEntry->name); + ControllerProcEntry->mode = S_IFDIR | S_IRUGO | S_IXUGO; + proc_register(&DAC960_ProcDirectoryEntry, ControllerProcEntry); + InitialStatusProcEntry = &Controller->InitialStatusProcEntry; + InitialStatusProcEntry->name = "initial_status"; + InitialStatusProcEntry->namelen = strlen(InitialStatusProcEntry->name); + InitialStatusProcEntry->mode = S_IFREG | S_IRUGO; + InitialStatusProcEntry->data = Controller; + InitialStatusProcEntry->read_proc = DAC960_ProcReadInitialStatus; + proc_register(ControllerProcEntry, InitialStatusProcEntry); + CurrentStatusProcEntry = &Controller->CurrentStatusProcEntry; + CurrentStatusProcEntry->name = "current_status"; + CurrentStatusProcEntry->namelen = strlen(CurrentStatusProcEntry->name); + CurrentStatusProcEntry->mode = S_IFREG | S_IRUGO; + CurrentStatusProcEntry->data = Controller; + CurrentStatusProcEntry->read_proc = DAC960_ProcReadCurrentStatus; + proc_register(ControllerProcEntry, CurrentStatusProcEntry); + UserCommandProcEntry = &Controller->UserCommandProcEntry; + UserCommandProcEntry->name = "user_command"; + UserCommandProcEntry->namelen = strlen(UserCommandProcEntry->name); + UserCommandProcEntry->mode = S_IFREG | S_IWUSR | S_IRUSR; + UserCommandProcEntry->data = Controller; + UserCommandProcEntry->read_proc = DAC960_ProcReadUserCommand; + UserCommandProcEntry->write_proc = DAC960_ProcWriteUserCommand; + proc_register(ControllerProcEntry, UserCommandProcEntry); + } +} + + +/* + DAC960_DestroyProcEntries destroys the /proc/rd/... entries for the DAC960 + Driver. +*/ + +static void DAC960_DestroyProcEntries(void) +{ + proc_unregister(&proc_root, DAC960_ProcDirectoryEntry.low_ino); +} + + +/* + Include Module support if requested. +*/ + +#ifdef MODULE + + +int init_module(void) +{ + int ControllerNumber, LogicalDriveNumber; + DAC960_Initialize(); + if (DAC960_ActiveControllerCount == 0) return -1; + for (ControllerNumber = 0; + ControllerNumber < DAC960_ControllerCount; + ControllerNumber++) + { + DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; + if (Controller == NULL) continue; + DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo); + for (LogicalDriveNumber = 0; + LogicalDriveNumber < Controller->LogicalDriveCount; + LogicalDriveNumber++) + resetup_one_dev(&Controller->GenericDiskInfo, LogicalDriveNumber); + } + return 0; +} + + +void cleanup_module(void) +{ + DAC960_Finalize(&DAC960_NotifierBlock, SYS_RESTART, NULL); +} + + +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/DAC960.h linux.pre11.3/drivers/block/DAC960.h --- linux.vanilla/drivers/block/DAC960.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/block/DAC960.h Tue Jul 20 00:27:58 1999 @@ -0,0 +1,2184 @@ +/* + + Linux Driver for Mylex DAC960 and DAC1100 PCI RAID Controllers + + Copyright 1998-1999 by Leonard N. Zubkoff + + This program is free software; you may redistribute 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 complete details. + + The author respectfully requests that any modifications to this software be + sent directly to him for evaluation and testing. + +*/ + + +/* + Define the maximum number of DAC960 Controllers supported by this driver. +*/ + +#define DAC960_MaxControllers 8 + + +/* + Define the maximum number of Controller Channels supported by this driver. +*/ + +#define DAC960_MaxChannels 3 + + +/* + Define the maximum number of Targets per Channel supported by this driver. +*/ + +#define DAC960_MaxTargets 16 + + +/* + Define the maximum number of Logical Drives supported by any DAC960 model. +*/ + +#define DAC960_MaxLogicalDrives 32 + + +/* + Define a Boolean data type. +*/ + +typedef enum { false, true } __attribute__ ((packed)) boolean; + + +/* + Define a 32 bit I/O Address data type. +*/ + +typedef unsigned int DAC960_IO_Address_T; + + +/* + Define a 32 bit PCI Bus Address data type. +*/ + +typedef unsigned int DAC960_PCI_Address_T; + + +/* + Define a 32 bit Bus Address data type. +*/ + +typedef unsigned int DAC960_BusAddress_T; + + +/* + Define a 32 bit Byte Count data type. +*/ + +typedef unsigned int DAC960_ByteCount_T; + + +/* + Define the DAC960 Command Opcodes. +*/ + +typedef enum +{ + /* I/O Commands */ + DAC960_ReadExtended = 0x33, + DAC960_WriteExtended = 0x34, + DAC960_ReadAheadExtended = 0x35, + DAC960_ReadExtendedWithScatterGather = 0xB3, + DAC960_WriteExtendedWithScatterGather = 0xB4, + DAC960_Read = 0x36, + DAC960_ReadWithOldScatterGather = 0xB6, + DAC960_Write = 0x37, + DAC960_WriteWithOldScatterGather = 0xB7, + DAC960_DCDB = 0x04, + DAC960_DCDBWithScatterGather = 0x84, + DAC960_Flush = 0x0A, + /* Controller Status Related Commands */ + DAC960_Enquiry = 0x53, + DAC960_Enquiry2 = 0x1C, + DAC960_GetLogicalDriveElement = 0x55, + DAC960_GetLogicalDriveInformation = 0x19, + DAC960_IOPortRead = 0x39, + DAC960_IOPortWrite = 0x3A, + DAC960_GetSDStats = 0x3E, + DAC960_GetPDStats = 0x3F, + DAC960_PerformEventLogOperation = 0x72, + /* Device Related Commands */ + DAC960_StartDevice = 0x10, + DAC960_GetDeviceState = 0x50, + DAC960_StopChannel = 0x13, + DAC960_StartChannel = 0x12, + DAC960_ResetChannel = 0x1A, + /* Commands Associated with Data Consistency and Errors */ + DAC960_Rebuild = 0x09, + DAC960_RebuildAsync = 0x16, + DAC960_CheckConsistency = 0x0F, + DAC960_CheckConsistencyAsync = 0x1E, + DAC960_RebuildStat = 0x0C, + DAC960_GetRebuildProgress = 0x27, + DAC960_RebuildControl = 0x1F, + DAC960_ReadBadBlockTable = 0x0B, + DAC960_ReadBadDataTable = 0x25, + DAC960_ClearBadDataTable = 0x26, + DAC960_GetErrorTable = 0x17, + DAC960_AddCapacityAsync = 0x2A, + /* Configuration Related Commands */ + DAC960_ReadConfig2 = 0x3D, + DAC960_WriteConfig2 = 0x3C, + DAC960_ReadConfigurationOnDisk = 0x4A, + DAC960_WriteConfigurationOnDisk = 0x4B, + DAC960_ReadConfiguration = 0x4E, + DAC960_ReadBackupConfiguration = 0x4D, + DAC960_WriteConfiguration = 0x4F, + DAC960_AddConfiguration = 0x4C, + DAC960_ReadConfigurationLabel = 0x48, + DAC960_WriteConfigurationLabel = 0x49, + /* Firmware Upgrade Related Commands */ + DAC960_LoadImage = 0x20, + DAC960_StoreImage = 0x21, + DAC960_ProgramImage = 0x22, + /* Diagnostic Commands */ + DAC960_SetDiagnosticMode = 0x31, + DAC960_RunDiagnostic = 0x32, + /* Subsystem Service Commands */ + DAC960_GetSubsystemData = 0x70, + DAC960_SetSubsystemParameters = 0x71 +} +__attribute__ ((packed)) +DAC960_CommandOpcode_T; + + +/* + Define the DAC960 Command Identifier type. +*/ + +typedef unsigned char DAC960_CommandIdentifier_T; + + +/* + Define the DAC960 Command Status Codes. +*/ + +#define DAC960_NormalCompletion 0x0000 /* Common */ +#define DAC960_CheckConditionReceived 0x0002 /* Common */ +#define DAC960_NoDeviceAtAddress 0x0102 /* Common */ +#define DAC960_InvalidDeviceAddress 0x0105 /* Common */ +#define DAC960_InvalidParameter 0x0105 /* Common */ +#define DAC960_IrrecoverableDataError 0x0001 /* I/O */ +#define DAC960_LogicalDriveNonexistentOrOffline 0x0002 /* I/O */ +#define DAC960_AccessBeyondEndOfLogicalDrive 0x0105 /* I/O */ +#define DAC960_BadDataEncountered 0x010C /* I/O */ +#define DAC960_DeviceBusy 0x0008 /* DCDB */ +#define DAC960_DeviceNonresponsive 0x000E /* DCDB */ +#define DAC960_CommandTerminatedAbnormally 0x000F /* DCDB */ +#define DAC960_UnableToStartDevice 0x0002 /* Device */ +#define DAC960_InvalidChannelOrTargetOrModifier 0x0105 /* Device */ +#define DAC960_ChannelBusy 0x0106 /* Device */ +#define DAC960_ChannelNotStopped 0x0002 /* Device */ +#define DAC960_AttemptToRebuildOnlineDrive 0x0002 /* Consistency */ +#define DAC960_RebuildBadBlocksEncountered 0x0003 /* Consistency */ +#define DAC960_NewDiskFailedDuringRebuild 0x0004 /* Consistency */ +#define DAC960_RebuildOrCheckAlreadyInProgress 0x0106 /* Consistency */ +#define DAC960_DependentDiskIsDead 0x0002 /* Consistency */ +#define DAC960_InconsistentBlocksFound 0x0003 /* Consistency */ +#define DAC960_InvalidOrNonredundantLogicalDrive 0x0105 /* Consistency */ +#define DAC960_NoRebuildOrCheckInProgress 0x0105 /* Consistency */ +#define DAC960_RebuildInProgress_DataValid 0x0000 /* Consistency */ +#define DAC960_RebuildFailed_LogicalDriveFailure 0x0002 /* Consistency */ +#define DAC960_RebuildFailed_BadBlocksOnOther 0x0003 /* Consistency */ +#define DAC960_RebuildFailed_NewDriveFailed 0x0004 /* Consistency */ +#define DAC960_RebuildSuccessful 0x0100 /* Consistency */ +#define DAC960_AddCapacityInProgress 0x0004 /* Consistency */ +#define DAC960_AddCapacityFailedOrSuspended 0x00F4 /* Consistency */ +#define DAC960_Config2ChecksumError 0x0002 /* Configuration */ +#define DAC960_ConfigurationSuspended 0x0106 /* Configuration */ +#define DAC960_FailedToConfigureNVRAM 0x0105 /* Configuration */ +#define DAC960_ConfigurationNotSavedStateChange 0x0106 /* Configuration */ +#define DAC960_SubsystemNotInstalled 0x0001 /* Subsystem */ +#define DAC960_SubsystemFailed 0x0002 /* Subsystem */ +#define DAC960_SubsystemBusy 0x0106 /* Subsystem */ + +typedef unsigned short DAC960_CommandStatus_T; + + +/* + Define the Enquiry reply structure. +*/ + +typedef struct DAC960_Enquiry +{ + unsigned char NumberOfLogicalDrives; /* Byte 0 */ + unsigned int :24; /* Bytes 1-3 */ + unsigned int LogicalDriveSizes[32]; /* Bytes 4-131 */ + unsigned short FlashAge; /* Bytes 132-133 */ + struct { + boolean DeferredWriteError:1; /* Byte 134 Bit 0 */ + boolean BatteryLow:1; /* Byte 134 Bit 1 */ + unsigned char :6; /* Byte 134 Bits 2-7 */ + } StatusFlags; + unsigned char :8; /* Byte 135 */ + unsigned char MinorFirmwareVersion; /* Byte 136 */ + unsigned char MajorFirmwareVersion; /* Byte 137 */ + enum { + DAC960_NoStandbyRebuildOrCheckInProgress = 0x00, + DAC960_StandbyRebuildInProgress = 0x01, + DAC960_BackgroundRebuildInProgress = 0x02, + DAC960_BackgroundCheckInProgress = 0x03, + DAC960_StandbyRebuildCompletedWithError = 0xFF, + DAC960_BackgroundRebuildOrCheckFailed_DriveFailed = 0xF0, + DAC960_BackgroundRebuildOrCheckFailed_LogicalDriveFailed = 0xF1, + DAC960_BackgroundRebuildOrCheckFailed_OtherCauses = 0xF2, + DAC960_BackgroundRebuildOrCheckSuccessfullyTerminated = 0xF3 + } __attribute__ ((packed)) RebuildFlag; /* Byte 138 */ + unsigned char MaxCommands; /* Byte 139 */ + unsigned char OfflineLogicalDriveCount; /* Byte 140 */ + unsigned char :8; /* Byte 141 */ + unsigned short EventLogSequenceNumber; /* Bytes 142-143 */ + unsigned char CriticalLogicalDriveCount; /* Byte 144 */ + unsigned int :24; /* Bytes 145-147 */ + unsigned char DeadDriveCount; /* Byte 148 */ + unsigned char :8; /* Byte 149 */ + unsigned char RebuildCount; /* Byte 150 */ + struct { + unsigned char :3; /* Byte 151 Bits 0-2 */ + boolean BatteryBackupUnitPresent:1; /* Byte 151 Bit 3 */ + unsigned char :3; /* Byte 151 Bits 4-6 */ + unsigned char :1; /* Byte 151 Bit 7 */ + } MiscFlags; + struct { + unsigned char TargetID; + unsigned char Channel; + } DeadDrives[21]; /* Bytes 152-194 */ + unsigned char Reserved[62]; /* Bytes 195-255 */ +} +__attribute__ ((packed)) +DAC960_Enquiry_T; + + +/* + Define the Enquiry2 reply structure. +*/ + +typedef struct DAC960_Enquiry2 +{ + struct { + enum { + DAC960_P_PD_PU = 0x01, + DAC960_PL = 0x02, + DAC960_PG = 0x10, + DAC960_PJ = 0x11, + DAC960_PR = 0x12, + DAC960_PT = 0x13, + DAC960_PTL0 = 0x14, + DAC960_PRL = 0x15, + DAC960_PTL1 = 0x16, + DAC1164_P = 0x20 + } __attribute__ ((packed)) SubModel; /* Byte 0 */ + unsigned char ActualChannels; /* Byte 1 */ + enum { + DAC960_FiveChannelBoard = 0x01, + DAC960_ThreeChannelBoard = 0x02, + DAC960_TwoChannelBoard = 0x03, + DAC960_ThreeChannelASIC_DAC = 0x04 + } __attribute__ ((packed)) Model; /* Byte 2 */ + enum { + DAC960_EISA_Controller = 0x01, + DAC960_MicroChannel_Controller = 0x02, + DAC960_PCI_Controller = 0x03, + DAC960_SCSItoSCSI_Controller = 0x08 + } __attribute__ ((packed)) ProductFamily; /* Byte 3 */ + } HardwareID; /* Bytes 0-3 */ + /* MajorVersion.MinorVersion-FirmwareType-TurnID */ + struct { + unsigned char MajorVersion; /* Byte 4 */ + unsigned char MinorVersion; /* Byte 5 */ + unsigned char TurnID; /* Byte 6 */ + char FirmwareType; /* Byte 7 */ + } FirmwareID; /* Bytes 4-7 */ + unsigned char :8; /* Byte 8 */ + unsigned int :24; /* Bytes 9-11 */ + unsigned char ConfiguredChannels; /* Byte 12 */ + unsigned char ActualChannels; /* Byte 13 */ + unsigned char MaxTargets; /* Byte 14 */ + unsigned char MaxTags; /* Byte 15 */ + unsigned char MaxLogicalDrives; /* Byte 16 */ + unsigned char MaxArms; /* Byte 17 */ + unsigned char MaxSpans; /* Byte 18 */ + unsigned char :8; /* Byte 19 */ + unsigned int :32; /* Bytes 20-23 */ + unsigned int MemorySize; /* Bytes 24-27 */ + unsigned int CacheSize; /* Bytes 28-31 */ + unsigned int FlashMemorySize; /* Bytes 32-35 */ + unsigned int NonVolatileMemorySize; /* Bytes 36-39 */ + struct { + enum { + DAC960_DRAM = 0x00, + DAC960_EDO = 0x01, + DAC960_SDRAM = 0x02 + } __attribute__ ((packed)) RamType:3; /* Byte 40 Bits 0-2 */ + enum { + DAC960_None = 0x00, + DAC960_Parity = 0x01, + DAC960_ECC = 0x02 + } __attribute__ ((packed)) ErrorCorrection:3; /* Byte 40 Bits 3-5 */ + boolean FastPageMode:1; /* Byte 40 Bit 6 */ + boolean LowPowerMemory:1; /* Byte 40 Bit 7 */ + unsigned char :8; /* Bytes 41 */ + } MemoryType; + unsigned short ClockSpeed; /* Bytes 42-43 */ + unsigned short MemorySpeed; /* Bytes 44-45 */ + unsigned short HardwareSpeed; /* Bytes 46-47 */ + unsigned int :32; /* Bytes 48-51 */ + unsigned int :32; /* Bytes 52-55 */ + unsigned char :8; /* Byte 56 */ + unsigned char :8; /* Byte 57 */ + unsigned short :16; /* Bytes 58-59 */ + unsigned short MaxCommands; /* Bytes 60-61 */ + unsigned short MaxScatterGatherEntries; /* Bytes 62-63 */ + unsigned short MaxDriveCommands; /* Bytes 64-65 */ + unsigned short MaxIODescriptors; /* Bytes 66-67 */ + unsigned short MaxCombinedSectors; /* Bytes 68-69 */ + unsigned char Latency; /* Byte 70 */ + unsigned char :8; /* Byte 71 */ + unsigned char SCSITimeout; /* Byte 72 */ + unsigned char :8; /* Byte 73 */ + unsigned short MinFreeLines; /* Bytes 74-75 */ + unsigned int :32; /* Bytes 76-79 */ + unsigned int :32; /* Bytes 80-83 */ + unsigned char RebuildRateConstant; /* Byte 84 */ + unsigned char :8; /* Byte 85 */ + unsigned char :8; /* Byte 86 */ + unsigned char :8; /* Byte 87 */ + unsigned int :32; /* Bytes 88-91 */ + unsigned int :32; /* Bytes 92-95 */ + unsigned short PhysicalDriveBlockSize; /* Bytes 96-97 */ + unsigned short LogicalDriveBlockSize; /* Bytes 98-99 */ + unsigned short MaxBlocksPerCommand; /* Bytes 100-101 */ + unsigned short BlockFactor; /* Bytes 102-103 */ + unsigned short CacheLineSize; /* Bytes 104-105 */ + struct { + enum { + DAC960_Narrow_8bit = 0x00, + DAC960_Wide_16bit = 0x01, + DAC960_Wide_32bit = 0x02 + } __attribute__ ((packed)) BusWidth:2; /* Byte 106 Bits 0-1 */ + enum { + DAC960_Fast = 0x00, + DAC960_Ultra = 0x01, + DAC960_Ultra2 = 0x02 + } __attribute__ ((packed)) BusSpeed:2; /* Byte 106 Bits 2-3 */ + boolean Differential:1; /* Byte 106 Bit 4 */ + unsigned char :3; /* Byte 106 Bits 5-7 */ + } SCSICapability; + unsigned char :8; /* Byte 107 */ + unsigned int :32; /* Bytes 108-111 */ + unsigned short FirmwareBuildNumber; /* Bytes 112-113 */ + enum { + DAC960_AEMI = 0x01, + DAC960_OEM1 = 0x02, + DAC960_OEM2 = 0x04, + DAC960_OEM3 = 0x08, + DAC960_Conner = 0x10, + DAC960_SAFTE = 0x20 + } __attribute__ ((packed)) FaultManagementType; /* Byte 114 */ + unsigned char :8; /* Byte 115 */ + struct { + boolean Clustering:1; /* Byte 116 Bit 0 */ + boolean MylexOnlineRAIDExpansion:1; /* Byte 116 Bit 1 */ + unsigned int :30; /* Bytes 116-119 */ + } FirmwareFeatures; + unsigned int :32; /* Bytes 120-123 */ + unsigned int :32; /* Bytes 124-127 */ +} +DAC960_Enquiry2_T; + + +/* + Define the Logical Drive State type. +*/ + +typedef enum +{ + DAC960_LogicalDrive_Online = 0x03, + DAC960_LogicalDrive_Critical = 0x04, + DAC960_LogicalDrive_Offline = 0xFF +} +__attribute__ ((packed)) +DAC960_LogicalDriveState_T; + + +/* + Define the Get Logical Drive Information reply structure. +*/ + +typedef struct DAC960_LogicalDriveInformation +{ + unsigned int LogicalDriveSize; /* Bytes 0-3 */ + DAC960_LogicalDriveState_T LogicalDriveState; /* Byte 4 */ + unsigned char RAIDLevel:7; /* Byte 5 Bits 0-6 */ + boolean WriteBack:1; /* Byte 5 Bit 7 */ + unsigned int :16; /* Bytes 6-7 */ +} +DAC960_LogicalDriveInformation_T; + + +/* + Define the Perform Event Log Operation Types. +*/ + +typedef enum +{ + DAC960_GetEventLogEntry = 0x00 +} +__attribute__ ((packed)) +DAC960_PerformEventLogOpType_T; + + +/* + Define the Get Event Log Entry reply structure. +*/ + +typedef struct DAC960_EventLogEntry +{ + unsigned char MessageType; /* Byte 0 */ + unsigned char MessageLength; /* Byte 1 */ + unsigned char TargetID:5; /* Byte 2 Bits 0-4 */ + unsigned char Channel:3; /* Byte 2 Bits 5-7 */ + unsigned char LogicalUnit:6; /* Byte 3 Bits 0-5 */ + unsigned char :2; /* Byte 3 Bits 6-7 */ + unsigned short SequenceNumber; /* Bytes 4-5 */ + unsigned char ErrorCode:7; /* Byte 6 Bits 0-6 */ + boolean Valid:1; /* Byte 6 Bit 7 */ + unsigned char SegmentNumber; /* Byte 7 */ + unsigned char SenseKey:4; /* Byte 8 Bits 0-3 */ + unsigned char :1; /* Byte 8 Bit 4 */ + boolean ILI:1; /* Byte 8 Bit 5 */ + boolean EOM:1; /* Byte 8 Bit 6 */ + boolean Filemark:1; /* Byte 8 Bit 7 */ + unsigned char Information[4]; /* Bytes 9-12 */ + unsigned char AdditionalSenseLength; /* Byte 13 */ + unsigned char CommandSpecificInformation[4]; /* Bytes 14-17 */ + unsigned char AdditionalSenseCode; /* Byte 18 */ + unsigned char AdditionalSenseCodeQualifier; /* Byte 19 */ + unsigned char Dummy[12]; /* Bytes 20-31 */ +} +DAC960_EventLogEntry_T; + + +/* + Define the Physical Device State type. +*/ + +typedef enum +{ + DAC960_Device_Dead = 0x00, + DAC960_Device_WriteOnly = 0x02, + DAC960_Device_Online = 0x03, + DAC960_Device_Standby = 0x10 +} +__attribute__ ((packed)) +DAC960_PhysicalDeviceState_T; + + +/* + Define the Get Device State reply structure. +*/ + +typedef struct DAC960_DeviceState +{ + boolean Present:1; /* Byte 0 Bit 0 */ + unsigned char :7; /* Byte 0 Bits 1-7 */ + enum { + DAC960_OtherType = 0x00, + DAC960_DiskType = 0x01, + DAC960_SequentialType = 0x02, + DAC960_CDROM_or_WORM_Type = 0x03 + } __attribute__ ((packed)) DeviceType:2; /* Byte 1 Bits 0-1 */ + boolean :1; /* Byte 1 Bit 2 */ + boolean Fast20:1; /* Byte 1 Bit 3 */ + boolean Sync:1; /* Byte 1 Bit 4 */ + boolean Fast:1; /* Byte 1 Bit 5 */ + boolean Wide:1; /* Byte 1 Bit 6 */ + boolean TaggedQueuingSupported:1; /* Byte 1 Bit 7 */ + DAC960_PhysicalDeviceState_T DeviceState; /* Byte 2 */ + unsigned char :8; /* Byte 3 */ + unsigned char SynchronousMultiplier; /* Byte 4 */ + unsigned char SynchronousOffset:5; /* Byte 5 Bits 0-4 */ + unsigned char :3; /* Byte 5 Bits 5-7 */ + unsigned long DiskSize __attribute__ ((packed)); /* Bytes 6-9 */ +} +DAC960_DeviceState_T; + + +/* + Define the Get Rebuild Progress reply structure. +*/ + +typedef struct DAC960_RebuildProgress +{ + unsigned int LogicalDriveNumber; /* Bytes 0-3 */ + unsigned int LogicalDriveSize; /* Bytes 4-7 */ + unsigned int RemainingBlocks; /* Bytes 8-11 */ +} +DAC960_RebuildProgress_T; + + +/* + Define the Error Table Entry and Get Error Table reply structure. +*/ + +typedef struct DAC960_ErrorTableEntry +{ + unsigned char ParityErrorCount; /* Byte 0 */ + unsigned char SoftErrorCount; /* Byte 1 */ + unsigned char HardErrorCount; /* Byte 2 */ + unsigned char MiscErrorCount; /* Byte 3 */ +} +DAC960_ErrorTableEntry_T; + + +/* + Define the Get Error Table reply structure. +*/ + +typedef struct DAC960_ErrorTable +{ + DAC960_ErrorTableEntry_T + ErrorTableEntries[DAC960_MaxChannels][DAC960_MaxTargets]; +} +DAC960_ErrorTable_T; + + +/* + Define the Config2 reply structure. +*/ + +typedef struct DAC960_Config2 +{ + unsigned char :1; /* Byte 0 Bit 0 */ + boolean ActiveNegationEnabled:1; /* Byte 0 Bit 1 */ + unsigned char :5; /* Byte 0 Bits 2-6 */ + boolean NoRescanIfResetReceivedDuringScan:1; /* Byte 0 Bit 7 */ + boolean StorageWorksSupportEnabled:1; /* Byte 1 Bit 0 */ + boolean HewlettPackardSupportEnabled:1; /* Byte 1 Bit 1 */ + boolean NoDisconnectOnFirstCommand:1; /* Byte 1 Bit 2 */ + unsigned char :2; /* Byte 1 Bits 3-4 */ + boolean AEMI_ARM:1; /* Byte 1 Bit 5 */ + boolean AEMI_OFM:1; /* Byte 1 Bit 6 */ + unsigned char :1; /* Byte 1 Bit 7 */ + enum { + DAC960_OEMID_Mylex = 0x00, + DAC960_OEMID_IBM = 0x08, + DAC960_OEMID_HP = 0x0A, + DAC960_OEMID_DEC = 0x0C, + DAC960_OEMID_Siemens = 0x10, + DAC960_OEMID_Intel = 0x12 + } __attribute__ ((packed)) OEMID; /* Byte 2 */ + unsigned char OEMModelNumber; /* Byte 3 */ + unsigned char PhysicalSector; /* Byte 4 */ + unsigned char LogicalSector; /* Byte 5 */ + unsigned char BlockFactor; /* Byte 6 */ + boolean ReadAheadEnabled:1; /* Byte 7 Bit 0 */ + boolean LowBIOSDelay:1; /* Byte 7 Bit 1 */ + unsigned char :2; /* Byte 7 Bits 2-3 */ + boolean ReassignRestrictedToOneSector:1; /* Byte 7 Bit 4 */ + unsigned char :1; /* Byte 7 Bit 5 */ + boolean ForceUnitAccessDuringWriteRecovery:1; /* Byte 7 Bit 6 */ + boolean EnableLeftSymmetricRAID5Algorithm:1; /* Byte 7 Bit 7 */ + unsigned char DefaultRebuildRate; /* Byte 8 */ + unsigned char :8; /* Byte 9 */ + unsigned char BlocksPerCacheLine; /* Byte 10 */ + unsigned char BlocksPerStripe; /* Byte 11 */ + struct { + enum { + DAC960_Async = 0x00, + DAC960_Sync_8MHz = 0x01, + DAC960_Sync_5MHz = 0x02, + DAC960_Sync_10or20MHz = 0x03 /* Bits 0-1 */ + } __attribute__ ((packed)) Speed:2; + boolean Force8Bit:1; /* Bit 2 */ + boolean DisableFast20:1; /* Bit 3 */ + unsigned char :3; /* Bits 4-6 */ + boolean EnableTaggedQueuing:1; /* Bit 7 */ + } __attribute__ ((packed)) ChannelParameters[6]; /* Bytes 12-17 */ + unsigned char SCSIInitiatorID; /* Byte 18 */ + unsigned char :8; /* Byte 19 */ + enum { + DAC960_StartupMode_ControllerSpinUp = 0x00, + DAC960_StartupMode_PowerOnSpinUp = 0x01 + } __attribute__ ((packed)) StartupMode; /* Byte 20 */ + unsigned char SimultaneousDeviceSpinUpCount; /* Byte 21 */ + unsigned char SecondsDelayBetweenSpinUps; /* Byte 22 */ + unsigned char Reserved1[29]; /* Bytes 23-51 */ + boolean BIOSDisabled:1; /* Byte 52 Bit 0 */ + boolean CDROMBootEnabled:1; /* Byte 52 Bit 1 */ + unsigned char :3; /* Byte 52 Bits 2-4 */ + enum { + DAC960_Geometry_128_32 = 0x00, + DAC960_Geometry_255_63 = 0x01, + DAC960_Geometry_Reserved1 = 0x02, + DAC960_Geometry_Reserved2 = 0x03 + } __attribute__ ((packed)) DriveGeometry:2; /* Byte 52 Bits 5-6 */ + unsigned char :1; /* Byte 52 Bit 7 */ + unsigned char Reserved2[9]; /* Bytes 53-61 */ + unsigned short Checksum; /* Bytes 62-63 */ +} +DAC960_Config2_T; + + +/* + Define the DCDB request structure. +*/ + +typedef struct DAC960_DCDB +{ + unsigned char TargetID:4; /* Byte 0 Bits 0-3 */ + unsigned char Channel:4; /* Byte 0 Bits 4-7 */ + enum { + DAC960_DCDB_NoDataTransfer = 0, + DAC960_DCDB_DataTransferDeviceToSystem = 1, + DAC960_DCDB_DataTransferSystemToDevice = 2, + DAC960_DCDB_IllegalDataTransfer = 3 + } __attribute__ ((packed)) Direction:2; /* Byte 1 Bits 0-1 */ + boolean EarlyStatus:1; /* Byte 1 Bit 2 */ + unsigned char :1; /* Byte 1 Bit 3 */ + enum { + DAC960_DCDB_Timeout_24_hours = 0, + DAC960_DCDB_Timeout_10_seconds = 1, + DAC960_DCDB_Timeout_60_seconds = 2, + DAC960_DCDB_Timeout_10_minutes = 3 + } __attribute__ ((packed)) Timeout:2; /* Byte 1 Bits 4-5 */ + boolean NoAutomaticRequestSense:1; /* Byte 1 Bit 6 */ + boolean DisconnectPermitted:1; /* Byte 1 Bit 7 */ + unsigned short TransferLength; /* Bytes 2-3 */ + DAC960_BusAddress_T BusAddress; /* Bytes 4-7 */ + unsigned char CDBLength:4; /* Byte 8 Bits 0-3 */ + unsigned char TransferLengthHigh4:4; /* Byte 8 Bits 4-7 */ + unsigned char SenseLength; /* Byte 9 */ + unsigned char CDB[12]; /* Bytes 10-21 */ + unsigned char SenseData[64]; /* Bytes 22-85 */ + unsigned char Status; /* Byte 86 */ + unsigned char :8; /* Byte 87 */ +} +DAC960_DCDB_T; + + +/* + Define the Scatter/Gather List Type 1 32 Bit Address 32 Bit Byte Count + structure. +*/ + +typedef struct DAC960_ScatterGatherSegment +{ + DAC960_BusAddress_T SegmentDataPointer; /* Bytes 0-3 */ + DAC960_ByteCount_T SegmentByteCount; /* Bytes 4-7 */ +} +DAC960_ScatterGatherSegment_T; + + +/* + Define the 13 Byte DAC960 Command Mailbox structure. Bytes 13-15 are + not used. The Command Mailbox structure is padded to 16 bytes for + efficient access. +*/ + +typedef union DAC960_CommandMailbox +{ + unsigned int Words[4]; /* Words 0-3 */ + unsigned char Bytes[16]; /* Bytes 0-15 */ + struct { + DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + unsigned char Dummy[14]; /* Bytes 2-15 */ + } __attribute__ ((packed)) Common; + struct { + DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + unsigned char Dummy1[6]; /* Bytes 2-7 */ + DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */ + unsigned char Dummy2[4]; /* Bytes 12-15 */ + } __attribute__ ((packed)) Type3; + struct { + DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + unsigned char Dummy1[5]; /* Bytes 2-6 */ + unsigned char LogicalDriveNumber:6; /* Byte 7 Bits 0-6 */ + boolean AutoRestore:1; /* Byte 7 Bit 7 */ + unsigned char Dummy2[8]; /* Bytes 8-15 */ + } __attribute__ ((packed)) Type3C; + struct { + DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + unsigned char Channel; /* Byte 2 */ + unsigned char TargetID; /* Byte 3 */ + DAC960_PhysicalDeviceState_T DeviceState:5; /* Byte 4 Bits 0-4 */ + unsigned char Modifier:3; /* Byte 4 Bits 5-7 */ + unsigned char Dummy1[3]; /* Bytes 5-7 */ + DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */ + unsigned char Dummy2[4]; /* Bytes 12-15 */ + } __attribute__ ((packed)) Type3D; + struct { + DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_PerformEventLogOpType_T OperationType; /* Byte 2 */ + unsigned char OperationQualifier; /* Byte 3 */ + unsigned short SequenceNumber; /* Bytes 4-5 */ + unsigned char Dummy1[2]; /* Bytes 6-7 */ + DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */ + unsigned char Dummy2[4]; /* Bytes 12-15 */ + } __attribute__ ((packed)) Type3E; + struct { + DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + unsigned char Dummy1[2]; /* Bytes 2-3 */ + unsigned char RebuildRateConstant; /* Byte 4 */ + unsigned char Dummy2[3]; /* Bytes 5-7 */ + DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */ + unsigned char Dummy3[4]; /* Bytes 12-15 */ + } __attribute__ ((packed)) Type3R; + struct { + DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + unsigned short TransferLength; /* Bytes 2-3 */ + unsigned int LogicalBlockAddress; /* Bytes 4-7 */ + DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */ + unsigned char LogicalDriveNumber; /* Byte 12 */ + unsigned char Dummy[3]; /* Bytes 13-15 */ + } __attribute__ ((packed)) Type4; + struct { + DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + struct { + unsigned short TransferLength:11; /* Bytes 2-3 */ + unsigned char LogicalDriveNumber:5; /* Byte 3 Bits 3-7 */ + } __attribute__ ((packed)) LD; + unsigned int LogicalBlockAddress; /* Bytes 4-7 */ + DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */ + unsigned char ScatterGatherCount:6; /* Byte 12 Bits 0-5 */ + enum { + DAC960_ScatterGather_32BitAddress_32BitByteCount = 0x0, + DAC960_ScatterGather_32BitAddress_16BitByteCount = 0x1, + DAC960_ScatterGather_32BitByteCount_32BitAddress = 0x2, + DAC960_ScatterGather_16BitByteCount_32BitAddress = 0x3 + } __attribute__ ((packed)) ScatterGatherType:2; /* Byte 12 Bits 6-7 */ + unsigned char Dummy[3]; /* Bytes 13-15 */ + } __attribute__ ((packed)) Type5; + struct { + DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + unsigned char CommandOpcode2; /* Byte 2 */ + unsigned char :8; /* Byte 3 */ + DAC960_BusAddress_T CommandMailboxesBusAddress; /* Bytes 4-7 */ + DAC960_BusAddress_T StatusMailboxesBusAddress; /* Bytes 8-11 */ + unsigned char Dummy[4]; /* Bytes 12-15 */ + } __attribute__ ((packed)) TypeX; +} +DAC960_CommandMailbox_T; + + +/* + Define the DAC960 Driver IOCTL requests. +*/ + +#define DAC960_IOCTL_GET_CONTROLLER_COUNT 0xDAC001 +#define DAC960_IOCTL_GET_CONTROLLER_INFO 0xDAC002 +#define DAC960_IOCTL_EXECUTE_COMMAND 0xDAC003 + + +/* + Define the DAC960_IOCTL_GET_CONTROLLER_INFO reply structure. +*/ + +typedef struct DAC960_ControllerInfo +{ + unsigned char ControllerNumber; + unsigned char PCI_Bus; + unsigned char PCI_Device; + unsigned char PCI_Function; + unsigned char IRQ_Channel; + unsigned char Channels; + DAC960_PCI_Address_T PCI_Address; + unsigned char ModelName[16]; + unsigned char FirmwareVersion[16]; +} +DAC960_ControllerInfo_T; + + +/* + Define the User Mode DAC960_IOCTL_EXECUTE_COMMAND request structure. +*/ + +typedef struct DAC960_UserCommand +{ + unsigned char ControllerNumber; + DAC960_CommandMailbox_T CommandMailbox; + int DataTransferLength; + void *DataTransferBuffer; + DAC960_DCDB_T *DCDB; +} +DAC960_UserCommand_T; + + +/* + Define the Kernel Mode DAC960_IOCTL_EXECUTE_COMMAND request structure. +*/ + +typedef struct DAC960_KernelCommand +{ + unsigned char ControllerNumber; + DAC960_CommandMailbox_T CommandMailbox; + int DataTransferLength; + void *DataTransferBuffer; + DAC960_DCDB_T *DCDB; + DAC960_CommandStatus_T CommandStatus; + void (*CompletionFunction)(struct DAC960_KernelCommand *); + void *CompletionData; +} +DAC960_KernelCommand_T; + + +/* + Import the Kernel Mode IOCTL interface. +*/ + +extern int DAC960_KernelIOCTL(unsigned int Request, void *Argument); + + +/* + Virtual_to_Bus maps from Kernel Virtual Addresses to PCI Bus Addresses. +*/ + +static inline DAC960_BusAddress_T Virtual_to_Bus(void *VirtualAddress) +{ + return (DAC960_BusAddress_T) virt_to_bus(VirtualAddress); +} + + +/* + Bus_to_Virtual maps from PCI Bus Addresses to Kernel Virtual Addresses. +*/ + +static inline void *Bus_to_Virtual(DAC960_BusAddress_T BusAddress) +{ + return (void *) bus_to_virt(BusAddress); +} + + +/* + DAC960_DriverVersion protects the private portion of this file. +*/ + +#ifdef DAC960_DriverVersion + + +/* + Define the maximum Driver Queue Depth and Controller Queue Depth supported + by any DAC960 model. +*/ + +#define DAC960_MaxDriverQueueDepth 127 +#define DAC960_MaxControllerQueueDepth 128 + + +/* + Define the maximum number of Scatter/Gather Segments supported by any + DAC960 model. +*/ + +#define DAC960_MaxScatterGatherSegments 33 + + +/* + Define the number of Command Mailboxes and Status Mailboxes used by the + Memory Mailbox Interface. +*/ + +#define DAC960_CommandMailboxCount 256 +#define DAC960_StatusMailboxCount 1024 + + +/* + Define the DAC960 Controller Monitoring Timer Interval. +*/ + +#define DAC960_MonitoringTimerInterval (10 * HZ) + + +/* + Define the DAC960 Controller Secondary Monitoring Interval. +*/ + +#define DAC960_SecondaryMonitoringInterval (60 * HZ) + + +/* + Define the DAC960 Controller Progress Reporting Interval. +*/ + +#define DAC960_ProgressReportingInterval (60 * HZ) + + +/* + Define the maximum number of Partitions allowed for each Logical Drive. +*/ + +#define DAC960_MaxPartitions 8 +#define DAC960_MaxPartitionsBits 3 + + +/* + Define macros to extract the Controller Number, Logical Drive Number, and + Partition Number from a Kernel Device, and to construct a Major Number, Minor + Number, and Kernel Device from the Controller Number, Logical Drive Number, + and Partition Number. There is one Major Number assigned to each Controller. + The associated Minor Number is divided into the Logical Drive Number and + Partition Number. +*/ + +#define DAC960_ControllerNumber(Device) \ + (MAJOR(Device) - DAC960_MAJOR) + +#define DAC960_LogicalDriveNumber(Device) \ + (MINOR(Device) >> DAC960_MaxPartitionsBits) + +#define DAC960_PartitionNumber(Device) \ + (MINOR(Device) & (DAC960_MaxPartitions - 1)) + +#define DAC960_MajorNumber(ControllerNumber) \ + (DAC960_MAJOR + (ControllerNumber)) + +#define DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber) \ + (((LogicalDriveNumber) << DAC960_MaxPartitionsBits) | (PartitionNumber)) + +#define DAC960_MinorCount (DAC960_MaxLogicalDrives \ + * DAC960_MaxPartitions) + +#define DAC960_KernelDevice(ControllerNumber, \ + LogicalDriveNumber, \ + PartitionNumber) \ + MKDEV(DAC960_MajorNumber(ControllerNumber), \ + DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber)) + + +/* + Define the DAC960 Controller fixed Block Size and Block Size Bits. +*/ + +#define DAC960_BlockSize 512 +#define DAC960_BlockSizeBits 9 + + +/* + Define the Controller Line, Status Buffer, Rebuild Progress, and + User Message Sizes. +*/ + +#define DAC960_LineBufferSize 100 +#define DAC960_StatusBufferSize 5000 +#define DAC960_RebuildProgressSize 200 +#define DAC960_UserMessageSize 200 + + +/* + Define the types of DAC960 Controllers that are supported. +*/ + +typedef enum +{ + DAC960_V5_Controller = 1, /* DAC1164P */ + DAC960_V4_Controller = 2, /* DAC960PTL/PJ/PG */ + DAC960_V3_Controller = 3 /* DAC960PU/PD/PL */ +} +DAC960_ControllerType_T; + + +/* + Define the Driver Message Levels. +*/ + +typedef enum DAC960_MessageLevel +{ + DAC960_AnnounceLevel = 0, + DAC960_InfoLevel = 1, + DAC960_NoticeLevel = 2, + DAC960_WarningLevel = 3, + DAC960_ErrorLevel = 4, + DAC960_ProgressLevel = 5, + DAC960_CriticalLevel = 6, + DAC960_UserCriticalLevel = 7 +} +DAC960_MessageLevel_T; + +static char + *DAC960_MessageLevelMap[] = + { KERN_NOTICE, KERN_NOTICE, KERN_NOTICE, KERN_WARNING, + KERN_ERR, KERN_CRIT, KERN_CRIT, KERN_CRIT }; + + +/* + Define Driver Message macros. +*/ + +#define DAC960_Announce(Format, Arguments...) \ + DAC960_Message(DAC960_AnnounceLevel, Format, ##Arguments) + +#define DAC960_Info(Format, Arguments...) \ + DAC960_Message(DAC960_InfoLevel, Format, ##Arguments) + +#define DAC960_Notice(Format, Arguments...) \ + DAC960_Message(DAC960_NoticeLevel, Format, ##Arguments) + +#define DAC960_Warning(Format, Arguments...) \ + DAC960_Message(DAC960_WarningLevel, Format, ##Arguments) + +#define DAC960_Error(Format, Arguments...) \ + DAC960_Message(DAC960_ErrorLevel, Format, ##Arguments) + +#define DAC960_Progress(Format, Arguments...) \ + DAC960_Message(DAC960_ProgressLevel, Format, ##Arguments) + +#define DAC960_Critical(Format, Arguments...) \ + DAC960_Message(DAC960_CriticalLevel, Format, ##Arguments) + +#define DAC960_UserCritical(Format, Arguments...) \ + DAC960_Message(DAC960_UserCriticalLevel, Format, ##Arguments) + + +/* + Define types for some of the structures that interface with the rest + of the Linux Kernel and I/O Subsystem. +*/ + +typedef struct buffer_head BufferHeader_T; +typedef struct file File_T; +typedef struct file_operations FileOperations_T; +typedef struct gendisk GenericDiskInfo_T; +typedef struct hd_geometry DiskGeometry_T; +typedef struct hd_struct DiskPartition_T; +typedef struct inode Inode_T; +typedef struct inode_operations InodeOperations_T; +typedef kdev_t KernelDevice_T; +typedef struct notifier_block NotifierBlock_T; +typedef struct pci_dev PCI_Device_T; +typedef struct proc_dir_entry PROC_DirectoryEntry_T; +typedef unsigned long ProcessorFlags_T; +typedef struct pt_regs Registers_T; +typedef struct request IO_Request_T; +typedef struct semaphore Semaphore_T; +typedef struct super_block SuperBlock_T; +typedef struct timer_list Timer_T; +typedef struct wait_queue WaitQueue_T; + + +/* + Define the DAC960 Controller Status Mailbox structure. +*/ + +typedef union DAC960_StatusMailbox +{ + unsigned int Word; /* Bytes 0-3 */ + struct { + DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 0 */ + unsigned char :7; /* Byte 1 Bits 0-6 */ + boolean Valid:1; /* Byte 1 Bit 7 */ + DAC960_CommandStatus_T CommandStatus; /* Bytes 2-3 */ + } Fields; +} +DAC960_StatusMailbox_T; + + +/* + Define the DAC960 Driver Command Types. +*/ + +typedef enum +{ + DAC960_ReadCommand = 1, + DAC960_WriteCommand = 2, + DAC960_ReadRetryCommand = 3, + DAC960_WriteRetryCommand = 4, + DAC960_MonitoringCommand = 5, + DAC960_ImmediateCommand = 6, + DAC960_QueuedCommand = 7 +} +DAC960_CommandType_T; + + +/* + Define the DAC960 Driver Command structure. +*/ + +typedef struct DAC960_Command +{ + DAC960_CommandType_T CommandType; + DAC960_CommandMailbox_T CommandMailbox; + DAC960_CommandStatus_T CommandStatus; + struct DAC960_Controller *Controller; + struct DAC960_Command *Next; + Semaphore_T *Semaphore; + unsigned int LogicalDriveNumber; + unsigned int BlockNumber; + unsigned int BlockCount; + unsigned int SegmentCount; + BufferHeader_T *BufferHeader; + DAC960_KernelCommand_T *KernelCommand; + DAC960_ScatterGatherSegment_T + ScatterGatherList[DAC960_MaxScatterGatherSegments]; +} +DAC960_Command_T; + + +/* + Define the DAC960 Driver Controller structure. +*/ + +typedef struct DAC960_Controller +{ + void *BaseAddress; + void *MemoryMappedAddress; + DAC960_ControllerType_T ControllerType; + DAC960_IO_Address_T IO_Address; + DAC960_PCI_Address_T PCI_Address; + unsigned char ControllerNumber; + unsigned char ControllerName[4]; + unsigned char ModelName[12]; + unsigned char FullModelName[18]; + unsigned char FirmwareVersion[14]; + unsigned char Bus; + unsigned char Device; + unsigned char Function; + unsigned char IRQ_Channel; + unsigned char Channels; + unsigned char MemorySize; + unsigned char LogicalDriveCount; + unsigned char GeometryTranslationHeads; + unsigned char GeometryTranslationSectors; + unsigned short ControllerQueueDepth; + unsigned short DriverQueueDepth; + unsigned short MaxBlocksPerCommand; + unsigned short MaxScatterGatherSegments; + unsigned short StripeSize; + unsigned short SegmentSize; + unsigned short NewEventLogSequenceNumber; + unsigned short OldEventLogSequenceNumber; + unsigned short InitialStatusLength; + unsigned short CurrentStatusLength; + unsigned short UserStatusLength; + unsigned short RebuildProgressLength; + unsigned int ControllerUsageCount; + unsigned int EnquiryIndex; + unsigned int LogicalDriveInformationIndex; + unsigned int ErrorTableIndex; + unsigned int DeviceStateIndex; + unsigned int DeviceStateChannel; + unsigned int DeviceStateTargetID; + unsigned long MonitoringTimerCount; + unsigned long SecondaryMonitoringTime; + unsigned long LastProgressReportTime; + boolean DualModeMemoryMailboxInterface; + boolean SAFTE_EnclosureManagementEnabled; + boolean ControllerInitialized; + boolean MonitoringCommandDeferred; + boolean NeedLogicalDriveInformation; + boolean NeedErrorTableInformation; + boolean NeedDeviceStateInformation; + boolean NeedRebuildProgress; + boolean NeedConsistencyCheckProgress; + boolean EphemeralProgressMessage; + Timer_T MonitoringTimer; + GenericDiskInfo_T GenericDiskInfo; + DAC960_Command_T *FreeCommands; + DAC960_CommandMailbox_T *FirstCommandMailbox; + DAC960_CommandMailbox_T *LastCommandMailbox; + DAC960_CommandMailbox_T *NextCommandMailbox; + DAC960_CommandMailbox_T *PreviousCommandMailbox1; + DAC960_CommandMailbox_T *PreviousCommandMailbox2; + DAC960_StatusMailbox_T *FirstStatusMailbox; + DAC960_StatusMailbox_T *LastStatusMailbox; + DAC960_StatusMailbox_T *NextStatusMailbox; + PROC_DirectoryEntry_T ControllerProcEntry; + PROC_DirectoryEntry_T InitialStatusProcEntry; + PROC_DirectoryEntry_T CurrentStatusProcEntry; + PROC_DirectoryEntry_T UserCommandProcEntry; + WaitQueue_T *CommandWaitQueue; + DAC960_Enquiry_T Enquiry[2]; + DAC960_ErrorTable_T ErrorTable[2]; + DAC960_EventLogEntry_T EventLogEntry; + DAC960_RebuildProgress_T RebuildProgress; + DAC960_CommandStatus_T LastRebuildStatus; + DAC960_LogicalDriveInformation_T + LogicalDriveInformation[2][DAC960_MaxLogicalDrives]; + DAC960_LogicalDriveState_T LogicalDriveInitialState[DAC960_MaxLogicalDrives]; + DAC960_DeviceState_T DeviceState[2][DAC960_MaxChannels][DAC960_MaxTargets]; + DAC960_Command_T Commands[DAC960_MaxDriverQueueDepth]; + DiskPartition_T DiskPartitions[DAC960_MinorCount]; + int LogicalDriveUsageCount[DAC960_MaxLogicalDrives]; + int PartitionSizes[DAC960_MinorCount]; + int BlockSizes[DAC960_MinorCount]; + int MaxSectorsPerRequest[DAC960_MinorCount]; + int MaxSegmentsPerRequest[DAC960_MinorCount]; + boolean DirectCommandActive[DAC960_MaxChannels][DAC960_MaxTargets]; + char InitialStatusBuffer[DAC960_StatusBufferSize]; + char CurrentStatusBuffer[DAC960_StatusBufferSize]; + char UserStatusBuffer[DAC960_UserMessageSize]; + char RebuildProgressBuffer[DAC960_RebuildProgressSize]; +} +DAC960_Controller_T; + + +/* + DAC960_AcquireControllerLock acquires exclusive access to Controller. +*/ + +static inline +void DAC960_AcquireControllerLock(DAC960_Controller_T *Controller, + ProcessorFlags_T *ProcessorFlags) +{ + spin_lock_irqsave(&io_request_lock, *ProcessorFlags); +} + + +/* + DAC960_ReleaseControllerLock releases exclusive access to Controller. +*/ + +static inline +void DAC960_ReleaseControllerLock(DAC960_Controller_T *Controller, + ProcessorFlags_T *ProcessorFlags) +{ + spin_unlock_irqrestore(&io_request_lock, *ProcessorFlags); +} + + +/* + DAC960_AcquireControllerLockRF acquires exclusive access to Controller, + but is only called from the request function with the io_request_lock held. +*/ + +static inline +void DAC960_AcquireControllerLockRF(DAC960_Controller_T *Controller, + ProcessorFlags_T *ProcessorFlags) +{ +} + + +/* + DAC960_ReleaseControllerLockRF releases exclusive access to Controller, + but is only called from the request function with the io_request_lock held. +*/ + +static inline +void DAC960_ReleaseControllerLockRF(DAC960_Controller_T *Controller, + ProcessorFlags_T *ProcessorFlags) +{ +} + + +/* + DAC960_AcquireControllerLockIH acquires exclusive access to Controller, + but is only called from the interrupt handler. +*/ + +static inline +void DAC960_AcquireControllerLockIH(DAC960_Controller_T *Controller, + ProcessorFlags_T *ProcessorFlags) +{ + spin_lock_irqsave(&io_request_lock, *ProcessorFlags); +} + + +/* + DAC960_ReleaseControllerLockIH releases exclusive access to Controller, + but is only called from the interrupt handler. +*/ + +static inline +void DAC960_ReleaseControllerLockIH(DAC960_Controller_T *Controller, + ProcessorFlags_T *ProcessorFlags) +{ + spin_unlock_irqrestore(&io_request_lock, *ProcessorFlags); +} + + +/* + Define the DAC960 V5 Controller Interface Register Offsets. +*/ + +#define DAC960_V5_RegisterWindowSize 0x80 + +typedef enum +{ + DAC960_V5_InboundDoorBellRegisterOffset = 0x60, + DAC960_V5_OutboundDoorBellRegisterOffset = 0x61, + DAC960_V5_InterruptMaskRegisterOffset = 0x34, + DAC960_V5_CommandOpcodeRegisterOffset = 0x50, + DAC960_V5_CommandIdentifierRegisterOffset = 0x51, + DAC960_V5_MailboxRegister2Offset = 0x52, + DAC960_V5_MailboxRegister3Offset = 0x53, + DAC960_V5_MailboxRegister4Offset = 0x54, + DAC960_V5_MailboxRegister5Offset = 0x55, + DAC960_V5_MailboxRegister6Offset = 0x56, + DAC960_V5_MailboxRegister7Offset = 0x57, + DAC960_V5_MailboxRegister8Offset = 0x58, + DAC960_V5_MailboxRegister9Offset = 0x59, + DAC960_V5_MailboxRegister10Offset = 0x5A, + DAC960_V5_MailboxRegister11Offset = 0x5B, + DAC960_V5_MailboxRegister12Offset = 0x5C, + DAC960_V5_StatusCommandIdentifierRegOffset = 0x5D, + DAC960_V5_StatusRegisterOffset = 0x5E +} +DAC960_V5_RegisterOffsets_T; + + +/* + Define the structure of the DAC960 V5 Inbound Door Bell Register. +*/ + +typedef union DAC960_V5_InboundDoorBellRegister +{ + unsigned char All; + struct { + boolean HardwareMailboxNewCommand:1; /* Bit 0 */ + boolean AcknowledgeHardwareMailboxStatus:1; /* Bit 1 */ + boolean GenerateInterrupt:1; /* Bit 2 */ + boolean ControllerReset:1; /* Bit 3 */ + boolean MemoryMailboxNewCommand:1; /* Bit 4 */ + unsigned char :3; /* Bits 5-7 */ + } Write; + struct { + boolean HardwareMailboxEmpty:1; /* Bit 0 */ + unsigned char :7; /* Bits 1-7 */ + } Read; +} +DAC960_V5_InboundDoorBellRegister_T; + + +/* + Define the structure of the DAC960 V5 Outbound Door Bell Register. +*/ + +typedef union DAC960_V5_OutboundDoorBellRegister +{ + unsigned char All; + struct { + boolean AcknowledgeHardwareMailboxInterrupt:1; /* Bit 0 */ + boolean AcknowledgeMemoryMailboxInterrupt:1; /* Bit 1 */ + unsigned char :6; /* Bits 2-7 */ + } Write; + struct { + boolean HardwareMailboxStatusAvailable:1; /* Bit 0 */ + boolean MemoryMailboxStatusAvailable:1; /* Bit 1 */ + unsigned char :6; /* Bits 2-7 */ + } Read; +} +DAC960_V5_OutboundDoorBellRegister_T; + + +/* + Define the structure of the DAC960 V5 Interrupt Mask Register. +*/ + +typedef union DAC960_V5_InterruptMaskRegister +{ + unsigned char All; + struct { + unsigned char :2; /* Bits 0-1 */ + boolean DisableInterrupts:1; /* Bit 2 */ + unsigned char :5; /* Bits 3-7 */ + } Bits; +} +DAC960_V5_InterruptMaskRegister_T; + + +/* + Define inline functions to provide an abstraction for reading and writing the + DAC960 V5 Controller Interface Registers. +*/ + +static inline +void DAC960_V5_HardwareMailboxNewCommand(void *ControllerBaseAddress) +{ + DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_V5_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) +{ + DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_V5_GenerateInterrupt(void *ControllerBaseAddress) +{ + DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.GenerateInterrupt = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_V5_ControllerReset(void *ControllerBaseAddress) +{ + DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.ControllerReset = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_V5_MemoryMailboxNewCommand(void *ControllerBaseAddress) +{ + DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); +} + +static inline +boolean DAC960_V5_HardwareMailboxEmptyP(void *ControllerBaseAddress) +{ + DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); + return InboundDoorBellRegister.Read.HardwareMailboxEmpty; +} + +static inline +void DAC960_V5_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) +{ + DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; + writeb(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset); +} + +static inline +void DAC960_V5_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) +{ + DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; + writeb(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset); +} + +static inline +void DAC960_V5_AcknowledgeInterrupt(void *ControllerBaseAddress) +{ + DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; + OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; + writeb(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset); +} + +static inline +boolean DAC960_V5_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) +{ + DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset); + return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable; +} + +static inline +boolean DAC960_V5_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) +{ + DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset); + return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable; +} + +static inline +void DAC960_V5_EnableInterrupts(void *ControllerBaseAddress) +{ + DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister; + InterruptMaskRegister.All = 0; + InterruptMaskRegister.Bits.DisableInterrupts = false; + writeb(InterruptMaskRegister.All, + ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset); +} + +static inline +void DAC960_V5_DisableInterrupts(void *ControllerBaseAddress) +{ + DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister; + InterruptMaskRegister.All = 0; + InterruptMaskRegister.Bits.DisableInterrupts = true; + writeb(InterruptMaskRegister.All, + ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset); +} + +static inline +boolean DAC960_V5_InterruptsEnabledP(void *ControllerBaseAddress) +{ + DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister; + InterruptMaskRegister.All = + readb(ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset); + return !InterruptMaskRegister.Bits.DisableInterrupts; +} + +static inline +void DAC960_V5_WriteCommandMailbox(DAC960_CommandMailbox_T *NextCommandMailbox, + DAC960_CommandMailbox_T *CommandMailbox) +{ + NextCommandMailbox->Words[1] = CommandMailbox->Words[1]; + NextCommandMailbox->Words[2] = CommandMailbox->Words[2]; + NextCommandMailbox->Words[3] = CommandMailbox->Words[3]; + NextCommandMailbox->Words[0] = CommandMailbox->Words[0]; +} + +static inline +void DAC960_V5_WriteHardwareMailbox(void *ControllerBaseAddress, + DAC960_CommandMailbox_T *CommandMailbox) +{ + writel(CommandMailbox->Words[0], + ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset); + writel(CommandMailbox->Words[1], + ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset); + writel(CommandMailbox->Words[2], + ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset); + writeb(CommandMailbox->Bytes[12], + ControllerBaseAddress + DAC960_V5_MailboxRegister12Offset); +} + +static inline DAC960_CommandIdentifier_T +DAC960_V5_ReadStatusCommandIdentifier(void *ControllerBaseAddress) +{ + return readb(ControllerBaseAddress + + DAC960_V5_StatusCommandIdentifierRegOffset); +} + +static inline DAC960_CommandStatus_T +DAC960_V5_ReadStatusRegister(void *ControllerBaseAddress) +{ + return readw(ControllerBaseAddress + DAC960_V5_StatusRegisterOffset); +} + +static inline +void DAC960_V5_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller) +{ + void *ControllerBaseAddress = Controller->BaseAddress; + writel(0x743C485E, + ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset); + writel((unsigned long) Controller->FirstCommandMailbox, + ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset); + writew(Controller->NextCommandMailbox - Controller->FirstCommandMailbox, + ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset); + writew(Controller->NextStatusMailbox - Controller->FirstStatusMailbox, + ControllerBaseAddress + DAC960_V5_MailboxRegister10Offset); +} + +static inline +void DAC960_V5_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller, + void **MemoryMailboxAddress, + short *NextCommandMailboxIndex, + short *NextStatusMailboxIndex) +{ + void *ControllerBaseAddress = Controller->BaseAddress; + if (readl(ControllerBaseAddress + + DAC960_V5_CommandOpcodeRegisterOffset) != 0x743C485E) + return; + *MemoryMailboxAddress = + (void *) readl(ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset); + *NextCommandMailboxIndex = + readw(ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset); + *NextStatusMailboxIndex = + readw(ControllerBaseAddress + DAC960_V5_MailboxRegister10Offset); +} + + +/* + Define the DAC960 V4 Controller Interface Register Offsets. +*/ + +#define DAC960_V4_RegisterWindowSize 0x2000 + +typedef enum +{ + DAC960_V4_InboundDoorBellRegisterOffset = 0x0020, + DAC960_V4_OutboundDoorBellRegisterOffset = 0x002C, + DAC960_V4_InterruptMaskRegisterOffset = 0x0034, + DAC960_V4_CommandOpcodeRegisterOffset = 0x1000, + DAC960_V4_CommandIdentifierRegisterOffset = 0x1001, + DAC960_V4_MailboxRegister2Offset = 0x1002, + DAC960_V4_MailboxRegister3Offset = 0x1003, + DAC960_V4_MailboxRegister4Offset = 0x1004, + DAC960_V4_MailboxRegister5Offset = 0x1005, + DAC960_V4_MailboxRegister6Offset = 0x1006, + DAC960_V4_MailboxRegister7Offset = 0x1007, + DAC960_V4_MailboxRegister8Offset = 0x1008, + DAC960_V4_MailboxRegister9Offset = 0x1009, + DAC960_V4_MailboxRegister10Offset = 0x100A, + DAC960_V4_MailboxRegister11Offset = 0x100B, + DAC960_V4_MailboxRegister12Offset = 0x100C, + DAC960_V4_StatusCommandIdentifierRegOffset = 0x1018, + DAC960_V4_StatusRegisterOffset = 0x101A +} +DAC960_V4_RegisterOffsets_T; + + +/* + Define the structure of the DAC960 V4 Inbound Door Bell Register. +*/ + +typedef union DAC960_V4_InboundDoorBellRegister +{ + unsigned int All; + struct { + boolean HardwareMailboxNewCommand:1; /* Bit 0 */ + boolean AcknowledgeHardwareMailboxStatus:1; /* Bit 1 */ + boolean GenerateInterrupt:1; /* Bit 2 */ + boolean ControllerReset:1; /* Bit 3 */ + boolean MemoryMailboxNewCommand:1; /* Bit 4 */ + unsigned int :27; /* Bits 5-31 */ + } Write; + struct { + boolean HardwareMailboxFull:1; /* Bit 0 */ + unsigned int :31; /* Bits 1-31 */ + } Read; +} +DAC960_V4_InboundDoorBellRegister_T; + + +/* + Define the structure of the DAC960 V4 Outbound Door Bell Register. +*/ + +typedef union DAC960_V4_OutboundDoorBellRegister +{ + unsigned int All; + struct { + boolean AcknowledgeHardwareMailboxInterrupt:1; /* Bit 0 */ + boolean AcknowledgeMemoryMailboxInterrupt:1; /* Bit 1 */ + unsigned int :30; /* Bits 2-31 */ + } Write; + struct { + boolean HardwareMailboxStatusAvailable:1; /* Bit 0 */ + boolean MemoryMailboxStatusAvailable:1; /* Bit 1 */ + unsigned int :30; /* Bits 2-31 */ + } Read; +} +DAC960_V4_OutboundDoorBellRegister_T; + + +/* + Define the structure of the DAC960 V4 Interrupt Mask Register. +*/ + +typedef union DAC960_V4_InterruptMaskRegister +{ + unsigned int All; + struct { + unsigned int MessageUnitInterruptMask1:2; /* Bits 0-1 */ + boolean DisableInterrupts:1; /* Bit 2 */ + unsigned int MessageUnitInterruptMask2:5; /* Bits 3-7 */ + unsigned int Reserved0:24; /* Bits 8-31 */ + } Bits; +} +DAC960_V4_InterruptMaskRegister_T; + + +/* + Define inline functions to provide an abstraction for reading and writing the + DAC960 V4 Controller Interface Registers. +*/ + +static inline +void DAC960_V4_HardwareMailboxNewCommand(void *ControllerBaseAddress) +{ + DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true; + writel(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_V4_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) +{ + DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true; + writel(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_V4_GenerateInterrupt(void *ControllerBaseAddress) +{ + DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.GenerateInterrupt = true; + writel(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_V4_ControllerReset(void *ControllerBaseAddress) +{ + DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.ControllerReset = true; + writel(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_V4_MemoryMailboxNewCommand(void *ControllerBaseAddress) +{ + DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true; + writel(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); +} + +static inline +boolean DAC960_V4_HardwareMailboxFullP(void *ControllerBaseAddress) +{ + DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = + readl(ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); + return InboundDoorBellRegister.Read.HardwareMailboxFull; +} + +static inline +void DAC960_V4_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) +{ + DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; + writel(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset); +} + +static inline +void DAC960_V4_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) +{ + DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; + writel(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset); +} + +static inline +void DAC960_V4_AcknowledgeInterrupt(void *ControllerBaseAddress) +{ + DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; + OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; + writel(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset); +} + +static inline +boolean DAC960_V4_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) +{ + DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = + readl(ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset); + return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable; +} + +static inline +boolean DAC960_V4_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) +{ + DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = + readl(ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset); + return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable; +} + +static inline +void DAC960_V4_EnableInterrupts(void *ControllerBaseAddress) +{ + DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister; + InterruptMaskRegister.All = 0; + InterruptMaskRegister.Bits.MessageUnitInterruptMask1 = 0x3; + InterruptMaskRegister.Bits.DisableInterrupts = false; + InterruptMaskRegister.Bits.MessageUnitInterruptMask2 = 0x1F; + writel(InterruptMaskRegister.All, + ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset); +} + +static inline +void DAC960_V4_DisableInterrupts(void *ControllerBaseAddress) +{ + DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister; + InterruptMaskRegister.All = 0; + InterruptMaskRegister.Bits.MessageUnitInterruptMask1 = 0x3; + InterruptMaskRegister.Bits.DisableInterrupts = true; + InterruptMaskRegister.Bits.MessageUnitInterruptMask2 = 0x1F; + writel(InterruptMaskRegister.All, + ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset); +} + +static inline +boolean DAC960_V4_InterruptsEnabledP(void *ControllerBaseAddress) +{ + DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister; + InterruptMaskRegister.All = + readl(ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset); + return !InterruptMaskRegister.Bits.DisableInterrupts; +} + +static inline +void DAC960_V4_WriteCommandMailbox(DAC960_CommandMailbox_T *NextCommandMailbox, + DAC960_CommandMailbox_T *CommandMailbox) +{ + NextCommandMailbox->Words[1] = CommandMailbox->Words[1]; + NextCommandMailbox->Words[2] = CommandMailbox->Words[2]; + NextCommandMailbox->Words[3] = CommandMailbox->Words[3]; + NextCommandMailbox->Words[0] = CommandMailbox->Words[0]; +} + +static inline +void DAC960_V4_WriteHardwareMailbox(void *ControllerBaseAddress, + DAC960_CommandMailbox_T *CommandMailbox) +{ + writel(CommandMailbox->Words[0], + ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset); + writel(CommandMailbox->Words[1], + ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset); + writel(CommandMailbox->Words[2], + ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset); + writeb(CommandMailbox->Bytes[12], + ControllerBaseAddress + DAC960_V4_MailboxRegister12Offset); +} + +static inline DAC960_CommandIdentifier_T +DAC960_V4_ReadStatusCommandIdentifier(void *ControllerBaseAddress) +{ + return readb(ControllerBaseAddress + + DAC960_V4_StatusCommandIdentifierRegOffset); +} + +static inline DAC960_CommandStatus_T +DAC960_V4_ReadStatusRegister(void *ControllerBaseAddress) +{ + return readw(ControllerBaseAddress + DAC960_V4_StatusRegisterOffset); +} + +static inline +void DAC960_V4_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller) +{ + void *ControllerBaseAddress = Controller->BaseAddress; + writel(0xAABBFFFF, + ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset); + writel((unsigned long) Controller->FirstCommandMailbox, + ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset); + writew(Controller->NextCommandMailbox - Controller->FirstCommandMailbox, + ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset); + writew(Controller->NextStatusMailbox - Controller->FirstStatusMailbox, + ControllerBaseAddress + DAC960_V4_MailboxRegister10Offset); +} + +static inline +void DAC960_V4_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller, + void **MemoryMailboxAddress, + short *NextCommandMailboxIndex, + short *NextStatusMailboxIndex) +{ + void *ControllerBaseAddress = Controller->BaseAddress; + if (readl(ControllerBaseAddress + + DAC960_V4_CommandOpcodeRegisterOffset) != 0xAABBFFFF) + return; + *MemoryMailboxAddress = + (void *) readl(ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset); + *NextCommandMailboxIndex = + readw(ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset); + *NextStatusMailboxIndex = + readw(ControllerBaseAddress + DAC960_V4_MailboxRegister10Offset); +} + + +/* + Define the DAC960 V3 Controller Interface Register Offsets. +*/ + +#define DAC960_V3_RegisterWindowSize 0x80 + +typedef enum +{ + DAC960_V3_CommandOpcodeRegisterOffset = 0x00, + DAC960_V3_CommandIdentifierRegisterOffset = 0x01, + DAC960_V3_MailboxRegister2Offset = 0x02, + DAC960_V3_MailboxRegister3Offset = 0x03, + DAC960_V3_MailboxRegister4Offset = 0x04, + DAC960_V3_MailboxRegister5Offset = 0x05, + DAC960_V3_MailboxRegister6Offset = 0x06, + DAC960_V3_MailboxRegister7Offset = 0x07, + DAC960_V3_MailboxRegister8Offset = 0x08, + DAC960_V3_MailboxRegister9Offset = 0x09, + DAC960_V3_MailboxRegister10Offset = 0x0A, + DAC960_V3_MailboxRegister11Offset = 0x0B, + DAC960_V3_MailboxRegister12Offset = 0x0C, + DAC960_V3_StatusCommandIdentifierRegOffset = 0x0D, + DAC960_V3_StatusRegisterOffset = 0x0E, + DAC960_V3_InboundDoorBellRegisterOffset = 0x40, + DAC960_V3_OutboundDoorBellRegisterOffset = 0x41, + DAC960_V3_InterruptEnableRegisterOffset = 0x43 +} +DAC960_V3_RegisterOffsets_T; + + +/* + Define the structure of the DAC960 V3 Inbound Door Bell Register. +*/ + +typedef union DAC960_V3_InboundDoorBellRegister +{ + unsigned char All; + struct { + boolean NewCommand:1; /* Bit 0 */ + boolean AcknowledgeStatus:1; /* Bit 1 */ + boolean GenerateInterrupt:1; /* Bit 2 */ + boolean ControllerReset:1; /* Bit 3 */ + unsigned char :4; /* Bits 4-7 */ + } Write; + struct { + boolean MailboxFull:1; /* Bit 0 */ + unsigned char :7; /* Bits 1-7 */ + } Read; +} +DAC960_V3_InboundDoorBellRegister_T; + + +/* + Define the structure of the DAC960 V3 Outbound Door Bell Register. +*/ + +typedef union DAC960_V3_OutboundDoorBellRegister +{ + unsigned char All; + struct { + boolean AcknowledgeInterrupt:1; /* Bit 0 */ + unsigned char :7; /* Bits 1-7 */ + } Write; + struct { + boolean StatusAvailable:1; /* Bit 0 */ + unsigned char :7; /* Bits 1-7 */ + } Read; +} +DAC960_V3_OutboundDoorBellRegister_T; + + +/* + Define the structure of the DAC960 V3 Interrupt Enable Register. +*/ + +typedef union DAC960_V3_InterruptEnableRegister +{ + unsigned char All; + struct { + boolean EnableInterrupts:1; /* Bit 0 */ + unsigned char :7; /* Bits 1-7 */ + } Bits; +} +DAC960_V3_InterruptEnableRegister_T; + + +/* + Define inline functions to provide an abstraction for reading and writing the + DAC960 V3 Controller Interface Registers. +*/ + +static inline +void DAC960_V3_NewCommand(void *ControllerBaseAddress) +{ + DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.NewCommand = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_V3_AcknowledgeStatus(void *ControllerBaseAddress) +{ + DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.AcknowledgeStatus = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_V3_GenerateInterrupt(void *ControllerBaseAddress) +{ + DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.GenerateInterrupt = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_V3_ControllerReset(void *ControllerBaseAddress) +{ + DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.ControllerReset = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); +} + +static inline +boolean DAC960_V3_MailboxFullP(void *ControllerBaseAddress) +{ + DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); + return InboundDoorBellRegister.Read.MailboxFull; +} + +static inline +void DAC960_V3_AcknowledgeInterrupt(void *ControllerBaseAddress) +{ + DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeInterrupt = true; + writeb(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_V3_OutboundDoorBellRegisterOffset); +} + +static inline +boolean DAC960_V3_StatusAvailableP(void *ControllerBaseAddress) +{ + DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_V3_OutboundDoorBellRegisterOffset); + return OutboundDoorBellRegister.Read.StatusAvailable; +} + +static inline +void DAC960_V3_EnableInterrupts(void *ControllerBaseAddress) +{ + DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister; + InterruptEnableRegister.All = 0; + InterruptEnableRegister.Bits.EnableInterrupts = true; + writeb(InterruptEnableRegister.All, + ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset); +} + +static inline +void DAC960_V3_DisableInterrupts(void *ControllerBaseAddress) +{ + DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister; + InterruptEnableRegister.All = 0; + InterruptEnableRegister.Bits.EnableInterrupts = false; + writeb(InterruptEnableRegister.All, + ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset); +} + +static inline +boolean DAC960_V3_InterruptsEnabledP(void *ControllerBaseAddress) +{ + DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister; + InterruptEnableRegister.All = + readb(ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset); + return InterruptEnableRegister.Bits.EnableInterrupts; +} + +static inline +void DAC960_V3_WriteCommandMailbox(void *ControllerBaseAddress, + DAC960_CommandMailbox_T *CommandMailbox) +{ + writel(CommandMailbox->Words[0], + ControllerBaseAddress + DAC960_V3_CommandOpcodeRegisterOffset); + writel(CommandMailbox->Words[1], + ControllerBaseAddress + DAC960_V3_MailboxRegister4Offset); + writel(CommandMailbox->Words[2], + ControllerBaseAddress + DAC960_V3_MailboxRegister8Offset); + writeb(CommandMailbox->Bytes[12], + ControllerBaseAddress + DAC960_V3_MailboxRegister12Offset); +} + +static inline DAC960_CommandIdentifier_T +DAC960_V3_ReadStatusCommandIdentifier(void *ControllerBaseAddress) +{ + return readb(ControllerBaseAddress + + DAC960_V3_StatusCommandIdentifierRegOffset); +} + +static inline DAC960_CommandStatus_T +DAC960_V3_ReadStatusRegister(void *ControllerBaseAddress) +{ + return readw(ControllerBaseAddress + DAC960_V3_StatusRegisterOffset); +} + + +/* + Define compatibility macros between Linux 2.0 and Linux 2.1. +*/ + +#if LINUX_VERSION_CODE < 0x20100 + +#define MODULE_PARM(Variable, Type) +#define ioremap_nocache(Offset, Size) vremap(Offset, Size) +#define iounmap(Address) vfree(Address) + +#endif + + +/* + Define prototypes for the forward referenced DAC960 Driver Internal Functions. +*/ + +static void DAC960_FinalizeController(DAC960_Controller_T *); +static int DAC960_Finalize(NotifierBlock_T *, unsigned long, void *); +static void DAC960_RequestFunction0(void); +static void DAC960_RequestFunction1(void); +static void DAC960_RequestFunction2(void); +static void DAC960_RequestFunction3(void); +static void DAC960_RequestFunction4(void); +static void DAC960_RequestFunction5(void); +static void DAC960_RequestFunction6(void); +static void DAC960_RequestFunction7(void); +static void DAC960_InterruptHandler(int, void *, Registers_T *); +static void DAC960_QueueMonitoringCommand(DAC960_Command_T *); +static void DAC960_MonitoringTimerFunction(unsigned long); +static int DAC960_Open(Inode_T *, File_T *); +static int DAC960_Release(Inode_T *, File_T *); +static int DAC960_IOCTL(Inode_T *, File_T *, unsigned int, unsigned long); +static int DAC960_UserIOCTL(Inode_T *, File_T *, unsigned int, unsigned long); +static void DAC960_InitializeGenericDiskInfo(GenericDiskInfo_T *); +static void DAC960_Message(DAC960_MessageLevel_T, char *, + DAC960_Controller_T *, ...); +static void DAC960_CreateProcEntries(void); +static void DAC960_DestroyProcEntries(void); + + +/* + Export the Kernel Mode IOCTL interface. +*/ + +EXPORT_SYMBOL(DAC960_KernelIOCTL); + + +#endif /* DAC960_DriverVersion */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/Makefile linux.pre11.3/drivers/block/Makefile --- linux.vanilla/drivers/block/Makefile Fri Apr 16 22:10:51 1999 +++ linux.pre11.3/drivers/block/Makefile Tue Jul 20 00:28:19 1999 @@ -234,6 +234,22 @@ endif endif +ifeq ($(CONFIG_BLK_CPQ_DA),y) +L_OBJS += cpqarray.o +else + ifeq ($(CONFIG_BLK_CPQ_DA),m) + M_OBJS += cpqarray.o + endif +endif + +ifeq ($(CONFIG_BLK_DEV_DAC960),y) +LX_OBJS += DAC960.o +else + ifeq ($(CONFIG_BLK_DEV_DAC960),m) + MX_OBJS += DAC960.o + endif +endif + ifeq ($(CONFIG_BLK_DEV_MD),y) LX_OBJS += md.o diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/cpqarray.c linux.pre11.3/drivers/block/cpqarray.c --- linux.vanilla/drivers/block/cpqarray.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/block/cpqarray.c Mon Jul 19 23:55:17 1999 @@ -0,0 +1,1791 @@ +/* + * Disk Array driver for Compaq SMART2 Controllers + * Copyright 1998 Compaq Computer 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, GOOD TITLE or + * NON INFRINGEMENT. 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. + * + * Questions/Comments/Bugfixes to arrays@compaq.com + * + * If you want to make changes, improve or add functionality to this + * driver, you'll probably need the Compaq Array Controller Interface + * Specificiation (Document number ECG086/1198) + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SMART2_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) + +#define DRIVER_NAME "Compaq SMART2 Driver (v 1.0.5)" +#define DRIVER_VERSION SMART2_DRIVER_VERSION(1,0,5) +#define MAJOR_NR COMPAQ_SMART2_MAJOR +#include +#include +#include + +#include "cpqarray.h" +#include "ida_cmd.h" +#include "smart1,2.h" +#include "ida_ioctl.h" + +#define READ_AHEAD 128 +#define NR_CMDS 128 /* This could probably go as high as ~400 */ + +#define MAX_CTLR 8 +#define CTLR_SHIFT 8 + +static int nr_ctlr = 0; +static ctlr_info_t *hba[MAX_CTLR] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +static int eisa[8] = { 0, 0 ,0 ,0, 0, 0 ,0 ,0 }; + +#define NR_PRODUCTS (sizeof(products)/sizeof(struct board_type)) + +/* board_id = Subsystem Device ID & Vendor ID + * product = Marketing Name for the board + * access = Address of the struct of function pointers + */ +struct board_type products[] = { + { 0x0040110E, "IDA", &smart1_access }, + { 0x0140110E, "IDA-2", &smart1_access }, + { 0x1040110E, "IAES", &smart1_access }, + { 0x2040110E, "SMART", &smart1_access }, + { 0x3040110E, "SMART-2/E", &smart2e_access }, + { 0x40300E11, "SMART-2/P", &smart2_access }, + { 0x40310E11, "SMART-2SL", &smart2_access }, + { 0x40320E11, "Smart Array 3200", &smart2_access }, + { 0x40330E11, "Smart Array 3100ES", &smart2_access }, + { 0x40340E11, "Smart Array 221", &smart2_access }, + { 0x40400E11, "Integrated Array", &smart4_access }, + { 0x40500E11, "Smart Array 4200", &smart4_access }, + { 0x40510E11, "Smart Array 4250ES", &smart4_access }, +}; + +static struct hd_struct * ida; +static int * ida_sizes; +static int * ida_blocksizes; +static int * ida_hardsizes; +static struct gendisk ida_gendisk[MAX_CTLR]; + +struct proc_dir_entry *proc_array = NULL; + +/* Debug... */ +#define DBG(s) do { s } while(0) +/* Debug (general info)... */ +#define DBGINFO(s) do { } while(0) +/* Debug Paranoid... */ +#define DBGP(s) do { } while(0) +/* Debug Extra Paranoid... */ +#define DBGPX(s) do { } while(0) + +int cpqarray_init(void); +static int cpqarray_pci_detect(void); +static int cpqarray_pci_init(ctlr_info_t *c, unchar bus, unchar device_fn); +static ulong remap_pci_mem(ulong base, ulong size); +static int cpqarray_eisa_detect(void); +static int pollcomplete(int ctlr); +static void getgeometry(int ctlr); +static void start_fwbk(int ctlr); + +static cmdlist_t * cmd_alloc(ctlr_info_t *h); +static void cmd_free(ctlr_info_t *h, cmdlist_t *c); + +static int sendcmd( + __u8 cmd, + int ctlr, + void *buff, + size_t size, + unsigned int blk, + unsigned int blkcnt, + unsigned int log_unit ); + +static int ida_open(struct inode *inode, struct file *filep); +static int ida_release(struct inode *inode, struct file *filep); +static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg); +static int ida_ctlr_ioctl(int ctlr, int dsk, ida_ioctl_t *io); + +static void do_ida_request(int i); +/* + * This is a hack. This driver eats a major number for each controller, and + * sets blkdev[xxx].request_fn to each one of these so the real request + * function knows what controller its working with. + */ +#define DO_IDA_REQUEST(x) { do_ida_request(x); } + +static void do_ida_request0(void) DO_IDA_REQUEST(0); +static void do_ida_request1(void) DO_IDA_REQUEST(1); +static void do_ida_request2(void) DO_IDA_REQUEST(2); +static void do_ida_request3(void) DO_IDA_REQUEST(3); +static void do_ida_request4(void) DO_IDA_REQUEST(4); +static void do_ida_request5(void) DO_IDA_REQUEST(5); +static void do_ida_request6(void) DO_IDA_REQUEST(6); +static void do_ida_request7(void) DO_IDA_REQUEST(7); + +static void start_io(ctlr_info_t *h); + +static inline void addQ(cmdlist_t **Qptr, cmdlist_t *c); +static inline cmdlist_t *removeQ(cmdlist_t **Qptr, cmdlist_t *c); +static inline void complete_buffers(struct buffer_head *bh, int ok); +static inline void complete_command(cmdlist_t *cmd, int timeout); + +static void do_ida_intr(int irq, void *dev_id, struct pt_regs * regs); +static void ida_timer(unsigned long tdata); +static int frevalidate_logvol(kdev_t dev); +static int revalidate_logvol(kdev_t dev, int maxusage); +static int revalidate_allvol(kdev_t dev); + +static void ida_procinit(int i); +static int ida_proc_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data); + +static void ida_geninit(struct gendisk *g) +{ + int ctlr = g-ida_gendisk; + int i,j; + drv_info_t *drv; + + for(i=0; idrv[i]; + if (!drv->nr_blks) + continue; + ida[(ctlr<nr_blks; + + for(j=0; j<16; j++) { + ida_blocksizes[(ctlr<blk_size; + } + ida_gendisk[ctlr].nr_real++; + } + +} + +struct file_operations ida_fops = { + NULL, /* lseek - default */ + block_read, /* read - general block-dev read */ + block_write, /* write - general block-dev write */ + NULL, /* readdir - bad */ + NULL, /* select */ + ida_ioctl, /* ioctl */ + NULL, /* mmap */ + ida_open, /* open code */ + NULL, + ida_release, /* release */ + block_fsync, /* fsync */ + NULL, /* fasync */ + NULL, /* Disk change */ + frevalidate_logvol, /* revalidate */ +}; + + +/* + * Get us a file in /proc/array that says something about each controller. + * Create /proc/array if it doesn't exist yet. + */ +static void ida_procinit(int i) +{ + struct proc_dir_entry *pd; + + if (proc_array == NULL) { + proc_array = create_proc_entry("array", S_IFDIR|S_IRUGO|S_IXUGO, + &proc_root); + if (!proc_array) return; + } + + pd = create_proc_entry(hba[i]->devname, S_IFREG|S_IRUGO, proc_array); + if (!pd) return; + pd->read_proc = ida_proc_get_info; + pd->data = hba[i]; +} + +/* + * Report information about this controller. + */ +static int ida_proc_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data) +{ + off_t pos = 0; + off_t len = 0; + int size, i, ctlr; + ctlr_info_t *h = (ctlr_info_t*)data; + drv_info_t *drv; +#ifdef CPQ_PROC_PRINT_QUEUES + cmdlist_t *c; +#endif + + ctlr = h->ctlr; + size = sprintf(buffer, "%s: Compaq %s Controller\n" + " Board ID: %08lx\n" + " Firmware Revision: %c%c%c%c\n" + " Controller Sig: %08lx\n" + " Memory Address: %08lx\n" + " I/O Port: %04x\n" + " IRQ: %x\n" + " Logical drives: %d\n" + " Physical drives: %d\n\n" + " Current Q depth: %d\n" + " Max Q depth since init: %d\n\n", + h->devname, + h->product_name, + (unsigned long)h->board_id, + h->firm_rev[0], h->firm_rev[1], h->firm_rev[2], h->firm_rev[3], + (unsigned long)h->ctlr_sig, (unsigned long)h->vaddr, + (unsigned int) h->ioaddr, (unsigned int)h->intr, + h->log_drives, h->phys_drives, + h->Qdepth, h->maxQsinceinit); + + pos += size; len += size; + + size = sprintf(buffer+len, "Logical Drive Info:\n"); + pos += size; len += size; + + for(i=0; ilog_drives; i++) { + drv = &h->drv[i]; + size = sprintf(buffer+len, "ida/c%dd%d: blksz=%d nr_blks=%d\n", + ctlr, i, drv->blk_size, drv->nr_blks); + pos += size; len += size; + } + +#ifdef CPQ_PROC_PRINT_QUEUES + size = sprintf(buffer+len, "\nCurrent Queues:\n"); + pos += size; len += size; + + c = h->reqQ; + size = sprintf(buffer+len, "reqQ = %p", c); pos += size; len += size; + if (c) c=c->next; + while(c && c != h->reqQ) { + size = sprintf(buffer+len, "->%p", c); + pos += size; len += size; + c=c->next; + } + + c = h->cmpQ; + size = sprintf(buffer+len, "\ncmpQ = %p", c); pos += size; len += size; + if (c) c=c->next; + while(c && c != h->cmpQ) { + size = sprintf(buffer+len, "->%p", c); + pos += size; len += size; + c=c->next; + } + + size = sprintf(buffer+len, "\n"); pos += size; len += size; +#endif + size = sprintf(buffer+len, "nr_allocs = %d\nnr_frees = %d\n", + h->nr_allocs, h->nr_frees); + pos += size; len += size; + + *eof = 1; + *start = buffer+offset; + len -= offset; + if (len>length) + len = length; + return len; +} + +#ifdef MODULE + +MODULE_PARM(eisa, "1-8i"); +EXPORT_NO_SYMBOLS; + +/* This is a bit of a hack... */ +int init_module(void) +{ + int i, j; + if (cpqarray_init() == 0) /* all the block dev numbers already used */ + return -EIO; /* or no controllers were found */ + + for(i=0; iaccess.set_intr_mask(hba[i], 0); + free_irq(hba[i]->intr, hba[i]); + iounmap((void*)hba[i]->vaddr); + unregister_blkdev(MAJOR_NR+i, hba[i]->devname); + del_timer(&hba[i]->timer); + remove_proc_entry(hba[i]->devname, proc_array); + kfree(hba[i]->cmd_pool); + kfree(hba[i]->cmd_pool_bits); + + if (gendisk_head == &ida_gendisk[i]) { + gendisk_head = ida_gendisk[i].next; + } else { + for(g=gendisk_head; g; g=g->next) { + if (g->next == &ida_gendisk[i]) { + g->next = ida_gendisk[i].next; + break; + } + } + } + } + remove_proc_entry("array", &proc_root); + kfree(ida); + kfree(ida_sizes); + kfree(ida_hardsizes); + kfree(ida_blocksizes); + + +} +#endif /* MODULE */ + +/* + * This is it. Find all the controllers and register them. I really hate + * stealing all these major device numbers. + * returns the number of block devices registered. + */ +int cpqarray_init(void) +{ + void (*request_fns[MAX_CTLR])(void) = { + do_ida_request0, do_ida_request1, + do_ida_request2, do_ida_request3, + do_ida_request4, do_ida_request5, + do_ida_request6, do_ida_request7, + }; + int i; + int num_cntlrs_reg = 0; + + /* detect controllers */ + cpqarray_pci_detect(); + cpqarray_eisa_detect(); + + if (nr_ctlr == 0) + return(num_cntlrs_reg); + + printk(DRIVER_NAME "\n"); + printk("Found %d controller(s)\n", nr_ctlr); + + /* allocate space for disk structs */ + ida = kmalloc(sizeof(struct hd_struct)*nr_ctlr*NWD*16, GFP_KERNEL); + + if(ida==NULL) + { + printk( KERN_ERR "cpqarray: out of memory"); + return(num_cntlrs_reg); + } + ida_sizes = kmalloc(sizeof(int)*nr_ctlr*NWD*16, GFP_KERNEL); + if(ida_sizes==NULL) + { + kfree(ida); + printk( KERN_ERR "cpqarray: out of memory"); + return(num_cntlrs_reg); + } + + ida_blocksizes = kmalloc(sizeof(int)*nr_ctlr*NWD*16, GFP_KERNEL); + if(ida_blocksizes==NULL) + { + kfree(ida); + kfree(ida_sizes); + printk( KERN_ERR "cpqarray: out of memory"); + return(num_cntlrs_reg); + } + + ida_hardsizes = kmalloc(sizeof(int)*nr_ctlr*NWD*16, GFP_KERNEL); + if(ida_hardsizes==NULL) + { + kfree(ida); + kfree(ida_sizes); + kfree(ida_blocksizes); + printk( KERN_ERR "cpqarray: out of memory"); + return(num_cntlrs_reg); + } + + memset(ida, 0, sizeof(struct hd_struct)*nr_ctlr*NWD*16); + memset(ida_sizes, 0, sizeof(int)*nr_ctlr*NWD*16); + memset(ida_blocksizes, 0, sizeof(int)*nr_ctlr*NWD*16); + memset(ida_hardsizes, 0, sizeof(int)*nr_ctlr*NWD*16); + memset(ida_gendisk, 0, sizeof(struct gendisk)*MAX_CTLR); + + /* + * register block devices + * Find disks and fill in structs + * Get an interrupt, set the Q depth and get into /proc + */ + for(i=0; i< nr_ctlr; i++) { + /* If this successful it should insure that we are the only */ + /* instance of the driver */ + if (register_blkdev(MAJOR_NR+i, hba[i]->devname, &ida_fops)) { + printk(KERN_ERR "cpqarray: Unable to get major number %d for ida\n", + MAJOR_NR+i); + continue; + } + + hba[i]->access.set_intr_mask(hba[i], 0); + if (request_irq(hba[i]->intr, do_ida_intr, + SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i])) { + + printk(KERN_ERR "cpqarray: Unable to get irq %d for %s\n", + hba[i]->intr, hba[i]->devname); + unregister_blkdev(MAJOR_NR+i, hba[i]->devname); + continue; + } + num_cntlrs_reg++; + hba[i]->cmd_pool = (cmdlist_t *)kmalloc( + NR_CMDS * sizeof(cmdlist_t), GFP_KERNEL); + hba[i]->cmd_pool_bits = (__u32*)kmalloc( + ((NR_CMDS+31)/32)*sizeof(__u32), GFP_KERNEL); + + if(hba[i]->cmd_pool_bits == NULL || hba[i]->cmd_pool == NULL) + { + nr_ctlr = i; + if(hba[i]->cmd_pool_bits) + kfree(hba[i]->cmd_pool_bits); + if(hba[i]->cmd_pool) + kfree(hba[i]->cmd_pool); + free_irq(hba[i]->intr, hba[i]); + unregister_blkdev(MAJOR_NR+i, hba[i]->devname); + num_cntlrs_reg--; + printk( KERN_ERR "cpqarray: out of memory"); + + /* If num_cntlrs_reg == 0, no controllers worked. + * init_module will fail, so clean up global + * memory that clean_module would do. + */ + if (num_cntlrs_reg == 0) + { + kfree(ida); + kfree(ida_sizes); + kfree(ida_hardsizes); + kfree(ida_blocksizes); + } + return(num_cntlrs_reg); + + } + memset(hba[i]->cmd_pool, 0, NR_CMDS * sizeof(cmdlist_t)); + memset(hba[i]->cmd_pool_bits, 0, ((NR_CMDS+31)/32)*sizeof(__u32)); + printk(KERN_INFO "cpqarray: Finding drives on %s", + hba[i]->devname); + getgeometry(i); + start_fwbk(i); + + hba[i]->access.set_intr_mask(hba[i], FIFO_NOT_EMPTY); + + ida_procinit(i); + ida_gendisk[i].major = MAJOR_NR + i; + ida_gendisk[i].major_name = "ida"; + ida_gendisk[i].minor_shift = NWD_SHIFT; + ida_gendisk[i].max_p = 16; + ida_gendisk[i].max_nr = 16; + ida_gendisk[i].init = ida_geninit; + ida_gendisk[i].part = ida + (i*256); + ida_gendisk[i].sizes = ida_sizes + (i*256); + /* ida_gendisk[i].nr_real is handled by getgeometry */ + + blk_dev[MAJOR_NR+i].request_fn = request_fns[i]; + blksize_size[MAJOR_NR+i] = ida_blocksizes + (i*256); + hardsect_size[MAJOR_NR+i] = ida_hardsizes + (i*256); + read_ahead[MAJOR_NR+i] = READ_AHEAD; + + /* Get on the disk list */ + ida_gendisk[i].next = gendisk_head; + gendisk_head = &ida_gendisk[i]; + + init_timer(&hba[i]->timer); + hba[i]->timer.expires = jiffies + IDA_TIMER; + hba[i]->timer.data = (unsigned long)hba[i]; + hba[i]->timer.function = ida_timer; + add_timer(&hba[i]->timer); + + } + /* done ! */ + return(num_cntlrs_reg); +} + +/* + * Find the controller and initialize it + * Cannot use the class code to search, because older array controllers use + * 0x018000 and new ones use 0x010400. So I might as well search for each + * each device IDs, being there are only going to be three of them. + */ +static int cpqarray_pci_detect(void) +{ + int index; + unchar bus=0, dev_fn=0; + +#define IDA_BOARD_TYPES 3 + static int ida_vendor_id[IDA_BOARD_TYPES] = { PCI_VENDOR_ID_DEC, + PCI_VENDOR_ID_NCR, PCI_VENDOR_ID_COMPAQ }; + static int ida_device_id[IDA_BOARD_TYPES] = { PCI_DEVICE_ID_COMPAQ_42XX, + PCI_DEVICE_ID_NCR_53C1510, PCI_DEVICE_ID_COMPAQ_SMART2P }; + int brdtype; + + /* search for all PCI board types that could be for this driver */ + for(brdtype=0; brdtypedevname, "ida%d", nr_ctlr); + hba[nr_ctlr]->ctlr = nr_ctlr; + nr_ctlr++; + + } + } + + return nr_ctlr; +} +/* + * Find the IO address of the controller, its IRQ and so forth. Fill + * in some basic stuff into the ctlr_info_t structure. + */ +static int cpqarray_pci_init(ctlr_info_t *c, unchar bus, unchar device_fn) +{ + ushort vendor_id, device_id, command; + unchar cache_line_size, latency_timer; + unchar irq, revision; + uint addr[6]; + __u32 board_id; + struct pci_dev *pdev; + + int i; + + pdev = pci_find_slot(bus, device_fn); + vendor_id = pdev->vendor; + device_id = pdev->device; + irq = pdev->irq; + + for(i=0; i<6; i++) + addr[i] = pdev->base_address[i]; + + (void) pcibios_read_config_word(bus, device_fn, + PCI_COMMAND,&command); + (void) pcibios_read_config_byte(bus, device_fn, + PCI_CLASS_REVISION,&revision); + (void) pcibios_read_config_byte(bus, device_fn, + PCI_CACHE_LINE_SIZE, &cache_line_size); + (void) pcibios_read_config_byte(bus, device_fn, + PCI_LATENCY_TIMER, &latency_timer); + + (void) pcibios_read_config_dword(bus, device_fn, 0x2c, &board_id); + +DBGINFO( + printk("vendor_id = %x\n", vendor_id); + printk("device_id = %x\n", device_id); + printk("command = %x\n", command); + for(i=0; i<6; i++) + printk("addr[%d] = %x\n", i, addr[i]); + printk("revision = %x\n", revision); + printk("irq = %x\n", irq); + printk("cache_line_size = %x\n", cache_line_size); + printk("latency_timer = %x\n", latency_timer); + printk("board_id = %x\n", board_id); +); + + c->intr = irq; + c->ioaddr = addr[0] & ~0x1; + + /* + * Memory base addr is first addr with the first bit _not_ set + */ + for(i=0; i<6; i++) + if (!(addr[i] & 0x1)) { + c->paddr = addr[i]; + break; + } + c->vaddr = remap_pci_mem(c->paddr, 128); + c->board_id = board_id; + + for(i=0; iproduct_name = products[i].product_name; + c->access = *(products[i].access); + break; + } + } + if (i == NR_PRODUCTS) { + printk(KERN_WARNING "cpqarray: Sorry, I don't know how" + " to access the SMART Array controller %08lx\n", + (unsigned long)board_id); + return -1; + } + + return 0; +} + +/* + * Map (physical) PCI mem into (virtual) kernel space + */ +static ulong remap_pci_mem(ulong base, ulong size) +{ + ulong page_base = ((ulong) base) & PAGE_MASK; + ulong page_offs = ((ulong) base) - page_base; + ulong page_remapped = (ulong) ioremap(page_base, page_offs+size); + + return (ulong) (page_remapped ? (page_remapped + page_offs) : 0UL); +} + +/* + * Copy the contents of the ints[] array passed to us by init. + */ +void cpqarray_setup(char *str, int *ints) +{ + int i; + for(i=0; iioaddr = eisa[i]; + + /* + * Read the config register to find our interrupt + */ + intr = inb(eisa[i]+0xCC0) >> 4; + if (intr & 1) intr = 11; + else if (intr & 2) intr = 10; + else if (intr & 4) intr = 14; + else if (intr & 8) intr = 15; + + hba[nr_ctlr]->intr = intr; + sprintf(hba[nr_ctlr]->devname, "ida%d", nr_ctlr); + hba[nr_ctlr]->product_name = products[j].product_name; + hba[nr_ctlr]->access = *(products[j].access); + hba[nr_ctlr]->ctlr = nr_ctlr; + hba[nr_ctlr]->board_id = board_id; + +DBGINFO( + printk("i = %d, j = %d\n", i, j); + printk("irq = %x\n", intr); + printk("product name = %s\n", products[j].product_name); + printk("board_id = %x\n", board_id); +); + + nr_ctlr++; + i++; + } + + return nr_ctlr; +} + + +/* + * Open. Make sure the device is really there. + */ +static int ida_open(struct inode *inode, struct file *filep) +{ + int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR; + int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT; + + DBGINFO(printk("ida_open %x (%x:%x)\n", inode->i_rdev, ctlr, dsk) ); + if (ctlr > MAX_CTLR || hba[ctlr] == NULL) + return -ENXIO; + + if (!suser() && ida_sizes[(ctlr << CTLR_SHIFT) + + MINOR(inode->i_rdev)] == 0) + return -ENXIO; + + /* + * Root is allowed to open raw volume zero even if its not configured + * so array config can still work. I don't think I really like this, + * but I'm already using way to many device nodes to claim another one + * for "raw controller". + */ + if (suser() + && ida_sizes[(ctlr << CTLR_SHIFT) + MINOR(inode->i_rdev)] == 0 + && MINOR(inode->i_rdev) != 0) + return -ENXIO; + + hba[ctlr]->drv[dsk].usage_count++; + hba[ctlr]->usage_count++; + MOD_INC_USE_COUNT; + return 0; +} + +/* + * Close. Sync first. + */ +static int ida_release(struct inode *inode, struct file *filep) +{ + int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR; + int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT; + + DBGINFO(printk("ida_release %x (%x:%x)\n", inode->i_rdev, ctlr, dsk) ); + fsync_dev(inode->i_rdev); + + hba[ctlr]->drv[dsk].usage_count--; + hba[ctlr]->usage_count--; + MOD_DEC_USE_COUNT; + return 0; +} + +/* + * Enqueuing and dequeuing functions for cmdlists. + */ +static inline void addQ(cmdlist_t **Qptr, cmdlist_t *c) +{ + if (*Qptr == NULL) { + *Qptr = c; + c->next = c->prev = c; + } else { + c->prev = (*Qptr)->prev; + c->next = (*Qptr); + (*Qptr)->prev->next = c; + (*Qptr)->prev = c; + } +} + +static inline cmdlist_t *removeQ(cmdlist_t **Qptr, cmdlist_t *c) +{ + if (c && c->next != c) { + if (*Qptr == c) *Qptr = c->next; + c->prev->next = c->next; + c->next->prev = c->prev; + } else { + *Qptr = NULL; + } + return c; +} + +/* + * Get a request and submit it to the controller. + * This routine needs to grab all the requests it possibly can from the + * req Q and submit them. Interrupts are off (and need to be off) when you + * are in here (either via the dummy do_ida_request functions or by being + * called from the interrupt handler + */ +static void do_ida_request(int ctlr) +{ + ctlr_info_t *h = hba[ctlr]; + cmdlist_t *c; + int seg, sect; + char *lastdataend; + struct buffer_head *bh; + struct request *creq; + + creq = blk_dev[MAJOR_NR+ctlr].current_request; + if (creq == NULL || creq->rq_status == RQ_INACTIVE) + { + start_io(h); + return; + } + + if (ctlr != MAJOR(creq->rq_dev)-MAJOR_NR || + ctlr > nr_ctlr || h == NULL) { + printk("cpqarray: doreq cmd for %d, %x at %p\n", + ctlr, creq->rq_dev, creq); + complete_buffers(creq->bh, 0); + start_io(h); + return; + } + + if ((c = cmd_alloc(h)) == NULL) + { + start_io(h); + return; + } + + bh = creq->bh; + + c->ctlr = ctlr; + c->hdr.unit = MINOR(creq->rq_dev) >> NWD_SHIFT; + c->hdr.size = sizeof(rblk_t) >> 2; + c->size += sizeof(rblk_t); + + c->req.hdr.blk = ida[(ctlr<rq_dev)].start_sect + creq->sector; + c->bh = bh; +DBGPX( + if (bh == NULL) + panic("bh == NULL?"); + + printk("sector=%d, nr_sectors=%d\n", creq->sector, creq->nr_sectors); +); + seg = 0; lastdataend = NULL; + sect = 0; + while(bh) { + sect += bh->b_size/512; +DBGPX( + if (bh->b_size % 512) { + printk("Oh damn. %d+%d, size = %d\n", creq->sector, sect, bh->b_size); + panic("b_size %% 512 != 0"); + } +); + if (bh->b_data == lastdataend) { + c->req.sg[seg-1].size += bh->b_size; + lastdataend += bh->b_size; + } else { + c->req.sg[seg].size = bh->b_size; + c->req.sg[seg].addr = (__u32)virt_to_bus(bh->b_data); + lastdataend = bh->b_data + bh->b_size; + if (++seg == SG_MAX) + break; + } + bh = bh->b_reqnext; + } +DBGPX( printk("Submitting %d sectors in %d segments\n", sect, seg); ); + c->req.hdr.sg_cnt = seg; + c->req.hdr.blk_cnt = sect; + + creq->sector += sect; + creq->nr_sectors -= sect; + + /* Ready the next request: + * Fix up creq if we still have more buffers in the buffer chain, or + * mark this request as done and ready the next one. + */ + if (creq->nr_sectors) { +DBGPX( + if (bh==NULL) { + printk("sector=%d, nr_sectors=%d, sect=%d, seg=%d\n", + creq->sector, creq->nr_sectors, sect, seg); + panic("mother..."); + } +); + creq->bh = bh->b_reqnext; + bh->b_reqnext = NULL; +DBGPX( printk("More to do on same request %p\n", creq); ); + } else { +DBGPX( printk("Done with %p, queueing %p\n", creq, creq->next); ); + creq->rq_status = RQ_INACTIVE; + blk_dev[MAJOR_NR+ctlr].current_request = creq->next; + wake_up(&wait_for_request); + } + + c->req.hdr.cmd = (creq->cmd == READ) ? IDA_READ : IDA_WRITE; + c->type = CMD_RWREQ; + + /* Put the request on the tail of the request queue */ + addQ(&h->reqQ, c); + h->Qdepth++; + if (h->Qdepth > h->maxQsinceinit) + h->maxQsinceinit = h->Qdepth; + + start_io(h); +} + +/* + * start_io submits everything on a controller's request queue + * and moves it to the completion queue. + * + * Interrupts had better be off if you're in here + */ +static void start_io(ctlr_info_t *h) +{ + cmdlist_t *c; + + while((c = h->reqQ) != NULL) { + /* Can't do anything if we're busy */ + if (h->access.fifo_full(h) == 0) + return; + + /* Get the first entry from the request Q */ + removeQ(&h->reqQ, c); + h->Qdepth--; + + /* Tell the controller to do our bidding */ + h->access.submit_command(h, c); + + /* Get onto the completion Q */ + addQ(&h->cmpQ, c); + } +} + +static inline void complete_buffers(struct buffer_head *bh, int ok) +{ + struct buffer_head *xbh; + while(bh) { + xbh = bh->b_reqnext; + bh->b_reqnext = NULL; + + bh->b_end_io(bh, ok); + + bh = xbh; + } +} +/* + * Mark all buffers that cmd was responsible for + */ +static inline void complete_command(cmdlist_t *cmd, int timeout) +{ + char buf[80]; + int ok=1; + + if (cmd->req.hdr.rcode & RCODE_NONFATAL && + (hba[cmd->ctlr]->misc_tflags & MISC_NONFATAL_WARN) == 0) { + sprintf(buf, "Non Fatal error on ida/c%dd%d\n", + cmd->ctlr, cmd->hdr.unit); + console_print(buf); + hba[cmd->ctlr]->misc_tflags |= MISC_NONFATAL_WARN; + } + if (cmd->req.hdr.rcode & RCODE_FATAL) { + sprintf(buf, "Fatal error on ida/c%dd%d\n", + cmd->ctlr, cmd->hdr.unit); + console_print(buf); + ok = 0; + } + if (cmd->req.hdr.rcode & RCODE_INVREQ) { + sprintf(buf, "Invalid request on ida/c%dd%d = (cmd=%x sect=%d cnt=%d sg=%d ret=%x)\n", + cmd->ctlr, cmd->hdr.unit, cmd->req.hdr.cmd, + cmd->req.hdr.blk, cmd->req.hdr.blk_cnt, + cmd->req.hdr.sg_cnt, cmd->req.hdr.rcode); + console_print(buf); + ok = 0; + } + if (timeout) ok = 0; + complete_buffers(cmd->bh, ok); +} + +/* + * The controller will interrupt us upon completion of commands. + * Find the command on the completion queue, remove it, tell the OS and + * try to queue up more IO + */ +static void do_ida_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + ctlr_info_t *h = dev_id; + cmdlist_t *c; + unsigned long istat; + unsigned long flags; + __u32 a,a1; + + + istat = h->access.intr_pending(h); + /* Is this interrupt for us? */ + if (istat == 0) + return; + + /* + * If there are completed commands in the completion queue, + * we had better do something about it. + */ + spin_lock_irqsave(&io_request_lock, flags); + if (istat & FIFO_NOT_EMPTY) { + while((a = h->access.command_completed(h))) { + a1 = a; a &= ~3; + if ((c = h->cmpQ) == NULL) + { + printk(KERN_WARNING "cpqarray: Completion of %08lx ignored\n", (unsigned long)a1); + continue; + } + while(c->busaddr != a) { + c = c->next; + if (c == h->cmpQ) + break; + } + /* + * If we've found the command, take it off the + * completion Q and free it + */ + if (c->busaddr == a) { + removeQ(&h->cmpQ, c); + if (c->type == CMD_RWREQ) { + complete_command(c, 0); + cmd_free(h, c); + } else if (c->type == CMD_IOCTL_PEND) { + c->type = CMD_IOCTL_DONE; + } + continue; + } + } + } + + /* + * See if we can queue up some more IO + */ + do_ida_request(h->ctlr); + spin_unlock_irqrestore(&io_request_lock, flags); +} + +/* + * This timer was for timing out requests that haven't happened after + * IDA_TIMEOUT. That wasn't such a good idea. This timer is used to + * reset a flags structure so we don't flood the user with + * "Non-Fatal error" messages. + */ +static void ida_timer(unsigned long tdata) +{ + ctlr_info_t *h = (ctlr_info_t*)tdata; + + h->timer.expires = jiffies + IDA_TIMER; + add_timer(&h->timer); + h->misc_tflags = 0; +} + +/* + * ida_ioctl does some miscellaneous stuff like reporting drive geometry, + * setting readahead and submitting commands from userspace to the controller. + */ +static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg) +{ + int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR; + int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT; + int error; + int diskinfo[4]; + struct hd_geometry *geo = (struct hd_geometry *)arg; + ida_ioctl_t *io = (ida_ioctl_t*)arg; + ida_ioctl_t my_io; + + switch(cmd) { + case HDIO_GETGEO: + if (hba[ctlr]->drv[dsk].cylinders) { + diskinfo[0] = hba[ctlr]->drv[dsk].heads; + diskinfo[1] = hba[ctlr]->drv[dsk].sectors; + diskinfo[2] = hba[ctlr]->drv[dsk].cylinders; + } else { + diskinfo[0] = 0xff; + diskinfo[1] = 0x3f; + diskinfo[2] = hba[ctlr]->drv[dsk].nr_blks / (0xff*0x3f); + } + put_user(diskinfo[0], &geo->heads); + put_user(diskinfo[1], &geo->sectors); + put_user(diskinfo[2], &geo->cylinders); + put_user(ida[(ctlr<i_rdev)].start_sect, &geo->start); + return 0; + case IDAGETDRVINFO: + return copy_to_user(&io->c.drv,&hba[ctlr]->drv[dsk],sizeof(drv_info_t)); + case BLKGETSIZE: + if (!arg) return -EINVAL; + put_user(ida[(ctlr<i_rdev)].nr_sects, (long*)arg); + return 0; + case BLKRASET: + if (!suser()) return -EACCES; + if (!(inode->i_rdev)) return -EINVAL; + if (arg>0xff) return -EINVAL; + read_ahead[MAJOR(inode->i_rdev)] = arg; + return 0; + case BLKRAGET: + if (!arg) return -EINVAL; + put_user(read_ahead[MAJOR(inode->i_rdev)], (int*)arg); + return 0; + case BLKRRPART: + return revalidate_logvol(inode->i_rdev, 1); + case IDAPASSTHRU: + if (!suser()) return -EPERM; + error = copy_from_user(&my_io, io, sizeof(my_io)); + if (error) return error; + error = ida_ctlr_ioctl(ctlr, dsk, &my_io); + if (error) return error; + error = copy_to_user(io, &my_io, sizeof(my_io)); + return error; + case IDAGETCTLRSIG: + if (!arg) return -EINVAL; + put_user(hba[ctlr]->ctlr_sig, (int*)arg); + return 0; + case IDAREVALIDATEVOLS: + return revalidate_allvol(inode->i_rdev); + case IDADRIVERVERSION: + if (!arg) return -EINVAL; + put_user(DRIVER_VERSION, (unsigned long*)arg); + return 0; + + RO_IOCTLS(inode->i_rdev, arg); + + default: + return -EBADRQC; + } + +} +/* + * ida_ctlr_ioctl is for passing commands to the controller from userspace. + * The command block (io) has already been copied to kernel space for us, + * however, any elements in the sglist need to be copied to kernel space + * or copied back to userspace. + * + * Only root may perform a controller passthru command, however I'm not doing + * any serious sanity checking on the arguments. Doing an IDA_WRITE_MEDIA and + * putting a 64M buffer in the sglist is probably a *bad* idea. + */ +static int ida_ctlr_ioctl(int ctlr, int dsk, ida_ioctl_t *io) +{ + ctlr_info_t *h = hba[ctlr]; + cmdlist_t *c; + void *p = NULL; + unsigned long flags; + int error; + + if ((c = cmd_alloc(NULL)) == NULL) + return -ENOMEM; + c->ctlr = ctlr; + c->hdr.unit = (io->unit & UNITVALID) ? (io->unit & ~UNITVALID) : dsk; + c->hdr.size = sizeof(rblk_t) >> 2; + c->size += sizeof(rblk_t); + + c->req.hdr.cmd = io->cmd; + c->req.hdr.blk = io->blk; + c->req.hdr.blk_cnt = io->blk_cnt; + c->type = CMD_IOCTL_PEND; + + /* Pre submit processing */ + switch(io->cmd) { + case PASSTHRU_A: + p = kmalloc(io->sg[0].size, GFP_KERNEL); + if (!p) + { + error = -ENOMEM; + cmd_free(NULL, c); + return(error); + } + copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size); + c->req.bp = virt_to_bus(&(io->c)); + c->req.sg[0].size = io->sg[0].size; + c->req.sg[0].addr = virt_to_bus(p); + c->req.hdr.sg_cnt = 1; + break; + case IDA_READ: + p = kmalloc(io->sg[0].size, GFP_KERNEL); + if (!p) + { + error = -ENOMEM; + cmd_free(NULL, c); + return(error); + } + + c->req.sg[0].size = io->sg[0].size; + c->req.sg[0].addr = virt_to_bus(p); + c->req.hdr.sg_cnt = 1; + break; + case IDA_WRITE: + case IDA_WRITE_MEDIA: + case DIAG_PASS_THRU: + p = kmalloc(io->sg[0].size, GFP_KERNEL); + if (!p) + { + error = -ENOMEM; + cmd_free(NULL, c); + return(error); + } + copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size); + c->req.sg[0].size = io->sg[0].size; + c->req.sg[0].addr = virt_to_bus(p); + c->req.hdr.sg_cnt = 1; + break; + default: + c->req.sg[0].size = sizeof(io->c); + c->req.sg[0].addr = virt_to_bus(&io->c); + c->req.hdr.sg_cnt = 1; + } + + /* Put the request on the tail of the request queue */ + spin_lock_irqsave(&io_request_lock, flags); + addQ(&h->reqQ, c); + h->Qdepth++; + start_io(h); + spin_unlock_irqrestore(&io_request_lock, flags); + + /* Wait for completion */ + while(c->type != CMD_IOCTL_DONE) + schedule(); + + /* Post submit processing */ + switch(io->cmd) { + case PASSTHRU_A: + case IDA_READ: + case DIAG_PASS_THRU: + copy_to_user((void*)io->sg[0].addr, p, io->sg[0].size); + /* fall through and free p */ + case IDA_WRITE: + case IDA_WRITE_MEDIA: + kfree(p); + break; + default: + /* Nothing to do */ + } + + io->rcode = c->req.hdr.rcode; + cmd_free(NULL, c); + return(0); +} + +/* + * Commands are pre-allocated in a large block. Here we use a simple bitmap + * scheme to suballocte them to the driver. Operations that are not time + * critical (and can wait for kmalloc and possibly sleep) can pass in NULL + * as the first argument to get a new command. + */ +static cmdlist_t * cmd_alloc(ctlr_info_t *h) +{ + cmdlist_t * c; + int i; + + if (h == NULL) { + c = (cmdlist_t*)kmalloc(sizeof(cmdlist_t), GFP_KERNEL); + if(c==NULL) + return NULL; + } else { + do { + i = find_first_zero_bit(h->cmd_pool_bits, NR_CMDS); + if (i == NR_CMDS) + return NULL; + } while(test_and_set_bit(i%32, h->cmd_pool_bits+(i/32)) != 0); + c = h->cmd_pool + i; + h->nr_allocs++; + } + + memset(c, 0, sizeof(cmdlist_t)); + c->busaddr = virt_to_bus(c); + return c; +} + +static void cmd_free(ctlr_info_t *h, cmdlist_t *c) +{ + int i; + + if (h == NULL) { + kfree(c); + } else { + i = c - h->cmd_pool; + clear_bit(i%32, h->cmd_pool_bits+(i/32)); + h->nr_frees++; + } +} + +/*********************************************************************** + name: sendcmd + Send a command to an IDA using the memory mapped FIFO interface + and wait for it to complete. + This routine should only be called at init time. +***********************************************************************/ +static int sendcmd( + __u8 cmd, + int ctlr, + void *buff, + size_t size, + unsigned int blk, + unsigned int blkcnt, + unsigned int log_unit ) +{ + cmdlist_t *c; + int complete; + unsigned long temp; + unsigned long i; + ctlr_info_t *info_p = hba[ctlr]; + + c = cmd_alloc(info_p); + c->ctlr = ctlr; + c->hdr.unit = log_unit; + c->hdr.prio = 0; + c->hdr.size = sizeof(rblk_t) >> 2; + c->size += sizeof(rblk_t); + + /* The request information. */ + c->req.hdr.next = 0; + c->req.hdr.rcode = 0; + c->req.bp = 0; + c->req.hdr.sg_cnt = 1; + c->req.hdr.reserved = 0; + + if (size == 0) + c->req.sg[0].size = 512; + else + c->req.sg[0].size = size; + + c->req.hdr.blk = blk; + c->req.hdr.blk_cnt = blkcnt; + c->req.hdr.cmd = (unsigned char) cmd; + c->req.sg[0].addr = (__u32) virt_to_bus(buff); + /* + * Disable interrupt + */ + info_p->access.set_intr_mask(info_p, 0); + /* Make sure there is room in the command FIFO */ + /* Actually it should be completely empty at this time. */ + for (i = 200000; i > 0; i--) { + temp = info_p->access.fifo_full(info_p); + if (temp != 0) { + break; + } + udelay(10); +DBG( + printk(KERN_WARNING "cpqarray ida%d: idaSendPciCmd FIFO full," + " waiting!\n", ctlr); +); + } + /* + * Send the cmd + */ + info_p->access.submit_command(info_p, c); + complete = pollcomplete(ctlr); + if (complete != 1) { + if (complete != c->busaddr) { + printk( KERN_WARNING + "cpqarray ida%d: idaSendPciCmd " + "Invalid command list address returned! (%08lx)\n", + ctlr, (unsigned long)complete); + cmd_free(info_p, c); + return (IO_ERROR); + } + } else { + printk( KERN_WARNING + "cpqarray ida%d: idaSendPciCmd Timeout out, " + "No command list address returned!\n", + ctlr); + cmd_free(info_p, c); + return (IO_ERROR); + } + + if (c->req.hdr.rcode & 0x00FE) { + if (!(c->req.hdr.rcode & BIG_PROBLEM)) { + printk( KERN_WARNING + "cpqarray ida%d: idaSendPciCmd, error: " + "Controller failed at init time " + "cmd: 0x%x, return code = 0x%x\n", + ctlr, c->req.hdr.cmd, c->req.hdr.rcode); + + cmd_free(info_p, c); + return (IO_ERROR); + } + } + cmd_free(info_p, c); + return (IO_OK); +} + +static int frevalidate_logvol(kdev_t dev) +{ + return revalidate_logvol(dev, 0); +} + +/* + * revalidate_allvol is for online array config utilities. After a + * utility reconfigures the drives in the array, it can use this function + * (through an ioctl) to make the driver zap any previous disk structs for + * that controller and get new ones. + * + * Right now I'm using the getgeometry() function to do this, but this + * function should probably be finer grained and allow you to revalidate one + * particualar logical volume (instead of all of them on a particular + * controller). + */ +static int revalidate_allvol(kdev_t dev) +{ + int ctlr, i; + unsigned long flags; + + ctlr = MAJOR(dev) - MAJOR_NR; + if (MINOR(dev) != 0) + return -ENXIO; + + spin_lock_irqsave(&io_request_lock, flags); + if (hba[ctlr]->usage_count > 1) { + spin_unlock_irqrestore(&io_request_lock, flags); + printk(KERN_WARNING "cpqarray: Device busy for volume" + " revalidation (usage=%d)\n", hba[ctlr]->usage_count); + return -EBUSY; + } + spin_unlock_irqrestore(&io_request_lock, flags); + hba[ctlr]->usage_count++; + + /* + * Set the partition and block size structures for all volumes + * on this controller to zero. We will reread all of this data + */ + memset(ida+(ctlr*256), 0, sizeof(struct hd_struct)*NWD*16); + memset(ida_sizes+(ctlr*256), 0, sizeof(int)*NWD*16); + memset(ida_blocksizes+(ctlr*256), 0, sizeof(int)*NWD*16); + memset(ida_hardsizes+(ctlr*256), 0, sizeof(int)*NWD*16); + memset(hba[ctlr]->drv, 0, sizeof(drv_info_t)*NWD); + ida_gendisk[ctlr].nr_real = 0; + + /* + * Tell the array controller not to give us any interupts while + * we check the new geometry. Then turn interrupts back on when + * we're done. + */ + hba[ctlr]->access.set_intr_mask(hba[ctlr], 0); + getgeometry(ctlr); + hba[ctlr]->access.set_intr_mask(hba[ctlr], FIFO_NOT_EMPTY); + + ida_geninit(&ida_gendisk[ctlr]); + for(i=0; iusage_count--; + return 0; +} + +/* Borrowed and adapted from sd.c */ +static int revalidate_logvol(kdev_t dev, int maxusage) +{ + int ctlr, target; + struct gendisk *gdev; + unsigned long flags; + int max_p; + int start; + int i; + + target = DEVICE_NR(dev); + ctlr = MAJOR(dev) - MAJOR_NR; + gdev = &ida_gendisk[ctlr]; + + spin_lock_irqsave(&io_request_lock, flags); + if (hba[ctlr]->drv[target].usage_count > maxusage) { + spin_unlock_irqrestore(&io_request_lock, flags); + printk(KERN_WARNING "cpqarray: Device busy for " + "revalidation (usage=%d)\n", + hba[ctlr]->drv[target].usage_count); + return -EBUSY; + } + + hba[ctlr]->drv[target].usage_count++; + spin_unlock_irqrestore(&io_request_lock, flags); + + max_p = gdev->max_p; + start = target << gdev->minor_shift; + + for(i=max_p; i>=0; i--) { + int minor = start+i; + kdev_t devi = MKDEV(MAJOR_NR + ctlr, minor); + struct super_block *sb = get_super(devi); + sync_dev(devi); + if (sb) invalidate_inodes(sb); + invalidate_buffers(devi); + 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; + } + + gdev->part[start].nr_sects = hba[ctlr]->drv[target].nr_blks; + resetup_one_dev(gdev, target); + hba[ctlr]->drv[target].usage_count--; + return 0; +} + + +/******************************************************************** + name: pollcomplete + Wait polling for a command to complete. + The memory mapped FIFO is polled for the completion. + Used only at init time, interrupts disabled. + ********************************************************************/ +static int pollcomplete(int ctlr) +{ + int done; + int i; + + /* Wait (up to 2 seconds) for a command to complete */ + + for (i = 200000; i > 0; i--) { + done = hba[ctlr]->access.command_completed(hba[ctlr]); + if (done == 0) { + udelay(10); /* a short fixed delay */ + } else + return (done); + } + /* Invalid address to tell caller we ran out of time */ + return 1; +} +/***************************************************************** + start_fwbk + Starts controller firmwares background processing. + Currently only the Integrated Raid controller needs this done. + If the PCI mem address registers are written to after this, + data corruption may occur +*****************************************************************/ +static void start_fwbk(int ctlr) +{ + id_ctlr_t *id_ctlr_buf; + int ret_code; + + if( hba[ctlr]->board_id != 0x40400E11) + /* Not a Integrated Raid, so there is nothing for us to do */ + return; + printk(KERN_DEBUG "cpqarray: Starting firmware's background" + " processing\n"); + /* Command does not return anything, but idasend command needs a + buffer */ + id_ctlr_buf = (id_ctlr_t *)kmalloc(sizeof(id_ctlr_t), GFP_KERNEL); + if(id_ctlr_buf==NULL) + { + printk(KERN_WARNING "cpqarray: Out of memory. " + "Unable to start background processing.\n"); + return; + } + ret_code = sendcmd(RESUME_BACKGROUND_ACTIVITY, ctlr, + id_ctlr_buf, 0, 0, 0, 0); + if(ret_code != IO_OK) + printk(KERN_WARNING "cpqarray: Unable to start" + " background processing\n"); + kfree(id_ctlr_buf); +} +/***************************************************************** + getgeometry + Get ida logical volume geometry from the controller + This is a large bit of code which once existed in two flavors, + It is used only at init time. +*****************************************************************/ +static void getgeometry(int ctlr) +{ + id_log_drv_t *id_ldrive; + id_ctlr_t *id_ctlr_buf; + sense_log_drv_stat_t *id_lstatus_buf; + config_t *sense_config_buf; + unsigned int log_unit, log_index; + int ret_code, size; + drv_info_t *drv; + ctlr_info_t *info_p = hba[ctlr]; + + info_p->log_drv_map = 0; + + id_ldrive = (id_log_drv_t *)kmalloc(sizeof(id_log_drv_t), GFP_KERNEL); + if(id_ldrive == NULL) + { + printk( KERN_ERR "cpqarray: out of memory.\n"); + return; + } + id_ctlr_buf = (id_ctlr_t *)kmalloc(sizeof(id_ctlr_t), GFP_KERNEL); + if(id_ctlr_buf == NULL) + { + kfree(id_ldrive); + printk( KERN_ERR "cpqarray: out of memory.\n"); + return; + } + + id_lstatus_buf = (sense_log_drv_stat_t *)kmalloc(sizeof(sense_log_drv_stat_t), GFP_KERNEL); + if(id_lstatus_buf == NULL) + { + kfree(id_ctlr_buf); + kfree(id_ldrive); + printk( KERN_ERR "cpqarray: out of memory.\n"); + return; + } + + sense_config_buf = (config_t *)kmalloc(sizeof(config_t), GFP_KERNEL); + if(sense_config_buf == NULL) + { + kfree(id_lstatus_buf); + kfree(id_ctlr_buf); + kfree(id_ldrive); + printk( KERN_ERR "cpqarray: out of memory.\n"); + return; + } + + memset(id_ldrive, 0, sizeof(id_log_drv_t)); + memset(id_ctlr_buf, 0, sizeof(id_ctlr_t)); + memset(id_lstatus_buf, 0, sizeof(sense_log_drv_stat_t)); + memset(sense_config_buf, 0, sizeof(config_t)); + + info_p->phys_drives = 0; + info_p->log_drv_map = 0; + info_p->drv_assign_map = 0; + info_p->drv_spare_map = 0; + info_p->mp_failed_drv_map = 0; /* only initialized here */ + /* Get controllers info for this logical drive */ + ret_code = sendcmd(ID_CTLR, ctlr, id_ctlr_buf, 0, 0, 0, 0); + if (ret_code == IO_ERROR) { + /* + * If can't get controller info, set the logical drive map to 0, + * so the idastubopen will fail on all logical drives + * on the controller. + */ + /* Free all the buffers and return */ + printk(KERN_ERR "cpqarray: error sending ID controller\n"); + kfree(sense_config_buf); + kfree(id_lstatus_buf); + kfree(id_ctlr_buf); + kfree(id_ldrive); + return; + } + + info_p->log_drives = id_ctlr_buf->nr_drvs;; + *(__u32*)(info_p->firm_rev) = *(__u32*)(id_ctlr_buf->firm_rev); + info_p->ctlr_sig = id_ctlr_buf->cfg_sig; + + printk(" (%s)\n", info_p->product_name); + /* + * Initialize logical drive map to zero + */ + log_index = 0; + /* + * Get drive geometry for all logical drives + */ + if (id_ctlr_buf->nr_drvs > 16) + printk(KERN_WARNING "cpqarray ida%d: This driver supports " + "16 logical drives per controller.\n. " + " Additional drives will not be " + "detected\n", ctlr); + + for (log_unit = 0; + (log_index < id_ctlr_buf->nr_drvs) + && (log_unit < NWD); + log_unit++) { + + size = sizeof(sense_log_drv_stat_t); + + /* + Send "Identify logical drive status" cmd + */ + ret_code = sendcmd(SENSE_LOG_DRV_STAT, + ctlr, id_lstatus_buf, size, 0, 0, log_unit); + if (ret_code == IO_ERROR) { + /* + If can't get logical drive status, set + the logical drive map to 0, so the + idastubopen will fail for all logical drives + on the controller. + */ + info_p->log_drv_map = 0; + printk( KERN_WARNING + "cpqarray ida%d: idaGetGeometry - Controller" + " failed to report status of logical drive %d\n" + "Access to this controller has been disabled\n", + ctlr, log_unit); + /* Free all the buffers and return */ + kfree(sense_config_buf); + kfree(id_lstatus_buf); + kfree(id_ctlr_buf); + kfree(id_ldrive); + return; + } + /* + Make sure the logical drive is configured + */ + if (id_lstatus_buf->status != LOG_NOT_CONF) { + ret_code = sendcmd(ID_LOG_DRV, ctlr, id_ldrive, + sizeof(id_log_drv_t), 0, 0, log_unit); + /* + If error, the bit for this + logical drive won't be set and + idastubopen will return error. + */ + if (ret_code != IO_ERROR) { + drv = &info_p->drv[log_unit]; + drv->blk_size = id_ldrive->blk_size; + drv->nr_blks = id_ldrive->nr_blks; + drv->cylinders = id_ldrive->drv.cyl; + drv->heads = id_ldrive->drv.heads; + drv->sectors = id_ldrive->drv.sect_per_track; + info_p->log_drv_map |= (1 << log_unit); + + printk(KERN_INFO "cpqarray ida/c%dd%d: blksz=%d nr_blks=%d\n", + ctlr, log_unit, drv->blk_size, drv->nr_blks); + ret_code = sendcmd(SENSE_CONFIG, + ctlr, sense_config_buf, + sizeof(config_t), 0, 0, log_unit); + if (ret_code == IO_ERROR) { + info_p->log_drv_map = 0; + /* Free all the buffers and return */ + printk(KERN_ERR "cpqarray: error sending sense config\n"); + kfree(sense_config_buf); + kfree(id_lstatus_buf); + kfree(id_ctlr_buf); + kfree(id_ldrive); + return; + + } + info_p->phys_drives = + sense_config_buf->ctlr_phys_drv; + info_p->drv_assign_map + |= sense_config_buf->drv_asgn_map; + info_p->drv_assign_map + |= sense_config_buf->spare_asgn_map; + info_p->drv_spare_map + |= sense_config_buf->spare_asgn_map; + } /* end of if no error on id_ldrive */ + log_index = log_index + 1; + } /* end of if logical drive configured */ + } /* end of for log_unit */ + kfree(sense_config_buf); + kfree(id_ldrive); + kfree(id_lstatus_buf); + kfree(id_ctlr_buf); + return; +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/cpqarray.h linux.pre11.3/drivers/block/cpqarray.h --- linux.vanilla/drivers/block/cpqarray.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/block/cpqarray.h Tue Jul 20 01:53:07 1999 @@ -0,0 +1,120 @@ +/* + * Disk Array driver for Compaq SMART2 Controllers + * Copyright 1998 Compaq Computer 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, GOOD TITLE or + * NON INFRINGEMENT. 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. + * + * Questions/Comments/Bugfixes to arrays@compaq.com + * + * If you want to make changes, improve or add functionality to this + * driver, you'll probably need the Compaq Array Controller Interface + * Specificiation (Document number ECG086/1198) + */ +#ifndef CPQARRAY_H +#define CPQARRAY_H + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#include +#endif + +#include "ida_cmd.h" + +#define IO_OK 0 +#define IO_ERROR 1 +#define NWD 16 +#define NWD_SHIFT 4 + +#define IDA_TIMER (5*HZ) +#define IDA_TIMEOUT (10*HZ) + +#define MISC_NONFATAL_WARN 0x01 + +typedef struct { + unsigned blk_size; + unsigned nr_blks; + unsigned cylinders; + unsigned heads; + unsigned sectors; + int usage_count; +} drv_info_t; + +#ifdef __KERNEL__ + +struct ctlr_info; +typedef struct ctlr_info ctlr_info_t; + +struct access_method { + void (*submit_command)(ctlr_info_t *h, cmdlist_t *c); + void (*set_intr_mask)(ctlr_info_t *h, unsigned long val); + unsigned long (*fifo_full)(ctlr_info_t *h); + unsigned long (*intr_pending)(ctlr_info_t *h); + unsigned long (*command_completed)(ctlr_info_t *h); +}; + +struct board_type { + __u32 board_id; + char *product_name; + struct access_method *access; +}; + +struct ctlr_info { + int ctlr; + char devname[8]; + __u32 log_drv_map; + __u32 drv_assign_map; + __u32 drv_spare_map; + __u32 mp_failed_drv_map; + + char firm_rev[4]; + int ctlr_sig; + + int log_drives; + int phys_drives; + + __u32 board_id; + char *product_name; + + __u32 vaddr; + __u32 paddr; + __u32 ioaddr; + int intr; + int usage_count; + drv_info_t drv[NWD]; + struct proc_dir_entry *proc; + + struct access_method access; + + cmdlist_t *reqQ; + cmdlist_t *cmpQ; + cmdlist_t *cmd_pool; + __u32 *cmd_pool_bits; + + unsigned int Qdepth; + unsigned int maxQsinceinit; + + unsigned int nr_requests; + unsigned int nr_allocs; + unsigned int nr_frees; + struct timer_list timer; + unsigned int misc_tflags; +}; +#endif + +#endif /* CPQARRAY_H */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/genhd.c linux.pre11.3/drivers/block/genhd.c --- linux.vanilla/drivers/block/genhd.c Fri Apr 16 22:10:51 1999 +++ linux.pre11.3/drivers/block/genhd.c Tue Jul 20 01:39:05 1999 @@ -30,6 +30,7 @@ #include #include +#include /* * Many architectures don't like unaligned accesses, which is @@ -58,6 +59,9 @@ extern int chr_dev_init(void); extern int blk_dev_init(void); +#ifdef CONFIG_BLK_DEV_DAC960 +extern void DAC960_Initialize(void); +#endif extern int scsi_dev_init(void); extern int net_dev_init(void); @@ -65,6 +69,20 @@ extern void note_bootable_part(kdev_t dev, int part); #endif +static char *raid_name (struct gendisk *hd, int minor, int major_base, + char *buf) +{ + int ctlr = hd->major - major_base; + int disk = minor >> hd->minor_shift; + int part = minor & (( 1 << hd->minor_shift) - 1); + if (part == 0) + sprintf(buf, "%s/c%dd%d", hd->major_name, ctlr, disk); + else + sprintf(buf, "%s/c%dd%dp%d", hd->major_name, ctlr, disk, + part); + return buf; +} + /* * disk_name() is used by genhd.c and md.c. * It formats the devicename of the indicated disk @@ -81,6 +99,8 @@ * IDE devices use multiple major numbers, but the drives * are named as: {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}.. * This requires special handling here. + * + * MD devices are named md0, md1, ... md15, fix it up here. */ switch (hd->major) { case IDE5_MAJOR: @@ -96,6 +116,8 @@ case IDE0_MAJOR: maj = "hd"; break; + case MD_MAJOR: + unit -= 'a'-'0'; } part = minor & ((1 << hd->minor_shift) - 1); if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) { @@ -108,6 +130,13 @@ return buf; } } + if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= + COMPAQ_SMART2_MAJOR+7) { + return raid_name (hd, minor, COMPAQ_SMART2_MAJOR, buf); + } + if (hd->major >= DAC960_MAJOR && hd->major <= DAC960_MAJOR+7) { + return raid_name (hd, minor, DAC960_MAJOR, buf); + } if (part) sprintf(buf, "%s%c%d", maj, unit, part); else @@ -115,11 +144,16 @@ return buf; } -static void add_partition (struct gendisk *hd, int minor, int start, int size) +static void add_partition (struct gendisk *hd, int minor, + int start, int size, int type) { - char buf[8]; - hd->part[minor].start_sect = start; - hd->part[minor].nr_sects = size; + char buf[MAX_DISKNAME_LEN]; + struct hd_struct *p = hd->part+minor; + + p->start_sect = start; + p->nr_sects = size; + p->type = type; + printk(" %s", disk_name(hd, minor, buf)); } @@ -140,49 +174,49 @@ static unsigned int get_ptable_blocksize(kdev_t dev) { - int ret = 1024; + int ret = 1024; - /* - * See whether the low-level driver has given us a minumum blocksize. - * If so, check to see whether it is larger than the default of 1024. - */ - if (!blksize_size[MAJOR(dev)]) - { - return ret; - } + /* + * See whether the low-level driver has given us a minumum blocksize. + * If so, check to see whether it is larger than the default of 1024. + */ + if (!blksize_size[MAJOR(dev)]) + return ret; - /* - * Check for certain special power of two sizes that we allow. - * With anything larger than 1024, we must force the blocksize up to - * the natural blocksize for the device so that we don't have to try - * and read partial sectors. Anything smaller should be just fine. - */ + /* + * Check for certain special power of two sizes that we allow. + * With anything larger than 1024, we must force the blocksize up to + * the natural blocksize for the device so that we don't have to try + * and read partial sectors. Anything smaller should be just fine. + */ - switch( blksize_size[MAJOR(dev)][MINOR(dev)] ) - { - case 2048: - ret = 2048; - break; - case 4096: - ret = 4096; - break; - case 8192: - ret = 8192; - break; - case 1024: - case 512: - case 256: - case 0: - /* - * These are all OK. - */ - break; - default: - panic("Strange blocksize for partition table\n"); - } + switch( blksize_size[MAJOR(dev)][MINOR(dev)] ) { + case 2048: + ret = 2048; + break; + + case 4096: + ret = 4096; + break; + + case 8192: + ret = 8192; + break; + + case 1024: + case 512: + case 256: + case 0: + /* + * These are all OK. + */ + break; - return ret; + default: + panic("Strange blocksize for partition table\n"); + } + return ret; } #ifdef CONFIG_MSDOS_PARTITION @@ -255,7 +289,8 @@ first_sector + first_size)) continue; - add_partition(hd, current_minor, this_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size); + add_partition(hd, current_minor, this_sector+START_SECT(p)*sector_size, + NR_SECTS(p)*sector_size, ptype(SYS_IND(p))); current_minor++; if ((current_minor & mask) == 0) goto done; @@ -319,7 +354,8 @@ * one but add_partition starts relative to sector * zero of the disk. Therefore, must add the offset * of the current partition */ - add_partition(hd, current_minor, s->s_start+offset, s->s_size); + add_partition(hd, current_minor, + s->s_start+offset, s->s_size, 0); current_minor++; } brelse(bh); @@ -365,7 +401,7 @@ } /* if the bsd partition is not currently known to linux, we end * up here */ - add_partition(hd, current_minor, bsd_p->p_offset, bsd_p->p_size); + add_partition(hd, current_minor, bsd_p->p_offset, bsd_p->p_size, 0); current_minor++; } /* @@ -432,7 +468,7 @@ break; if (p->s_label != UNIXWARE_FS_UNUSED) { - add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p)); + add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p), 0); current_minor++; } p++; @@ -552,7 +588,8 @@ for (i=1 ; i<=4 ; minor++,i++,p++) { if (!NR_SECTS(p)) continue; - add_partition(hd, minor, first_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size); + add_partition(hd, minor, first_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size, + ptype(SYS_IND(p))); if (is_extended_partition(p)) { printk(" <"); /* @@ -619,7 +656,8 @@ break; if (!(START_SECT(p) && NR_SECTS(p))) continue; - add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p)); + add_partition(hd, current_minor, START_SECT(p), + NR_SECTS(p), 0); } } printk("\n"); @@ -677,12 +715,10 @@ label = (struct disklabel *) (bh->b_data+64); partition = label->d_partitions; if (label->d_magic != DISKLABELMAGIC) { - printk("magic: %08x\n", label->d_magic); brelse(bh); return 0; } if (label->d_magic2 != DISKLABELMAGIC) { - printk("magic2: %08x\n", label->d_magic2); brelse(bh); return 0; } @@ -692,7 +728,7 @@ if (partition->p_size) add_partition(hd, current_minor, first_sector+partition->p_offset, - partition->p_size); + partition->p_size, 0); current_minor++; } printk("\n"); @@ -711,7 +747,14 @@ struct buffer_head *bh; struct sun_disklabel { unsigned char info[128]; /* Informative text string */ - unsigned char spare[292]; /* Boot information etc. */ + unsigned char spare0[14]; + struct sun_disklabelinfo { + unsigned char spare1; + unsigned char id; + unsigned char spare2; + unsigned char flags; + } infos[8]; + unsigned char spare1[246]; /* Boot information etc. */ unsigned short rspeed; /* Disk rotational speed */ unsigned short pcylcount; /* Physical cylinder count */ unsigned short sparecyl; /* extra sects per cylinder */ @@ -765,7 +808,8 @@ st_sector = first_sector + be32_to_cpu(p->start_cylinder) * spc; num_sectors = be32_to_cpu(p->num_sectors); if (num_sectors) - add_partition(hd, current_minor, st_sector, num_sectors); + add_partition(hd, current_minor, st_sector, + num_sectors, ptype(label->infos[i].id)); current_minor++; } printk("\n"); @@ -776,14 +820,11 @@ #endif /* CONFIG_SUN_PARTITION */ #ifdef CONFIG_SGI_PARTITION -#include static int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector) { - int i, csum; - unsigned int *ui; - unsigned int start, blocks, cs; - int magic; + int i, csum, magic; + unsigned int *ui, start, blocks, cs; struct buffer_head *bh; struct sgi_disklabel { int magic_mushroom; /* Big fat spliff... */ @@ -841,7 +882,7 @@ start = be32_to_cpu(p->first_block); if(!blocks) continue; - add_partition(hd, current_minor, start, blocks); + add_partition(hd, current_minor, start, blocks, 0); current_minor++; } printk("\n"); @@ -852,7 +893,6 @@ #endif #ifdef CONFIG_AMIGA_PARTITION -#include #include static __inline__ u32 @@ -923,27 +963,30 @@ blk = htonl(pb->pb_Next); if (pb->pb_ID == htonl(IDNAME_PARTITION) && checksum_block( (u32 *)pb,htonl(pb->pb_SummedLongs) & 0x7F) == 0 ) { - + /* Tell Kernel about it */ if (!(nr_sects = (htonl(pb->pb_Environment[10]) + 1 - htonl(pb->pb_Environment[9])) * htonl(pb->pb_Environment[3]) * htonl(pb->pb_Environment[5]))) { + brelse(bh); continue; } start_sect = htonl(pb->pb_Environment[9]) * htonl(pb->pb_Environment[3]) * htonl(pb->pb_Environment[5]); - add_partition(hd,current_minor,start_sect,nr_sects); + add_partition(hd,current_minor, + start_sect,nr_sects,0); current_minor++; res = 1; } brelse(bh); } printk("\n"); - break; } + else + brelse(bh); } rdb_done: @@ -1056,7 +1099,7 @@ blocks_in_map = be32_to_cpu(part->map_count); add_partition(hd, current_minor, fsec + be32_to_cpu(part->start_block) * (secsize/512), - be32_to_cpu(part->block_count) * (secsize/512)); + be32_to_cpu(part->block_count) * (secsize/512), 0); #ifdef CONFIG_PPC /* @@ -1147,7 +1190,7 @@ } add_partition(hd, minor, partsect + xrs->part[0].st, - xrs->part[0].siz); + xrs->part[0].siz, 0); if (!(xrs->part[1].flg & 1)) { /* end of linked partition list */ @@ -1173,7 +1216,7 @@ else { /* we don't care about other id's */ - add_partition (hd, minor, pi->st, pi->siz); + add_partition (hd, minor, pi->st, pi->siz, 0); } } } @@ -1200,7 +1243,7 @@ memcmp (pi->id, "RAW", 3) == 0) ) { part_fmt = 2; - add_partition (hd, minor, pi->st, pi->siz); + add_partition (hd, minor, pi->st, pi->siz, 0); } } printk(" >"); @@ -1215,11 +1258,59 @@ } #endif /* CONFIG_ATARI_PARTITION */ +#ifdef CONFIG_ULTRIX_PARTITION + +static int ultrix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector) +{ + int i, minor = current_minor; + struct buffer_head *bh; + struct ultrix_disklabel { + long pt_magic; /* magic no. indicating part. info exits */ + int pt_valid; /* set by driver if pt is current */ + struct pt_info { + int pi_nblocks; /* no. of sectors */ + unsigned long pi_blkoff; /* block offset for start */ + } pt_part[8]; + } *label; + +#define PT_MAGIC 0x032957 /* Partition magic number */ +#define PT_VALID 1 /* Indicates if struct is valid */ + +#define SBLOCK ((unsigned long)((16384 - sizeof(struct ultrix_disklabel)) \ + /get_ptable_blocksize(dev))) + + bh = bread (dev, SBLOCK, get_ptable_blocksize(dev)); + if (!bh) { + printk (" unable to read block 0x%lx\n", SBLOCK); + return -1; + } + + label = (struct ultrix_disklabel *)(bh->b_data + + get_ptable_blocksize(dev) + - sizeof(struct ultrix_disklabel)); + + if (label->pt_magic == PT_MAGIC && label->pt_valid == PT_VALID) { + for (i=0; i<8; i++, minor++) + if (label->pt_part[i].pi_nblocks) + add_partition(hd, minor, + label->pt_part[i].pi_blkoff, + label->pt_part[i].pi_nblocks); + brelse(bh); + printk ("\n"); + return 1; + } else { + brelse(bh); + return 0; + } +} + +#endif /* CONFIG_ULTRIX_PARTITION */ + static void check_partition(struct gendisk *hd, kdev_t dev) { static int first_time = 1; unsigned long first_sector; - char buf[8]; + char buf[MAX_DISKNAME_LEN]; if (first_time) printk("Partition check:\n"); @@ -1264,6 +1355,10 @@ if(sgi_partition(hd, dev, first_sector)) return; #endif +#ifdef CONFIG_ULTRIX_PARTITION + if(ultrix_partition(hd, dev, first_sector)) + return; +#endif printk(" unknown partition table\n"); } @@ -1323,6 +1418,7 @@ __initfunc(void device_setup(void)) { extern void console_map_init(void); + extern void cpqarray_init(void); #ifdef CONFIG_PARPORT extern int parport_init(void); #endif @@ -1340,6 +1436,9 @@ chr_dev_init(); blk_dev_init(); sti(); +#ifdef CONFIG_BLK_DEV_DAC960 + DAC960_Initialize(); +#endif #ifdef CONFIG_FC4_SOC /* This has to be done before scsi_dev_init */ soc_probe(); @@ -1347,6 +1446,9 @@ #ifdef CONFIG_SCSI scsi_dev_init(); #endif +#ifdef CONFIG_BLK_CPQ_DA + cpqarray_init(); +#endif #ifdef CONFIG_INET net_dev_init(); #endif @@ -1373,7 +1475,7 @@ int get_partition_list(char * page) { struct gendisk *p; - char buf[32]; + char buf[MAX_DISKNAME_LEN]; int n, len; len = sprintf(page, "major minor #blocks name\n\n"); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ida_cmd.h linux.pre11.3/drivers/block/ida_cmd.h --- linux.vanilla/drivers/block/ida_cmd.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/block/ida_cmd.h Tue Jul 20 01:53:07 1999 @@ -0,0 +1,347 @@ +/* + * Disk Array driver for Compaq SMART2 Controllers + * Copyright 1998 Compaq Computer 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, GOOD TITLE or + * NON INFRINGEMENT. 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. + * + * Questions/Comments/Bugfixes to arrays@compaq.com + * + * If you want to make changes, improve or add functionality to this + * driver, you'll probably need the Compaq Array Controller Interface + * Specificiation (Document number ECG086/1198) + */ +#ifndef ARRAYCMD_H +#define ARRAYCMD_H + +#include +#if 0 +#include +#endif + +/* for the Smart Array 42XX cards */ +#define S42XX_REQUEST_PORT_OFFSET 0x40 +#define S42XX_REPLY_INTR_MASK_OFFSET 0x34 +#define S42XX_REPLY_PORT_OFFSET 0x44 +#define S42XX_INTR_STATUS 0x30 + +#define S42XX_INTR_OFF 0x08 +#define S42XX_INTR_PENDING 0x08 + +#define COMMAND_FIFO 0x04 +#define COMMAND_COMPLETE_FIFO 0x08 +#define INTR_MASK 0x0C +#define INTR_STATUS 0x10 +#define INTR_PENDING 0x14 + +#define FIFO_NOT_EMPTY 0x01 +#define FIFO_NOT_FULL 0x02 + +#define BIG_PROBLEM 0x40 +#define LOG_NOT_CONF 2 + +#pragma pack(1) +typedef struct { + __u32 size; + __u32 addr; +} sg_t; + +#define RCODE_NONFATAL 0x02 +#define RCODE_FATAL 0x04 +#define RCODE_INVREQ 0x10 +typedef struct { + __u16 next; + __u8 cmd; + __u8 rcode; + __u32 blk; + __u16 blk_cnt; + __u8 sg_cnt; + __u8 reserved; +} rhdr_t; + +#define SG_MAX 32 +typedef struct { + rhdr_t hdr; + sg_t sg[SG_MAX]; + __u32 bp; +} rblk_t; + +typedef struct { + __u8 unit; + __u8 prio; + __u16 size; +} chdr_t; + +#define CMD_RWREQ 0x00 +#define CMD_IOCTL_PEND 0x01 +#define CMD_IOCTL_DONE 0x02 + +typedef struct cmdlist { + chdr_t hdr; + rblk_t req; + __u32 size; + int retry_cnt; + __u32 busaddr; + int ctlr; + struct cmdlist *prev; + struct cmdlist *next; + struct buffer_head *bh; + int type; +} cmdlist_t; + +#define ID_CTLR 0x11 +typedef struct { + __u8 nr_drvs; + __u32 cfg_sig; + __u8 firm_rev[4]; + __u8 rom_rev[4]; + __u8 hw_rev; + __u32 bb_rev; + __u32 drv_present_map; + __u32 ext_drv_map; + __u32 board_id; + __u8 cfg_error; + __u32 non_disk_bits; + __u8 bad_ram_addr; + __u8 cpu_rev; + __u8 pdpi_rev; + __u8 epic_rev; + __u8 wcxc_rev; + __u8 marketing_rev; + __u8 ctlr_flags; + __u8 host_flags; + __u8 expand_dis; + __u8 scsi_chips; + __u32 max_req_blocks; + __u32 ctlr_clock; + __u8 drvs_per_bus; + __u16 big_drv_present_map[8]; + __u16 big_ext_drv_map[8]; + __u16 big_non_disk_map[8]; + __u16 task_flags; + __u8 icl_bus; + __u8 red_modes; + __u8 cur_red_mode; + __u8 red_ctlr_stat; + __u8 red_fail_reason; + __u8 reserved[403]; +} id_ctlr_t; + +typedef struct { + __u16 cyl; + __u8 heads; + __u8 xsig; + __u8 psectors; + __u16 wpre; + __u8 maxecc; + __u8 drv_ctrl; + __u16 pcyls; + __u8 pheads; + __u16 landz; + __u8 sect_per_track; + __u8 cksum; +} drv_param_t; + +#define ID_LOG_DRV 0x10 +typedef struct { + __u16 blk_size; + __u32 nr_blks; + drv_param_t drv; + __u8 fault_tol; + __u8 reserved; + __u8 bios_disable; +} id_log_drv_t; + +#define ID_LOG_DRV_EXT 0x18 +typedef struct { + __u32 log_drv_id; + __u8 log_drv_label[64]; + __u8 reserved[418]; +} id_log_drv_ext_t; + +#define SENSE_LOG_DRV_STAT 0x12 +typedef struct { + __u8 status; + __u32 fail_map; + __u16 read_err[32]; + __u16 write_err[32]; + __u8 drv_err_data[256]; + __u8 drq_timeout[32]; + __u32 blks_to_recover; + __u8 drv_recovering; + __u16 remap_cnt[32]; + __u32 replace_drv_map; + __u32 act_spare_map; + __u8 spare_stat; + __u8 spare_repl_map[32]; + __u32 repl_ok_map; + __u8 media_exch; + __u8 cache_fail; + __u8 expn_fail; + __u8 unit_flags; + __u16 big_fail_map[8]; + __u16 big_remap_map[8]; + __u16 big_repl_map[8]; + __u16 big_act_spare_map[8]; + __u8 big_spar_repl_map[128]; + __u16 big_repl_ok_map[8]; + __u8 big_drv_rebuild; + __u8 reserved[36]; +} sense_log_drv_stat_t; + +#define START_RECOVER 0x13 + +#define ID_PHYS_DRV 0x15 +typedef struct { + __u8 scsi_bus; + __u8 scsi_id; + __u16 blk_size; + __u32 nr_blks; + __u32 rsvd_blks; + __u8 drv_model[40]; + __u8 drv_sn[40]; + __u8 drv_fw[8]; + __u8 scsi_iq_bits; + __u8 compaq_drv_stmp; + __u8 last_fail; + __u8 phys_drv_flags; + __u8 phys_drv_flags1; + __u8 scsi_lun; + __u8 phys_drv_flags2; + __u8 reserved; + __u32 spi_speed_rules; + __u8 phys_connector[2]; + __u8 phys_box_on_bus; + __u8 phys_bay_in_box; +} id_phys_drv_t; + +#define BLINK_DRV_LEDS 0x16 +typedef struct { + __u32 blink_duration; + __u32 reserved; + __u8 blink[256]; + __u8 reserved1[248]; +} blink_drv_leds_t; + +#define SENSE_BLINK_LEDS 0x17 +typedef struct { + __u32 blink_duration; + __u32 btime_elap; + __u8 blink[256]; + __u8 reserved1[248]; +} sense_blink_leds_t; + +#define IDA_READ 0x20 +#define IDA_WRITE 0x30 +#define IDA_WRITE_MEDIA 0x31 +#define RESET_TO_DIAG 0x40 +#define DIAG_PASS_THRU 0x41 + +#define SENSE_CONFIG 0x50 +#define SET_CONFIG 0x51 +typedef struct { + __u32 cfg_sig; + __u16 compat_port; + __u8 data_dist_mode; + __u8 surf_an_ctrl; + __u16 ctlr_phys_drv; + __u16 log_unit_phys_drv; + __u16 fault_tol_mode; + __u8 phys_drv_param[16]; + drv_param_t drv; + __u32 drv_asgn_map; + __u16 dist_factor; + __u32 spare_asgn_map; + __u8 reserved[6]; + __u16 os; + __u8 ctlr_order; + __u8 extra_info; + __u32 data_offs; + __u8 parity_backedout_write_drvs; + __u8 parity_dist_mode; + __u8 parity_shift_fact; + __u8 bios_disable_flag; + __u32 blks_on_vol; + __u32 blks_per_drv; + __u8 scratch[16]; + __u16 big_drv_map[8]; + __u16 big_spare_map[8]; + __u8 ss_source_vol; + __u8 mix_drv_cap_range; + struct { + __u16 big_drv_map[8]; + __u32 blks_per_drv; + __u16 fault_tol_mode; + __u16 dist_factor; + } MDC_range[4]; + __u8 reserved1[248]; +} config_t; + +#define BYPASS_VOL_STATE 0x52 +#define SS_CREATE_VOL 0x53 +#define CHANGE_CONFIG 0x54 +#define SENSE_ORIG_CONF 0x55 +#define REORDER_LOG_DRV 0x56 +typedef struct { + __u8 old_units[32]; +} reorder_log_drv_t; + +#define LABEL_LOG_DRV 0x57 +typedef struct { + __u8 log_drv_label[64]; +} label_log_drv_t; + +#define SS_TO_VOL 0x58 + +#define SET_SURF_DELAY 0x60 +typedef struct { + __u16 delay; + __u8 reserved[510]; +} surf_delay_t; + +#define SET_OVERHEAT_DELAY 0x61 +typedef struct { + __u16 delay; +} overhead_delay_t; + +#define SET_MP_DELAY +typedef struct { + __u16 delay; + __u8 reserved[510]; +} mp_delay_t; + +#define PASSTHRU_A 0x91 +typedef struct { + __u8 target; + __u8 bus; + __u8 lun; + __u32 timeout; + __u32 flags; + __u8 status; + __u8 error; + __u8 cdb_len; + __u8 sense_error; + __u8 sense_key; + __u32 sense_info; + __u8 sense_code; + __u8 sense_qual; + __u8 residual; + __u8 reserved[4]; + __u8 cdb[12]; +} scsi_param_t; + +#define RESUME_BACKGROUND_ACTIVITY 0x99 +#pragma pack() + +#endif /* ARRAYCMD_H */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ida_ioctl.h linux.pre11.3/drivers/block/ida_ioctl.h --- linux.vanilla/drivers/block/ida_ioctl.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/block/ida_ioctl.h Tue Jul 20 01:53:07 1999 @@ -0,0 +1,83 @@ +/* + * Disk Array driver for Compaq SMART2 Controllers + * Copyright 1998 Compaq Computer 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, GOOD TITLE or + * NON INFRINGEMENT. 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. + * + * Questions/Comments/Bugfixes to arrays@compaq.com + * + * If you want to make changes, improve or add functionality to this + * driver, you'll probably need the Compaq Array Controller Interface + * Specificiation (Document number ECG086/1198) + */ +#ifndef IDA_IOCTL_H +#define IDA_IOCTL_H + +#include "ida_cmd.h" +#include "cpqarray.h" + +#define IDAGETDRVINFO 0x27272828 +#define IDAPASSTHRU 0x28282929 +#define IDAGETCTLRSIG 0x29293030 +#define IDAREVALIDATEVOLS 0x30303131 +#define IDADRIVERVERSION 0x31313232 + +/* + * Normally, the ioctl determines the logical unit for this command by + * the major,minor number of the fd passed to ioctl. If you need to send + * a command to a different/nonexistant unit (such as during config), you + * can override the normal behavior by setting the unit valid bit. (Normally, + * it should be zero) The controller the command is sent to is still + * determined by the major number of the open device. + */ + +#define UNITVALID 0x80 +typedef struct { + __u8 cmd; + __u8 rcode; + __u8 unit; + __u32 blk; + __u16 blk_cnt; + +/* currently, sg_cnt is assumed to be 1: only the 0th element of sg is used */ + struct { + void *addr; + size_t size; + } sg[SG_MAX]; + int sg_cnt; + + union ctlr_cmds { + drv_info_t drv; + unsigned char buf[512]; + + id_ctlr_t id_ctlr; + drv_param_t drv_param; + id_log_drv_t id_log_drv; + id_log_drv_ext_t id_log_drv_ext; + sense_log_drv_stat_t sense_log_drv_stat; + id_phys_drv_t id_phys_drv; + blink_drv_leds_t blink_drv_leds; + sense_blink_leds_t sense_blink_leds; + config_t config; + reorder_log_drv_t reorder_log_drv; + label_log_drv_t label_log_drv; + surf_delay_t surf_delay; + overhead_delay_t overhead_delay; + mp_delay_t mp_delay; + scsi_param_t scsi_param; + } c; +} ida_ioctl_t; + +#endif /* IDA_IOCTL_H */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ide-cd.c linux.pre11.3/drivers/block/ide-cd.c --- linux.vanilla/drivers/block/ide-cd.c Fri Apr 16 22:10:51 1999 +++ linux.pre11.3/drivers/block/ide-cd.c Mon Jul 19 23:55:59 1999 @@ -2121,20 +2121,23 @@ msf.cdmsf_frame0); /* Make sure the TOC is up to date. */ - stat = cdrom_read_toc (drive, NULL); - if (stat) return stat; + if (cmd != CDROMREADRAW) { + stat = cdrom_read_toc (drive, NULL); + if (stat) + return stat; - toc = info->toc; + toc = info->toc; - if (lba < 0 || lba >= toc->capacity) - return -EINVAL; + if (lba < 0 || lba >= toc->capacity) + return -EINVAL; + } buf = (char *) kmalloc (blocksize, GFP_KERNEL); if (buf == NULL) return -ENOMEM; - stat = cdrom_read_block (drive, format, lba, 1, buf, blocksize, - NULL); + stat = cdrom_read_block (drive, format, lba, 1, buf, + blocksize, NULL); if (stat == 0) { if (cmd == CDROMREADMODE2) { diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ide-floppy.c linux.pre11.3/drivers/block/ide-floppy.c --- linux.vanilla/drivers/block/ide-floppy.c Mon Dec 28 23:09:41 1998 +++ linux.pre11.3/drivers/block/ide-floppy.c Mon Jul 19 23:55:59 1999 @@ -1,7 +1,7 @@ /* - * linux/drivers/block/ide-floppy.c Version 0.8 Dec 7, 1997 + * linux/drivers/block/ide-floppy.c Version 0.9 Jul 4, 1999 * - * Copyright (C) 1996, 1997 Gadi Oxman + * Copyright (C) 1996 - 1999 Gadi Oxman */ /* @@ -26,9 +26,12 @@ * Issue START command only if TEST UNIT READY fails. * Add work-around for IOMEGA ZIP revision 21.D. * Remove idefloppy_get_capabilities(). + * Ver 0.9 Jul 4 99 Fix a bug which might have caused the number of + * bytes requested on each interrupt to be zero. + * Thanks to for pointing this out. */ -#define IDEFLOPPY_VERSION "0.8" +#define IDEFLOPPY_VERSION "0.9" #include #include @@ -1001,7 +1004,7 @@ 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 */ + bcount.all = IDE_MIN(pc->request_transfer, 63 * 1024); #ifdef CONFIG_BLK_DEV_IDEDMA if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) { @@ -1524,9 +1527,19 @@ floppy->pc = floppy->pc_stack; if (gcw.drq_type == 1) set_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags); - if (strcmp(drive->id->model, "IOMEGA ZIP 100 ATAPI") == 0 && - ((strcmp(drive->id->fw_rev, "21.D") == 0) || - (strcmp(drive->id->fw_rev, "23.D") == 0))) { + /* + * We used to check revisions here. At this point however + * I'm giving up. Just assume they are all broken, its easier. + * + * The actual reason for the workarounds was likely + * a driver bug after all rather than a firmware bug, + * and the workaround below used to hide it. It should + * be fixed as of version 1.9, but to be on the safe side + * we'll leave the limitation below for the 2.2.x tree. + */ + + if (strcmp(drive->id->model, "IOMEGA ZIP 100 ATAPI") == 0) + { for (i = 0; i < 1 << PARTN_BITS; i++) max_sectors[major][minor + i] = 64; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ide-tape.c linux.pre11.3/drivers/block/ide-tape.c --- linux.vanilla/drivers/block/ide-tape.c Sat Jan 9 21:50:36 1999 +++ linux.pre11.3/drivers/block/ide-tape.c Mon Jul 19 23:55:59 1999 @@ -1,7 +1,7 @@ /* - * linux/drivers/block/ide-tape.c Version 1.14 Dec 30, 1998 + * linux/drivers/block/ide-tape.c Version 1.15 Jul 4, 1999 * - * Copyright (C) 1995 - 1998 Gadi Oxman + * Copyright (C) 1995 - 1999 Gadi Oxman * * This driver was constructed as a student project in the software laboratory * of the faculty of electrical engineering in the Technion - Israel's @@ -214,6 +214,9 @@ * Ver 1.13 Jan 2 98 Add "speed == 0" work-around for HP COLORADO 5GB * Ver 1.14 Dec 30 98 Partial fixes for the Sony/AIWA tape drives. * Replace cli()/sti() with hwgroup spinlocks. + * Ver 1.15 Mar 25 99 Fix SMP race condition by replacing hwgroup + * spinlock with private per-tape spinlock. + * Fix use of freed memory. * * Here are some words from the first releases of hd.c, which are quoted * in ide.c and apply here as well: @@ -693,6 +696,7 @@ int excess_bh_size; /* Wasted space in each stage */ unsigned int flags; /* Status/Action flags */ + spinlock_t spinlock; /* protects the ide-tape queue */ } idetape_tape_t; /* @@ -1439,7 +1443,7 @@ #if IDETAPE_DEBUG_LOG printk (KERN_INFO "Reached idetape_add_stage_tail\n"); #endif /* IDETAPE_DEBUG_LOG */ - spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags); + spin_lock_irqsave(&tape->spinlock, flags); stage->next=NULL; if (tape->last_stage != NULL) tape->last_stage->next=stage; @@ -1450,7 +1454,7 @@ tape->next_stage=tape->last_stage; tape->nr_stages++; tape->nr_pending_stages++; - spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags); + spin_unlock_irqrestore(&tape->spinlock, flags); } /* @@ -1552,7 +1556,9 @@ ide_drive_t *drive = hwgroup->drive; struct request *rq = hwgroup->rq; idetape_tape_t *tape = drive->driver_data; + unsigned long flags; int error; + int remove_stage = 0; #if IDETAPE_DEBUG_LOG printk (KERN_INFO "Reached idetape_end_request\n"); @@ -1567,6 +1573,7 @@ if (error) tape->failed_pc = NULL; + spin_lock_irqsave(&tape->spinlock, flags); if (tape->active_data_request == rq) { /* The request was a pipelined data transfer request */ tape->active_stage = NULL; tape->active_data_request = NULL; @@ -1577,7 +1584,7 @@ if (error == IDETAPE_ERROR_EOD) idetape_abort_pipeline (drive); } - idetape_remove_stage_head (drive); + remove_stage = 1; } if (tape->next_stage != NULL) { idetape_active_next_stage (drive); @@ -1595,6 +1602,9 @@ idetape_increase_max_pipeline_stages (drive); } ide_end_drive_cmd (drive, 0, 0); + if (remove_stage) + idetape_remove_stage_head (drive); + spin_unlock_irqrestore(&tape->spinlock, flags); } /* @@ -2335,6 +2345,7 @@ static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq) { struct semaphore sem = MUTEX_LOCKED; + idetape_tape_t *tape = drive->driver_data; #if IDETAPE_DEBUG_BUGS if (rq == NULL || !IDETAPE_RQ_CMD (rq->cmd)) { @@ -2343,9 +2354,9 @@ } #endif /* IDETAPE_DEBUG_BUGS */ rq->sem = &sem; - spin_unlock(&HWGROUP(drive)->spinlock); + spin_unlock(&tape->spinlock); down(&sem); - spin_lock_irq(&HWGROUP(drive)->spinlock); + spin_lock_irq(&tape->spinlock); } /* @@ -2419,10 +2430,10 @@ */ return (idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, blocks, tape->merge_stage->bh)); } - spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags); + spin_lock_irqsave(&tape->spinlock, flags); if (tape->active_stage == tape->first_stage) idetape_wait_for_request(drive, tape->active_data_request); - spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags); + spin_unlock_irqrestore(&tape->spinlock, flags); rq_ptr = &tape->first_stage->rq; bytes_read = tape->tape_block_size * (rq_ptr->nr_sectors - rq_ptr->current_nr_sectors); @@ -2471,12 +2482,12 @@ * Pay special attention to possible race conditions. */ while ((new_stage = idetape_kmalloc_stage (tape)) == NULL) { - spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags); + spin_lock_irqsave(&tape->spinlock, flags); if (idetape_pipeline_active (tape)) { idetape_wait_for_request(drive, tape->active_data_request); - spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags); + spin_unlock_irqrestore(&tape->spinlock, flags); } else { - spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags); + spin_unlock_irqrestore(&tape->spinlock, flags); idetape_insert_pipeline_into_queue (drive); if (idetape_pipeline_active (tape)) continue; @@ -2533,11 +2544,11 @@ if (tape->first_stage == NULL) return; - spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags); + spin_lock_irqsave(&tape->spinlock, flags); tape->next_stage = NULL; if (idetape_pipeline_active (tape)) idetape_wait_for_request(drive, tape->active_data_request); - spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags); + spin_unlock_irqrestore(&tape->spinlock, flags); while (tape->first_stage != NULL) idetape_remove_stage_head (drive); @@ -2557,7 +2568,7 @@ if (!idetape_pipeline_active (tape)) idetape_insert_pipeline_into_queue (drive); - spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags); + spin_lock_irqsave(&tape->spinlock, flags); if (!idetape_pipeline_active (tape)) goto abort; #if IDETAPE_DEBUG_BUGS @@ -2567,7 +2578,7 @@ #endif /* IDETAPE_DEBUG_BUGS */ idetape_wait_for_request(drive, &tape->last_stage->rq); abort: - spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags); + spin_unlock_irqrestore(&tape->spinlock, flags); } static void idetape_pad_zeros (ide_drive_t *drive, int bcount) @@ -2812,10 +2823,10 @@ * Wait until the first read-ahead request * is serviced. */ - spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags); + spin_lock_irqsave(&tape->spinlock, flags); if (tape->active_stage == tape->first_stage) idetape_wait_for_request(drive, tape->active_data_request); - spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags); + spin_unlock_irqrestore(&tape->spinlock, flags); if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK) count++; @@ -3559,6 +3570,8 @@ u16 speed; struct idetape_id_gcw gcw; + memset (tape, 0, sizeof (idetape_tape_t)); + tape->spinlock = (spinlock_t)SPIN_LOCK_UNLOCKED; drive->driver_data = tape; drive->ready_stat = 0; /* An ATAPI device ignores DRDY */ drive->dsc_overlap = 1; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ide.c linux.pre11.3/drivers/block/ide.c --- linux.vanilla/drivers/block/ide.c Tue Jun 15 16:49:48 1999 +++ linux.pre11.3/drivers/block/ide.c Mon Jul 19 23:55:59 1999 @@ -1416,6 +1416,17 @@ hwgroup->handler = NULL; (void)ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]); del_timer(&(hwgroup->timer)); + { + struct request *rq; + unsigned long block, sectors; + + if ((rq = hwgroup->rq) != NULL) { + block = rq->sector; + block += drive->part[MINOR(rq->rq_dev)&PARTN_MASK].start_sect + drive->sect0; + sectors = drive->using_dma ? rq->nr_sectors : drive->mult_count ? drive->mult_count : 1; + } + } + spin_unlock_irqrestore(&hwgroup->spinlock, flags); if (drive->unmask) ide__sti(); /* local CPU only */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ll_rw_blk.c linux.pre11.3/drivers/block/ll_rw_blk.c --- linux.vanilla/drivers/block/ll_rw_blk.c Wed Mar 24 10:55:15 1999 +++ linux.pre11.3/drivers/block/ll_rw_blk.c Tue Jul 20 00:35:18 1999 @@ -108,6 +108,11 @@ */ int * max_sectors[MAX_BLKDEV] = { NULL, NULL, }; +/* + * Max number of segments per request + */ +int * max_segments[MAX_BLKDEV] = { NULL, NULL, }; + static inline int get_max_sectors(kdev_t dev) { if (!max_sectors[MAJOR(dev)]) @@ -115,6 +120,13 @@ return max_sectors[MAJOR(dev)][MINOR(dev)]; } +static inline int get_max_segments(kdev_t dev) +{ + if (!max_segments[MAJOR(dev)]) + return MAX_SEGMENTS; + return max_segments[MAJOR(dev)][MINOR(dev)]; +} + /* * Is called with the request spinlock aquired. * NOTE: the device-specific queue() functions @@ -266,7 +278,7 @@ } static inline void drive_stat_acct(int cmd, unsigned long nr_sectors, - short disk_index) + short disk_index) { kstat.dk_drive[disk_index]++; if (cmd == READ) { @@ -291,24 +303,31 @@ void add_request(struct blk_dev_struct * dev, struct request * req) { + int major = MAJOR(req->rq_dev); + int minor = MINOR(req->rq_dev); struct request * tmp, **current_request; short disk_index; unsigned long flags; int queue_new_request = 0; - switch (MAJOR(req->rq_dev)) { + switch (major) { + case DAC960_MAJOR+0: + disk_index = (minor & 0x00f8) >> 3; + if (disk_index < 4) + drive_stat_acct(req->cmd, req->nr_sectors, disk_index); + break; case SCSI_DISK0_MAJOR: - disk_index = (MINOR(req->rq_dev) & 0x00f0) >> 4; + disk_index = (minor & 0x00f0) >> 4; if (disk_index < 4) drive_stat_acct(req->cmd, req->nr_sectors, disk_index); break; case IDE0_MAJOR: /* same as HD_MAJOR */ case XT_DISK_MAJOR: - disk_index = (MINOR(req->rq_dev) & 0x0040) >> 6; + disk_index = (minor & 0x0040) >> 6; drive_stat_acct(req->cmd, req->nr_sectors, disk_index); break; case IDE1_MAJOR: - disk_index = ((MINOR(req->rq_dev) & 0x0040) >> 6) + 2; + disk_index = ((minor & 0x0040) >> 6) + 2; drive_stat_acct(req->cmd, req->nr_sectors, disk_index); default: break; @@ -346,8 +365,12 @@ tmp->next = req; /* for SCSI devices, call request_fn unconditionally */ - if (scsi_blk_major(MAJOR(req->rq_dev))) + if (scsi_blk_major(major) || + (major >= DAC960_MAJOR+0 && major <= DAC960_MAJOR+7) || + (major >= COMPAQ_SMART2_MAJOR+0 && + major <= COMPAQ_SMART2_MAJOR+7)) queue_new_request = 1; + out: if (queue_new_request) (dev->request_fn)(); @@ -357,29 +380,39 @@ /* * Has to be called with the request spinlock aquired */ -static inline void attempt_merge (struct request *req, int max_sectors) +static inline void attempt_merge (struct request *req, + int max_sectors, + int max_segments) { struct request *next = req->next; + int total_segments; if (!next) return; if (req->sector + req->nr_sectors != next->sector) return; - if (next->sem || req->cmd != next->cmd || req->rq_dev != next->rq_dev || req->nr_sectors + next->nr_sectors > max_sectors) + if (next->sem || req->cmd != next->cmd || req->rq_dev != next->rq_dev || + req->nr_sectors + next->nr_sectors > max_sectors) + return; + total_segments = req->nr_segments + next->nr_segments; + if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data) + total_segments--; + if (total_segments > max_segments) return; req->bhtail->b_reqnext = next->bh; req->bhtail = next->bhtail; req->nr_sectors += next->nr_sectors; + req->nr_segments = total_segments; next->rq_status = RQ_INACTIVE; req->next = next->next; wake_up (&wait_for_request); } -void make_request(int major,int rw, struct buffer_head * bh) +void make_request(int major, int rw, struct buffer_head * bh) { unsigned int sector, count; struct request * req; - int rw_ahead, max_req, max_sectors; + int rw_ahead, max_req, max_sectors, max_segments; unsigned long flags; count = bh->b_size >> 9; @@ -397,15 +430,20 @@ if (maxsector < count || maxsector - count < sector) { bh->b_state &= (1 << BH_Lock); - /* This may well happen - the kernel calls bread() - without checking the size of the device, e.g., - when mounting a device. */ + /* This may well happen - the kernel calls bread() + without checking the size of the device, e.g., + when mounting a device. */ printk(KERN_INFO - "attempt to access beyond end of device\n"); + "attempt to access beyond end of device\n"); printk(KERN_INFO "%s: rw=%d, want=%d, limit=%d\n", - kdevname(bh->b_rdev), rw, - (sector + count)>>1, - blk_size[major][MINOR(bh->b_rdev)]); + kdevname(bh->b_rdev), rw, + (sector + count)>>1, + blk_size[major][MINOR(bh->b_rdev)]); + printk(KERN_INFO "dev %s blksize=%d blocknr=%ld sector=%ld size=%ld count=%d\n", + kdevname(bh->b_dev), + blksize_size[major][MINOR(bh->b_dev)], + bh->b_blocknr, bh->b_rsector, bh->b_size, bh->b_count); + goto end_io; } } @@ -437,13 +475,13 @@ break; default: printk(KERN_ERR "make_request: bad block dev cmd," - " must be R/W/RA/WA\n"); + " must be R/W/RA/WA\n"); goto end_io; } /* look for a free request. */ /* Loop uses two requests, 1 for loop and 1 for the real device. - * Cut max_req in half to avoid running out and deadlocking. */ + * Cut max_req in half to avoid running out and deadlocking. */ if ((major == LOOP_MAJOR) || (major == NBD_MAJOR)) max_req >>= 1; @@ -451,6 +489,7 @@ * Try to coalesce the new request with old requests */ max_sectors = get_max_sectors(bh->b_rdev); + max_segments = get_max_segments(bh->b_rdev); /* * Now we acquire the request spinlock, we have to be mega careful @@ -497,6 +536,22 @@ case SCSI_DISK6_MAJOR: case SCSI_DISK7_MAJOR: case SCSI_CDROM_MAJOR: + case DAC960_MAJOR+0: + case DAC960_MAJOR+1: + case DAC960_MAJOR+2: + case DAC960_MAJOR+3: + case DAC960_MAJOR+4: + case DAC960_MAJOR+5: + case DAC960_MAJOR+6: + case DAC960_MAJOR+7: + case COMPAQ_SMART2_MAJOR+0: + case COMPAQ_SMART2_MAJOR+1: + case COMPAQ_SMART2_MAJOR+2: + case COMPAQ_SMART2_MAJOR+3: + case COMPAQ_SMART2_MAJOR+4: + case COMPAQ_SMART2_MAJOR+5: + case COMPAQ_SMART2_MAJOR+6: + case COMPAQ_SMART2_MAJOR+7: do { if (req->sem) @@ -509,13 +564,25 @@ continue; /* Can we add it to the end of this request? */ if (req->sector + req->nr_sectors == sector) { + if (req->bhtail->b_data + req->bhtail->b_size + != bh->b_data) { + if (req->nr_segments < max_segments) + req->nr_segments++; + else continue; + } req->bhtail->b_reqnext = bh; req->bhtail = bh; req->nr_sectors += count; /* Can we now merge this req with the next? */ - attempt_merge(req, max_sectors); + attempt_merge(req, max_sectors, max_segments); /* or to the beginning? */ } else if (req->sector - count == sector) { + if (bh->b_data + bh->b_size + != req->bh->b_data) { + if (req->nr_segments < max_segments) + req->nr_segments++; + else continue; + } bh->b_reqnext = req->bh; req->bh = bh; req->buffer = bh->b_data; @@ -549,6 +616,7 @@ req->errors = 0; req->sector = sector; req->nr_sectors = count; + req->nr_segments = 1; req->current_nr_sectors = count; req->buffer = bh->b_data; req->sem = NULL; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/loop.c linux.pre11.3/drivers/block/loop.c --- linux.vanilla/drivers/block/loop.c Tue Jun 15 16:49:48 1999 +++ linux.pre11.3/drivers/block/loop.c Mon Jul 19 23:56:58 1999 @@ -27,7 +27,13 @@ * - Should use an own CAP_* category instead of CAP_SYS_ADMIN * - Should use the underlying filesystems/devices read function if possible * to support read ahead (and for write) - */ + * + * WARNING/FIXME: + * - The block number as IV passing to low level transfer functions is broken: + * it passes the underlying device's block number instead of the + * offset. This makes it change for a given block when the file is + * moved/restored/copied and also doesn't work over NFS. + */ #include @@ -107,7 +113,7 @@ static int xor_status(struct loop_device *lo, struct loop_info *info) { - if (info->lo_encrypt_key_size < 0) + if (info->lo_encrypt_key_size <= 0) return -EINVAL; return 0; } @@ -369,6 +375,10 @@ a file structure */ lo->lo_backing_file = NULL; } else if (S_ISREG(inode->i_mode)) { + if (!inode->i_op->bmap) { + printk(KERN_ERR "loop: device has no block access/not implemented\n"); + goto out_putf; + } /* Backed by a regular file - we need to hold onto a file structure for this file. We'll use it to @@ -504,8 +514,6 @@ if ((unsigned int) info.lo_encrypt_key_size > LO_KEY_SIZE) return -EINVAL; type = info.lo_encrypt_type; - if (info.lo_encrypt_key_size == 0 && type == LO_CRYPT_XOR) - return -EINVAL; if (type >= MAX_LO_CRYPT || xfer_funcs[type] == NULL) return -EINVAL; err = loop_release_xfer(lo); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/nbd.c linux.pre11.3/drivers/block/nbd.c --- linux.vanilla/drivers/block/nbd.c Wed Mar 24 10:55:15 1999 +++ linux.pre11.3/drivers/block/nbd.c Mon Jul 19 23:27:39 1999 @@ -401,7 +401,7 @@ return 0; case NBD_SET_SIZE_BLOCKS: nbd_sizes[dev] = arg; - nbd_bytesizes[dev] = arg << nbd_blksize_bits[dev]; + nbd_bytesizes[dev] = ((u64) arg) << nbd_blksize_bits[dev]; return 0; case NBD_DO_IT: if (!lo->file) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/rd.c linux.pre11.3/drivers/block/rd.c --- linux.vanilla/drivers/block/rd.c Thu May 27 22:11:53 1999 +++ linux.pre11.3/drivers/block/rd.c Mon Jul 19 23:57:15 1999 @@ -517,7 +517,7 @@ } if (nblocks > (rd_length[unit] >> RDBLK_SIZE_BITS)) { - printk("RAMDISK: image too big! (%d/%d blocks)\n", + printk("RAMDISK: image too big! (%d/%ld blocks)\n", nblocks, rd_length[unit] >> RDBLK_SIZE_BITS); goto done; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/smart1,2.h linux.pre11.3/drivers/block/smart1,2.h --- linux.vanilla/drivers/block/smart1,2.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/block/smart1,2.h Mon Jul 19 23:57:15 1999 @@ -0,0 +1,274 @@ +/* + * Disk Array driver for Compaq SMART2 Controllers + * Copyright 1998 Compaq Computer 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, GOOD TITLE or + * NON INFRINGEMENT. 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. + * + * Questions/Comments/Bugfixes to arrays@compaq.com + * + * If you want to make changes, improve or add functionality to this + * driver, you'll probably need the Compaq Array Controller Interface + * Specificiation (Document number ECG086/1198) + */ + +/* + * This file contains the controller communication implementation for + * Compaq SMART-1 and SMART-2 controllers. To the best of my knowledge, + * this should support: + * + * PCI: + * SMART-2/P, SMART-2DH, SMART-2SL, SMART-221, SMART-3100ES, SMART-3200 + * Integerated SMART Array Controller, SMART-4200, SMART-4250ES + * + * EISA: + * SMART-2/E, SMART, IAES, IDA-2, IDA + */ + +/* + * Memory mapped FIFO interface (SMART 42xx cards) + */ +static void smart4_submit_command(ctlr_info_t *h, cmdlist_t *c) +{ + writel(c->busaddr, h->vaddr + S42XX_REQUEST_PORT_OFFSET); +} + +/* + * This card is the oposite of the other cards. + * 0 turns interrupts on... + * 0x08 turns them off... + */ +static void smart4_intr_mask(ctlr_info_t *h, unsigned long val) +{ + if (val) + { /* Turn interrupts on */ + writel(0, h->vaddr + S42XX_REPLY_INTR_MASK_OFFSET); + } else /* Turn them off */ + { + writel( S42XX_INTR_OFF, + h->vaddr + S42XX_REPLY_INTR_MASK_OFFSET); + } +} + +/* + * For this card fifo is full if reading this port returns 0! + * + */ +static unsigned long smart4_fifo_full(ctlr_info_t *h) +{ + + return (~readl(h->vaddr + S42XX_REQUEST_PORT_OFFSET)); +} + +/* This type of controller returns -1 if the fifo is empty, + * Not 0 like the others. + * And we need to let it know we read a value out + */ +static unsigned long smart4_completed(ctlr_info_t *h) +{ + long register_value + = readl(h->vaddr + S42XX_REPLY_PORT_OFFSET); + + /* Fifo is empty */ + if( register_value == -1) + return 0; + + /* Need to let it know we got the reply */ + /* We do this by writing a 0 to the port we just read from */ + writel(0, h->vaddr + S42XX_REPLY_PORT_OFFSET); + + return ((unsigned long) register_value); +} + + /* + * This hardware returns interrupt pending at a different place and + * it does not tell us if the fifo is empty, we will have check + * that by getting a 0 back from the comamnd_completed call. + */ +static unsigned long smart4_intr_pending(ctlr_info_t *h) +{ + unsigned long register_value = + readl(h->vaddr + S42XX_INTR_STATUS); + + if( register_value & S42XX_INTR_PENDING) + return FIFO_NOT_EMPTY; + return 0 ; +} + +static struct access_method smart4_access = { + smart4_submit_command, + smart4_intr_mask, + smart4_fifo_full, + smart4_intr_pending, + smart4_completed, +}; + +/* + * Memory mapped FIFO interface (PCI SMART2 and SMART 3xxx cards) + */ +static void smart2_submit_command(ctlr_info_t *h, cmdlist_t *c) +{ + writel(c->busaddr, h->vaddr + COMMAND_FIFO); +} + +static void smart2_intr_mask(ctlr_info_t *h, unsigned long val) +{ + writel(val, h->vaddr + INTR_MASK); +} + +static unsigned long smart2_fifo_full(ctlr_info_t *h) +{ + return readl(h->vaddr + COMMAND_FIFO); +} + +static unsigned long smart2_completed(ctlr_info_t *h) +{ + return readl(h->vaddr + COMMAND_COMPLETE_FIFO); +} + +static unsigned long smart2_intr_pending(ctlr_info_t *h) +{ + return readl(h->vaddr + INTR_PENDING); +} + +static struct access_method smart2_access = { + smart2_submit_command, + smart2_intr_mask, + smart2_fifo_full, + smart2_intr_pending, + smart2_completed, +}; + +/* + * IO access for SMART-2/E cards + */ +static void smart2e_submit_command(ctlr_info_t *h, cmdlist_t *c) +{ + outl(c->busaddr, h->ioaddr + COMMAND_FIFO); +} + +static void smart2e_intr_mask(ctlr_info_t *h, unsigned long val) +{ + outl(val, h->ioaddr + INTR_MASK); +} + +static unsigned long smart2e_fifo_full(ctlr_info_t *h) +{ + return inl(h->ioaddr + COMMAND_FIFO); +} + +static unsigned long smart2e_completed(ctlr_info_t *h) +{ + return inl(h->ioaddr + COMMAND_COMPLETE_FIFO); +} + +static unsigned long smart2e_intr_pending(ctlr_info_t *h) +{ + return inl(h->ioaddr + INTR_PENDING); +} + +static struct access_method smart2e_access = { + smart2e_submit_command, + smart2e_intr_mask, + smart2e_fifo_full, + smart2e_intr_pending, + smart2e_completed, +}; + +/* + * IO access for older SMART-1 type cards + */ +#define SMART1_SYSTEM_MASK 0xC8E +#define SMART1_SYSTEM_DOORBELL 0xC8F +#define SMART1_LOCAL_MASK 0xC8C +#define SMART1_LOCAL_DOORBELL 0xC8D +#define SMART1_INTR_MASK 0xC89 +#define SMART1_LISTADDR 0xC90 +#define SMART1_LISTLEN 0xC94 +#define SMART1_TAG 0xC97 +#define SMART1_COMPLETE_ADDR 0xC98 +#define SMART1_LISTSTATUS 0xC9E + +#define CHANNEL_BUSY 0x01 +#define CHANNEL_CLEAR 0x02 + +static void smart1_submit_command(ctlr_info_t *h, cmdlist_t *c) +{ + /* + * This __u16 is actually a bunch of control flags on SMART + * and below. We want them all to be zero. + */ + c->hdr.size = 0; + + outb(CHANNEL_CLEAR, h->ioaddr + SMART1_SYSTEM_DOORBELL); + + outl(c->busaddr, h->ioaddr + SMART1_LISTADDR); + outw(c->size, h->ioaddr + SMART1_LISTLEN); + + outb(CHANNEL_BUSY, h->ioaddr + SMART1_LOCAL_DOORBELL); +} + +static void smart1_intr_mask(ctlr_info_t *h, unsigned long val) +{ + if (val == 1) { + outb(0xFD, h->ioaddr + SMART1_SYSTEM_DOORBELL); + outb(CHANNEL_BUSY, h->ioaddr + SMART1_LOCAL_DOORBELL); + outb(0x01, h->ioaddr + SMART1_INTR_MASK); + outb(0x01, h->ioaddr + SMART1_SYSTEM_MASK); + } else { + outb(0, h->ioaddr + 0xC8E); + } +} + +static unsigned long smart1_fifo_full(ctlr_info_t *h) +{ + unsigned char chan; + chan = inb(h->ioaddr + SMART1_SYSTEM_DOORBELL) & CHANNEL_CLEAR; + return chan; +} + +static unsigned long smart1_completed(ctlr_info_t *h) +{ + unsigned char status; + unsigned long cmd; + + if (inb(h->ioaddr + SMART1_SYSTEM_DOORBELL) & CHANNEL_BUSY) { + outb(CHANNEL_BUSY, h->ioaddr + SMART1_SYSTEM_DOORBELL); + + cmd = inl(h->ioaddr + SMART1_COMPLETE_ADDR); + status = inb(h->ioaddr + SMART1_LISTSTATUS); + + outb(CHANNEL_CLEAR, h->ioaddr + SMART1_LOCAL_DOORBELL); + + if (cmd) ((cmdlist_t*)bus_to_virt(cmd))->req.hdr.rcode = status; + } else { + cmd = 0; + } + return cmd; +} + +static unsigned long smart1_intr_pending(ctlr_info_t *h) +{ + unsigned char chan; + chan = inb(h->ioaddr + SMART1_SYSTEM_DOORBELL) & CHANNEL_BUSY; + return chan; +} + +static struct access_method smart1_access = { + smart1_submit_command, + smart1_intr_mask, + smart1_fifo_full, + smart1_intr_pending, + smart1_completed, +}; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/cdrom/cdrom.c linux.pre11.3/drivers/cdrom/cdrom.c --- linux.vanilla/drivers/cdrom/cdrom.c Thu May 27 22:11:53 1999 +++ linux.pre11.3/drivers/cdrom/cdrom.c Mon Jul 19 23:57:24 1999 @@ -1145,8 +1145,10 @@ ((cdi->ops->capability & ~cdi->mask & CDC_PLAY_AUDIO)!=0)); strcpy(cdrom_drive_info+pos,"\n\n"); - *lenp=pos+3; - + pos += 3; + if (*lenp > pos) + *lenp = pos; + return proc_dostring(ctl, write, filp, buffer, lenp); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/Config.in linux.pre11.3/drivers/char/Config.in --- linux.vanilla/drivers/char/Config.in Thu May 27 22:11:53 1999 +++ linux.pre11.3/drivers/char/Config.in Mon Jul 19 23:27:49 1999 @@ -28,6 +28,9 @@ tristate 'Digiboard PC/Xx Support' CONFIG_DIGI fi tristate 'Cyclades async mux support' CONFIG_CYCLADES + if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_CYCLADES" != "n" ]; then + bool ' Cyclades-Z interrupt mode operation (EXPERIMENTAL)' CONFIG_CYZ_INTR + fi bool 'Stallion multiport serial support' CONFIG_STALDRV if [ "$CONFIG_STALDRV" = "y" ]; then tristate ' Stallion EasyIO or EC8/32 support' CONFIG_STALLION @@ -144,6 +147,11 @@ dep_tristate 'SF16FMI Radio' CONFIG_RADIO_SF16FMI $CONFIG_VIDEO_DEV if [ "$CONFIG_RADIO_SF16FMI" = "y" ]; then hex ' SF16FMI I/O port (0x284 or 0x384)' CONFIG_RADIO_SF16FMI_PORT 284 + fi + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + if [ "$CONFIG_SGI" = "y" ]; then + dep_tristate 'SGI Vino Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_VINO $CONFIG_VIDEO_DEV + fi fi dep_tristate 'Typhoon Radio (a.k.a. EcoRadio)' CONFIG_RADIO_TYPHOON $CONFIG_VIDEO_DEV if [ "$CONFIG_PROC_FS" = "y" ]; then diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/Makefile linux.pre11.3/drivers/char/Makefile --- linux.vanilla/drivers/char/Makefile Thu May 27 22:11:53 1999 +++ linux.pre11.3/drivers/char/Makefile Mon Jul 19 23:27:49 1999 @@ -30,16 +30,30 @@ ifeq ($(CONFIG_SERIAL),y) ifeq ($(CONFIG_SUN_SERIAL),) - LX_OBJS += serial.o + ifeq ($(CONFIG_SGI_SERIAL),) + ifeq ($(CONFIG_DECSTATION),) + ifeq ($(CONFIG_BAGET_MIPS),) + LX_OBJS += serial.o + endif + endif + endif endif else ifeq ($(CONFIG_SERIAL),m) ifeq ($(CONFIG_SUN_SERIAL),) - MX_OBJS += serial.o + ifeq ($(CONFIG_SGI_SERIAL),) + ifeq ($(CONFIG_DECSTATION),) + ifeq ($(CONFIG_BAGET_MIPS),) + MX_OBJS += serial.o + endif + endif + endif endif endif endif +ifndef CONFIG_DECSTATION +ifndef CONFIG_BAGET_MIPS ifndef CONFIG_SUN_KEYBOARD ifdef CONFIG_VT LX_OBJS += keyboard.o @@ -57,6 +71,8 @@ ifdef CONFIG_MAGIC_SYSRQ LX_OBJS += sysrq.o endif +endif +endif ifeq ($(CONFIG_ATARI_DSP56K),y) L_OBJS += dsp56k.o @@ -362,6 +378,14 @@ endif endif +ifeq ($(CONFIG_VIDEO_VINO),y) +L_OBJS += vino.o +else + ifeq ($(CONFIG_VIDEO_VINO),m) + M_OBJS += vino.o + endif +endif + ifeq ($(CONFIG_RADIO_AZTECH),y) L_OBJS += radio-aztech.o else @@ -477,6 +501,10 @@ MOD_SUB_DIRS += hfmodem endif +endif + +ifeq ($(CONFIG_DZ),y) + L_OBJS += dz.o endif include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/bttv.c linux.pre11.3/drivers/char/bttv.c --- linux.vanilla/drivers/char/bttv.c Tue Jun 15 16:49:48 1999 +++ linux.pre11.3/drivers/char/bttv.c Mon Jul 19 23:57:53 1999 @@ -43,7 +43,6 @@ #include #include #include -#include #if LINUX_VERSION_CODE >= 0x020100 #include @@ -81,8 +80,8 @@ #include "bttv.h" #include "tuner.h" -#define DEBUG(x) /* Debug driver */ -#define IDEBUG(x) /* Debug interrupt handler */ +#define DEBUG(x) /* Debug driver */ +#define IDEBUG(x) /* Debug interrupt handler */ #if LINUX_VERSION_CODE >= 0x020117 MODULE_PARM(vidmem,"i"); @@ -110,7 +109,7 @@ #define CARD_DEFAULT 0 #endif -static unsigned int remap[BTTV_MAX]; /* remap Bt848 */ +static unsigned long remap[BTTV_MAX]; /* remap Bt848 */ static unsigned int radio[BTTV_MAX]; static unsigned int card[BTTV_MAX] = { CARD_DEFAULT, CARD_DEFAULT, CARD_DEFAULT, CARD_DEFAULT }; @@ -129,51 +128,80 @@ #define EEPROM_WRITE_DELAY 20000 #define BURSTOFFSET 76 - - /*******************************/ /* Memory management functions */ /*******************************/ -/* convert virtual user memory address to physical address */ -/* (virt_to_phys only works for kmalloced kernel memory) */ +#define MDEBUG(x) do { } while(0) /* Debug memory management */ + +/* [DaveM] I've recoded most of this so that: + * 1) It's easier to tell what is happening + * 2) It's more portable, especially for translating things + * out of vmalloc mapped areas in the kernel. + * 3) Less unnecessary translations happen. + * + * The code used to assume that the kernel vmalloc mappings + * existed in the page tables of every process, this is simply + * not guarenteed. We now use pgd_offset_k which is the + * defined way to get at the kernel page tables. + */ -static inline unsigned long uvirt_to_phys(unsigned long adr) +/* Given PGD from the address space's page table, return the kernel + * virtual mapping of the physical memory mapped at ADR. + */ +static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr) { - pgd_t *pgd; + unsigned long ret = 0UL; pmd_t *pmd; pte_t *ptep, pte; - pgd = pgd_offset(current->mm, adr); - if (pgd_none(*pgd)) - return 0; - pmd = pmd_offset(pgd, adr); - if (pmd_none(*pmd)) - return 0; - ptep = pte_offset(pmd, adr/*&(~PGDIR_MASK)*/); - pte = *ptep; - if(pte_present(pte)) - return - virt_to_phys((void *)(pte_page(pte)|(adr&(PAGE_SIZE-1)))); - return 0; + if (!pgd_none(*pgd)) { + pmd = pmd_offset(pgd, adr); + if (!pmd_none(*pmd)) { + ptep = pte_offset(pmd, adr); + pte = *ptep; + if(pte_present(pte)) + ret = (pte_page(pte)|(adr&(PAGE_SIZE-1))); + } + } + MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret)); + return ret; } static inline unsigned long uvirt_to_bus(unsigned long adr) { - return virt_to_bus(phys_to_virt(uvirt_to_phys(adr))); -} + unsigned long kva, ret; -/* convert virtual kernel memory address to physical address */ -/* (virt_to_phys only works for kmalloced kernel memory) */ + kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr); + ret = virt_to_bus((void *)kva); + MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret)); + return ret; +} -static inline unsigned long kvirt_to_phys(unsigned long adr) +static inline unsigned long kvirt_to_bus(unsigned long adr) { - return uvirt_to_phys(VMALLOC_VMADDR(adr)); + unsigned long va, kva, ret; + + va = VMALLOC_VMADDR(adr); + kva = uvirt_to_kva(pgd_offset_k(va), va); + ret = virt_to_bus((void *)kva); + MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret)); + return ret; } -static inline unsigned long kvirt_to_bus(unsigned long adr) +/* Here we want the physical address of the memory. + * This is used when initializing the contents of the + * area and marking the pages as reserved. + */ +static inline unsigned long kvirt_to_pa(unsigned long adr) { - return uvirt_to_bus(VMALLOC_VMADDR(adr)); + unsigned long va, kva, ret; + + va = VMALLOC_VMADDR(adr); + kva = uvirt_to_kva(pgd_offset_k(va), va); + ret = __pa(kva); + MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret)); + return ret; } static void * rvmalloc(unsigned long size) @@ -188,8 +216,8 @@ adr=(unsigned long) mem; while (size > 0) { - page = kvirt_to_phys(adr); - mem_map_reserve(MAP_NR(phys_to_virt(page))); + page = kvirt_to_pa(adr); + mem_map_reserve(MAP_NR(__va(page))); adr+=PAGE_SIZE; size-=PAGE_SIZE; } @@ -206,8 +234,8 @@ adr=(unsigned long) mem; while (size > 0) { - page = kvirt_to_phys(adr); - mem_map_unreserve(MAP_NR(phys_to_virt(page))); + page = kvirt_to_pa(adr); + mem_map_unreserve(MAP_NR(__va(page))); adr+=PAGE_SIZE; size-=PAGE_SIZE; } @@ -541,13 +569,15 @@ /* Aimslab VHX */ { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}}, /* Zoltrix TV-Max */ - { 3, 1, 0, 2,15, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}}, + { 3, 1, 0, 2, 0x00000f, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0x8}}, /* Pixelview PlayTV (bt878) */ { 3, 4, 0, 2, 0x01e000, { 2, 0, 1, 1}, {0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 }}, /* "Leadtek WinView 601", */ { 3, 1, 0, 2, 0x8300f8, { 2, 3, 1, 1,0}, {0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007}}, /* AVEC Intercapture */ { 3, 1, 9, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}}, + /* LifeView FlyKit w/o Tuner */ + { 3, 1, -1, 2, 0xc00, { 0, 3, 1, 1}} }; #define TVCARDS (sizeof(tvcards)/sizeof(tvcard)) @@ -823,30 +853,30 @@ unsigned int *po=(unsigned int *) btv->vbi_odd; unsigned int *pe=(unsigned int *) btv->vbi_even; - DEBUG(printk(KERN_DEBUG "vbiodd: 0x%08x\n",(int)btv->vbi_odd)); - DEBUG(printk(KERN_DEBUG "vbievn: 0x%08x\n",(int)btv->vbi_even)); - DEBUG(printk(KERN_DEBUG "po: 0x%08x\n",(int)po)); - DEBUG(printk(KERN_DEBUG "pe: 0x%08x\n",(int)pe)); + DEBUG(printk(KERN_DEBUG "vbiodd: 0x%lx\n",(long)btv->vbi_odd)); + DEBUG(printk(KERN_DEBUG "vbievn: 0x%lx\n",(long)btv->vbi_even)); + DEBUG(printk(KERN_DEBUG "po: 0x%lx\n",(long)po)); + DEBUG(printk(KERN_DEBUG "pe: 0x%lx\n",(long)pe)); - *(po++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(po++)=0; + *(po++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(po++)=0; for (i=0; i<16; i++) { - *(po++)=VBI_RISC; - *(po++)=kvirt_to_bus((unsigned long)btv->vbibuf+i*2048); + *(po++)=cpu_to_le32(VBI_RISC); + *(po++)=cpu_to_le32(kvirt_to_bus((unsigned long)btv->vbibuf+i*2048)); } - *(po++)=BT848_RISC_JUMP; - *(po++)=virt_to_bus(btv->risc_jmp+4); + *(po++)=cpu_to_le32(BT848_RISC_JUMP); + *(po++)=cpu_to_le32(virt_to_bus(btv->risc_jmp+4)); - *(pe++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(pe++)=0; + *(pe++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(pe++)=0; for (i=16; i<32; i++) { - *(pe++)=VBI_RISC; - *(pe++)=kvirt_to_bus((unsigned long)btv->vbibuf+i*2048); + *(pe++)=cpu_to_le32(VBI_RISC); + *(pe++)=cpu_to_le32(kvirt_to_bus((unsigned long)btv->vbibuf+i*2048)); } - *(pe++)=BT848_RISC_JUMP|BT848_RISC_IRQ|(0x01<<16); - *(pe++)=virt_to_bus(btv->risc_jmp+10); - DEBUG(printk(KERN_DEBUG "po: 0x%08x\n",(int)po)); - DEBUG(printk(KERN_DEBUG "pe: 0x%08x\n",(int)pe)); + *(pe++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(0x01<<16)); + *(pe++)=cpu_to_le32(virt_to_bus(btv->risc_jmp+10)); + DEBUG(printk(KERN_DEBUG "po: 0x%lx\n",(long)po)); + DEBUG(printk(KERN_DEBUG "pe: 0x%lx\n",(long)pe)); } int fmtbppx2[16] = { @@ -881,8 +911,8 @@ unsigned long bpl=1024; /* bytes per line */ unsigned long vadr=(unsigned long) vbuf; - *(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0; - *(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=0; + *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(ro++)=0; + *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(re++)=0; /* In PAL 650 blocks of 256 DWORDs are sampled, but only if VDELAY is 2 and without separate VBI grabbing. @@ -890,17 +920,17 @@ for (line=0; line < 640; line++) { - *(ro++)=BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL; - *(ro++)=kvirt_to_bus(vadr); - *(re++)=BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL; - *(re++)=kvirt_to_bus(vadr+BTTV_MAX_FBUF/2); + *(ro++)=cpu_to_le32(BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL); + *(ro++)=cpu_to_le32(kvirt_to_bus(vadr)); + *(re++)=cpu_to_le32(BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL); + *(re++)=cpu_to_le32(kvirt_to_bus(vadr+BTTV_MAX_FBUF/2)); vadr+=bpl; } - *(ro++)=BT848_RISC_JUMP; - *(ro++)=btv->bus_vbi_even; - *(re++)=BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16); - *(re++)=btv->bus_vbi_odd; + *(ro++)=cpu_to_le32(BT848_RISC_JUMP); + *(ro++)=cpu_to_le32(btv->bus_vbi_even); + *(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16)); + *(re++)=cpu_to_le32(btv->bus_vbi_odd); return 0; } @@ -954,8 +984,8 @@ cradr=cbadr+csize; inter = (height>btv->win.cropheight/2) ? 1 : 0; - *(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3; *(ro++)=0; - *(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3; *(re++)=0; + *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3); *(ro++)=0; + *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3); *(re++)=0; for (line=0; line < (height<<(1^inter)); line++) { @@ -991,15 +1021,15 @@ todo-=bl; if(!todo) rcmd|=BT848_RISC_EOL; /* if this is the last EOL */ - *((*rp)++)=rcmd|bl; - *((*rp)++)=blcb|(blcr<<16); - *((*rp)++)=kvirt_to_bus(vadr); + *((*rp)++)=cpu_to_le32(rcmd|bl); + *((*rp)++)=cpu_to_le32(blcb|(blcr<<16)); + *((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr)); vadr+=bl; if((rcmd&(15<<28))==BT848_RISC_WRITE123) { - *((*rp)++)=kvirt_to_bus(cbadr); + *((*rp)++)=cpu_to_le32(kvirt_to_bus(cbadr)); cbadr+=blcb; - *((*rp)++)=kvirt_to_bus(cradr); + *((*rp)++)=cpu_to_le32(kvirt_to_bus(cradr)); cradr+=blcr; } @@ -1007,10 +1037,10 @@ } } - *(ro++)=BT848_RISC_JUMP; - *(ro++)=btv->bus_vbi_even; - *(re++)=BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16); - *(re++)=btv->bus_vbi_odd; + *(ro++)=cpu_to_le32(BT848_RISC_JUMP); + *(ro++)=cpu_to_le32(btv->bus_vbi_even); + *(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16)); + *(re++)=cpu_to_le32(btv->bus_vbi_odd); return 0; } @@ -1037,8 +1067,8 @@ inter = (height>btv->win.cropheight/2) ? 1 : 0; bpl=width*fmtbppx2[palette2fmt[palette]&0xf]/2; - *(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0; - *(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=0; + *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(ro++)=0; + *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(re++)=0; for (line=0; line < (height<<(1^inter)); line++) { @@ -1050,35 +1080,35 @@ bl=PAGE_SIZE-((PAGE_SIZE-1)&vadr); if (bpl<=bl) { - *((*rp)++)=BT848_RISC_WRITE|BT848_RISC_SOL| - BT848_RISC_EOL|bpl; - *((*rp)++)=kvirt_to_bus(vadr); + *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| + BT848_RISC_EOL|bpl); + *((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr)); vadr+=bpl; } else { todo=bpl; - *((*rp)++)=BT848_RISC_WRITE|BT848_RISC_SOL|bl; - *((*rp)++)=kvirt_to_bus(vadr); + *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|bl); + *((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr)); vadr+=bl; todo-=bl; while (todo>PAGE_SIZE) { - *((*rp)++)=BT848_RISC_WRITE|PAGE_SIZE; - *((*rp)++)=kvirt_to_bus(vadr); + *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|PAGE_SIZE); + *((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr)); vadr+=PAGE_SIZE; todo-=PAGE_SIZE; } - *((*rp)++)=BT848_RISC_WRITE|BT848_RISC_EOL|todo; - *((*rp)++)=kvirt_to_bus(vadr); + *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|todo); + *((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr)); vadr+=todo; } } - *(ro++)=BT848_RISC_JUMP; - *(ro++)=btv->bus_vbi_even; - *(re++)=BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16); - *(re++)=btv->bus_vbi_odd; + *(ro++)=cpu_to_le32(BT848_RISC_JUMP); + *(ro++)=cpu_to_le32(btv->bus_vbi_even); + *(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16)); + *(re++)=cpu_to_le32(btv->bus_vbi_odd); return 0; } @@ -1162,10 +1192,10 @@ adr=btv->win.vidadr+btv->win.x*bpp+btv->win.y*bpl; if ((clipmap=vmalloc(VIDEO_CLIPMAP_SIZE))==NULL) { /* can't clip, don't generate any risc code */ - *(ro++)=BT848_RISC_JUMP; - *(ro++)=btv->bus_vbi_even; - *(re++)=BT848_RISC_JUMP; - *(re++)=btv->bus_vbi_odd; + *(ro++)=cpu_to_le32(BT848_RISC_JUMP); + *(ro++)=cpu_to_le32(btv->bus_vbi_even); + *(re++)=cpu_to_le32(BT848_RISC_JUMP); + *(re++)=cpu_to_le32(btv->bus_vbi_odd); } if (ncr < 0) { /* bitmap was pased */ memcpy(clipmap, (unsigned char *)cr, VIDEO_CLIPMAP_SIZE); @@ -1187,8 +1217,8 @@ if (btv->win.y<0) clip_draw_rectangle(clipmap, 0, 0, 1024, -(btv->win.y)); - *(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0; - *(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=0; + *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(ro++)=0; + *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(re++)=0; /* translate bitmap to risc code */ for (line=outofmem=0; line < (height<bus_vbi_even; - *(re++)=BT848_RISC_JUMP; - *(re++)=btv->bus_vbi_odd; + *(ro++)=cpu_to_le32(BT848_RISC_JUMP); + *(ro++)=cpu_to_le32(btv->bus_vbi_even); + *(re++)=cpu_to_le32(BT848_RISC_JUMP); + *(re++)=cpu_to_le32(btv->bus_vbi_odd); } /* set geometry for even/odd frames @@ -1297,6 +1327,23 @@ set_pll(btv); btwrite(fmt, BT848_COLOR_FMT); +#ifdef __sparc__ + if(fmt == BT848_COLOR_FMT_RGB32 || + fmt == BT848_COLOR_FMT_RGB24) { + btwrite((BT848_COLOR_CTL_GAMMA | + BT848_COLOR_CTL_WSWAP_ODD | + BT848_COLOR_CTL_WSWAP_EVEN | + BT848_COLOR_CTL_BSWAP_ODD | + BT848_COLOR_CTL_BSWAP_EVEN), + BT848_COLOR_CTL); + } else if(fmt == BT848_COLOR_FMT_RGB16 || + fmt == BT848_COLOR_FMT_RGB15) { + btwrite((BT848_COLOR_CTL_GAMMA | + BT848_COLOR_CTL_BSWAP_ODD | + BT848_COLOR_CTL_BSWAP_EVEN), + BT848_COLOR_CTL); + } +#endif hactive=width; vtc=0; @@ -1474,7 +1521,7 @@ btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI); btor(BT848_VSCALE_COMB, BT848_O_VSCALE_HI); } - btv->risc_jmp[12]=BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ; + btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ); } btor(3, BT848_CAP_CTL); btor(3, BT848_GPIO_DMA_CTL); @@ -1661,12 +1708,13 @@ struct video_capability b; strcpy(b.name,btv->video_dev.name); b.type = VID_TYPE_CAPTURE| - VID_TYPE_TUNER| VID_TYPE_TELETEXT| VID_TYPE_OVERLAY| VID_TYPE_CLIPPING| VID_TYPE_FRAMERAM| - VID_TYPE_SCALES; + VID_TYPE_SCALES| + ((tvcards[btv->type].tuner != -1) + ? VID_TYPE_TUNER : 0); b.channels = tvcards[btv->type].video_inputs; b.audios = tvcards[btv->type].audio_inputs; b.maxwidth = tvnorms[btv->win.norm].swidth; @@ -2268,7 +2316,7 @@ pos=(unsigned long) btv->fbuffer; while (size > 0) { - page = kvirt_to_phys(pos); + page = kvirt_to_pa(pos); if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) return -EAGAIN; start+=PAGE_SIZE; @@ -3110,44 +3158,44 @@ int flags=btv->cap; /* Sync to start of odd field */ - btv->risc_jmp[0]=BT848_RISC_SYNC|BT848_RISC_RESYNC|BT848_FIFO_STATUS_VRE; + btv->risc_jmp[0]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC|BT848_FIFO_STATUS_VRE); btv->risc_jmp[1]=0; /* Jump to odd vbi sub */ - btv->risc_jmp[2]=BT848_RISC_JUMP|(0x5<<20); + btv->risc_jmp[2]=cpu_to_le32(BT848_RISC_JUMP|(0x5<<20)); if (flags&8) - btv->risc_jmp[3]=virt_to_bus(btv->vbi_odd); + btv->risc_jmp[3]=cpu_to_le32(virt_to_bus(btv->vbi_odd)); else - btv->risc_jmp[3]=virt_to_bus(btv->risc_jmp+4); + btv->risc_jmp[3]=cpu_to_le32(virt_to_bus(btv->risc_jmp+4)); /* Jump to odd sub */ - btv->risc_jmp[4]=BT848_RISC_JUMP|(0x6<<20); + btv->risc_jmp[4]=cpu_to_le32(BT848_RISC_JUMP|(0x6<<20)); if (flags&2) - btv->risc_jmp[5]=virt_to_bus(btv->risc_odd); + btv->risc_jmp[5]=cpu_to_le32(virt_to_bus(btv->risc_odd)); else - btv->risc_jmp[5]=virt_to_bus(btv->risc_jmp+6); + btv->risc_jmp[5]=cpu_to_le32(virt_to_bus(btv->risc_jmp+6)); /* Sync to start of even field */ - btv->risc_jmp[6]=BT848_RISC_SYNC|BT848_RISC_RESYNC|BT848_FIFO_STATUS_VRO; + btv->risc_jmp[6]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC|BT848_FIFO_STATUS_VRO); btv->risc_jmp[7]=0; /* Jump to even vbi sub */ - btv->risc_jmp[8]=BT848_RISC_JUMP; + btv->risc_jmp[8]=cpu_to_le32(BT848_RISC_JUMP); if (flags&4) - btv->risc_jmp[9]=virt_to_bus(btv->vbi_even); + btv->risc_jmp[9]=cpu_to_le32(virt_to_bus(btv->vbi_even)); else - btv->risc_jmp[9]=virt_to_bus(btv->risc_jmp+10); + btv->risc_jmp[9]=cpu_to_le32(virt_to_bus(btv->risc_jmp+10)); /* Jump to even sub */ - btv->risc_jmp[10]=BT848_RISC_JUMP|(8<<20); + btv->risc_jmp[10]=cpu_to_le32(BT848_RISC_JUMP|(8<<20)); if (flags&1) - btv->risc_jmp[11]=virt_to_bus(btv->risc_even); + btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_even)); else - btv->risc_jmp[11]=virt_to_bus(btv->risc_jmp+12); + btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_jmp+12)); - btv->risc_jmp[12]=BT848_RISC_JUMP; - btv->risc_jmp[13]=virt_to_bus(btv->risc_jmp); + btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP); + btv->risc_jmp[13]=cpu_to_le32(virt_to_bus(btv->risc_jmp)); /* enable capturing */ btaor(flags, ~0x0f, BT848_CAP_CTL); @@ -3165,7 +3213,7 @@ /* reset the bt848 */ btwrite(0, BT848_SRESET); - DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%08x\n",i,(unsigned int) btv->bt848_mem)); + DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%lx\n",i,(unsigned long) btv->bt848_mem)); /* default setup for max. PAL size in a 1024xXXX hicolor framebuffer */ btv->win.norm=0; /* change this to 1 for NTSC, 2 for SECAM */ @@ -3330,8 +3378,7 @@ if (!astat) return; btwrite(astat,BT848_INT_STAT); - IDEBUG(printk ("bttv%d: astat %08x\n", btv->nr, astat)); - IDEBUG(printk ("bttv%d: stat %08x\n", btv->nr, stat)); + IDEBUG(printk ("bttv%d: astat %08x stat %08x\n", btv->nr, astat, stat)); /* get device status bits */ dstat=btread(BT848_DSTATUS); @@ -3387,8 +3434,8 @@ btv->gro = btv->gro_next; btv->gre = btv->gre_next; btv->grf = btv->grf_next; - btv->risc_jmp[5]=btv->gro; - btv->risc_jmp[11]=btv->gre; + btv->risc_jmp[5]=cpu_to_le32(btv->gro); + btv->risc_jmp[11]=cpu_to_le32(btv->gre); bt848_set_geo(btv, btv->gwidth, btv->gheight, btv->gfmt); @@ -3405,9 +3452,9 @@ } if (stat&(8<<28)) { - btv->risc_jmp[5]=btv->gro; - btv->risc_jmp[11]=btv->gre; - btv->risc_jmp[12]=BT848_RISC_JUMP; + btv->risc_jmp[5]=cpu_to_le32(btv->gro); + btv->risc_jmp[11]=cpu_to_le32(btv->gre); + btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP); bt848_set_geo(btv, btv->gwidth, btv->gheight, btv->gfmt); } @@ -3502,14 +3549,16 @@ if (remap[bttv_num]) { + unsigned int dw = btv->bt848_adr; + if (remap[bttv_num] < 0x1000) remap[bttv_num]<<=20; remap[bttv_num]&=PCI_BASE_ADDRESS_MEM_MASK; - printk(KERN_INFO "bttv%d: remapping to : 0x%08x.\n", + printk(KERN_INFO "bttv%d: remapping to : 0x%lx.\n", bttv_num,remap[bttv_num]); remap[bttv_num]|=btv->bt848_adr&(~PCI_BASE_ADDRESS_MEM_MASK); pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, remap[bttv_num]); - pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &btv->bt848_adr); + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &dw); btv->dev->base_address[0] = btv->bt848_adr; } btv->bt848_adr&=PCI_BASE_ADDRESS_MEM_MASK; @@ -3518,7 +3567,7 @@ bttv_num,btv->id, btv->revision); printk("bus: %d, devfn: %d, ",dev->bus->number, dev->devfn); printk("irq: %d, ",btv->irq); - printk("memory: 0x%08x.\n", btv->bt848_adr); + printk("memory: 0x%lx.\n", btv->bt848_adr); btv->pll.pll_crystal = 0; btv->pll.pll_ifreq = 0; @@ -3542,7 +3591,11 @@ } } +#ifdef __sparc__ + btv->bt848_mem=(unsigned char *)btv->bt848_adr; +#else btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000); +#endif /* clear interrupt mask */ btwrite(0, BT848_INT_MASK); @@ -3817,17 +3870,17 @@ if (btv->risc_even) kfree((void *) btv->risc_even); - DEBUG(printk(KERN_DEBUG "free: risc_jmp: 0x%08x.\n", btv->risc_jmp)); + DEBUG(printk(KERN_DEBUG "free: risc_jmp: 0x%p.\n", btv->risc_jmp)); if (btv->risc_jmp) kfree((void *) btv->risc_jmp); - DEBUG(printk(KERN_DEBUG "bt848_vbibuf: 0x%08x.\n", btv->vbibuf)); + DEBUG(printk(KERN_DEBUG "bt848_vbibuf: 0x%p.\n", btv->vbibuf)); if (btv->vbibuf) vfree((void *) btv->vbibuf); free_irq(btv->irq,btv); - DEBUG(printk(KERN_DEBUG "bt848_mem: 0x%08x.\n", btv->bt848_mem)); + DEBUG(printk(KERN_DEBUG "bt848_mem: 0x%p.\n", btv->bt848_mem)); if (btv->bt848_mem) iounmap(btv->bt848_mem); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/bttv.h linux.pre11.3/drivers/char/bttv.h --- linux.vanilla/drivers/char/bttv.h Tue Jun 15 16:49:48 1999 +++ linux.pre11.3/drivers/char/bttv.h Tue Jul 20 01:56:13 1999 @@ -102,9 +102,9 @@ #else struct pci_dev *dev; #endif - unsigned char irq; /* IRQ used by Bt848 card */ + unsigned int irq; /* IRQ used by Bt848 card */ unsigned char revision; - unsigned int bt848_adr; /* bus address of IO mem returned by PCI BIOS */ + unsigned long bt848_adr; /* bus address of IO mem returned by PCI BIOS */ unsigned char *bt848_mem; /* pointer to mapped IO memory */ unsigned long busriscmem; u32 *riscmem; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/bw-qcam.c linux.pre11.3/drivers/char/bw-qcam.c --- linux.vanilla/drivers/char/bw-qcam.c Mon Mar 29 10:25:55 1999 +++ linux.pre11.3/drivers/char/bw-qcam.c Mon Jul 19 23:58:05 1999 @@ -159,6 +159,8 @@ struct qcam_device *q; q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); + if(q==NULL) + return NULL; q->pport = port; q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL, diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/c-qcam.c linux.pre11.3/drivers/char/c-qcam.c --- linux.vanilla/drivers/char/c-qcam.c Tue Dec 22 23:19:37 1998 +++ linux.pre11.3/drivers/char/c-qcam.c Mon Jul 19 23:58:05 1999 @@ -641,6 +641,8 @@ struct qcam_device *q; q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); + if(q==NULL) + return NULL; q->pport = port; q->pdev = parport_register_device(port, "c-qcam", NULL, NULL, diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/cyclades.c linux.pre11.3/drivers/char/cyclades.c --- linux.vanilla/drivers/char/cyclades.c Tue Jun 15 16:49:48 1999 +++ linux.pre11.3/drivers/char/cyclades.c Mon Jul 19 23:27:49 1999 @@ -1,7 +1,7 @@ #define BLOCKMOVE #define Z_WAKE static char rcsid[] = -"$Revision: 2.2.2.2 $$Date: 1999/05/21 17:18:15 $"; +"$Revision: 2.2.2.3 $$Date: 1999/06/28 11:13:29 $"; /* * linux/drivers/char/cyclades.c @@ -31,6 +31,16 @@ * void cleanup_module(void); * * $Log: cyclades.c,v $ + * Revision 2.2.2.3 1999/06/28 11:13:29 ivan + * Added support for interrupt mode operation for the Z cards; + * Removed the driver inactivity control for the Z; + * Added a missing MOD_DEC_USE_COUNT in the cy_open function for when + * the Z firmware is not loaded yet; + * Replaced the "manual" Z Tx flush buffer by a call to a FW command of + * same functionality; + * Implemented workaround for IRQ setting loss on the PCI configuration + * registers after a PCI bridge EEPROM reload (affects PLX9060 only); + * * Revision 2.2.2.2 1999/05/14 17:18:15 ivan * /proc entry location changed to /proc/tty/driver/cyclades; * Added support to shared IRQ's (only for PCI boards); @@ -528,7 +538,7 @@ constant in the definition below. No other change is necessary to support more boards/ports. */ -#define NR_PORTS 128 +#define NR_PORTS 256 #define ZE_V1_NPORTS 64 #define ZO_V1 0 @@ -810,13 +820,15 @@ #ifndef CONFIG_COBALT_27 static void cy_probe(int, void *, struct pt_regs *); #endif /* CONFIG_COBALT_27 */ -static void cyz_poll(unsigned long); #ifdef CYCLOM_SHOW_STATUS static void show_status(int); #endif static int cyclades_get_proc_info(char *, char **, off_t , int , int *, void *); +#ifndef CONFIG_CYZ_INTR +static void cyz_poll(unsigned long); + /* The Cyclades-Z polling cycle is defined by this variable */ static long cyz_polling_cycle = CZ_DEF_POLL; @@ -825,6 +837,7 @@ cyz_timerlist = { NULL, NULL, 0, 0, cyz_poll }; +#endif /* CONFIG_CYZ_INTR */ /************************************************** error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long)); @@ -1197,7 +1210,7 @@ if((cinfo = (struct cyclades_card *)dev_id) == 0){ #ifdef CY_DEBUG_INTERRUPTS - printk("cy_interrupt: spurious interrupt %d\n\r", irq); + printk("cyy_interrupt: spurious interrupt %d\n\r", irq); #endif return; /* spurious interrupt */ } @@ -1229,7 +1242,7 @@ } if (status & CySRReceive) { /* reception interrupt */ #ifdef CY_DEBUG_INTERRUPTS - printk("cy_interrupt: rcvd intr, chip %d\n\r", chip); + printk("cyy_interrupt: rcvd intr, chip %d\n\r", chip); #endif /* determine the channel & change to that context */ save_xir = (u_char) cy_readb(base_addr+(CyRIR<flip.char_buf_ptr++ = 0; /* If the flip buffer itself is - overflowing, we still loose + overflowing, we still lose the next incoming character. */ if(tty->flip.count @@ -1356,7 +1369,7 @@ is empty, we know we can always stuff a dozen characters. */ #ifdef CY_DEBUG_INTERRUPTS - printk("cy_interrupt: xmit intr, chip %d\n\r", chip); + printk("cyy_interrupt: xmit intr, chip %d\n\r", chip); #endif /* determine the channel & change to that context */ @@ -1636,12 +1649,285 @@ } /* cyz_update_channel */ #endif - +#ifdef CONFIG_CYZ_INTR static void cyz_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + struct tty_struct *tty; + struct cyclades_card *cinfo; + struct cyclades_port *info; + static volatile struct FIRM_ID *firm_id; + static volatile struct ZFW_CTRL *zfw_ctrl; + static volatile struct BOARD_CTRL *board_ctrl; + static volatile struct CH_CTRL *ch_ctrl; + static volatile struct BUF_CTRL *buf_ctrl; + uclong channel; + ucchar cmd; + uclong param; + uclong hw_ver, fw_ver; + char data; + volatile int char_count, special_count; +#ifdef BLOCKMOVE + int small_count; +#endif + volatile uclong tx_put, tx_get, tx_bufsize; + volatile uclong rx_put, rx_get, rx_bufsize; + + if((cinfo = (struct cyclades_card *)dev_id) == 0){ +#ifdef CY_DEBUG_INTERRUPTS + printk("cyz_interrupt: spurious interrupt %d\n\r", irq); +#endif + return; /* spurious interrupt */ + } + + firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS); + if (!ISZLOADED(*cinfo)) { +#ifdef CY_DEBUG_INTERRUPTS + printk("cyz_interrupt: board not yet loaded (INT %d).\n\r", irq); +#endif + return; + } + + zfw_ctrl = (struct ZFW_CTRL *) + (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr)); + board_ctrl = &(zfw_ctrl->board_ctrl); + fw_ver = cy_readl(&board_ctrl->fw_version); + hw_ver = cy_readl(&((struct RUNTIME_9060 *) + (cinfo->ctl_addr))->mail_box_0); + + while(cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { + special_count = 0; + info = &cy_port[channel + cinfo->first_line]; + if((tty = info->tty) == 0) continue; + ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); + buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); + + switch(cmd){ + case C_CM_PR_ERROR: + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = TTY_PARITY; + *tty->flip.char_buf_ptr++ = 0; + special_count++; + break; + case C_CM_FR_ERROR: + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = TTY_FRAME; + *tty->flip.char_buf_ptr++ = 0; + special_count++; + break; + case C_CM_RXBRK: + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = TTY_BREAK; + *tty->flip.char_buf_ptr++ = 0; + special_count++; + break; + case C_CM_MDCD: + if (info->flags & ASYNC_CHECK_CD){ + if ((fw_ver > 241 ? + ((u_long)param) : + cy_readl(&ch_ctrl[channel].rs_status)) & C_RS_DCD) { + /* SP("Open Wakeup\n"); */ + cy_sched_event(info, + Cy_EVENT_OPEN_WAKEUP); + }else if(!((info->flags + & ASYNC_CALLOUT_ACTIVE) + &&(info->flags + & ASYNC_CALLOUT_NOHUP))){ + /* SP("Hangup\n"); */ + cy_sched_event(info, + Cy_EVENT_HANGUP); + } + } + break; + case C_CM_MCTS: + if (info->flags & ASYNC_CTS_FLOW) { + if(info->tty->hw_stopped){ + if( cy_readl(&ch_ctrl[channel].rs_status) & C_RS_DCD){ + /* cy_start isn't used because... + HW flow is handled by the board */ + /* SP("Write Wakeup\n"); */ + cy_sched_event(info, + Cy_EVENT_WRITE_WAKEUP); + } + }else{ + if(!(cy_readl(&ch_ctrl[channel].rs_status) & C_RS_CTS)){ + /* cy_stop isn't used because + HW flow is handled by the board */ + /* SP("Write stop\n"); */ + } + } + } + break; + case C_CM_MRI: + break; + case C_CM_MDSR: + break; +#ifdef Z_WAKE + case C_CM_IOCTLW: + cy_sched_event(info, Cy_EVENT_SHUTDOWN_WAKEUP); + break; +#endif + case C_CM_RXHIWM: + case C_CM_RXNNDT: + /* Reception Interrupt */ +#ifdef CY_DEBUG_INTERRUPTS + printk("cyz_interrupt: rcvd intr, card %d, port %ld\n\r", + info->card, channel); +#endif + + rx_get = cy_readl(&buf_ctrl->rx_get); + rx_put = cy_readl(&buf_ctrl->rx_put); + rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize); + if (rx_put >= rx_get) + char_count = rx_put - rx_get; + else + char_count = rx_put - rx_get + rx_bufsize; + + if ( char_count ){ + +#ifdef CY_ENABLE_MONITORING + info->mon.int_count++; + info->mon.char_count += char_count; + if (char_count > info->mon.char_max) + info->mon.char_max = char_count; + info->mon.char_last = char_count; +#endif + info->idle_stats.recv_bytes += char_count; + info->idle_stats.recv_idle = jiffies; + if( tty == 0){ + /* flush received characters */ + rx_get = (rx_get + char_count) & (rx_bufsize - 1); + /* SP("-"); */ + info->rflush_count++; + }else{ +#ifdef BLOCKMOVE + /* we'd like to use memcpy(t, f, n) and memset(s, c, count) + for performance, but because of buffer boundaries, there + may be several steps to the operation */ + while(0 < (small_count + = cy_min((rx_bufsize - rx_get), + cy_min((TTY_FLIPBUF_SIZE - tty->flip.count), + char_count)))){ + + memcpy_fromio(tty->flip.char_buf_ptr, + (char *)(cinfo->base_addr + + cy_readl(&buf_ctrl->rx_bufaddr) + + rx_get), + small_count); + + tty->flip.char_buf_ptr += small_count; + memset(tty->flip.flag_buf_ptr, + TTY_NORMAL, + small_count); + tty->flip.flag_buf_ptr += small_count; + rx_get = (rx_get + small_count) & (rx_bufsize - 1); + char_count -= small_count; + tty->flip.count += small_count; + } +#else + while(char_count--){ + if (tty->flip.count >= TTY_FLIPBUF_SIZE){ + break; + } + data = cy_readb(cinfo->base_addr + + cy_readl(&buf_ctrl->rx_bufaddr) + rx_get); + rx_get = (rx_get + 1) & (rx_bufsize - 1); + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = TTY_NORMAL; + *tty->flip.char_buf_ptr++ = data; + } +#endif + queue_task(&tty->flip.tqueue, &tq_timer); + } + /* Update rx_get */ + cy_writel(&buf_ctrl->rx_get, rx_get); + } + break; + case C_CM_TXBEMPTY: + case C_CM_TXLOWWM: + case C_CM_INTBACK: + /* Transmission Interrupt */ +#ifdef CY_DEBUG_INTERRUPTS + printk("cyz_interrupt: xmit intr, card %d, port %ld\n\r", + info->card, channel); +#endif + + tx_get = cy_readl(&buf_ctrl->tx_get); + tx_put = cy_readl(&buf_ctrl->tx_put); + tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize); + if (tx_put >= tx_get) + char_count = tx_get - tx_put - 1 + tx_bufsize; + else + char_count = tx_get - tx_put - 1; + + if ( char_count ){ + + if( tty == 0 ){ + goto ztxdone; + } + + if(info->x_char) { /* send special char */ + data = info->x_char; + + cy_writeb((cinfo->base_addr + + cy_readl(&buf_ctrl->tx_bufaddr) + tx_put), data); + tx_put = (tx_put + 1) & (tx_bufsize - 1); + info->x_char = 0; + char_count--; + } +#ifdef BLOCKMOVE + while(0 < (small_count + = cy_min((tx_bufsize - tx_put), + cy_min ((SERIAL_XMIT_SIZE - info->xmit_tail), + cy_min(info->xmit_cnt, char_count))))){ + + memcpy_toio((char *)(cinfo->base_addr + + cy_readl(&buf_ctrl->tx_bufaddr) + tx_put), + &info->xmit_buf[info->xmit_tail], + small_count); + + tx_put = (tx_put + small_count) & (tx_bufsize - 1); + char_count -= small_count; + info->xmit_cnt -= small_count; + info->xmit_tail = + (info->xmit_tail + small_count) & (SERIAL_XMIT_SIZE - 1); + } +#else + while (info->xmit_cnt && char_count){ + data = info->xmit_buf[info->xmit_tail]; + info->xmit_cnt--; + info->xmit_tail = + (info->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1); + + cy_writeb(cinfo->base_addr + + cy_readl(&buf_ctrl->tx_bufaddr) + tx_put, + data); + tx_put = (tx_put + 1) & (tx_bufsize - 1); + char_count--; + } + +#endif + ztxdone: + if (info->xmit_cnt < WAKEUP_CHARS) { + cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); + } + /* Update tx_put */ + cy_writel(&buf_ctrl->tx_put, tx_put); + } + break; + case C_CM_FATAL: + /* should do something with this !!! */ + break; + } + if(special_count){ + queue_task(&tty->flip.tqueue, &tq_timer); + } + } + + return; } /* cyz_interrupt */ +#else /* CONFIG_CYZ_INTR */ static void cyz_poll(unsigned long arg) @@ -1675,7 +1961,6 @@ firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS); if (!ISZLOADED(*cinfo)) { - cinfo->inact_ctrl = 0; continue; } @@ -1686,12 +1971,6 @@ hw_ver = cy_readl(&((struct RUNTIME_9060 *) (cinfo->ctl_addr))->mail_box_0); - /* Enables the firmware inactivity control */ - if ((fw_ver > 0x00000310L) && (!cinfo->inact_ctrl)) { - param = cyz_issue_cmd( &cy_card[card], 0L, C_CM_TINACT, 0L); - cinfo->inact_ctrl = 1; - } - while(cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1){ char_count = 0; info = &cy_port[ channel + cinfo->first_line ]; @@ -1922,17 +2201,13 @@ } /* poll every 40 ms */ cyz_timerlist.expires = jiffies + cyz_polling_cycle; - - /* refresh inactivity counter */ - if (cinfo->inact_ctrl) { - cy_writel(&board_ctrl->inactivity, (uclong) ZF_TINACT); - } } add_timer(&cyz_timerlist); return; } /* cyz_poll */ +#endif /* CONFIG_CYZ_INTR */ /********** End of block of Cyclades-Z specific code *********/ /***********************************************************/ @@ -2053,12 +2328,27 @@ cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE); #ifdef Z_WAKE +#ifdef CONFIG_CYZ_INTR cy_writel(&ch_ctrl[channel].intr_enable, - C_IN_MDCD|C_IN_MCTS|C_IN_IOCTLW); + C_IN_TXBEMPTY|C_IN_TXLOWWM|C_IN_RXHIWM|C_IN_RXNNDT| + C_IN_IOCTLW| + C_IN_MDCD|C_IN_MCTS); #else cy_writel(&ch_ctrl[channel].intr_enable, + C_IN_IOCTLW| C_IN_MDCD|C_IN_MCTS); -#endif +#endif /* CONFIG_CYZ_INTR */ +#else +#ifdef CONFIG_CYZ_INTR + cy_writel(&ch_ctrl[channel].intr_enable, + C_IN_TXBEMPTY|C_IN_TXLOWWM|C_IN_RXHIWM|C_IN_RXNNDT| + C_IN_MDCD|C_IN_MCTS); +#else + cy_writel(&ch_ctrl[channel].intr_enable, + C_IN_MDCD|C_IN_MCTS); +#endif /* CONFIG_CYZ_INTR */ +#endif /* Z_WAKE */ + retval = cyz_issue_cmd( &cy_card[card], channel, C_CM_IOCTL, 0L); /* was C_CM_RESET */ if (retval != 0){ @@ -2126,11 +2416,21 @@ cy_readb(base_addr+(CySRER<card].intr_enabled) { + retval = cyz_issue_cmd(&cy_card[info->card], + 0, C_CM_IRQ_ENBL, 0L); + if (retval != 0){ + printk("cyc:IRQ enable retval was %x\n", retval); + } + cy_card[info->card].intr_enabled = 1; + } + } +#endif /* CONFIG_CYZ_INTR */ } #ifdef CY_DEBUG_OTHER printk("cyc:cy_open ttyC%d\n", info->line); /* */ @@ -3798,14 +4114,14 @@ if (break_state == -1) { if (!info->breakon) { info->breakon = 1; - if (!info->xmit_cnt ) { + if (!info->xmit_cnt) { start_xmit(info); } } } else { if (!info->breakoff) { info->breakoff = 1; - if (!info->xmit_cnt ) { + if (!info->xmit_cnt) { start_xmit(info); } } @@ -4053,6 +4369,7 @@ case CYGETCD1400VER: ret_val = info->chip_rev; break; +#ifndef CONFIG_CYZ_INTR case CYZSETPOLLCYCLE: cyz_polling_cycle = (arg * HZ) / 1000; ret_val = 0; @@ -4060,6 +4377,7 @@ case CYZGETPOLLCYCLE: ret_val = (cyz_polling_cycle * 1000) / HZ; break; +#endif /* CONFIG_CYZ_INTR */ case CYSETWAIT: info->closing_wait = (unsigned short)arg * HZ/100; ret_val = 0; @@ -4333,7 +4651,7 @@ cy_flush_buffer(struct tty_struct *tty) { struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - int card, channel; + int card, channel, retval; unsigned long flags; #ifdef CY_DEBUG_IO @@ -4351,19 +4669,10 @@ if (IS_CYC_Z(cy_card[card])) { /* If it is a Z card, flush the on-board buffers as well */ - static volatile struct FIRM_ID *firm_id; - static volatile struct ZFW_CTRL *zfw_ctrl; - static volatile struct CH_CTRL *ch_ctrl; - static volatile struct BUF_CTRL *buf_ctrl; - - firm_id = (struct FIRM_ID *)(cy_card[card].base_addr + ID_ADDRESS); - zfw_ctrl = (struct ZFW_CTRL *) (cy_card[card].base_addr + - cy_readl(&firm_id->zfwctrl_addr)); - ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); - buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); - - while (cy_readl(&buf_ctrl->tx_get) != cy_readl(&buf_ctrl->tx_put)) - cy_writel(&buf_ctrl->tx_put, cy_readl(&buf_ctrl->tx_get)); + retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_TX, 0L); + if (retval != 0) { + printk("cyc: flush_buffer retval was %x\n", retval); + } } wake_up_interruptible(&tty->write_wait); if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) @@ -4872,10 +5181,11 @@ return(i); } +#ifdef CONFIG_CYZ_INTR /* allocate IRQ only if board has an IRQ */ - if( (1 < cy_pci_irq) && (cy_pci_irq < 15) ) { - if(request_irq(cy_pci_irq,cyz_interrupt, - SA_SHIRQ,"Cyclades-Z",&cy_card[j])) + if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) { + if(request_irq(cy_pci_irq, cyz_interrupt, + SA_SHIRQ, "Cyclades-Z", &cy_card[j])) { printk("Could not allocate IRQ%d ", cy_pci_irq); @@ -4884,6 +5194,7 @@ return(i); } } +#endif /* CONFIG_CYZ_INTR */ /* set cy_card */ @@ -4896,7 +5207,7 @@ /* print message */ /* don't report IRQ if board is no IRQ */ - if( (cy_pci_irq < 15) && (cy_pci_irq > 1) ) { + if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) { printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", j+1,(ulong)cy_pci_addr2, (ulong)(cy_pci_addr2 + CyPCI_Zwin - 1), @@ -4908,6 +5219,11 @@ } printk("%d channels starting from port %d.\n", cy_pci_nchan,cy_next_channel); +#ifdef CONFIG_CYZ_INTR + /* Enable interrupts on the PLX chip */ + cy_writew(cy_pci_addr0+0x68, + cy_readw(cy_pci_addr0+0x68)|0x0900); +#endif /* CONFIG_CYZ_INTR */ cy_next_channel += cy_pci_nchan; } } @@ -4927,10 +5243,6 @@ (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); printk("Cyclades-Z/PCI: New Cyclades-Z board. FPGA not loaded\n"); #endif - /* The following clears the firmware id word. This ensures - that the driver will not attempt to talk to the board - until it has been properly initialized. - */ PAUSE /* This must be the new Cyclades-Ze/PCI. */ cy_pci_nchan = ZE_V1_NPORTS; @@ -4955,10 +5267,11 @@ return(i); } +#ifdef CONFIG_CYZ_INTR /* allocate IRQ only if board has an IRQ */ - if( (1 < cy_pci_irq) && (cy_pci_irq < 15) ) { - if(request_irq(cy_pci_irq,cyz_interrupt, - SA_SHIRQ,"Cyclades-Z",&cy_card[j])) + if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) { + if(request_irq(cy_pci_irq, cyz_interrupt, + SA_SHIRQ, "Cyclades-Z", &cy_card[j])) { printk("Could not allocate IRQ%d ", cy_pci_irq); @@ -4967,6 +5280,7 @@ return(i); } } +#endif /* CONFIG_CYZ_INTR */ /* set cy_card */ cy_card[j].base_addr = cy_pci_addr2; @@ -4978,7 +5292,7 @@ /* print message */ /* don't report IRQ if board is no IRQ */ - if( (cy_pci_irq < 15) && (cy_pci_irq > 1) ) { + if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) { printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", j+1,(ulong)cy_pci_addr2, (ulong)(cy_pci_addr2 + CyPCI_Ze_win - 1), @@ -4990,6 +5304,11 @@ } printk("%d channels starting from port %d.\n", cy_pci_nchan,cy_next_channel); +#ifdef CONFIG_CYZ_INTR + /* Enable interrupts on the PLX chip */ + cy_writew(cy_pci_addr0+0x68, + cy_readw(cy_pci_addr0+0x68)|0x0900); +#endif /* CONFIG_CYZ_INTR */ cy_next_channel += cy_pci_nchan; } if (ZeIndex != 0) { @@ -5219,6 +5538,7 @@ mailbox = cy_readl(&((struct RUNTIME_9060 *) cy_card[board].ctl_addr)->mail_box_0); nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8; + cinfo->intr_enabled = 0; for (port = cinfo->first_line ; port < cinfo->first_line + nports; port++) @@ -5342,15 +5662,17 @@ } } } - - if ( number_z_boards && !cyz_timeron){ - cyz_timeron++; + +#ifndef CONFIG_CYZ_INTR + if (number_z_boards && !cyz_timeron){ + cyz_timeron++; cyz_timerlist.expires = jiffies + 1; add_timer(&cyz_timerlist); #ifdef CY_PCI_DEBUG printk("Cyclades-Z polling initialized\n"); #endif } +#endif /* CONFIG_CYZ_INTR */ #ifdef CY_PROC ent = create_proc_entry("cyclades", S_IFREG | S_IRUGO, 0); @@ -5377,10 +5699,12 @@ int e1, e2; unsigned long flags; +#ifndef CONFIG_CYZ_INTR if (cyz_timeron){ cyz_timeron = 0; del_timer(&cyz_timerlist); } +#endif /* CONFIG_CYZ_INTR */ save_flags(flags); cli(); remove_bh(CYCLADES_BH); @@ -5396,6 +5720,9 @@ for (i = 0; i < NR_CARDS; i++) { if (cy_card[i].base_addr != 0 +#ifndef CONFIG_CYZ_INTR + && cy_card[i].num_chips != -1 /* not a Z card */ +#endif /* CONFIG_CYZ_INTR */ && cy_card[i].irq) { free_irq(cy_card[i].irq, &cy_card[i]); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/dz.c linux.pre11.3/drivers/char/dz.c --- linux.vanilla/drivers/char/dz.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/char/dz.c Mon Jul 19 23:27:55 1999 @@ -0,0 +1,1601 @@ +/* + * dz.c: Serial port driver for DECStations equiped + * with the DZ chipset. + * + * Copyright (C) 1998 Olivier A. D. Lebaillif + * + * Email: olivier.lebaillif@ifrsys.com + * + * [31-AUG-98] triemer + * Changed IRQ to use Harald's dec internals interrupts.h + * removed base_addr code - moving address assignment to setup.c + * Changed name of dz_init to rs_init to be consistent with tc code + * [13-NOV-98] triemer fixed code to receive characters + * after patches by harald to irq code. + * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout + * field from "current" - somewhere between 2.1.121 and 2.1.131 + */ + +#ifdef MODULE +#include +#include +#else +#define MOD_INC_USE_COUNT +#define MOD_DEC_USE_COUNT +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* for definition of SERIAL */ +#include + +/* for definition of struct console */ +#ifdef CONFIG_SERIAL_CONSOLE +#define CONSOLE_LINE (3) +#include +#endif /* ifdef CONFIG_SERIAL_CONSOLE */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define DEBUG_DZ 1 +#ifdef DEBUG_DZ +#include +#include +#include +#include +#include +#include +#include + +extern int (*prom_printf) (char *,...); +#endif + + + +#include "dz.h" + +#define DZ_INTR_DEBUG 1 + +DECLARE_TASK_QUEUE(tq_serial); + +extern struct wait_queue *keypress_wait; +static struct dz_serial *lines[4]; +static unsigned char tmp_buffer[256]; + + + +#ifdef DEBUG_DZ +/* + * debugging code to send out chars via prom + */ +static void debug_console( const char *s,int count) +{ + unsigned i; + + for (i = 0; i < count; i++) { + if (*s == 10) + prom_printf("%c", 13); + prom_printf("%c", *s++); + } +} +#endif + +/* + * ------------------------------------------------------------ + * dz_in () and dz_out () + * + * These routines are used to access the registers of the DZ + * chip, hiding relocation differences between implementation. + * ------------------------------------------------------------ + */ + +static inline unsigned short dz_in (struct dz_serial *info, unsigned offset) +{ + volatile unsigned short *addr = (volatile unsigned short *)(info->port + offset); + return *addr; +} + +static inline void dz_out (struct dz_serial *info, unsigned offset, unsigned short value) +{ + + volatile unsigned short *addr = (volatile unsigned short *)(info->port + offset); + *addr = value; + +} + +/* + * ------------------------------------------------------------ + * rs_stop () and rs_start () + * + * These routines are called before setting or resetting + * tty->stopped. They enable or disable transmitter interrupts, + * as necessary. + * ------------------------------------------------------------ + */ + +static void dz_stop (struct tty_struct *tty) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + unsigned short mask, tmp; + + + mask = 1 << info->line; + tmp = dz_in (info, DZ_TCR); /* read the TX flag */ + + tmp &= ~mask; /* clear the TX flag */ + dz_out (info, DZ_TCR, tmp); +} + +static void dz_start (struct tty_struct *tty) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + unsigned short mask, tmp; + + mask = 1 << info->line; + tmp = dz_in (info, DZ_TCR); /* read the TX flag */ + + tmp |= mask; /* set the TX flag */ + dz_out (info, DZ_TCR, tmp); + +} + +/* + * ------------------------------------------------------------ + * Here starts the interrupt handling routines. All of the + * following subroutines are declared as inline and are folded + * into dz_interrupt. They were separated out for readability's + * sake. + * + * Note: rs_interrupt() is a "fast" interrupt, which means that it + * runs with interrupts turned off. People who may want to modify + * rs_interrupt() should try to keep the interrupt handler as fast as + * possible. After you are done making modifications, it is not a bad + * idea to do: + * + * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer dz.c + * + * and look at the resulting assemble code in serial.s. + * + * ------------------------------------------------------------ + */ + +/* + * ------------------------------------------------------------ + * dz_sched_event () + * + * This routine is used by the interrupt handler to schedule + * processing in the software interrupt portion of the driver. + * ------------------------------------------------------------ + */ +static inline void dz_sched_event (struct dz_serial *info, int event) +{ + info->event |= 1 << event; + queue_task (&info->tqueue, &tq_serial); + mark_bh (SERIAL_BH); +} + +/* + * ------------------------------------------------------------ + * receive_char () + * + * This routine deals with inputs from any lines. + * ------------------------------------------------------------ + */ +static inline void receive_chars (struct dz_serial *info_in) +{ + + struct dz_serial *info; + struct tty_struct *tty = 0; + struct async_icount *icount; + int ignore = 0; + unsigned short status, tmp; + unsigned char ch; + + /* this code is going to be a problem... + the call to tty_flip_buffer is going to need + to be rethought... + */ + do + { + status = dz_in (info_in, DZ_RBUF); + info = lines[LINE(status)]; + + /* punt so we don't get duplicate characters */ + if (!(status & DZ_DVAL)) + goto ignore_char; + + + ch = UCHAR(status); /* grab the char */ + +#ifdef 0 + if (info->is_console) { + if (ch == 0) return; /* it's a break ... */ + + wake_up (&keypress_wait); /* It is a 'keyboard interrupt' ;-) */ + } +#endif + + tty = info->tty; /* now tty points to the proper dev */ + icount = &info->icount; + + if (!tty) break; + if (tty->flip.count >= TTY_FLIPBUF_SIZE) break; + + *tty->flip.char_buf_ptr = ch; + *tty->flip.flag_buf_ptr = 0; + icount->rx++; + + /* keep track of the statistics */ + if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) { + if (status & DZ_PERR) /* parity error */ + icount->parity++; + else if (status & DZ_FERR) /* frame error */ + icount->frame++; + if (status & DZ_OERR) /* overrun error */ + icount->overrun++; + + /* check to see if we should ignore the character + and mask off conditions that should be ignored + */ + + if (status & info->ignore_status_mask) { + if (++ignore > 100 ) break; + goto ignore_char; + } + + /* mask off the error conditions we want to ignore */ + tmp = status & info->read_status_mask; + + if (tmp & DZ_PERR) + { + *tty->flip.flag_buf_ptr = TTY_PARITY; + debug_console("PERR\n",5); + } + else if (tmp & DZ_FERR) + { + *tty->flip.flag_buf_ptr = TTY_FRAME; + debug_console("FERR\n",5); + } + if (tmp & DZ_OERR) + { + debug_console("OERR\n",5); + if (tty->flip.count < TTY_FLIPBUF_SIZE) { + tty->flip.count++; + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + *tty->flip.flag_buf_ptr = TTY_OVERRUN; + } + } + } + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + ignore_char: + } while (status & DZ_DVAL); + + if (tty) + tty_flip_buffer_push(tty); +} + +/* + * ------------------------------------------------------------ + * transmit_char () + * + * This routine deals with outputs to any lines. + * ------------------------------------------------------------ + */ +static inline void transmit_chars (struct dz_serial *info) +{ + unsigned char tmp; + + + + if (info->x_char) { /* XON/XOFF chars */ + dz_out (info, DZ_TDR, info->x_char); + info->icount.tx++; + info->x_char = 0; + return; + } + + /* if nothing to do or stopped or hardware stopped */ + if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tty->hw_stopped) { + dz_stop (info->tty); + return; + } + + /* if something to do ... (rember the dz has no output fifo so we go one char at a time :-< */ + tmp = (unsigned short)info->xmit_buf[info->xmit_tail++]; + dz_out (info, DZ_TDR, tmp); + info->xmit_tail = info->xmit_tail & (DZ_XMIT_SIZE - 1); + info->icount.tx++; + + if (--info->xmit_cnt < WAKEUP_CHARS) + dz_sched_event (info, DZ_EVENT_WRITE_WAKEUP); + + + /* Are we done */ + if (info->xmit_cnt <= 0) dz_stop (info->tty); +} + +/* + * ------------------------------------------------------------ + * check_modem_status () + * + * Only valid for the MODEM line duh ! + * ------------------------------------------------------------ + */ +static inline void check_modem_status (struct dz_serial *info) +{ + unsigned short status; + + /* if not ne modem line just return */ + if (info->line != DZ_MODEM) return; + + status = dz_in (info, DZ_MSR); + + /* it's easy, since DSR2 is the only bit in the register */ + if (status) info->icount.dsr++; +} + +/* + * ------------------------------------------------------------ + * dz_interrupt () + * + * this is the main interrupt routine for the DZ chip. + * It deals with the multiple ports. + * ------------------------------------------------------------ + */ +static void dz_interrupt (int irq, void *dev, struct pt_regs *regs) +{ + struct dz_serial *info; + unsigned short status; + + status = dz_in ((struct dz_serial *)dev, DZ_CSR); /* get the reason why we just got an irq */ + info = lines[LINE(status)]; /* re-arrange info the proper port */ + + if (status & DZ_RDONE) + receive_chars (info); /* the receive function */ + + if (status & DZ_TRDY) + transmit_chars (info); +} + +/* + * ------------------------------------------------------------------- + * Here ends the DZ interrupt routines. + * ------------------------------------------------------------------- + */ + +/* + * This routine is used to handle the "bottom half" processing for the + * serial driver, known also the "software interrupt" processing. + * This processing is done at the kernel interrupt level, after the + * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This + * is where time-consuming activities which can not be done in the + * interrupt driver proper are done; the interrupt driver schedules + * them using rs_sched_event(), and they get done here. + */ +static void do_serial_bh (void) +{ + run_task_queue (&tq_serial); +} + +static void do_softint (void *private_data) +{ + struct dz_serial *info = (struct dz_serial *)private_data; + struct tty_struct *tty = info->tty; + + if (!tty) return; + + if (test_and_clear_bit (DZ_EVENT_WRITE_WAKEUP, &info->event)) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup) (tty); + wake_up_interruptible (&tty->write_wait); + } +} + +/* + * ------------------------------------------------------------------- + * This routine is called from the scheduler tqueue when the interrupt + * routine has signalled that a hangup has occurred. The path of + * hangup processing is: + * + * serial interrupt routine -> (scheduler tqueue) -> + * do_serial_hangup() -> tty->hangup() -> rs_hangup() + * ------------------------------------------------------------------- + */ +static void do_serial_hangup (void *private_data) +{ + struct dz_serial *info = (struct dz_serial *)private_data; + struct tty_struct *tty = info->tty;; + + if (!tty) return; + + tty_hangup (tty); +} + +/* + * ------------------------------------------------------------------- + * startup () + * + * various initialization tasks + * ------------------------------------------------------------------- + */ +static int startup (struct dz_serial *info) +{ + unsigned long page, flags; + unsigned short tmp; + + if (info->is_initialized) return 0; + + save_flags (flags); + cli (); + + if (!info->port) { + if (info->tty) set_bit (TTY_IO_ERROR, &info->tty->flags); + restore_flags (flags); + return -ENODEV; + } + + if (!info->xmit_buf) { + page = get_free_page (GFP_KERNEL); + if (!page) { + restore_flags (flags); + return -ENOMEM; + } + info->xmit_buf = (unsigned char *)page; + } + + if (info->tty) clear_bit (TTY_IO_ERROR, &info->tty->flags); + + /* enable the interrupt and the scanning */ + tmp = dz_in (info, DZ_CSR); + tmp |= (DZ_RIE | DZ_TIE | DZ_MSE); + dz_out (info, DZ_CSR, tmp); + + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + /* set up the speed */ + change_speed (info); + + /* clear the line transmitter buffer + I can't figure out why I need to do this - but + its necessary - in order for the console portion + and the interrupt portion to live happily side by side. + */ + + /* clear the line transmitter buffer + I can't figure out why I need to do this - but + its necessary - in order for the console portion + and the interrupt portion to live happily side by side. + */ + + info->is_initialized = 1; + + restore_flags (flags); + return 0; +} + +/* + * ------------------------------------------------------------------- + * shutdown () + * + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. + * ------------------------------------------------------------------- + */ +static void shutdown (struct dz_serial *info) +{ + unsigned long flags; + unsigned short tmp; + + if (!info->is_initialized) return; + + save_flags (flags); + cli (); + + dz_stop (info->tty); + + + + info->cflags &= ~DZ_CREAD; /* turn off receive enable flag */ + dz_out (info, DZ_LPR, info->cflags); + + if (info->xmit_buf) { /* free Tx buffer */ + free_page ((unsigned long)info->xmit_buf); + info->xmit_buf = 0; + } + + if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { + tmp = dz_in (info, DZ_TCR); + if (tmp & DZ_MODEM_DTR) { + tmp &= ~DZ_MODEM_DTR; + dz_out (info, DZ_TCR, tmp); + } + } + + if (info->tty) set_bit (TTY_IO_ERROR, &info->tty->flags); + + info->is_initialized = 0; + restore_flags (flags); +} + +/* + * ------------------------------------------------------------------- + * change_speed () + * + * set the baud rate. + * ------------------------------------------------------------------- + */ +static void change_speed (struct dz_serial *info) +{ + unsigned long flags; + unsigned cflag; + int baud; + + if (!info->tty || !info->tty->termios) return; + + save_flags (flags); + cli (); + + info->cflags = info->line; + + cflag = info->tty->termios->c_cflag; + + switch (cflag & CSIZE) { + case CS5: info->cflags |= DZ_CS5; break; + case CS6: info->cflags |= DZ_CS6; break; + case CS7: info->cflags |= DZ_CS7; break; + case CS8: + default: info->cflags |= DZ_CS8; + } + + if (cflag & CSTOPB) info->cflags |= DZ_CSTOPB; + if (cflag & PARENB) info->cflags |= DZ_PARENB; + if (cflag & PARODD) info->cflags |= DZ_PARODD; + + baud = tty_get_baud_rate (info->tty); + switch (baud) { + case 50 : info->cflags |= DZ_B50; break; + case 75 : info->cflags |= DZ_B75; break; + case 110 : info->cflags |= DZ_B110; break; + case 134 : info->cflags |= DZ_B134; break; + case 150 : info->cflags |= DZ_B150; break; + case 300 : info->cflags |= DZ_B300; break; + case 600 : info->cflags |= DZ_B600; break; + case 1200: info->cflags |= DZ_B1200; break; + case 1800: info->cflags |= DZ_B1800; break; + case 2000: info->cflags |= DZ_B2000; break; + case 2400: info->cflags |= DZ_B2400; break; + case 3600: info->cflags |= DZ_B3600; break; + case 4800: info->cflags |= DZ_B4800; break; + case 7200: info->cflags |= DZ_B7200; break; + case 9600: + default : info->cflags |= DZ_B9600; + } + + info->cflags |= DZ_RXENAB; + dz_out (info, DZ_LPR, info->cflags); + + /* setup accept flag */ + info->read_status_mask = DZ_OERR; + if (I_INPCK(info->tty)) + info->read_status_mask |= (DZ_FERR | DZ_PERR); + + /* characters to ignore */ + info->ignore_status_mask = 0; + if (I_IGNPAR(info->tty)) + info->ignore_status_mask |= (DZ_FERR | DZ_PERR); + + restore_flags (flags); +} + +/* + * ------------------------------------------------------------------- + * dz_flush_char () + * + * Flush the buffer. + * ------------------------------------------------------------------- + */ +static void dz_flush_chars (struct tty_struct *tty) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + unsigned long flags; + + if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !info->xmit_buf) + return; + + save_flags (flags); + cli (); + + dz_start (info->tty); + + restore_flags (flags); +} + + +/* + * ------------------------------------------------------------------- + * dz_write () + * + * main output routine. + * ------------------------------------------------------------------- + */ +static int dz_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + unsigned long flags; + int c, ret = 0; + + if (!tty ) return ret; + if (!info->xmit_buf) return ret; + if (!tmp_buf) tmp_buf = tmp_buffer; + + + + if (from_user) { + + down (&tmp_buf_sem); + while (1) { + c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head)); + if (c <= 0) break; + + c -= copy_from_user (tmp_buf, buf, c); + if (!c) { + if (!ret) ret = -EFAULT; + break; + } + + save_flags (flags); + cli (); + + c = MIN(c, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head)); + memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); + info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE-1)); + info->xmit_cnt += c; + + restore_flags(flags); + + buf += c; + count -= c; + ret += c; + } + + up (&tmp_buf_sem); + } else { + + + while (1) { + save_flags (flags); + cli (); + + c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { + restore_flags (flags); + break; + } + memcpy (info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE-1)); + info->xmit_cnt += c; + + restore_flags (flags); + + buf += c; + count -= c; + ret += c; + } + } + + + if (info->xmit_cnt) + { + if (!tty->stopped) + { + if (!tty->hw_stopped) + { + dz_start (info->tty); + } + } + } + return ret; +} + +/* + * ------------------------------------------------------------------- + * dz_write_room () + * + * compute the amount of space available for writing. + * ------------------------------------------------------------------- + */ +static int dz_write_room (struct tty_struct *tty) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + int ret; + + ret = DZ_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) ret = 0; + return ret; +} + +/* + * ------------------------------------------------------------------- + * dz_chars_in_buffer () + * + * compute the amount of char left to be transmitted + * ------------------------------------------------------------------- + */ +static int dz_chars_in_buffer (struct tty_struct *tty) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + + return info->xmit_cnt; +} + +/* + * ------------------------------------------------------------------- + * dz_flush_buffer () + * + * Empty the output buffer + * ------------------------------------------------------------------- + */ +static void dz_flush_buffer (struct tty_struct *tty) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + + cli (); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + sti (); + + wake_up_interruptible (&tty->write_wait); + + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} + +/* + * ------------------------------------------------------------ + * dz_throttle () and dz_unthrottle () + * + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled (or not). + * ------------------------------------------------------------ + */ +static void dz_throttle (struct tty_struct *tty) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + + if (I_IXOFF(tty)) + info->x_char = STOP_CHAR(tty); +} + +static void dz_unthrottle (struct tty_struct *tty) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + info->x_char = START_CHAR(tty); + } +} + +static void dz_send_xchar (struct tty_struct *tty, char ch) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + + info->x_char = ch; + + if (ch) dz_start (info->tty); +} + +/* + * ------------------------------------------------------------ + * rs_ioctl () and friends + * ------------------------------------------------------------ + */ +static int get_serial_info (struct dz_serial *info, struct serial_struct *retinfo) +{ + struct serial_struct tmp; + + if (!retinfo) + return -EFAULT; + + memset (&tmp, 0, sizeof(tmp)); + + tmp.type = info->type; + tmp.line = info->line; + tmp.port = info->port; + tmp.irq = SERIAL; + tmp.flags = info->flags; + tmp.baud_base = info->baud_base; + tmp.close_delay = info->close_delay; + tmp.closing_wait = info->closing_wait; + + return copy_to_user (retinfo, &tmp, sizeof(*retinfo)); +} + +static int set_serial_info (struct dz_serial *info, struct serial_struct *new_info) +{ + struct serial_struct new_serial; + struct dz_serial old_info; + int retval = 0; + + if (!new_info) + return -EFAULT; + + copy_from_user (&new_serial, new_info, sizeof(new_serial)); + old_info = *info; + + if (!suser()) + return -EPERM; + + if (info->count > 1) + return -EBUSY; + + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + + info->baud_base = new_serial.baud_base; + info->type = new_serial.type; + info->close_delay = new_serial.close_delay; + info->closing_wait = new_serial.closing_wait; + + retval = startup (info); + return retval; +} + +/* + * get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int get_lsr_info (struct dz_serial *info, unsigned int *value) +{ + unsigned short status = dz_in (info, DZ_LPR); + + return put_user (status, value); +} + +/* + * This routine sends a break character out the serial port. + */ +static void send_break (struct dz_serial *info, int duration) +{ + unsigned long flags; + unsigned short tmp, mask; + + if (!info->port) + return; + + mask = 1 << info->line; + tmp = dz_in (info, DZ_TCR); + tmp |= mask; + + current->state = TASK_INTERRUPTIBLE; + + save_flags (flags); + cli(); + + dz_out (info, DZ_TCR, tmp); + + schedule_timeout(jiffies + duration); + + tmp &= ~mask; + dz_out (info, DZ_TCR, tmp); + + restore_flags (flags); +} + +static int dz_ioctl (struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) +{ + int error; + struct dz_serial * info = (struct dz_serial *)tty->driver_data; + int retval; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && + (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + case TCSBRK: /* SVID version: non-zero arg --> no break */ + retval = tty_check_change (tty); + if (retval) + return retval; + tty_wait_until_sent (tty, 0); + if (!arg) + send_break (info, HZ/4); /* 1/4 second */ + return 0; + + case TCSBRKP: /* support for POSIX tcsendbreak() */ + retval = tty_check_change (tty); + if (retval) + return retval; + tty_wait_until_sent (tty, 0); + send_break (info, arg ? arg*(HZ/10) : HZ/4); + return 0; + + case TIOCGSOFTCAR: + error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(long)); + if (error) + return error; + put_user (C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg); + return 0; + + case TIOCSSOFTCAR: + error = get_user (arg, (unsigned long *)arg); + if (error) + return error; + tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); + return 0; + + case TIOCGSERIAL: + error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(struct serial_struct)); + if (error) + return error; + return get_serial_info (info, (struct serial_struct *)arg); + + case TIOCSSERIAL: + return set_serial_info (info, (struct serial_struct *) arg); + + case TIOCSERGETLSR: /* Get line status register */ + error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(unsigned int)); + if (error) + return error; + else + return get_lsr_info (info, (unsigned int *)arg); + + case TIOCSERGSTRUCT: + error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(struct dz_serial)); + if (error) + return error; + copy_to_user((struct dz_serial *)arg, info, sizeof(struct dz_serial)); + return 0; + + default: + return -ENOIOCTLCMD; + } + + return 0; +} + +static void dz_set_termios (struct tty_struct *tty, + struct termios *old_termios) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + + if (tty->termios->c_cflag == old_termios->c_cflag) + return; + + change_speed (info); + + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + dz_start (tty); + } +} + +/* + * ------------------------------------------------------------ + * dz_close() + * + * This routine is called when the serial port gets closed. First, we + * wait for the last remaining data to be sent. Then, we turn off + * the transmit enable and receive enable flags. + * ------------------------------------------------------------ + */ +static void dz_close (struct tty_struct *tty, struct file *filp) +{ + struct dz_serial * info = (struct dz_serial *)tty->driver_data; + unsigned long flags; + + if (!info) return; + + save_flags (flags); + cli(); + + if (tty_hung_up_p (filp)) { + restore_flags (flags); + return; + } + + if ((tty->count == 1) && (info->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. Info->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk("dz_close: bad serial port count; tty->count is 1, " + "info->count is %d\n", info->count); + info->count = 1; + } + + if (--info->count < 0) { + printk("rs_close: bad serial port count for ttys%d: %d\n", + info->line, info->count); + info->count = 0; + } + + if (info->count) { + restore_flags (flags); + return; + } + info->flags |= DZ_CLOSING; + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & DZ_NORMAL_ACTIVE) + info->normal_termios = *tty->termios; + if (info->flags & DZ_CALLOUT_ACTIVE) + info->callout_termios = *tty->termios; + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + + if (info->closing_wait != DZ_CLOSING_WAIT_NONE) + tty_wait_until_sent (tty, info->closing_wait); + + /* + * At this point we stop accepting input. To do this, we + * disable the receive line status interrupts. + */ + + shutdown (info); + + if (tty->driver.flush_buffer) + tty->driver.flush_buffer (tty); + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer (tty); + tty->closing = 0; + info->event = 0; + info->tty = 0; + + if (tty->ldisc.num != ldiscs[N_TTY].num) { + if (tty->ldisc.close) + (tty->ldisc.close)(tty); + tty->ldisc = ldiscs[N_TTY]; + tty->termios->c_line = N_TTY; + if (tty->ldisc.open) + (tty->ldisc.open)(tty); + } + if (info->blocked_open) { + if (info->close_delay) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(jiffies + info->close_delay); + } + wake_up_interruptible (&info->open_wait); + } + + info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE | DZ_CLOSING); + wake_up_interruptible (&info->close_wait); + + restore_flags (flags); +} + +/* + * dz_hangup () --- called by tty_hangup() when a hangup is signaled. + */ +static void dz_hangup (struct tty_struct *tty) +{ + struct dz_serial *info = (struct dz_serial *)tty->driver_data; + + dz_flush_buffer (tty); + shutdown (info); + info->event = 0; + info->count = 0; + info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE); + info->tty = 0; + wake_up_interruptible (&info->open_wait); +} + +/* + * ------------------------------------------------------------ + * rs_open() and friends + * ------------------------------------------------------------ + */ +static int block_til_ready (struct tty_struct *tty, struct file *filp, struct dz_serial *info) +{ + struct wait_queue wait = { current, NULL }; + int retval; + int do_clocal = 0; + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (info->flags & DZ_CLOSING) { + interruptible_sleep_on (&info->close_wait); + return -EAGAIN; + } + + /* + * If this is a callout device, then just make sure the normal + * device isn't being used. + */ + if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { + if (info->flags & DZ_NORMAL_ACTIVE) + return -EBUSY; + + if ((info->flags & DZ_CALLOUT_ACTIVE) && + (info->flags & DZ_SESSION_LOCKOUT) && + (info->session != current->session)) + return -EBUSY; + + if ((info->flags & DZ_CALLOUT_ACTIVE) && + (info->flags & DZ_PGRP_LOCKOUT) && + (info->pgrp != current->pgrp)) + return -EBUSY; + info->flags |= DZ_CALLOUT_ACTIVE; + return 0; + } + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || + (tty->flags & (1 << TTY_IO_ERROR))) { + if (info->flags & DZ_CALLOUT_ACTIVE) + return -EBUSY; + info->flags |= DZ_NORMAL_ACTIVE; + return 0; + } + + if (info->flags & DZ_CALLOUT_ACTIVE) { + if (info->normal_termios.c_cflag & CLOCAL) + do_clocal = 1; + } else { + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + } + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, info->count is dropped by one, so that + * dz_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue (&info->open_wait, &wait); + + info->count--; + info->blocked_open++; + while (1) { + current->state = TASK_INTERRUPTIBLE; + if (tty_hung_up_p (filp) || !(info->is_initialized)) { + retval = -EAGAIN; + break; + } + if (!(info->flags & DZ_CALLOUT_ACTIVE) && + !(info->flags & DZ_CLOSING) && do_clocal) + break; + if (signal_pending (current)) { + retval = -ERESTARTSYS; + break; + } + schedule(); + } + + current->state = TASK_RUNNING; + remove_wait_queue (&info->open_wait, &wait); + if (!tty_hung_up_p(filp)) + info->count++; + info->blocked_open--; + + if (retval) + return retval; + info->flags |= DZ_NORMAL_ACTIVE; + return 0; +} + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port. It also performs the + * serial-specific initialization for the tty structure. + */ +static int dz_open (struct tty_struct *tty, struct file *filp) +{ + struct dz_serial *info; + int retval, line; + + line = MINOR(tty->device) - tty->driver.minor_start; + + /* The dz lines for the mouse/keyboard must be + * opened using their respective drivers. + */ + if ((line < 0) || (line >= DZ_NB_PORT)) + return -ENODEV; + + if ((line == DZ_KEYBOARD) || (line == DZ_MOUSE)) + return -ENODEV; + + info = lines[line]; + info->count++; + + tty->driver_data = info; + info->tty = tty; + + /* + * Start up serial port + */ + retval = startup (info); + if (retval) + return retval; + + + + retval = block_til_ready (tty, filp, info); + if (retval) + return retval; + + if ((info->count == 1) && (info->flags & DZ_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->normal_termios; + else + *tty->termios = info->callout_termios; + change_speed (info); + + } + + info->session = current->session; + info->pgrp = current->pgrp; + return 0; +} + +static void show_serial_version (void) +{ + printk("%s%s\n", dz_name, dz_version); +} + + +__initfunc(int dz_init(void)) +{ + int i, flags; + struct dz_serial *info; + + /* Setup base handler, and timer table. */ + init_bh (SERIAL_BH, do_serial_bh); + + show_serial_version (); + + memset(&serial_driver, 0, sizeof(struct tty_driver)); + serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.name = "ttyS"; + serial_driver.major = TTY_MAJOR; + serial_driver.minor_start = 64; + serial_driver.num = DZ_NB_PORT; + serial_driver.type = TTY_DRIVER_TYPE_SERIAL; + serial_driver.subtype = SERIAL_TYPE_NORMAL; + serial_driver.init_termios = tty_std_termios; + + serial_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver.flags = TTY_DRIVER_REAL_RAW; + serial_driver.refcount = &serial_refcount; + serial_driver.table = serial_table; + serial_driver.termios = serial_termios; + serial_driver.termios_locked = serial_termios_locked; + + serial_driver.open = dz_open; + serial_driver.close = dz_close; + serial_driver.write = dz_write; + serial_driver.flush_chars = dz_flush_chars; + serial_driver.write_room = dz_write_room; + serial_driver.chars_in_buffer = dz_chars_in_buffer; + serial_driver.flush_buffer = dz_flush_buffer; + serial_driver.ioctl = dz_ioctl; + serial_driver.throttle = dz_throttle; + serial_driver.unthrottle = dz_unthrottle; + serial_driver.send_xchar = dz_send_xchar; + serial_driver.set_termios = dz_set_termios; + serial_driver.stop = dz_stop; + serial_driver.start = dz_start; + serial_driver.hangup = dz_hangup; + + /* + * The callout device is just like normal device except for + * major number and the subtype code. + */ + callout_driver = serial_driver; + callout_driver.name = "cua"; + callout_driver.major = TTYAUX_MAJOR; + callout_driver.subtype = SERIAL_TYPE_CALLOUT; + + if (tty_register_driver (&serial_driver)) + panic("Couldn't register serial driver\n"); + if (tty_register_driver (&callout_driver)) + panic("Couldn't register callout driver\n"); + save_flags(flags); cli(); + + i = 0; + for (info = &multi[i]; i < DZ_NB_PORT; i++) + { + lines[i] = info; + info->magic = SERIAL_MAGIC; + + if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100)) + info->port = (unsigned long) KN01_DZ11_BASE; + else + info->port = (unsigned long) KN02_DZ11_BASE; + + info->line = i; + info->tty = 0; + info->close_delay = 50; + info->closing_wait = 3000; + info->x_char = 0; + info->event = 0; + info->count = 0; + info->blocked_open = 0; + info->tqueue.routine = do_softint; + info->tqueue.data = info; + info->tqueue_hangup.routine = do_serial_hangup; + info->tqueue_hangup.data = info; + info->callout_termios = callout_driver.init_termios; + info->normal_termios = serial_driver.init_termios; + info->open_wait = 0; + info->close_wait = 0; + + /* If we are pointing to address zero then punt - not correctly + set up in setup.c to handle this. */ + if (! info->port) + return 0; + + printk("ttyS%02d at 0x%04x (irq = %d)\n", info->line, info->port, SERIAL); + } + + /* reset the chip */ +#ifndef CONFIG_SERIAL_CONSOLE + dz_out(info, DZ_CSR, DZ_CLR); + while ((tmp = dz_in(info,DZ_CSR)) & DZ_CLR) ; + wbflush(); + + /* enable scanning */ + dz_out(info, DZ_CSR, DZ_MSE); +#endif + + /* order matters here... the trick is that flags + is updated... in request_irq - to immediatedly obliterate + it is unwise. */ + restore_flags(flags); + + + if (request_irq (SERIAL, dz_interrupt, SA_INTERRUPT, "DZ", lines[0])) + panic ("Unable to register DZ interrupt\n"); + + return 0; +} + +#ifdef CONFIG_SERIAL_CONSOLE +static void dz_console_put_char (unsigned char ch) +{ + long flags; + int loops = 2500; + unsigned short tmp = ch; + /* this code sends stuff out to serial device - spinning its + wheels and waiting. */ + + /* force the issue - point it at lines[3]*/ + dz_console=&multi[CONSOLE_LINE]; + + save_flags(flags); + cli(); + + + /* spin our wheels */ + while (((dz_in(dz_console,DZ_TCR) & DZ_TRDY) != DZ_TRDY) && loops--) + ; + + /* Actually transmit the character. */ + dz_out (dz_console, DZ_TDR, tmp); + + restore_flags(flags); +} +/* + * ------------------------------------------------------------------- + * dz_console_print () + * + * dz_console_print is registered for printk. + * ------------------------------------------------------------------- + */ +static void dz_console_print (struct console *cons, + const char *str, + unsigned int count) +{ +#ifdef DEBUG_DZ + prom_printf((char *)str); +#endif + while (count--) + { + if (*str == '\n') + dz_console_put_char ('\r'); + dz_console_put_char (*str++); + } +} + +static int dz_console_wait_key(struct console *co) +{ + return 0; +} + +static kdev_t dz_console_device(struct console *c) +{ + return MKDEV(TTY_MAJOR, 64 + c->index); +} + +__initfunc(static int dz_console_setup(struct console *co, char *options)) +{ + int baud = 9600; + int bits = 8; + int parity = 'n'; + int cflag = CREAD | HUPCL | CLOCAL; + char *s; + unsigned short mask,tmp; + + if (options) { + baud = simple_strtoul(options, NULL, 10); + s = options; + while(*s >= '0' && *s <= '9') + s++; + if (*s) + parity = *s++; + if (*s) + bits = *s - '0'; + } + + /* + * Now construct a cflag setting. + */ + switch(baud) { + case 1200: + cflag |= DZ_B1200; + break; + case 2400: + cflag |= DZ_B2400; + break; + case 4800: + cflag |= DZ_B4800; + break; + case 9600: + default: + cflag |= DZ_B9600; + break; + } + switch(bits) { + case 7: + cflag |= DZ_CS7; + break; + default: + case 8: + cflag |= DZ_CS8; + break; + } + switch(parity) { + case 'o': case 'O': + cflag |= DZ_PARODD; + break; + case 'e': case 'E': + cflag |= DZ_PARENB; + break; + } + co->cflag = cflag; + + /* TOFIX: force to console line */ + dz_console = &multi[CONSOLE_LINE]; + if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100)) + dz_console->port = KN01_DZ11_BASE; + else + dz_console->port = KN02_DZ11_BASE; + dz_console->line = CONSOLE_LINE; + + dz_out(dz_console, DZ_CSR, DZ_CLR); + while ((tmp = dz_in(dz_console,DZ_CSR)) & DZ_CLR) + ; + + /* enable scanning */ + dz_out(dz_console, DZ_CSR, DZ_MSE); + + /* Set up flags... */ + dz_console->cflags = 0; + dz_console->cflags |= DZ_B9600; + dz_console->cflags |= DZ_CS8; + dz_console->cflags |= DZ_PARENB; + dz_out (dz_console, DZ_LPR, dz_console->cflags); + + + mask = 1 << dz_console->line; + tmp = dz_in (dz_console, DZ_TCR); /* read the TX flag */ + if (!(tmp & mask)) { + tmp |= mask; /* set the TX flag */ + dz_out (dz_console, DZ_TCR, tmp); + } + + + /* TOFIX: force to console line */ + dz_console = &multi[CONSOLE_LINE]; + if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100)) + dz_console->port = KN01_DZ11_BASE; + else + dz_console->port = KN02_DZ11_BASE; + dz_console->line = CONSOLE_LINE; + + dz_out(dz_console, DZ_CSR, DZ_CLR); + while ((tmp = dz_in(dz_console,DZ_CSR)) & DZ_CLR) + ; + + /* enable scanning */ + dz_out(dz_console, DZ_CSR, DZ_MSE); + + /* Set up flags... */ + dz_console->cflags = 0; + dz_console->cflags |= DZ_B9600; + dz_console->cflags |= DZ_CS8; + dz_console->cflags |= DZ_PARENB; + dz_out (dz_console, DZ_LPR, dz_console->cflags); + + + mask = 1 << dz_console->line; + tmp = dz_in (dz_console, DZ_TCR); /* read the TX flag */ + if (!(tmp & mask)) { + tmp |= mask; /* set the TX flag */ + dz_out (dz_console, DZ_TCR, tmp); + } + + + return 0; +} + +static struct console dz_sercons = { + "ttyS", + dz_console_print, + NULL, + dz_console_device, + dz_console_wait_key, + NULL, + dz_console_setup, + CON_CONSDEV | CON_PRINTBUFFER, + CONSOLE_LINE, + 0, + NULL +}; + +__initfunc (long dz_serial_console_init(long kmem_start, long kmem_end)) +{ + register_console(&dz_sercons); + + return kmem_start; +} + +#endif /* ifdef CONFIG_SERIAL_CONSOLE */ + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/dz.h linux.pre11.3/drivers/char/dz.h --- linux.vanilla/drivers/char/dz.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/char/dz.h Mon Jul 19 23:27:55 1999 @@ -0,0 +1,242 @@ +/* + * dz.h: Serial port driver for DECStations equiped + * with the DZ chipset. + * + * Copyright (C) 1998 Olivier A. D. Lebaillif + * + * Email: olivier.lebaillif@ifrsys.com + * + */ +#ifndef DZ_SERIAL_H +#define DZ_SERIAL_H + +/* + * Definitions for the Control and Status Received. + */ +#define DZ_TRDY 0x8000 /* Transmitter empty */ +#define DZ_TIE 0x4000 /* Transmitter Interrupt Enable */ +#define DZ_RDONE 0x0080 /* Receiver data ready */ +#define DZ_RIE 0x0040 /* Receive Interrupt Enable */ +#define DZ_MSE 0x0020 /* Master Scan Enable */ +#define DZ_CLR 0x0010 /* Master reset */ +#define DZ_MAINT 0x0008 /* Loop Back Mode */ + +/* + * Definitions for the Received buffer. + */ +#define DZ_RBUF_MASK 0x00FF /* Data Mask in the Receive Buffer */ +#define DZ_LINE_MASK 0x0300 /* Line Mask in the Receive Buffer */ +#define DZ_DVAL 0x8000 /* Valid Data indicator */ +#define DZ_OERR 0x4000 /* Overrun error indicator */ +#define DZ_FERR 0x2000 /* Frame error indicator */ +#define DZ_PERR 0x1000 /* Parity error indicator */ + +#define LINE(x) (x & DZ_LINE_MASK) >> 8 /* Get the line number from the input buffer */ +#define UCHAR(x) (unsigned char)(x & DZ_RBUF_MASK) + +/* + * Definitions for the Transmit Register. + */ +#define DZ_LINE_KEYBOARD 0x0001 +#define DZ_LINE_MOUSE 0x0002 +#define DZ_LINE_MODEM 0x0004 +#define DZ_LINE_PRINTER 0x0008 + +#define DZ_MODEM_DTR 0x0400 /* DTR for the modem line (2) */ + +/* + * Definitions for the Modem Status Register. + */ +#define DZ_MODEM_DSR 0x0200 /* DSR for the modem line (2) */ + +/* + * Definitions for the Transmit Data Register. + */ +#define DZ_BRK0 0x0100 /* Break assertion for line 0 */ +#define DZ_BRK1 0x0200 /* Break assertion for line 1 */ +#define DZ_BRK2 0x0400 /* Break assertion for line 2 */ +#define DZ_BRK3 0x0800 /* Break assertion for line 3 */ + +/* + * Definitions for the Line Parameter Register. + */ +#define DZ_KEYBOARD 0x0000 /* line 0 = keyboard */ +#define DZ_MOUSE 0x0001 /* line 1 = mouse */ +#define DZ_MODEM 0x0002 /* line 2 = modem */ +#define DZ_PRINTER 0x0003 /* line 3 = printer */ + +#define DZ_CSIZE 0x0018 /* Number of bits per byte (mask) */ +#define DZ_CS5 0x0000 /* 5 bits per byte */ +#define DZ_CS6 0x0008 /* 6 bits per byte */ +#define DZ_CS7 0x0010 /* 7 bits per byte */ +#define DZ_CS8 0x0018 /* 8 bits per byte */ + +#define DZ_CSTOPB 0x0020 /* 2 stop bits instead of one */ + +#define DZ_PARENB 0x0040 /* Parity enable */ +#define DZ_PARODD 0x0080 /* Odd parity instead of even */ + +#define DZ_CBAUD 0x0E00 /* Baud Rate (mask) */ +#define DZ_B50 0x0000 +#define DZ_B75 0x0100 +#define DZ_B110 0x0200 +#define DZ_B134 0x0300 +#define DZ_B150 0x0400 +#define DZ_B300 0x0500 +#define DZ_B600 0x0600 +#define DZ_B1200 0x0700 +#define DZ_B1800 0x0800 +#define DZ_B2000 0x0900 +#define DZ_B2400 0x0A00 +#define DZ_B3600 0x0B00 +#define DZ_B4800 0x0C00 +#define DZ_B7200 0x0D00 +#define DZ_B9600 0x0E00 + +#define DZ_CREAD 0x1000 /* Enable receiver */ +#define DZ_RXENAB 0x1000 /* enable receive char */ +/* + * Addresses for the DZ registers + */ +#define DZ_CSR 0x00 /* Control and Status Register */ +#define DZ_RBUF 0x08 /* Receive Buffer */ +#define DZ_LPR 0x08 /* Line Parameters Register */ +#define DZ_TCR 0x10 /* Transmitter Control Register */ +#define DZ_MSR 0x18 /* Modem Status Register */ +#define DZ_TDR 0x18 /* Transmit Data Register */ + + +#define DZ_NB_PORT 4 + +#define DZ_XMIT_SIZE 4096 /* buffer size */ +#define WAKEUP_CHARS DZ_XMIT_SIZE/4 + +#define DZ_EVENT_WRITE_WAKEUP 0 + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +#define DZ_INITIALIZED 0x80000000 /* Serial port was initialized */ +#define DZ_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */ +#define DZ_NORMAL_ACTIVE 0x20000000 /* Normal device is active */ +#define DZ_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */ +#define DZ_CLOSING 0x08000000 /* Serial port is closing */ +#define DZ_CTS_FLOW 0x04000000 /* Do CTS flow control */ +#define DZ_CHECK_CD 0x02000000 /* i.e., CLOCAL */ + +#define DZ_CLOSING_WAIT_INF 0 +#define DZ_CLOSING_WAIT_NONE 65535 + +#define DZ_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */ +#define DZ_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */ +#define DZ_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */ + +struct dz_serial { + unsigned port; /* base address for the port */ + int type; + int flags; + int baud_base; + int blocked_open; + unsigned short close_delay; + unsigned short closing_wait; + unsigned short line; /* port/line number */ + unsigned short cflags; /* line configuration flag */ + unsigned short x_char; /* xon/xoff character */ + unsigned short read_status_mask; /* mask for read condition */ + unsigned short ignore_status_mask; /* mask for ignore condition */ + unsigned long event; /* mask used in BH */ + unsigned char *xmit_buf; /* Transmit buffer */ + int xmit_head; /* Position of the head */ + int xmit_tail; /* Position of the tail */ + int xmit_cnt; /* Count of the chars in the buffer */ + int count; /* indicates how many times it has been opened */ + int magic; + + struct async_icount icount; /* keep track of things ... */ + struct tty_struct *tty; /* tty associated */ + struct tq_struct tqueue; /* Queue for BH */ + struct tq_struct tqueue_hangup; + struct termios normal_termios; + struct termios callout_termios; + struct wait_queue *open_wait; + struct wait_queue *close_wait; + + long session; /* Session of opening process */ + long pgrp; /* pgrp of opening process */ + + unsigned char is_console; /* flag indicating a serial console */ + unsigned char is_initialized; +}; + +static struct dz_serial multi[DZ_NB_PORT]; /* Four serial lines in the DZ chip */ +static struct dz_serial *dz_console; +static struct tty_driver serial_driver, callout_driver; + +static struct tty_struct *serial_table[DZ_NB_PORT]; +static struct termios *serial_termios[DZ_NB_PORT]; +static struct termios *serial_termios_locked[DZ_NB_PORT]; + +static int serial_refcount; + +/* + * tmp_buf is used as a temporary buffer by serial_write. We need to + * lock it in case the copy_from_user blocks while swapping in a page, + * and some other program tries to do a serial write at the same time. + * Since the lock will only come under contention when the system is + * swapping and available memory is low, it makes sense to share one + * buffer across all the serial ports, since it significantly saves + * memory if large numbers of serial ports are open. + */ +static unsigned char *tmp_buf; +static struct semaphore tmp_buf_sem = MUTEX; + +static char *dz_name = "DECstation DZ serial driver version "; +static char *dz_version = "1.02"; + +static inline unsigned short dz_in (struct dz_serial *, unsigned); +static inline void dz_out (struct dz_serial *, unsigned, unsigned short); + +static inline void dz_sched_event (struct dz_serial *, int); +static inline void receive_chars (struct dz_serial *); +static inline void transmit_chars (struct dz_serial *); +static inline void check_modem_status (struct dz_serial *); + +static void dz_stop (struct tty_struct *); +static void dz_start (struct tty_struct *); +static void dz_interrupt (int, void *, struct pt_regs *); +static void do_serial_bh (void); +static void do_softint (void *); +static void do_serial_hangup (void *); +static void change_speed (struct dz_serial *); +static void dz_flush_chars (struct tty_struct *); +static void dz_console_print (struct console *, const char *, unsigned int); +static void dz_flush_buffer (struct tty_struct *); +static void dz_throttle (struct tty_struct *); +static void dz_unthrottle (struct tty_struct *); +static void dz_send_xchar (struct tty_struct *, char); +static void shutdown (struct dz_serial *); +static void send_break (struct dz_serial *, int); +static void dz_set_termios (struct tty_struct *, struct termios *); +static void dz_close (struct tty_struct *, struct file *); +static void dz_hangup (struct tty_struct *); +static void show_serial_version (void); + +static int dz_write (struct tty_struct *, int, const unsigned char *, int); +static int dz_write_room (struct tty_struct *); +static int dz_chars_in_buffer (struct tty_struct *); +static int startup (struct dz_serial *); +static int get_serial_info (struct dz_serial *, struct serial_struct *); +static int set_serial_info (struct dz_serial *, struct serial_struct *); +static int get_lsr_info (struct dz_serial *, unsigned int *); +static int dz_ioctl (struct tty_struct *, struct file *, unsigned int, unsigned long); +static int block_til_ready (struct tty_struct *, struct file *, struct dz_serial *); +static int dz_open (struct tty_struct *, struct file *); + +#ifdef MODULE +int init_module (void) +void cleanup_module (void) +#endif + +#endif + +#endif /* DZ_SERIAL_H */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/isicom.c linux.pre11.3/drivers/char/isicom.c --- linux.vanilla/drivers/char/isicom.c Thu May 27 22:11:53 1999 +++ linux.pre11.3/drivers/char/isicom.c Mon Jul 19 23:58:42 1999 @@ -14,7 +14,8 @@ * Printk clean up * 9/12/98 alan@redhat.com Rough port to 2.1.x * - * + * 10/6/99 sameer Merged the ISA and PCI drivers to + * a new unified driver. * *********************************************************** * * To use this driver you also need the support package. You @@ -51,8 +52,21 @@ #include #include +#include + #include +static int device_id[] = { 0x2028, + 0x2051, + 0x2052, + 0x2053, + 0x2054, + 0x2055, + 0x2056, + 0x2057, + 0x2058 + }; + static int isicom_refcount = 0; static int prev_card = 3; /* start servicing isi_card[0] */ static struct isi_board * irq_to_board[16] = { NULL, }; @@ -147,7 +161,7 @@ static int ISILoad_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { - unsigned int card, i, j, signature, status; + unsigned int card, i, j, signature, status, portcount = 0; unsigned short word_count, base; bin_frame frame; /* exec_record exec_rec; */ @@ -180,19 +194,38 @@ printk("."); } signature=(inw(base+0x4)) & 0xff; - - if (!(inw(base+0xe) & 0x1) || (inw(base+0x2))) { + if (isi_card[card].isa) { + + if (!(inw(base+0xe) & 0x1) || (inw(base+0x2))) { #ifdef ISICOM_DEBUG - printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe)); + printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe)); #endif - printk("\nISILoad:Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base); - return -EIO; - } - + printk("\nISILoad:ISA Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base); + return -EIO; + } + } + else { + portcount = inw(base+0x2); + if (!(inw(base+0xe) & 0x1) || ((portcount!=0) && (portcount!=4) && (portcount!=8))) { +#ifdef ISICOM_DEBUG + printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe)); +#endif + printk("\nISILoad:PCI Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base); + return -EIO; + } + } switch(signature) { case 0xa5: case 0xbb: - case 0xdd: isi_card[card].port_count = 8; + case 0xdd: + if (isi_card[card].isa) + isi_card[card].port_count = 8; + else { + if (portcount == 4) + isi_card[card].port_count = 4; + else + isi_card[card].port_count = 8; + } isi_card[card].shift_count = 12; break; @@ -310,7 +343,8 @@ outw(0x0, base); outw(0x0, base); InterruptTheCard(base); - + outw(0x0, base+0x4); /* for ISI4608 cards */ + isi_card[card].status |= FIRMWARE_LOADED; return 0; @@ -455,28 +489,7 @@ txcount--; } } -/* - * Replaced the code below with hopefully a faster loop - sameer - */ -/* - while (1) { - wrd = port->xmit_buf[port->xmit_tail++]; - port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1); - port->xmit_cnt--; - if (--txcount > 0) { - wrd |= (port->xmit_buf[port->xmit_tail++] << 8); - port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1); - port->xmit_cnt--; - outw(wrd, base); - if (--txcount <= 0) break; - } - else { - outw(wrd, base); - break; - } - } -*/ InterruptTheCard(base); if (port->xmit_cnt <= 0) port->status &= ~ISI_TXOK; @@ -531,12 +544,34 @@ unsigned char channel; short byte_count; - card = irq_to_board[irq]; + /* + * find the source of interrupt + */ + + for(count = 0; count < BOARD_COUNT; count++) { + card = &isi_card[count]; + if (card->base != 0) { + if (((card->isa == YES) && (card->irq == irq)) || + ((card->isa == NO) && (card->irq == irq) && (inw(card->base+0x0e) & 0x02))) + break; + } + card = NULL; + } + if (!card || !(card->status & FIRMWARE_LOADED)) { - printk(KERN_DEBUG "ISICOM: interrupt: not handling irq%d!.\n", irq); +/* printk(KERN_DEBUG "ISICOM: interrupt: not handling irq%d!.\n", irq);*/ return; } + base = card->base; + if (card->isa == NO) { + /* + * disable any interrupts from the PCI card and lower the + * interrupt line + */ + outw(0x8000, base+0x04); + ClearInterrupt(base); + } inw(base); /* get the dummy word out */ header = inw(base); @@ -548,12 +583,18 @@ if ((channel+1) > card->port_count) { printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%x): %d(channel) > port_count.\n", base, channel+1); - ClearInterrupt(base); + if (card->isa) + ClearInterrupt(base); + else + outw(0x0000, base+0x04); /* enable interrupts */ return; } port = card->ports + channel; if (!(port->flags & ASYNC_INITIALIZED)) { - ClearInterrupt(base); + if (card->isa) + ClearInterrupt(base); + else + outw(0x0000, base+0x04); /* enable interrupts */ return; } @@ -681,7 +722,10 @@ } queue_task(&tty->flip.tqueue, &tq_timer); } - ClearInterrupt(base); + if (card->isa == YES) + ClearInterrupt(base); + else + outw(0x0000, base+0x04); /* enable interrupts */ return; } @@ -1023,12 +1067,11 @@ return -ENODEV; } - /* open on higher 8 dev files on a 8 port card !!! */ - if (card->port_count == 8) - if (line > ((board * 16)+7)) { - printk(KERN_ERR "ISICOM: Opened >8 on a 8 port card.\n"); - return -ENODEV; - } + /* open on a port greater than the port count for the card !!! */ + if (line > ((board * 16) + card->port_count - 1)) { + printk(KERN_ERR "ISICOM: Open on a port which exceeds the port_count of the card!\n"); + return -ENODEV; + } port = &isi_ports[line]; if (isicom_paranoia_check(port, tty->device, "isicom_open")) return -ENODEV; @@ -1764,21 +1807,42 @@ static int register_isr(void) { - int count, done=0; + int count, done=0, card; + unsigned char request; for (count=0; count < BOARD_COUNT; count++ ) { if (isi_card[count].base) { - if (request_irq(isi_card[count].irq, isicom_interrupt, SA_INTERRUPT, ISICOM_NAME, NULL)) { - printk(KERN_WARNING "ISICOM: Could not install handler at Irq %d. Card%d will be disabled.\n", - isi_card[count].irq, count+1); + /* + * verify if the required irq has already been requested for + * another ISI Card, if so we already have it, else request it + */ + request = YES; + for(card = 0; card < count; card++) + if ((isi_card[card].base) && (isi_card[card].irq == isi_card[count].irq)) { + request = NO; + if ((isi_card[count].isa == NO) && (isi_card[card].isa == NO)) + break; + /* + * ISA cards cannot share interrupts with other + * PCI or ISA devices hence disable this card. + */ release_region(isi_card[count].base,16); - isi_card[count].base=0; + isi_card[count].base = 0; + break; } - else { - printk(KERN_INFO "ISICOM: Card%d at 0x%x using irq %d.\n", - count+1, isi_card[count].base, isi_card[count].irq); - - irq_to_board[isi_card[count].irq]=&isi_card[count]; - done++; + if (request == YES) { + if (request_irq(isi_card[count].irq, isicom_interrupt, SA_INTERRUPT, ISICOM_NAME, NULL)) { + printk(KERN_WARNING "ISICOM: Could not install handler at Irq %d. Card%d will be disabled.\n", + isi_card[count].irq, count+1); + release_region(isi_card[count].base,16); + isi_card[count].base=0; + } + else { + printk(KERN_INFO "ISICOM: Card%d at 0x%x using irq %d.\n", + count+1, isi_card[count].base, isi_card[count].irq); + + irq_to_board[isi_card[count].irq]=&isi_card[count]; + done++; + } } } } @@ -1787,14 +1851,24 @@ static void unregister_isr(void) { - int count; - for (count=0; count < BOARD_COUNT; count++ ) + int count, card; + unsigned char freeirq; + for (count=0; count < BOARD_COUNT; count++ ) { if (isi_card[count].base) { - free_irq(isi_card[count].irq, NULL); + freeirq = YES; + for(card = 0; card < count; card++) + if ((isi_card[card].base) && (isi_card[card].irq == isi_card[count].irq)) { + freeirq = NO; + break; + } + if (freeirq == YES) { + free_irq(isi_card[count].irq, NULL); #ifdef ISICOM_DEBUG - printk(KERN_DEBUG "ISICOM: Irq %d released for Card%d.\n",isi_card[count].irq, count+1); -#endif + printk(KERN_DEBUG "ISICOM: Irq %d released for Card%d.\n",isi_card[count].irq, count+1); +#endif + } } + } } static int isicom_init(void) @@ -1882,28 +1956,74 @@ int init_module(void) { - int retval, card; - - for(card=0; card < BOARD_COUNT; card++) - { - isi_card[card].base=io[card]; - isi_card[card].irq=irq[card]; - } - - for (card=0 ;card < BOARD_COUNT; card++) { - if (!((isi_card[card].irq==2)||(isi_card[card].irq==3)|| - (isi_card[card].irq==4)||(isi_card[card].irq==5)|| - (isi_card[card].irq==7)||(isi_card[card].irq==10)|| - (isi_card[card].irq==11)||(isi_card[card].irq==12)|| - (isi_card[card].irq==15))) { + struct pci_dev *dev = NULL; + int retval, card, idx, count; + unsigned char pciirq; + unsigned int ioaddr; + + card = 0; + for(idx=0; idx < BOARD_COUNT; idx++) { + if (io[idx]) { + isi_card[idx].base=io[idx]; + isi_card[idx].irq=irq[idx]; + isi_card[idx].isa=YES; + card++; + } + else { + isi_card[idx].base = 0; + isi_card[idx].irq = 0; + } + } + + for (idx=0 ;idx < card; idx++) { + if (!((isi_card[idx].irq==2)||(isi_card[idx].irq==3)|| + (isi_card[idx].irq==4)||(isi_card[idx].irq==5)|| + (isi_card[idx].irq==7)||(isi_card[idx].irq==10)|| + (isi_card[idx].irq==11)||(isi_card[idx].irq==12)|| + (isi_card[idx].irq==15))) { - if (isi_card[card].base) { + if (isi_card[idx].base) { printk(KERN_ERR "ISICOM: Irq %d unsupported. Disabling Card%d...\n", - isi_card[card].irq, card+1); - isi_card[card].base=0; + isi_card[idx].irq, idx+1); + isi_card[idx].base=0; + card--; } } } + + if (pci_present() && (card < BOARD_COUNT)) { + for (idx=0; idx < DEVID_COUNT; idx++) { + dev = NULL; + for (;;){ + if (!(dev = pci_find_device(VENDOR_ID, device_id[idx], dev))) + break; + if (card >= BOARD_COUNT) + break; + + /* found a PCI ISI card! */ + ioaddr = dev->base_address[3]; /* i.e at offset 0x1c in the + * PCI configuration register + * space. + */ + ioaddr &= PCI_BASE_ADDRESS_IO_MASK; + pciirq = dev->irq; + printk(KERN_INFO "ISI PCI Card(Device ID 0x%x)\n", device_id[idx]); + /* + * allot the first empty slot in the array + */ + for (count=0; count < BOARD_COUNT; count++) { + if (isi_card[count].base == 0) { + isi_card[count].base = ioaddr; + isi_card[count].irq = pciirq; + isi_card[count].isa = NO; + card++; + break; + } + } + } + if (card >= BOARD_COUNT) break; + } + } if (!(isi_card[0].base || isi_card[1].base || isi_card[2].base || isi_card[3].base)) { printk(KERN_ERR "ISICOM: No valid card configuration. Driver cannot be initialized...\n"); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/keyboard.c linux.pre11.3/drivers/char/keyboard.c --- linux.vanilla/drivers/char/keyboard.c Wed Apr 28 19:14:26 1999 +++ linux.pre11.3/drivers/char/keyboard.c Mon Jul 19 23:27:49 1999 @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -155,6 +156,7 @@ #ifdef CONFIG_MAGIC_SYSRQ static int sysrq_pressed; +int sysrq_enabled = 1; #endif /* @@ -247,7 +249,7 @@ sysrq_pressed = !up_flag; return; } else if (sysrq_pressed) { - if (!up_flag) + if (!up_flag && sysrq_enabled) handle_sysrq(kbd_sysrq_xlate[keycode], kbd_pt_regs, kbd, tty); return; } @@ -321,15 +323,31 @@ } } +#ifdef CONFIG_FORWARD_KEYBOARD +extern int forward_chars; void put_queue(int ch) { + if (forward_chars == fg_console+1){ + kbd_forward_char (ch); + } else { + wake_up(&keypress_wait); + if (tty) { + tty_insert_flip_char(tty, ch, 0); + con_schedule_flip(tty); + } + } +} +#else +void put_queue(int ch) +{ wake_up(&keypress_wait); if (tty) { tty_insert_flip_char(tty, ch, 0); con_schedule_flip(tty); } } +#endif static void puts_queue(char *cp) { diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/misc.c linux.pre11.3/drivers/char/misc.c --- linux.vanilla/drivers/char/misc.c Mon Mar 29 10:25:55 1999 +++ linux.pre11.3/drivers/char/misc.c Mon Jul 19 23:27:49 1999 @@ -268,6 +268,12 @@ #ifdef CONFIG_PMAC_PBOOK pmu_device_init(); #endif +#ifdef CONFIG_SGI_NEWPORT_GFX + gfx_register (); +#endif +#ifdef CONFIG_SGI + streamable_init (); +#endif if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) { printk("unable to get major %d for misc devices\n", MISC_MAJOR); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/pc_keyb.c linux.pre11.3/drivers/char/pc_keyb.c --- linux.vanilla/drivers/char/pc_keyb.c Wed Apr 28 19:14:26 1999 +++ linux.pre11.3/drivers/char/pc_keyb.c Mon Jul 19 23:27:52 1999 @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -34,15 +33,13 @@ #include #include -#include #include #include #include -#include /* Some configuration switches are present in the include file... */ -#include "pc_keyb.h" +#include /* Simple translation table for the SysRq keys */ @@ -57,10 +54,11 @@ "\r\000/"; /* 0x60 - 0x6f */ #endif -static void kbd_write(int address, int data); -static unsigned char handle_kbd_event(void); +static void kbd_write_command_w(int data); +static void kbd_write_output_w(int data); spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED; +static unsigned char handle_kbd_event(void); /* used only by send_data - set by keyboard_interrupt */ static volatile unsigned char reply_expected = 0; @@ -84,11 +82,6 @@ #define AUX_INTS_ON (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT) #define MAX_RETRIES 60 /* some aux operations take long time*/ - -#ifndef AUX_IRQ -# define AUX_IRQ 12 -#endif - #endif /* CONFIG_PSMOUSE */ /* @@ -426,13 +419,13 @@ */ static unsigned char handle_kbd_event(void) { - unsigned char status = inb(KBD_STATUS_REG); + unsigned char status = kbd_read_status(); + unsigned int work = 10000; while (status & KBD_STAT_OBF) { unsigned char scancode; - scancode = inb(KBD_DATA_REG); - + scancode = kbd_read_input(); if (status & KBD_STAT_MOUSE_OBF) { handle_mouse_event(scancode); } else { @@ -441,7 +434,14 @@ mark_bh(KEYBOARD_BH); } - status = inb(KBD_STATUS_REG); + status = kbd_read_status(); + + if(!work--) + { + printk(KERN_ERR "pc_keyb: controller jammed (0x%02X).\n", + status); + break; + } } return status; @@ -476,7 +476,7 @@ acknowledge = 0; /* Set by interrupt routine on receipt of ACK. */ resend = 0; reply_expected = 1; - kbd_write(KBD_DATA_REG, data); + kbd_write_output_w(data); for (;;) { if (acknowledge) return 1; @@ -527,14 +527,14 @@ #define KBD_NO_DATA (-1) /* No data */ #define KBD_BAD_DATA (-2) /* Parity or other error */ -static int __init kbd_read_input(void) +static int __init kbd_read_data(void) { int retval = KBD_NO_DATA; unsigned char status; - status = inb(KBD_STATUS_REG); + status = kbd_read_status(); if (status & KBD_STAT_OBF) { - unsigned char data = inb(KBD_DATA_REG); + unsigned char data = kbd_read_input(); retval = data; if (status & (KBD_STAT_GTO | KBD_STAT_PERR)) @@ -548,7 +548,7 @@ int maxread = 100; /* Random number */ do { - if (kbd_read_input() == KBD_NO_DATA) + if (kbd_read_data() == KBD_NO_DATA) break; } while (--maxread); } @@ -558,7 +558,7 @@ long timeout = KBD_INIT_TIMEOUT; do { - int retval = kbd_read_input(); + int retval = kbd_read_data(); if (retval >= 0) return retval; mdelay(1); @@ -566,13 +566,23 @@ return -1; } -static void kbd_write(int address, int data) +static void kbd_write_command_w(int data) +{ + unsigned long flags; + + spin_lock_irqsave(&kbd_controller_lock, flags); + kb_wait(); + kbd_write_command(data); + spin_unlock_irqrestore(&kbd_controller_lock, flags); +} + +static void kbd_write_output_w(int data) { unsigned long flags; spin_lock_irqsave(&kbd_controller_lock, flags); kb_wait(); - outb(data, address); + kbd_write_output(data); spin_unlock_irqrestore(&kbd_controller_lock, flags); } @@ -583,9 +593,9 @@ spin_lock_irqsave(&kbd_controller_lock, flags); kb_wait(); - outb(KBD_CCMD_WRITE_MODE, KBD_CNTL_REG); + kbd_write_command(KBD_CCMD_WRITE_MODE); kb_wait(); - outb(cmd, KBD_DATA_REG); + kbd_write_output(cmd); spin_unlock_irqrestore(&kbd_controller_lock, flags); } #endif /* CONFIG_PSMOUSE */ @@ -599,7 +609,7 @@ * This seems to be the only way to get it going. * If the test is successful a x55 is placed in the input buffer. */ - kbd_write(KBD_CNTL_REG, KBD_CCMD_SELF_TEST); + kbd_write_command_w(KBD_CCMD_SELF_TEST); if (kbd_wait_for_input() != 0x55) return "Keyboard failed self test"; @@ -608,14 +618,14 @@ * to test the keyboard clock and data lines. The results of the * test are placed in the input buffer. */ - kbd_write(KBD_CNTL_REG, KBD_CCMD_KBD_TEST); + kbd_write_command_w(KBD_CCMD_KBD_TEST); if (kbd_wait_for_input() != 0x00) return "Keyboard interface failed self test"; /* * Enable the keyboard by allowing the keyboard clock to run. */ - kbd_write(KBD_CNTL_REG, KBD_CCMD_KBD_ENABLE); + kbd_write_command_w(KBD_CCMD_KBD_ENABLE); /* * Reset keyboard. If the read times out @@ -626,7 +636,7 @@ * Set up to try again if the keyboard asks for RESEND. */ do { - kbd_write(KBD_DATA_REG, KBD_CMD_RESET); + kbd_write_output_w(KBD_CMD_RESET); status = kbd_wait_for_input(); if (status == KBD_REPLY_ACK) break; @@ -644,7 +654,7 @@ * Set up to try again if the keyboard asks for RESEND. */ do { - kbd_write(KBD_DATA_REG, KBD_CMD_DISABLE); + kbd_write_output_w(KBD_CMD_DISABLE); status = kbd_wait_for_input(); if (status == KBD_REPLY_ACK) break; @@ -652,37 +662,37 @@ return "Disable keyboard: no ACK"; } while (1); - kbd_write(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE); - kbd_write(KBD_DATA_REG, KBD_MODE_KBD_INT + kbd_write_command_w(KBD_CCMD_WRITE_MODE); + kbd_write_output_w(KBD_MODE_KBD_INT | KBD_MODE_SYS | KBD_MODE_DISABLE_MOUSE | KBD_MODE_KCC); /* ibm powerpc portables need this to use scan-code set 1 -- Cort */ - kbd_write(KBD_CNTL_REG, KBD_CCMD_READ_MODE); + kbd_write_command_w(KBD_CCMD_READ_MODE); if (!(kbd_wait_for_input() & KBD_MODE_KCC)) { /* * If the controller does not support conversion, * Set the keyboard to scan-code set 1. */ - kbd_write(KBD_DATA_REG, 0xF0); + kbd_write_output_w(0xF0); kbd_wait_for_input(); - kbd_write(KBD_DATA_REG, 0x01); + kbd_write_output_w(0x01); kbd_wait_for_input(); } - kbd_write(KBD_DATA_REG, KBD_CMD_ENABLE); + kbd_write_output_w(KBD_CMD_ENABLE); if (kbd_wait_for_input() != KBD_REPLY_ACK) return "Enable keyboard: no ACK"; /* * Finally, set the typematic rate to maximum. */ - kbd_write(KBD_DATA_REG, KBD_CMD_SET_RATE); + kbd_write_output_w(KBD_CMD_SET_RATE); if (kbd_wait_for_input() != KBD_REPLY_ACK) return "Set rate: no ACK"; - kbd_write(KBD_DATA_REG, 0x00); + kbd_write_output_w(0x00); if (kbd_wait_for_input() != KBD_REPLY_ACK) return "Set rate: no ACK"; @@ -691,8 +701,7 @@ void __init pckbd_init_hw(void) { - /* Get the keyboard controller registers (incomplete decode) */ - request_region(0x60, 16, "keyboard"); + kbd_request_region(); /* Flush any pending input. */ kbd_clear_input(); @@ -708,7 +717,7 @@ #endif /* Ok, finally allocate the IRQ, and off we go.. */ - request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard", NULL); + kbd_request_irq(keyboard_interrupt); } #if defined CONFIG_PSMOUSE @@ -732,16 +741,16 @@ * controller has an Auxiliary Port (a.k.a. Mouse Port). */ kb_wait(); - outb(KBD_CCMD_WRITE_AUX_OBUF, KBD_CNTL_REG); + kbd_write_command(KBD_CCMD_WRITE_AUX_OBUF); kb_wait(); - outb(0x5a, KBD_DATA_REG); /* 0x5a is a random dummy value. */ + kbd_write_output(0x5a); /* 0x5a is a random dummy value. */ do { - unsigned char status = inb(KBD_STATUS_REG); + unsigned char status = kbd_read_status(); if (status & KBD_STAT_OBF) { - (void) inb(KBD_DATA_REG); + (void) kbd_read_input(); if (status & KBD_STAT_MOUSE_OBF) { printk(KERN_INFO "Detected PS/2 Mouse Port.\n"); retval = 1; @@ -764,9 +773,9 @@ spin_lock_irqsave(&kbd_controller_lock, flags); kb_wait(); - outb(KBD_CCMD_WRITE_MOUSE, KBD_CNTL_REG); + kbd_write_command(KBD_CCMD_WRITE_MOUSE); kb_wait(); - outb(val, KBD_DATA_REG); + kbd_write_output(val); spin_unlock_irqrestore(&kbd_controller_lock, flags); } @@ -779,9 +788,9 @@ spin_lock_irqsave(&kbd_controller_lock, flags); kb_wait(); - outb(KBD_CCMD_WRITE_MOUSE, KBD_CNTL_REG); + kbd_write_command(KBD_CCMD_WRITE_MOUSE); kb_wait(); - outb(val, KBD_DATA_REG); + kbd_write_output(val); /* we expect an ACK in response. */ mouse_reply_expected++; kb_wait(); @@ -828,8 +837,8 @@ if (--aux_count) return 0; kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints */ - kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_DISABLE); - free_irq(AUX_IRQ, AUX_DEV); + kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE); + aux_free_irq(AUX_DEV); return 0; } @@ -844,11 +853,11 @@ return 0; } queue->head = queue->tail = 0; /* Flush input queue */ - if (request_irq(AUX_IRQ, keyboard_interrupt, SA_SHIRQ, "PS/2 Mouse", AUX_DEV)) { + if (aux_request_irq(keyboard_interrupt, AUX_DEV)) { aux_count--; return -EBUSY; } - kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_ENABLE); /* Enable the + kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable the auxiliary port on controller. */ aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */ @@ -967,14 +976,14 @@ queue->proc_list = NULL; #ifdef INITIALIZE_MOUSE - kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_ENABLE); /* Enable Aux. */ + kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable Aux. */ aux_write_ack(AUX_SET_SAMPLE); aux_write_ack(100); /* 100 samples/sec */ aux_write_ack(AUX_SET_RES); aux_write_ack(3); /* 8 counts per mm */ aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */ #endif /* INITIALIZE_MOUSE */ - kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */ + kbd_write_command(KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */ kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */ return 0; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/pc_keyb.h linux.pre11.3/drivers/char/pc_keyb.h --- linux.vanilla/drivers/char/pc_keyb.h Tue Feb 23 14:21:33 1999 +++ linux.pre11.3/drivers/char/pc_keyb.h Thu Jan 1 01:00:00 1970 @@ -1,130 +0,0 @@ -/* - * linux/drivers/char/pc_keyb.h - * - * PC Keyboard And Keyboard Controller - * - * (c) 1997 Martin Mares - */ - -/* - * Configuration Switches - */ - -#undef KBD_REPORT_ERR /* Report keyboard errors */ -#define KBD_REPORT_UNKN /* Report unknown scan codes */ -#define KBD_REPORT_TIMEOUTS /* Report keyboard timeouts */ -#undef KBD_IS_FOCUS_9000 /* We have the brain-damaged FOCUS-9000 keyboard */ -#undef INITIALIZE_MOUSE /* Define if your PS/2 mouse needs initialization. */ - - - -#define KBD_INIT_TIMEOUT 1000 /* Timeout in ms for initializing the keyboard */ -#define KBC_TIMEOUT 250 /* Timeout in ms for sending to keyboard controller */ -#define KBD_TIMEOUT 1000 /* Timeout in ms for keyboard command acknowledge */ - -/* - * Internal variables of the driver - */ - -extern unsigned char pckbd_read_mask; -extern unsigned char aux_device_present; - -/* - * Keyboard Controller Registers - */ - -#define KBD_STATUS_REG 0x64 /* Status register (R) */ -#define KBD_CNTL_REG 0x64 /* Controller command register (W) */ -#define KBD_DATA_REG 0x60 /* Keyboard data register (R/W) */ - -/* - * Keyboard Controller Commands - */ - -#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */ -#define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */ -#define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */ -#define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */ -#define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */ -#define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */ -#define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */ -#define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */ -#define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */ -#define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */ -#define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if - initiated by the auxiliary device */ -#define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */ - -/* - * Keyboard Commands - */ - -#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ -#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */ -#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */ -#define KBD_CMD_DISABLE 0xF5 /* Disable scanning */ -#define KBD_CMD_RESET 0xFF /* Reset */ - -/* - * Keyboard Replies - */ - -#define KBD_REPLY_POR 0xAA /* Power on reset */ -#define KBD_REPLY_ACK 0xFA /* Command ACK */ -#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */ - -/* - * Status Register Bits - */ - -#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */ -#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ -#define KBD_STAT_SELFTEST 0x04 /* Self test successful */ -#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */ -#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */ -#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */ -#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */ -#define KBD_STAT_PERR 0x80 /* Parity error */ - -#define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF) - -/* - * Controller Mode Register Bits - */ - -#define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */ -#define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */ -#define KBD_MODE_SYS 0x04 /* The system flag (?) */ -#define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */ -#define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */ -#define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */ -#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */ -#define KBD_MODE_RFU 0x80 - -/* - * Mouse Commands - */ - -#define AUX_SET_RES 0xE8 /* Set resolution */ -#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ -#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ -#define AUX_GET_SCALE 0xE9 /* Get scaling factor */ -#define AUX_SET_STREAM 0xEA /* Set stream mode */ -#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ -#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ -#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ -#define AUX_RESET 0xFF /* Reset aux device */ -#define AUX_ACK 0xFA /* Command byte ACK. */ - -#define AUX_BUF_SIZE 2048 /* This might be better divisible by - three to make overruns stay in sync - but then the read function would need - a lock etc - ick */ - -struct aux_queue { - unsigned long head; - unsigned long tail; - struct wait_queue *proc_list; - struct fasync_struct *fasync; - unsigned char buf[AUX_BUF_SIZE]; -}; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/qpmouse.c linux.pre11.3/drivers/char/qpmouse.c --- linux.vanilla/drivers/char/qpmouse.c Sun Nov 8 15:10:12 1998 +++ linux.pre11.3/drivers/char/qpmouse.c Mon Jul 19 23:27:52 1999 @@ -42,7 +42,7 @@ #include #include -#include "pc_keyb.h" /* mouse enable command.. */ +#include /* mouse enable command.. */ /* diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/radio-cadet.c linux.pre11.3/drivers/char/radio-cadet.c --- linux.vanilla/drivers/char/radio-cadet.c Tue Jun 15 16:49:48 1999 +++ linux.pre11.3/drivers/char/radio-cadet.c Mon Jul 19 23:27:55 1999 @@ -1,7 +1,7 @@ -/* cadet.c - A video4linux driver for the ADS Cadet AM/FM Radio Card +/* radio-cadet.c - A video4linux driver for the ADS Cadet AM/FM Radio Card * * by Fred Gleason - * Version 0.3.2 + * Version 0.3.3 * * (Loosely) based on code for the Aztech radio card by * @@ -346,17 +346,13 @@ static long cadet_read(struct video_device *v,char *buf,unsigned long count, int nonblock) { - int i=0,c; + int i=0; unsigned char readbuf[RDS_BUFFER]; if(rdsstat==0) { cadet_lock++; rdsstat=1; outb(0x80,io); /* Select RDS fifo */ - c=3*(inb(io)&0x03); - for(i=0;iflags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) +#define IRQ_T(state) \ + ((state->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) #define SERIAL_INLINE @@ -1003,7 +1004,7 @@ } else handler = rs_interrupt_single; - retval = request_irq(state->irq, handler, IRQ_T(info), + retval = request_irq(state->irq, handler, IRQ_T(state), "serial", NULL); if (retval) { if (capable(CAP_SYS_ADMIN)) { @@ -1168,7 +1169,7 @@ if (IRQ_ports[state->irq]) { free_irq(state->irq, NULL); retval = request_irq(state->irq, rs_interrupt_single, - IRQ_T(info), "serial", NULL); + IRQ_T(state), "serial", NULL); if (retval) printk("serial shutdown: request_irq: error %d" @@ -2017,7 +2018,7 @@ else handler = rs_interrupt; - retval = request_irq(state->irq, handler, IRQ_T(info), + retval = request_irq(state->irq, handler, IRQ_T(state), "serial", NULL); if (retval) { printk("Couldn't reallocate serial interrupt " diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/videodev.c linux.pre11.3/drivers/char/videodev.c --- linux.vanilla/drivers/char/videodev.c Tue Jun 15 16:49:48 1999 +++ linux.pre11.3/drivers/char/videodev.c Mon Jul 19 23:27:52 1999 @@ -63,6 +63,9 @@ #ifdef CONFIG_RADIO_RTRACK extern int rtrack_init(struct video_init *); #endif +#ifdef CONFIG_RADIO_RTRACK2 +extern int rtrack2_init(struct video_init *); +#endif #ifdef CONFIG_RADIO_SF16FMI extern int fmi_init(struct video_init *); #endif @@ -81,6 +84,9 @@ #ifdef CONFIG_VIDEO_PMS extern int init_pms_cards(struct video_init *); #endif +#ifdef CONFIG_VIDEO_ZORAN +extern int init_zoran_cards(struct video_init *); +#endif static struct video_init video_init_list[]={ #ifdef CONFIG_VIDEO_BT848 @@ -108,6 +114,9 @@ #ifdef CONFIG_RADIO_RTRACK {"RTrack", rtrack_init}, #endif +#ifdef CONFIG_RADIO_RTRACK2 + {"RTrack2", rtrack2_init}, +#endif #ifdef CONFIG_RADIO_SF16FMI {"SF16FMI", fmi_init}, #endif @@ -123,6 +132,9 @@ #ifdef CONFIG_RADIO_TYPHOON {"radio-typhoon", typhoon_init}, #endif +#ifdef CONFIG_VIDEO_ZORAN + {"zoran", init_zoran_cards}, +#endif {"end", NULL} }; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/vino.c linux.pre11.3/drivers/char/vino.c --- linux.vanilla/drivers/char/vino.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/char/vino.c Mon Jul 19 23:27:54 1999 @@ -0,0 +1,276 @@ +/* $Id: vino.c,v 1.4 1999/02/09 23:59:36 ulfc Exp $ + * drivers/char/vino.c + * + * (incomplete) Driver for the Vino Video input system found in SGI Indys. + * + * Copyright (C) 1999 Ulf Carlsson (ulfc@bun.falkenberg.se) + * + * This isn't complete yet, please don't expect any video until I've written + * some more code. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "vino.h" + +struct vino_device { + struct video_device vdev; + + unsigned long chan; +#define VINO_CHAN_A 0 +#define VINO_CHAN_B 1 + + unsigned long flags; +#define VINO_DMA_ACTIVE (1<<0) +}; + +/* We can actually receive TV and IndyCam input at the same time. Believe it or + * not.. + */ +static struct vino_device vino[2]; + +/* Those registers have to be accessed by either *one* 64 bit write or *one* 64 + * bit read. We need some asm to fix this. We can't use mips3 as standard + * because we just save 32 bits at context switch. + */ + +static __inline__ unsigned long long vino_reg_read(unsigned long addr) +{ + unsigned long long ret __attribute__ ((aligned (64))); + unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE); + unsigned long flags; + + save_and_cli(flags); + __asm__ __volatile__( + ".set\tmips3\n\t" + ".set\tnoat\n\t" + "ld\t$1,(%0)\n\t" + "sd\t$1,(%1)\n\t" + ".set\tat\n\t" + ".set\tmips0" + : + :"r" (virt_addr), + "r" (&ret) + :"$1"); + restore_flags(flags); + + return ret; +} + +static __inline__ void vino_reg_write(unsigned long long value, + unsigned long addr) +{ + unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE); + unsigned long flags; + + /* we might lose the upper parts of the registers which are not saved + * if there comes an interrupt in our way, play safe */ + + save_and_cli(flags); + __asm__ __volatile__( + ".set\tmips3\n\t" + ".set\tnoat\n\t" + "ld\t$1,(%0)\n\t" + "sd\t$1,(%1)\n\t" + ".set\tat\n\t" + ".set\tmips0" + : + :"r" (&value), + "r" (virt_addr) + :"$1"); + restore_flags(flags); +} + +static __inline__ void vino_reg_and(unsigned long long value, + unsigned long addr) +{ + unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE); + unsigned long flags; + + save_and_cli(flags); + __asm__ __volatile__( + ".set\tmips3\n\t" + ".set\tnoat\n\t" + "ld\t$1,(%0)\n\t" + "ld\t$2,(%1)\n\t" + "and\t$1,$1,$2\n\t" + "sd\t$1,(%0)\n\t" + ".set\tat\n\t" + ".set\tmips0" + : + :"r" (virt_addr), + "r" (&value) + :"$1","$2"); + restore_flags(flags); +} + +static __inline__ void vino_reg_or(unsigned long long value, + unsigned long addr) +{ + unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE); + unsigned long flags; + + save_and_cli(flags); + __asm__ __volatile__( + ".set\tmips3\n\t" + ".set\tnoat\n\t" + "ld\t$1,(%0)\n\t" + "ld\t$2,(%1)\n\t" + "or\t$1,$1,$2\n\t" + "sd\t$1,(%0)\n\t" + ".set\tat\n\t" + ".set\tmips0" + : + :"r" (virt_addr), + "r" (&value) + :"$1","$2"); + restore_flags(flags); +} + +static int vino_dma_setup(void) +{ + return 0; +} + +static void vino_dma_stop(void) +{ + +} + +static int vino_init(void) +{ + unsigned long ret; + unsigned short rev, id; + unsigned long long foo; + unsigned long *bar; + + bar = (unsigned long *) &foo; + + ret = vino_reg_read(VINO_REVID); + + rev = (ret & VINO_REVID_REV_MASK); + id = (ret & VINO_REVID_ID_MASK) >> 4; + + printk("Vino: ID:%02hx Rev:%02hx\n", id, rev); + + foo = vino_reg_read(VINO_A_DESC_DATA0); + printk("0x%lx", bar[0]); + printk("%lx ", bar[1]); + foo = vino_reg_read(VINO_A_DESC_DATA1); + printk("0x%lx", bar[0]); + printk("%lx ", bar[1]); + foo = vino_reg_read(VINO_A_DESC_DATA2); + printk("0x%lx", bar[0]); + printk("%lx ", bar[1]); + foo = vino_reg_read(VINO_A_DESC_DATA3); + printk("0x%lx", bar[0]); + printk("%lx\n", bar[1]); + foo = vino_reg_read(VINO_B_DESC_DATA0); + printk("0x%lx", bar[0]); + printk("%lx ", bar[1]); + foo = vino_reg_read(VINO_B_DESC_DATA1); + printk("0x%lx", bar[0]); + printk("%lx ", bar[1]); + foo = vino_reg_read(VINO_B_DESC_DATA2); + printk("0x%lx", bar[0]); + printk("%lx ", bar[1]); + foo = vino_reg_read(VINO_B_DESC_DATA3); + printk("0x%lx", bar[0]); + printk("%lx\n", bar[1]); + + return 0; +} + +static void vino_dma_go(struct vino_device *v) +{ + +} + +/* Reset the vino back to default state */ + +static void vino_setup(struct vino_device *v) +{ + +} + +static int vino_open(struct video_device *dev, int flags) +{ + MOD_INC_USE_COUNT; + return 0; +} + +static void vino_close(struct video_device *dev) +{ + MOD_DEC_USE_COUNT; +} + +static int vino_ioctl(struct video_device *dev, unsigned int cmd, void *arg) +{ + return 0; +} + +static int vino_mmap(struct video_device *dev, const char *adr, + unsigned long size) +{ + return 0; +} + +static struct video_device vino_dev = { + "Vino IndyCam/TV", + VID_TYPE_CAPTURE, + VID_HARDWARE_VINO, + vino_open, + vino_close, + NULL, /* vino_read */ + NULL, /* vino_write */ + NULL, /* vino_poll */ + vino_ioctl, + vino_mmap, + NULL, /* vino_init */ + NULL, + 0, + 0 +}; + +__initfunc(int init_vino(struct video_device *dev)) +{ + int err; + + err = vino_init(); + if (err) + return err; + +#if 0 + if (video_register_device(&vinodev, VFL_TYPE_GRABBER) == -1) { + return -ENODEV; + } +#endif + + return 0; +} + +#ifdef MODULE +int init_module(void) +{ + int err; + + err = vino_init(); + if (err) + return err; + + return 0; +} + +void cleanup_module(void) +{ +} +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/vino.h linux.pre11.3/drivers/char/vino.h --- linux.vanilla/drivers/char/vino.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/char/vino.h Mon Jul 19 23:27:55 1999 @@ -0,0 +1,118 @@ +/* $Id: vino.h,v 1.2 1999/02/09 23:03:53 ulfc Exp $ + * drivers/sgi/vino.h + * + * Copyright (C) 1999 Ulf Carlsson (ulfc@bun.falkenberg.se) + */ + +#define VINO_BASE 0x0008000 + +#define VINO_REVID 0x0000 +#define VINO_CTRL 0x0008 +#define VINO_INTSTAT 0x0010 /* Interrupt status */ +#define VINO_I2C_CTRL 0x0018 +#define VINO_I2C_DATA 0x0020 +#define VINO_A_ALPHA 0x0028 /* Channel A ... */ +#define VINO_A_CLIPS 0x0030 /* Clipping start */ +#define VINO_A_CLIPE 0x0038 /* Clipping end */ +#define VINO_A_FRAMERT 0x0040 /* Framerate */ +#define VINO_A_FLDCNT 0x0048 /* Field counter */ +#define VINO_A_LNSZ 0x0050 +#define VINO_A_LNCNT 0x0058 +#define VINO_A_PGIX 0x0060 /* Page index */ +#define VINO_A_DESC_PTR 0x0068 /* Ptr to next four descriptors */ +#define VINO_A_DESC_TLB_PTR 0x0070 /* Ptr to start of descriptor table */ +#define VINO_A_DESC_DATA0 0x0078 /* Descriptor data 0 */ +#define VINO_A_DESC_DATA1 0x0080 /* ... */ +#define VINO_A_DESC_DATA2 0x0088 +#define VINO_A_DESC_DATA3 0x0090 +#define VINO_A_FIFO_THRESHOLD 0x0098 /* FIFO threshold */ +#define VINO_A_FIFO_RP 0x00a0 +#define VINO_A_FIFO_WP 0x00a8 +#define VINO_B_ALPHA 0x00b0 /* Channel B ... */ +#define VINO_B_CLIPS 0x00b8 +#define VINO_B_CLIPE 0x00c0 +#define VINO_B_FRAMERT 0x00c8 +#define VINO_B_FLDCNT 0x00d0 +#define VINO_B_LNSZ 0x00d8 +#define VINO_B_LNCNT 0x00e0 +#define VINO_B_PGIX 0x00e8 +#define VINO_B_DESC_PTR 0x00f0 +#define VINO_B_DESC_TLB_PTR 0x00f8 +#define VINO_B_DESC_DATA0 0x0100 +#define VINO_B_DESC_DATA1 0x0108 +#define VINO_B_DESC_DATA2 0x0110 +#define VINO_B_DESC_DATA3 0x0118 +#define VINO_B_FIFO_THRESHOLD 0x0120 +#define VINO_B_FIFO_RP 0x0128 +#define VINO_B_FIFO_WP 0x0130 + +/* Bits in the VINO_REVID register */ + +#define VINO_REVID_REV_MASK 0x000f /* bits 0:3 */ +#define VINO_REVID_ID_MASK 0x00f0 /* bits 4:7 */ + +/* Bits in the VINO_CTRL register */ + +#define VINO_CTRL_LITTLE_ENDIAN (1<<0) +#define VINO_CTRL_A_FIELD_TRANS_INT (1<<1) /* Field transferred int */ +#define VINO_CTRL_A_FIFO_OF_INT (1<<2) /* FIFO overflow int */ +#define VINO_CTRL_A_END_DESC_TBL_INT (1<<3) /* End of desc table int */ +#define VINO_CTRL_B_FIELD_TRANS_INT (1<<4) /* Field transferred int */ +#define VINO_CTRL_B_FIFO_OF_INT (1<<5) /* FIFO overflow int */ +#define VINO_CTRL_B_END_DESC_TLB_INT (1<<6) /* End of desc table int */ +#define VINO_CTRL_A_DMA_ENBL (1<<7) +#define VINO_CTRL_A_INTERLEAVE_ENBL (1<<8) +#define VINO_CTRL_A_SYNC_ENBL (1<<9) +#define VINO_CTRL_A_SELECT (1<<10) /* 1=D1 0=Philips */ +#define VINO_CTRL_A_RGB (1<<11) /* 1=RGB 0=YUV */ +#define VINO_CTRL_A_LUMA_ONLY (1<<12) +#define VINO_CTRL_A_DEC_ENBL (1<<13) /* Decimation */ +#define VINO_CTRL_A_DEC_SCALE_MASK 0x1c000 /* bits 14:17 */ +#define VINO_CTRL_A_DEC_HOR_ONLY (1<<17) /* Horizontal only */ +#define VINO_CTRL_A_DITHER (1<<18) /* 24 -> 8 bit dither */ +#define VINO_CTRL_B_DMA_ENBL (1<<19) +#define VINO_CTRL_B_INTERLEAVE_ENBL (1<<20) +#define VINO_CTRL_B_SYNC_ENBL (1<<21) +#define VINO_CTRL_B_SELECT (1<<22) /* 1=D1 0=Philips */ +#define VINO_CTRL_B_RGB (1<<22) /* 1=RGB 0=YUV */ +#define VINO_CTRL_B_LUMA_ONLY (1<<23) +#define VINO_CTRL_B_DEC_ENBL (1<<24) /* Decimation */ +#define VINO_CTRL_B_DEC_SCALE_MASK 0x1c000000 /* bits 25:28 */ +#define VINO_CTRL_B_DEC_HOR_ONLY (1<<29) /* Decimation horizontal only */ +#define VINO_CTRL_B_DITHER (1<<30) /* ChanB 24 -> 8 bit dither */ + +/* Bits in the Interrupt and Status register */ + +#define VINO_INTSTAT_A_FIELD_TRANS (1<<0) /* Field transferred int */ +#define VINO_INTSTAT_A_FIFO_OF (1<<1) /* FIFO overflow int */ +#define VINO_INTSTAT_A_END_DESC_TBL (1<<2) /* End of desc table int */ +#define VINO_INTSTAT_B_FIELD_TRANS (1<<3) /* Field transferred int */ +#define VINO_INTSTAT_B_FIFO_OF (1<<4) /* FIFO overflow int */ +#define VINO_INTSTAT_B_END_DESC_TBL (1<<5) /* End of desc table int */ + +/* Bits in the Clipping Start register */ + +#define VINO_CLIPS_START 0x3ff /* bits 0:9 */ +#define VINO_CLIPS_ODD_MASK 0x7fc00 /* bits 10:18 */ +#define VINO_CLIPS_EVEN_MASK 0xff80000 /* bits 19:27 */ + +/* Bits in the Clipping End register */ + +#define VINO_CLIPE_END 0x3ff /* bits 0:9 */ +#define VINO_CLIPE_ODD_MASK 0x7fc00 /* bits 10:18 */ +#define VINO_CLIPE_EVEN_MASK 0xff80000 /* bits 19:27 */ + +/* Bits in the Frame Rate register */ + +#define VINO_FRAMERT_PAL (1<<0) /* 0=NTSC 1=PAL */ +#define VINO_FRAMERT_RT_MASK 0x1ffe /* bits 1:12 */ + +/* Bits in the VINO_I2C_CTRL */ + +#define VINO_CTRL_I2C_IDLE (1<<0) /* write: 0=force idle + * read: 0=idle 1=not idle */ +#define VINO_CTRL_I2C_DIR (1<<1) /* 0=read 1=write */ +#define VINO_CTRL_I2C_MORE_BYTES (1<<2) /* 0=last byte 1=more bytes */ +#define VINO_CTRL_I2C_TRANS_BUSY (1<<4) /* 0=trans done 1=trans busy */ +#define VINO_CTRL_I2C_ACK (1<<5) /* 0=ack received 1=ack not */ +#define VINO_CTRL_I2C_BUS_ERROR (1<<7) /* 0=no bus err 1=bus err */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/vt.c linux.pre11.3/drivers/char/vt.c --- linux.vanilla/drivers/char/vt.c Tue Feb 23 14:21:33 1999 +++ linux.pre11.3/drivers/char/vt.c Mon Jul 19 23:27:49 1999 @@ -88,7 +88,8 @@ * comments - KDMKTONE doesn't put the process to sleep. */ -#if defined(__i386__) || defined(__alpha__) || defined(__powerpc__) || defined(__mips__) +#if defined(__i386__) || defined(__alpha__) || defined(__powerpc__) \ + || (defined(__mips__) && !defined(CONFIG_SGI)) static void kd_nosound(unsigned long ignored) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/Config.in linux.pre11.3/drivers/isdn/Config.in --- linux.vanilla/drivers/isdn/Config.in Wed Mar 24 10:55:17 1999 +++ linux.pre11.3/drivers/isdn/Config.in Mon Jul 19 23:59:32 1999 @@ -9,6 +9,7 @@ fi fi bool 'Support audio via ISDN' CONFIG_ISDN_AUDIO +bool 'Support isdn diversion services' CONFIG_ISDN_DIVERSION if [ "$CONFIG_X25" != "n" ]; then bool 'X.25 PLP on top of ISDN (EXPERIMENTAL)' CONFIG_ISDN_X25 fi @@ -19,37 +20,53 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then bool 'HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO if [ "$CONFIG_HISAX_EURO" != "n" ]; then - bool 'Support for german tarifinfo' CONFIG_DE_AOC - bool 'Support for australian Microlink service (not for std. EURO)' CONFIG_HISAX_ML + bool 'Support for german chargeinfo' CONFIG_DE_AOC + bool 'Disable sending complete' CONFIG_HISAX_NO_SENDCOMPLETE + bool 'Disable sending low layer compatibility' CONFIG_HISAX_NO_LLC fi bool 'HiSax Support for german 1TR6' CONFIG_HISAX_1TR6 bool 'HiSax Support for Teles 16.0/8.0' CONFIG_HISAX_16_0 bool 'HiSax Support for Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3 - bool 'HiSax Support for Teles 16.3c' CONFIG_HISAX_TELES3C + bool 'HiSax Support for Teles PCI' CONFIG_HISAX_TELESPCI + bool 'HiSax Support for Teles S0Box' CONFIG_HISAX_S0BOX bool 'HiSax Support for AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1 + bool 'HiSax Support for AVM PnP/PCI (Fritz!PnP/PCI)' CONFIG_HISAX_FRITZPCI + bool 'HiSax Support for AVM A1 PCMCIA (Fritz)' CONFIG_HISAX_AVM_A1_PCMCIA bool 'HiSax Support for Elsa cards' CONFIG_HISAX_ELSA bool 'HiSax Support for ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2 bool 'HiSax Support for Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA bool 'HiSax Support for ASUSCOM cards' CONFIG_HISAX_ASUSCOM bool 'HiSax Support for TELEINT cards' CONFIG_HISAX_TELEINT - bool 'HiSax Support for Sedlbauer speed card/win/star' CONFIG_HISAX_SEDLBAUER + bool 'HiSax Support for HFC-S based cards' CONFIG_HISAX_HFCS + bool 'HiSax Support for Sedlbauer cards' CONFIG_HISAX_SEDLBAUER bool 'HiSax Support for USR Sportster internal TA' CONFIG_HISAX_SPORTSTER bool 'HiSax Support for MIC card' CONFIG_HISAX_MIC bool 'HiSax Support for NETjet card' CONFIG_HISAX_NETJET bool 'HiSax Support for Niccy PnP/PCI card' CONFIG_HISAX_NICCY + bool 'HiSax Support for Siemens I-Surf card' CONFIG_HISAX_ISURF + bool 'HiSax Support for HST Saphir card' CONFIG_HISAX_HSTSAPHIR + bool 'HiSax Support for Telekom A4T card' CONFIG_HISAX_BKM_A4T + bool 'HiSax Support for Scitel Quadro card' CONFIG_HISAX_SCT_QUADRO + bool 'HiSax Support for Gazel cards' CONFIG_HISAX_GAZEL if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then - if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then - bool 'HiSax Support for SPARC Am7930' CONFIG_HISAX_AMD7930 - bool 'HiSax Support for SPARC DBRI' CONFIG_HISAX_DBRI - fi + bool 'HiSax Support for HFC PCI-Bus cards (EXPERIMENTAL)' CONFIG_HISAX_HFC_PCI +# bool 'HiSax Support for TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU + if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then + bool 'HiSax Support for Am7930' CONFIG_HISAX_AMD7930 + fi fi fi if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then dep_tristate 'Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN dep_tristate 'IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN fi -dep_tristate 'AVM-B1 with CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN +dep_tristate 'Eicon.Diehl active card support' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN +dep_tristate 'AVM CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN if [ "$CONFIG_ISDN_DRV_AVMB1" != "n" ]; then + bool 'AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA + bool 'AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI + bool 'AVM T1/T1B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA + bool 'AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA bool 'Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON fi diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/Makefile linux.pre11.3/drivers/isdn/Makefile --- linux.vanilla/drivers/isdn/Makefile Sun Nov 8 15:08:07 1998 +++ linux.pre11.3/drivers/isdn/Makefile Mon Jul 19 23:59:32 1999 @@ -1,6 +1,6 @@ SUB_DIRS := MOD_SUB_DIRS := -ALL_SUB_DIRS := icn pcbit hisax avmb1 act2000 +ALL_SUB_DIRS := icn pcbit hisax avmb1 act2000 eicon divert L_OBJS := LX_OBJS := @@ -33,6 +33,7 @@ OX_OBJS += isdn_common.o ifdef CONFIG_ISDN_PPP O_OBJS += isdn_ppp.o + M_OBJS += isdn_bsdcomp.o endif ifdef CONFIG_ISDN_X25 O_OBJS += isdn_x25iface.o @@ -44,6 +45,12 @@ endif endif +ifeq ($(CONFIG_ISDN_DIVERSION),y) + ifeq ($(CONFIG_MODULES),y) + MOD_SUB_DIRS += divert + endif +endif + ifeq ($(CONFIG_ISDN_DRV_HISAX),y) L_OBJS += hisax/hisax.o SUB_DIRS += hisax @@ -111,6 +118,16 @@ else ifeq ($(CONFIG_ISDN_DRV_ACT2000),m) MOD_SUB_DIRS += act2000 + endif +endif + +ifeq ($(CONFIG_ISDN_DRV_EICON),y) + L_OBJS += eicon/eicon.o + SUB_DIRS += eicon + MOD_SUB_DIRS += eicon +else + ifeq ($(CONFIG_ISDN_DRV_EICON),m) + MOD_SUB_DIRS += eicon endif endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/act2000/act2000.h linux.pre11.3/drivers/isdn/act2000/act2000.h --- linux.vanilla/drivers/isdn/act2000/act2000.h Thu May 27 22:11:53 1999 +++ linux.pre11.3/drivers/isdn/act2000/act2000.h Mon Jul 19 23:59:32 1999 @@ -1,8 +1,8 @@ -/* $Id: act2000.h,v 1.5 1997/10/09 22:22:59 fritz Exp $ +/* $Id: act2000.h,v 1.7 1999/04/12 13:13:54 fritz Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. * - * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) * Thanks to Friedemann Baitinger and IBM Germany * * This program is free software; you can redistribute it and/or modify @@ -20,6 +20,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: act2000.h,v $ + * Revision 1.7 1999/04/12 13:13:54 fritz + * Made cards pointer static to avoid name-clash. + * + * Revision 1.6 1998/11/05 22:12:38 fritz + * Changed mail-address. + * * Revision 1.5 1997/10/09 22:22:59 fritz * New HL<->LL interface: * New BSENT callback with nr. of bytes included. @@ -212,8 +218,6 @@ isdn_if interface; /* Interface to upper layer */ char regname[35]; /* Name used for request_region */ } act2000_card; - -extern act2000_card *actcards; extern __inline__ void act2000_schedule_tx(act2000_card *card) { diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/act2000/act2000_isa.c linux.pre11.3/drivers/isdn/act2000/act2000_isa.c --- linux.vanilla/drivers/isdn/act2000/act2000_isa.c Sun Nov 8 15:10:14 1998 +++ linux.pre11.3/drivers/isdn/act2000/act2000_isa.c Mon Jul 19 23:59:32 1999 @@ -1,8 +1,8 @@ -/* $Id: act2000_isa.c,v 1.5 1998/02/12 23:06:47 keil Exp $ +/* $Id: act2000_isa.c,v 1.8 1999/01/05 18:29:25 he Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version). * - * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) * Thanks to Friedemann Baitinger and IBM Germany * * This program is free software; you can redistribute it and/or modify @@ -20,6 +20,17 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: act2000_isa.c,v $ + * Revision 1.8 1999/01/05 18:29:25 he + * merged remaining schedule_timeout() changes from 2.1.127 + * + * Revision 1.7 1998/11/05 22:12:41 fritz + * Changed mail-address. + * + * Revision 1.6 1998/06/17 19:51:09 he + * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) + * brute force fix to avoid Ugh's in isdn_tty_write() + * cleaned up some dead code + * * Revision 1.5 1998/02/12 23:06:47 keil * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/act2000/act2000_isa.h linux.pre11.3/drivers/isdn/act2000/act2000_isa.h --- linux.vanilla/drivers/isdn/act2000/act2000_isa.h Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/act2000/act2000_isa.h Mon Jul 19 23:59:32 1999 @@ -1,8 +1,8 @@ -/* $Id: act2000_isa.h,v 1.1 1997/09/23 18:00:07 fritz Exp $ +/* $Id: act2000_isa.h,v 1.2 1998/11/05 22:12:43 fritz Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version). * - * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) * Thanks to Friedemann Baitinger and IBM Germany * * This program is free software; you can redistribute it and/or modify @@ -20,6 +20,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: act2000_isa.h,v $ + * Revision 1.2 1998/11/05 22:12:43 fritz + * Changed mail-address. + * * Revision 1.1 1997/09/23 18:00:07 fritz * New driver for IBM Active 2000. * diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/act2000/capi.c linux.pre11.3/drivers/isdn/act2000/capi.c --- linux.vanilla/drivers/isdn/act2000/capi.c Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/act2000/capi.c Mon Jul 19 23:59:32 1999 @@ -1,9 +1,9 @@ -/* $Id: capi.c,v 1.7 1998/02/23 23:35:41 fritz Exp $ +/* $Id: capi.c,v 1.8 1998/11/05 22:12:46 fritz Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. * CAPI encoder/decoder * - * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) * Thanks to Friedemann Baitinger and IBM Germany * * This program is free software; you can redistribute it and/or modify @@ -21,6 +21,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: capi.c,v $ + * Revision 1.8 1998/11/05 22:12:46 fritz + * Changed mail-address. + * * Revision 1.7 1998/02/23 23:35:41 fritz * Eliminated some compiler warnings. * diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/act2000/capi.h linux.pre11.3/drivers/isdn/act2000/capi.h --- linux.vanilla/drivers/isdn/act2000/capi.h Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/act2000/capi.h Mon Jul 19 23:59:32 1999 @@ -1,8 +1,8 @@ -/* $Id: capi.h,v 1.4 1997/10/01 09:21:04 fritz Exp $ +/* $Id: capi.h,v 1.5 1998/11/05 22:12:48 fritz Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. * - * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) * Thanks to Friedemann Baitinger and IBM Germany * * This program is free software; you can redistribute it and/or modify @@ -20,6 +20,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: capi.h,v $ + * Revision 1.5 1998/11/05 22:12:48 fritz + * Changed mail-address. + * * Revision 1.4 1997/10/01 09:21:04 fritz * Removed old compatibility stuff for 2.0.X kernels. * From now on, this code is for 2.1.X ONLY! diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/act2000/module.c linux.pre11.3/drivers/isdn/act2000/module.c --- linux.vanilla/drivers/isdn/act2000/module.c Thu May 27 22:11:53 1999 +++ linux.pre11.3/drivers/isdn/act2000/module.c Mon Jul 19 23:59:32 1999 @@ -1,8 +1,8 @@ -/* $Id: module.c,v 1.7 1998/02/12 23:06:52 keil Exp $ +/* $Id: module.c,v 1.9 1999/04/12 13:13:56 fritz Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. * - * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) * Thanks to Friedemann Baitinger and IBM Germany * * This program is free software; you can redistribute it and/or modify @@ -20,6 +20,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: module.c,v $ + * Revision 1.9 1999/04/12 13:13:56 fritz + * Made cards pointer static to avoid name-clash. + * + * Revision 1.8 1998/11/05 22:12:51 fritz + * Changed mail-address. + * * Revision 1.7 1998/02/12 23:06:52 keil * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * @@ -57,7 +63,7 @@ }; #define ISA_NRPORTS (sizeof(isa_ports)/sizeof(unsigned short)) -act2000_card *actcards = (act2000_card *) NULL; +static act2000_card *cards = (act2000_card *) NULL; /* Parameters to be set by insmod */ static int act_bus = 0; @@ -589,7 +595,7 @@ static inline act2000_card * act2000_findcard(int driverid) { - act2000_card *p = actcards; + act2000_card *p = cards; while (p) { if (p->myid == driverid) @@ -714,8 +720,8 @@ card->bus = bus; card->port = port; card->irq = irq; - card->next = actcards; - actcards = card; + card->next = cards; + cards = card; } /* @@ -805,9 +811,9 @@ bus); } } - if (!actcards) + if (!cards) return 1; - p = actcards; + p = cards; while (p) { initialized = 0; if (!p->interface.statcallb) { @@ -870,9 +876,9 @@ kfree(p); p = q->next; } else { - actcards = p->next; + cards = p->next; kfree(p); - p = actcards; + p = cards; } failed++; } @@ -890,9 +896,9 @@ act2000_init(void) { printk(KERN_INFO "%s\n", DRIVERNAME); - if (!actcards) + if (!cards) act2000_addcard(act_bus, act_port, act_irq, act_id); - if (!actcards) + if (!cards) printk(KERN_INFO "act2000: No cards defined yet\n"); /* No symbols to export, hide all symbols */ EXPORT_NO_SYMBOLS; @@ -903,14 +909,14 @@ void cleanup_module(void) { - act2000_card *card = actcards; + act2000_card *card = cards; act2000_card *last; while (card) { unregister_card(card); del_timer(&card->ptimer); card = card->next; } - card = actcards; + card = cards; while (card) { last = card; card = card->next; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/Makefile linux.pre11.3/drivers/isdn/avmb1/Makefile --- linux.vanilla/drivers/isdn/avmb1/Makefile Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/avmb1/Makefile Mon Jul 19 23:59:32 1999 @@ -1,5 +1,5 @@ # -# $Id: Makefile,v 1.4 1997/03/30 17:10:40 calle Exp $ +# $Id: Makefile,v 1.5 1999/07/01 15:26:20 calle Exp $ # # Makefile for the CAPI and AVM-B1 device drivers. # @@ -11,6 +11,22 @@ # parent makes.. # # $Log: Makefile,v $ +# Revision 1.5 1999/07/01 15:26:20 calle +# complete new version (I love it): +# + new hardware independed "capi_driver" interface that will make it easy to: +# - support other controllers with CAPI-2.0 (i.e. USB Controller) +# - write a CAPI-2.0 for the passive cards +# - support serial link CAPI-2.0 boxes. +# + wrote "capi_driver" for all supported cards. +# + "capi_driver" (supported cards) now have to be configured with +# make menuconfig, in the past all supported cards where included +# at once. +# + new and better informations in /proc/capi/ +# + new ioctl to switch trace of capi messages per controller +# using "avmcapictrl trace [contr] on|off|...." +# + complete testcircle with all supported cards and also the +# PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. +# # Revision 1.4 1997/03/30 17:10:40 calle # added support for AVM-B1-PCI card. # @@ -56,20 +72,38 @@ ifeq ($(CONFIG_ISDN_DRV_AVMB1),y) O_TARGET += avmb1.o - O_OBJS += capi.o b1lli.o - OX_OBJS += capiutil.o b1capi.o capidrv.o - ifdef CONFIG_PCI - OX_OBJS += b1pci.o + OX_OBJS += kcapi.o + O_OBJS += capi.o kernelcapi.o + ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA + O_OBJS += b1isa.o + endif + ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI + O_OBJS += b1pci.o + endif + ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA + O_OBJS += t1isa.o + endif + ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA + OX_OBJS += b1pcmcia.o endif + OX_OBJS += capiutil.o capidrv.o b1.o else ifeq ($(CONFIG_ISDN_DRV_AVMB1),m) O_TARGET += kernelcapi.o - O_OBJS += b1lli.o - OX_OBJS += b1capi.o + OX_OBJS += kcapi.o M_OBJS += capi.o kernelcapi.o - MX_OBJS += capiutil.o capidrv.o - ifdef CONFIG_PCI - MX_OBJS += b1pci.o + ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA + M_OBJS += b1isa.o + endif + ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI + M_OBJS += b1pci.o + endif + ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA + M_OBJS += t1isa.o + endif + MX_OBJS += capiutil.o capidrv.o b1.o + ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA + MX_OBJS += b1pcmcia.o endif endif endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/avmcard.h linux.pre11.3/drivers/isdn/avmb1/avmcard.h --- linux.vanilla/drivers/isdn/avmb1/avmcard.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/avmb1/avmcard.h Mon Jul 19 23:59:32 1999 @@ -0,0 +1,535 @@ +/* + * $Id: avmcard.h,v 1.2 1999/07/05 15:09:45 calle Exp $ + * + * Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) + * + * $Log: avmcard.h,v $ + * Revision 1.2 1999/07/05 15:09:45 calle + * - renamed "appl_release" to "appl_released". + * - version und profile data now cleared on controller reset + * - extended /proc interface, to allow driver and controller specific + * informations to include by driver hackers. + * + * Revision 1.1 1999/07/01 15:26:22 calle + * complete new version (I love it): + * + new hardware independed "capi_driver" interface that will make it easy to: + * - support other controllers with CAPI-2.0 (i.e. USB Controller) + * - write a CAPI-2.0 for the passive cards + * - support serial link CAPI-2.0 boxes. + * + wrote "capi_driver" for all supported cards. + * + "capi_driver" (supported cards) now have to be configured with + * make menuconfig, in the past all supported cards where included + * at once. + * + new and better informations in /proc/capi/ + * + new ioctl to switch trace of capi messages per controller + * using "avmcapictrl trace [contr] on|off|...." + * + complete testcircle with all supported cards and also the + * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. + * + */ + +#ifndef _AVMCARD_H_ +#define _AVMCARD_H_ + +#define AVMB1_PORTLEN 0x1f +#define AVM_MAXVERSION 8 +#define AVM_NAPPS 30 +#define AVM_NCCI_PER_CHANNEL 4 + +/* + * Versions + */ + +#define VER_DRIVER 0 +#define VER_CARDTYPE 1 +#define VER_HWID 2 +#define VER_SERIAL 3 +#define VER_OPTION 4 +#define VER_PROTO 5 +#define VER_PROFILE 6 +#define VER_CAPI 7 + +enum avmcardtype { + avm_b1isa, + avm_b1pci, + avm_b1pcmcia, + avm_m1, + avm_m2, + avm_t1isa, + avm_t1pci +}; + +typedef struct avmcard { + char name[32]; + unsigned int port; + unsigned irq; + enum avmcardtype cardtype; + int cardnr; /* for t1isa */ + + int versionlen; + char versionbuf[1024]; + char *version[AVM_MAXVERSION]; + + char cardname[32]; + + char infobuf[128]; /* for function procinfo */ + char msgbuf[128]; /* capimsg msg part */ + char databuf[2048]; /* capimsg data part */ + + int interrupt; + + struct capi_ctr *ctrl; +} avmcard; + +extern int b1_irq_table[16]; + +/* + * LLI Messages to the ISDN-ControllerISDN Controller + */ + +#define SEND_POLL 0x72 /* + * after load <- RECEIVE_POLL + */ +#define SEND_INIT 0x11 /* + * first message <- RECEIVE_INIT + * int32 NumApplications int32 + * NumNCCIs int32 BoardNumber + */ +#define SEND_REGISTER 0x12 /* + * register an application int32 + * ApplIDId int32 NumMessages + * int32 NumB3Connections int32 + * NumB3Blocks int32 B3Size + * + * AnzB3Connection != 0 && + * AnzB3Blocks >= 1 && B3Size >= 1 + */ +#define SEND_RELEASE 0x14 /* + * deregister an application int32 + * ApplID + */ +#define SEND_MESSAGE 0x15 /* + * send capi-message int32 length + * capi-data ... + */ +#define SEND_DATA_B3_REQ 0x13 /* + * send capi-data-message int32 + * MsgLength capi-data ... int32 + * B3Length data .... + */ + +#define SEND_CONFIG 0x21 /* + */ + +#define SEND_POLLACK 0x73 /* T1 Watchdog */ + +/* + * LLI Messages from the ISDN-ControllerISDN Controller + */ + +#define RECEIVE_POLL 0x32 /* + * <- after SEND_POLL + */ +#define RECEIVE_INIT 0x27 /* + * <- after SEND_INIT int32 length + * byte total length b1struct board + * driver revision b1struct card + * type b1struct reserved b1struct + * serial number b1struct driver + * capability b1struct d-channel + * protocol b1struct CAPI-2.0 + * profile b1struct capi version + */ +#define RECEIVE_MESSAGE 0x21 /* + * <- after SEND_MESSAGE int32 + * AppllID int32 Length capi-data + * .... + */ +#define RECEIVE_DATA_B3_IND 0x22 /* + * received data int32 AppllID + * int32 Length capi-data ... + * int32 B3Length data ... + */ +#define RECEIVE_START 0x23 /* + * Handshake + */ +#define RECEIVE_STOP 0x24 /* + * Handshake + */ +#define RECEIVE_NEW_NCCI 0x25 /* + * int32 AppllID int32 NCCI int32 + * WindowSize + */ +#define RECEIVE_FREE_NCCI 0x26 /* + * int32 AppllID int32 NCCI + */ +#define RECEIVE_RELEASE 0x26 /* + * int32 AppllID int32 0xffffffff + */ +#define RECEIVE_TASK_READY 0x31 /* + * int32 tasknr + * int32 Length Taskname ... + */ +#define RECEIVE_DEBUGMSG 0x71 /* + * int32 Length message + * + */ + +#define WRITE_REGISTER 0x00 +#define READ_REGISTER 0x01 + +/* + * port offsets + */ + +#define B1_READ 0x00 +#define B1_WRITE 0x01 +#define B1_INSTAT 0x02 +#define B1_OUTSTAT 0x03 +#define B1_RESET 0x10 +#define B1_ANALYSE 0x04 + + +#define B1_STAT0(cardtype) ((cardtype) == avm_m1 ? 0x81200000l : 0x80A00000l) +#define B1_STAT1(cardtype) (0x80E00000l) + +/* ---------------------------------------------------------------- */ + +static inline unsigned char b1outp(unsigned int base, + unsigned short offset, + unsigned char value) +{ + outb(value, base + offset); + return inb(base + B1_ANALYSE); +} + + +static inline int b1_rx_full(unsigned int base) +{ + return inb(base + B1_INSTAT) & 0x1; +} + +static inline unsigned char b1_get_byte(unsigned int base) +{ + unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */ + while (!b1_rx_full(base) && time_before(jiffies, stop)); + if (b1_rx_full(base)) + return inb(base + B1_READ); + printk(KERN_CRIT "b1lli(0x%x): rx not full after 1 second\n", base); + return 0; +} + +static inline unsigned int b1_get_word(unsigned int base) +{ + unsigned int val = 0; + val |= b1_get_byte(base); + val |= (b1_get_byte(base) << 8); + val |= (b1_get_byte(base) << 16); + val |= (b1_get_byte(base) << 24); + return val; +} + +static inline int b1_tx_empty(unsigned int base) +{ + return inb(base + B1_OUTSTAT) & 0x1; +} + +static inline void b1_put_byte(unsigned int base, unsigned char val) +{ + while (!b1_tx_empty(base)); + b1outp(base, B1_WRITE, val); +} + +static inline int b1_save_put_byte(unsigned int base, unsigned char val) +{ + unsigned long stop = jiffies + 2 * HZ; + while (!b1_tx_empty(base) && time_before(jiffies,stop)); + if (!b1_tx_empty(base)) return -1; + b1outp(base, B1_WRITE, val); + return 0; +} + +static inline void b1_put_word(unsigned int base, unsigned int val) +{ + b1_put_byte(base, val & 0xff); + b1_put_byte(base, (val >> 8) & 0xff); + b1_put_byte(base, (val >> 16) & 0xff); + b1_put_byte(base, (val >> 24) & 0xff); +} + +static inline unsigned int b1_get_slice(unsigned int base, + unsigned char *dp) +{ + unsigned int len, i; + + len = i = b1_get_word(base); + while (i-- > 0) *dp++ = b1_get_byte(base); + return len; +} + +static inline void b1_put_slice(unsigned int base, + unsigned char *dp, unsigned int len) +{ + unsigned i = len; + b1_put_word(base, i); + while (i-- > 0) + b1_put_byte(base, *dp++); +} + +static void b1_wr_reg(unsigned int base, + unsigned int reg, + unsigned int value) +{ + b1_put_byte(base, WRITE_REGISTER); + b1_put_word(base, reg); + b1_put_word(base, value); +} + +static inline unsigned int b1_rd_reg(unsigned int base, + unsigned int reg) +{ + b1_put_byte(base, READ_REGISTER); + b1_put_word(base, reg); + return b1_get_word(base); + +} + +static inline void b1_reset(unsigned int base) +{ + b1outp(base, B1_RESET, 0); + udelay(55 * 2 * 1000); /* 2 TIC's */ + + b1outp(base, B1_RESET, 1); + udelay(55 * 2 * 1000); /* 2 TIC's */ + + b1outp(base, B1_RESET, 0); + udelay(55 * 2 * 1000); /* 2 TIC's */ +} + +static inline unsigned char b1_disable_irq(unsigned int base) +{ + return b1outp(base, B1_INSTAT, 0x00); +} + +/* ---------------------------------------------------------------- */ + +static inline void b1_set_test_bit(unsigned int base, + enum avmcardtype cardtype, + int onoff) +{ + b1_wr_reg(base, B1_STAT0(cardtype), onoff ? 0x21 : 0x20); +} + +static inline int b1_get_test_bit(unsigned int base, + enum avmcardtype cardtype) +{ + return (b1_rd_reg(base, B1_STAT0(cardtype)) & 0x01) != 0; +} + +/* ---------------------------------------------------------------- */ + +#define T1_FASTLINK 0x00 +#define T1_SLOWLINK 0x08 + +#define T1_READ B1_READ +#define T1_WRITE B1_WRITE +#define T1_INSTAT B1_INSTAT +#define T1_OUTSTAT B1_OUTSTAT +#define T1_IRQENABLE 0x05 +#define T1_FIFOSTAT 0x06 +#define T1_RESETLINK 0x10 +#define T1_ANALYSE 0x11 +#define T1_IRQMASTER 0x12 +#define T1_IDENT 0x17 +#define T1_RESETBOARD 0x1f + +#define T1F_IREADY 0x01 +#define T1F_IHALF 0x02 +#define T1F_IFULL 0x04 +#define T1F_IEMPTY 0x08 +#define T1F_IFLAGS 0xF0 + +#define T1F_OREADY 0x10 +#define T1F_OHALF 0x20 +#define T1F_OEMPTY 0x40 +#define T1F_OFULL 0x80 +#define T1F_OFLAGS 0xF0 + +/* there are HEMA cards with 1k and 4k FIFO out */ +#define FIFO_OUTBSIZE 256 +#define FIFO_INPBSIZE 512 + +#define HEMA_VERSION_ID 0 +#define HEMA_PAL_ID 0 + +static inline void t1outp(unsigned int base, + unsigned short offset, + unsigned char value) +{ + outb(value, base + offset); +} + +static inline unsigned char t1inp(unsigned int base, + unsigned short offset) +{ + return inb(base + offset); +} + +static inline int t1_isfastlink(unsigned int base) +{ + return (inb(base + T1_IDENT) & ~0x82) == 1; +} + +static inline unsigned char t1_fifostatus(unsigned int base) +{ + return inb(base + T1_FIFOSTAT); +} + +static inline unsigned int t1_get_slice(unsigned int base, + unsigned char *dp) +{ + unsigned int len, i; +#ifdef FASTLINK_DEBUG + unsigned wcnt = 0, bcnt = 0; +#endif + + len = i = b1_get_word(base); + if (t1_isfastlink(base)) { + int status; + while (i > 0) { + status = t1_fifostatus(base) & (T1F_IREADY|T1F_IHALF); + if (i >= FIFO_INPBSIZE) status |= T1F_IFULL; + + switch (status) { + case T1F_IREADY|T1F_IHALF|T1F_IFULL: + insb(base+B1_READ, dp, FIFO_INPBSIZE); + dp += FIFO_INPBSIZE; + i -= FIFO_INPBSIZE; +#ifdef FASTLINK_DEBUG + wcnt += FIFO_INPBSIZE; +#endif + break; + case T1F_IREADY|T1F_IHALF: + insb(base+B1_READ,dp, i); +#ifdef FASTLINK_DEBUG + wcnt += i; +#endif + dp += i; + i = 0; + if (i == 0) + break; + /* fall through */ + default: + *dp++ = b1_get_byte(base); + i--; +#ifdef FASTLINK_DEBUG + bcnt++; +#endif + break; + } + } +#ifdef FASTLINK_DEBUG + if (wcnt) + printk(KERN_DEBUG "b1lli(0x%x): get_slice l=%d w=%d b=%d\n", + base, len, wcnt, bcnt); +#endif + } else { + while (i-- > 0) + *dp++ = b1_get_byte(base); + } + return len; +} + +static inline void t1_put_slice(unsigned int base, + unsigned char *dp, unsigned int len) +{ + unsigned i = len; + b1_put_word(base, i); + if (t1_isfastlink(base)) { + int status; + while (i > 0) { + status = t1_fifostatus(base) & (T1F_OREADY|T1F_OHALF); + if (i >= FIFO_OUTBSIZE) status |= T1F_OEMPTY; + switch (status) { + case T1F_OREADY|T1F_OHALF|T1F_OEMPTY: + outsb(base+B1_WRITE, dp, FIFO_OUTBSIZE); + dp += FIFO_OUTBSIZE; + i -= FIFO_OUTBSIZE; + break; + case T1F_OREADY|T1F_OHALF: + outsb(base+B1_WRITE, dp, i); + dp += i; + i = 0; + break; + default: + b1_put_byte(base, *dp++); + i--; + break; + } + } + } else { + while (i-- > 0) + b1_put_byte(base, *dp++); + } +} + +static inline void t1_disable_irq(unsigned int base) +{ + t1outp(base, T1_IRQMASTER, 0x00); +} + +static inline void t1_reset(unsigned int base) +{ + /* reset T1 Controller */ + b1_reset(base); + /* disable irq on HEMA */ + t1outp(base, B1_INSTAT, 0x00); + t1outp(base, B1_OUTSTAT, 0x00); + t1outp(base, T1_IRQMASTER, 0x00); + /* reset HEMA board configuration */ + t1outp(base, T1_RESETBOARD, 0xf); +} + +static inline void b1_setinterrupt(unsigned int base, unsigned irq, + enum avmcardtype cardtype) +{ + switch (cardtype) { + case avm_t1isa: + t1outp(base, B1_INSTAT, 0x00); + t1outp(base, B1_INSTAT, 0x02); + t1outp(base, T1_IRQMASTER, 0x08); + break; + case avm_b1isa: + b1outp(base, B1_INSTAT, 0x00); + b1outp(base, B1_RESET, b1_irq_table[irq]); + b1outp(base, B1_INSTAT, 0x02); + break; + default: + case avm_m1: + case avm_m2: + case avm_b1pci: + b1outp(base, B1_INSTAT, 0x00); + b1outp(base, B1_RESET, 0xf0); + b1outp(base, B1_INSTAT, 0x02); + break; + } +} + +int b1_detect(unsigned int base, enum avmcardtype cardtype); +int b1_load_t4file(unsigned int base, capiloaddatapart * t4file); +int b1_load_config(unsigned int base, capiloaddatapart * config); +int b1_loaded(unsigned int base); +int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data); +void b1_reset_ctr(struct capi_ctr *ctrl); +void b1_register_appl(struct capi_ctr *ctrl, __u16 appl, + capi_register_params *rp); +void b1_release_appl(struct capi_ctr *ctrl, __u16 appl); +void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); +void b1_parse_version(avmcard *card); +void b1_handle_interrupt(avmcard * card); + +int b1ctl_read_proc(char *page, char **start, off_t off, + int count, int *eof, struct capi_ctr *ctrl); + + +#endif /* _AVMCARD_H_ */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/b1.c linux.pre11.3/drivers/isdn/avmb1/b1.c --- linux.vanilla/drivers/isdn/avmb1/b1.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/avmb1/b1.c Mon Jul 19 23:59:32 1999 @@ -0,0 +1,679 @@ +/* + * $Id: b1.c,v 1.4 1999/07/09 15:05:38 keil Exp $ + * + * Common module for AVM B1 cards. + * + * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) + * + * $Log: b1.c,v $ + * Revision 1.4 1999/07/09 15:05:38 keil + * compat.h is now isdn_compat.h + * + * Revision 1.3 1999/07/06 07:41:59 calle + * - changes in /proc interface + * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb. + * + * Revision 1.2 1999/07/05 15:09:47 calle + * - renamed "appl_release" to "appl_released". + * - version und profile data now cleared on controller reset + * - extended /proc interface, to allow driver and controller specific + * informations to include by driver hackers. + * + * Revision 1.1 1999/07/01 15:26:23 calle + * complete new version (I love it): + * + new hardware independed "capi_driver" interface that will make it easy to: + * - support other controllers with CAPI-2.0 (i.e. USB Controller) + * - write a CAPI-2.0 for the passive cards + * - support serial link CAPI-2.0 boxes. + * + wrote "capi_driver" for all supported cards. + * + "capi_driver" (supported cards) now have to be configured with + * make menuconfig, in the past all supported cards where included + * at once. + * + new and better informations in /proc/capi/ + * + new ioctl to switch trace of capi messages per controller + * using "avmcapictrl trace [contr] on|off|...." + * + complete testcircle with all supported cards and also the + * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "capilli.h" +#include "avmcard.h" +#include "capicmd.h" +#include "capiutil.h" + +static char *revision = "$Revision: 1.4 $"; + +/* ------------------------------------------------------------- */ + +MODULE_AUTHOR("Carsten Paeth "); + +/* ------------------------------------------------------------- */ + +int b1_irq_table[16] = +{0, + 0, + 0, + 192, /* irq 3 */ + 32, /* irq 4 */ + 160, /* irq 5 */ + 96, /* irq 6 */ + 224, /* irq 7 */ + 0, + 64, /* irq 9 */ + 80, /* irq 10 */ + 208, /* irq 11 */ + 48, /* irq 12 */ + 0, + 0, + 112, /* irq 15 */ +}; + +/* ------------------------------------------------------------- */ + +int b1_detect(unsigned int base, enum avmcardtype cardtype) +{ + int onoff, i; + + /* + * Statusregister 0000 00xx + */ + if ((inb(base + B1_INSTAT) & 0xfc) + || (inb(base + B1_OUTSTAT) & 0xfc)) + return 1; + /* + * Statusregister 0000 001x + */ + b1outp(base, B1_INSTAT, 0x2); /* enable irq */ + /* b1outp(base, B1_OUTSTAT, 0x2); */ + if ((inb(base + B1_INSTAT) & 0xfe) != 0x2 + /* || (inb(base + B1_OUTSTAT) & 0xfe) != 0x2 */) + return 2; + /* + * Statusregister 0000 000x + */ + b1outp(base, B1_INSTAT, 0x0); /* disable irq */ + b1outp(base, B1_OUTSTAT, 0x0); + if ((inb(base + B1_INSTAT) & 0xfe) + || (inb(base + B1_OUTSTAT) & 0xfe)) + return 3; + + for (onoff = !0, i= 0; i < 10 ; i++) { + b1_set_test_bit(base, cardtype, onoff); + if (b1_get_test_bit(base, cardtype) != onoff) + return 4; + onoff = !onoff; + } + + if (cardtype == avm_m1) + return 0; + + if ((b1_rd_reg(base, B1_STAT1(cardtype)) & 0x0f) != 0x01) + return 5; + + return 0; +} + +int b1_load_t4file(unsigned int base, capiloaddatapart * t4file) +{ + unsigned char buf[256]; + unsigned char *dp; + int i, left, retval; + + dp = t4file->data; + left = t4file->len; + while (left > sizeof(buf)) { + if (t4file->user) { + retval = copy_from_user(buf, dp, sizeof(buf)); + if (retval) + return -EFAULT; + } else { + memcpy(buf, dp, sizeof(buf)); + } + for (i = 0; i < sizeof(buf); i++) + if (b1_save_put_byte(base, buf[i]) < 0) { + printk(KERN_ERR "b1_load_t4file: corrupted t4 file ?\n"); + return -EIO; + } + left -= sizeof(buf); + dp += sizeof(buf); + } + if (left) { + if (t4file->user) { + retval = copy_from_user(buf, dp, left); + if (retval) + return -EFAULT; + } else { + memcpy(buf, dp, left); + } + for (i = 0; i < left; i++) + if (b1_save_put_byte(base, buf[i]) < 0) { + printk(KERN_ERR "b1_load_t4file: corrupted t4 file ?\n"); + return -EIO; + } + } + return 0; +} + +int b1_load_config(unsigned int base, capiloaddatapart * config) +{ + unsigned char buf[256]; + unsigned char *dp; + int i, j, left, retval; + + dp = config->data; + left = config->len; + if (left) { + b1_put_byte(base, SEND_CONFIG); + b1_put_word(base, 1); + b1_put_byte(base, SEND_CONFIG); + b1_put_word(base, left); + } + while (left > sizeof(buf)) { + if (config->user) { + retval = copy_from_user(buf, dp, sizeof(buf)); + if (retval) + return -EFAULT; + } else { + memcpy(buf, dp, sizeof(buf)); + } + for (i = 0; i < sizeof(buf); ) { + b1_put_byte(base, SEND_CONFIG); + for (j=0; j < 4; j++) { + b1_put_byte(base, buf[i++]); + } + } + left -= sizeof(buf); + dp += sizeof(buf); + } + if (left) { + if (config->user) { + retval = copy_from_user(buf, dp, left); + if (retval) + return -EFAULT; + } else { + memcpy(buf, dp, left); + } + for (i = 0; i < left; ) { + b1_put_byte(base, SEND_CONFIG); + for (j=0; j < 4; j++) { + if (i < left) + b1_put_byte(base, buf[i++]); + else + b1_put_byte(base, 0); + } + } + } + return 0; +} + +int b1_loaded(unsigned int base) +{ + unsigned long stop; + unsigned char ans; + unsigned long tout = 2; + + for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) { + if (b1_tx_empty(base)) + break; + } + if (!b1_tx_empty(base)) { + printk(KERN_ERR "b1_loaded: tx err, corrupted t4 file ?\n"); + return 0; + } + b1_put_byte(base, SEND_POLL); + for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) { + if (b1_rx_full(base)) { + if ((ans = b1_get_byte(base)) == RECEIVE_POLL) { + return 1; + } + printk(KERN_ERR "b1_loaded: got 0x%x, firmware not running\n", ans); + return 0; + } + } + printk(KERN_ERR "b1_loaded: firmware not running\n"); + return 0; +} + +/* ------------------------------------------------------------- */ + +int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) +{ + avmcard *card = (avmcard *)(ctrl->driverdata); + unsigned int port = card->port; + unsigned long flags; + int retval; + + b1_reset(port); + + if ((retval = b1_load_t4file(port, &data->firmware))) { + b1_reset(port); + printk(KERN_ERR "%s: failed to load t4file!!\n", + card->name); + return retval; + } + + b1_disable_irq(port); + + if (data->configuration.len > 0 && data->configuration.data) { + if ((retval = b1_load_config(port, &data->configuration))) { + b1_reset(port); + printk(KERN_ERR "%s: failed to load config!!\n", + card->name); + return retval; + } + } + + if (!b1_loaded(port)) { + printk(KERN_ERR "%s: failed to load t4file.\n", card->name); + return -EIO; + } + + save_flags(flags); + cli(); + b1_setinterrupt(port, card->irq, card->cardtype); + b1_put_byte(port, SEND_INIT); + b1_put_word(port, AVM_NAPPS); + b1_put_word(port, AVM_NCCI_PER_CHANNEL*2); + b1_put_word(port, ctrl->cnr - 1); + restore_flags(flags); + + return 0; +} + +void b1_reset_ctr(struct capi_ctr *ctrl) +{ + avmcard *card = (avmcard *)(ctrl->driverdata); + unsigned int port = card->port; + + b1_reset(port); + b1_reset(port); + + memset(card->version, 0, sizeof(card->version)); + ctrl->reseted(ctrl); +} + +void b1_register_appl(struct capi_ctr *ctrl, + __u16 appl, + capi_register_params *rp) +{ + avmcard *card = (avmcard *)(ctrl->driverdata); + unsigned int port = card->port; + unsigned long flags; + int nconn, want = rp->level3cnt; + + if (want > 0) nconn = want; + else nconn = ctrl->profile.nbchannel * -want; + if (nconn == 0) nconn = ctrl->profile.nbchannel; + + save_flags(flags); + cli(); + b1_put_byte(port, SEND_REGISTER); + b1_put_word(port, appl); + b1_put_word(port, 1024 * (nconn+1)); + b1_put_word(port, nconn); + b1_put_word(port, rp->datablkcnt); + b1_put_word(port, rp->datablklen); + restore_flags(flags); + + ctrl->appl_registered(ctrl, appl); +} + +void b1_release_appl(struct capi_ctr *ctrl, __u16 appl) +{ + avmcard *card = (avmcard *)(ctrl->driverdata); + unsigned int port = card->port; + unsigned long flags; + + save_flags(flags); + cli(); + b1_put_byte(port, SEND_RELEASE); + b1_put_word(port, appl); + restore_flags(flags); +} + +void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) +{ + avmcard *card = (avmcard *)(ctrl->driverdata); + unsigned int port = card->port; + unsigned long flags; + __u16 len = CAPIMSG_LEN(skb->data); + __u8 cmd = CAPIMSG_COMMAND(skb->data); + __u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data); + + save_flags(flags); + cli(); + if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { + __u16 dlen = CAPIMSG_DATALEN(skb->data); + b1_put_byte(port, SEND_DATA_B3_REQ); + b1_put_slice(port, skb->data, len); + b1_put_slice(port, skb->data + len, dlen); + } else { + b1_put_byte(port, SEND_MESSAGE); + b1_put_slice(port, skb->data, len); + } + restore_flags(flags); + dev_kfree_skb(skb); +} + +/* ------------------------------------------------------------- */ + +void b1_parse_version(avmcard *card) +{ + struct capi_ctr *ctrl = card->ctrl; + capi_profile *profp; + __u8 *dversion; + __u8 flag; + int i, j; + + for (j = 0; j < AVM_MAXVERSION; j++) + card->version[j] = "\0\0" + 1; + for (i = 0, j = 0; + j < AVM_MAXVERSION && i < card->versionlen; + j++, i += card->versionbuf[i] + 1) + card->version[j] = &card->versionbuf[i + 1]; + + strncpy(ctrl->serial, card->version[VER_SERIAL], CAPI_SERIAL_LEN); + memcpy(&ctrl->profile, card->version[VER_PROFILE],sizeof(capi_profile)); + strncpy(ctrl->manu, "AVM GmbH", CAPI_MANUFACTURER_LEN); + dversion = card->version[VER_DRIVER]; + ctrl->version.majorversion = 2; + ctrl->version.minorversion = 0; + ctrl->version.majormanuversion = (((dversion[0] - '0') & 0xf) << 4); + ctrl->version.majormanuversion |= ((dversion[2] - '0') & 0xf); + ctrl->version.minormanuversion = (dversion[3] - '0') << 4; + ctrl->version.minormanuversion |= + (dversion[5] - '0') * 10 + ((dversion[6] - '0') & 0xf); + + profp = &ctrl->profile; + + flag = ((__u8 *)(profp->manu))[1]; + switch (flag) { + case 0: strcpy(card->cardname, "B1"); break; + case 3: strcpy(card->cardname,"PCMCIA B"); break; + case 4: strcpy(card->cardname,"PCMCIA M1"); break; + case 5: strcpy(card->cardname,"PCMCIA M2"); break; + case 6: strcpy(card->cardname,"B1 V3.0"); break; + case 7: strcpy(card->cardname,"B1 PCI"); break; + default: sprintf(card->cardname, "AVM?%u", (unsigned int)flag); break; + } + printk(KERN_NOTICE "%s: card %d \"%s\" ready.\n", + card->name, ctrl->cnr, card->cardname); + + flag = ((__u8 *)(profp->manu))[3]; + if (flag) + printk(KERN_NOTICE "b1capi: card %d Protocol:%s%s%s%s%s%s%s\n", + ctrl->cnr, + (flag & 0x01) ? " DSS1" : "", + (flag & 0x02) ? " CT1" : "", + (flag & 0x04) ? " VN3" : "", + (flag & 0x08) ? " NI1" : "", + (flag & 0x10) ? " AUSTEL" : "", + (flag & 0x20) ? " ESS" : "", + (flag & 0x40) ? " 1TR6" : "" + ); + + flag = ((__u8 *)(profp->manu))[5]; + if (flag) + printk(KERN_NOTICE "%s: card %d Linetype:%s%s%s%s\n", + card->name, + ctrl->cnr, + (flag & 0x01) ? " point to point" : "", + (flag & 0x02) ? " point to multipoint" : "", + (flag & 0x08) ? " leased line without D-channel" : "", + (flag & 0x04) ? " leased line with D-channel" : "" + ); +} + +/* ------------------------------------------------------------- */ + +void b1_handle_interrupt(avmcard * card) +{ + struct capi_ctr *ctrl = card->ctrl; + unsigned char b1cmd; + struct sk_buff *skb; + + unsigned ApplId; + unsigned MsgLen; + unsigned DataB3Len; + unsigned NCCI; + unsigned WindowSize; + + if (!b1_rx_full(card->port)) + return; + + b1cmd = b1_get_byte(card->port); + + switch (b1cmd) { + + case RECEIVE_DATA_B3_IND: + + ApplId = (unsigned) b1_get_word(card->port); + MsgLen = b1_get_slice(card->port, card->msgbuf); + DataB3Len = b1_get_slice(card->port, card->databuf); + + if (!(skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC))) { + printk(KERN_ERR "%s: incoming packet dropped\n", + card->name); + } else { + memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); + memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len); + CAPIMSG_SETDATA(skb->data, skb->data + MsgLen); + ctrl->handle_capimsg(ctrl, ApplId, skb); + } + break; + + case RECEIVE_MESSAGE: + + ApplId = (unsigned) b1_get_word(card->port); + MsgLen = b1_get_slice(card->port, card->msgbuf); + if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { + printk(KERN_ERR "%s: incoming packet dropped\n", + card->name); + } else { + memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); + ctrl->handle_capimsg(ctrl, ApplId, skb); + } + break; + + case RECEIVE_NEW_NCCI: + + ApplId = b1_get_word(card->port); + NCCI = b1_get_word(card->port); + WindowSize = b1_get_word(card->port); + + ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize); + + break; + + case RECEIVE_FREE_NCCI: + + ApplId = b1_get_word(card->port); + NCCI = b1_get_word(card->port); + + if (NCCI != 0xffffffff) + ctrl->free_ncci(ctrl, ApplId, NCCI); + else ctrl->appl_released(ctrl, ApplId); + break; + + case RECEIVE_START: + /* b1_put_byte(card->port, SEND_POLLACK); */ + ctrl->resume_output(ctrl); + break; + + case RECEIVE_STOP: + ctrl->suspend_output(ctrl); + break; + + case RECEIVE_INIT: + + card->versionlen = b1_get_slice(card->port, card->versionbuf); + b1_parse_version(card); + printk(KERN_INFO "%s: %s-card (%s) now active\n", + card->name, + card->version[VER_CARDTYPE], + card->version[VER_DRIVER]); + ctrl->ready(ctrl); + break; + + case RECEIVE_TASK_READY: + ApplId = (unsigned) b1_get_word(card->port); + MsgLen = b1_get_slice(card->port, card->msgbuf); + card->msgbuf[MsgLen--] = 0; + while ( MsgLen >= 0 + && ( card->msgbuf[MsgLen] == '\n' + || card->msgbuf[MsgLen] == '\r')) + card->msgbuf[MsgLen--] = 0; + printk(KERN_INFO "%s: task %d \"%s\" ready.\n", + card->name, ApplId, card->msgbuf); + break; + + case RECEIVE_DEBUGMSG: + MsgLen = b1_get_slice(card->port, card->msgbuf); + card->msgbuf[MsgLen--] = 0; + while ( MsgLen >= 0 + && ( card->msgbuf[MsgLen] == '\n' + || card->msgbuf[MsgLen] == '\r')) + card->msgbuf[MsgLen--] = 0; + printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf); + break; + + case 0xff: + printk(KERN_ERR "%s: card removed ?\n", card->name); + return; + default: + printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n", + card->name, b1cmd); + return; + } +} + +/* ------------------------------------------------------------- */ +int b1ctl_read_proc(char *page, char **start, off_t off, + int count, int *eof, struct capi_ctr *ctrl) +{ + avmcard *card = (avmcard *)(ctrl->driverdata); + __u8 flag; + int len = 0; + char *s; + + len += sprintf(page+len, "%-16s %s\n", "name", card->name); + len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port); + len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); + switch (card->cardtype) { + case avm_b1isa: s = "B1 ISA"; break; + case avm_b1pci: s = "B1 PCI"; break; + case avm_b1pcmcia: s = "B1 PCMCIA"; break; + case avm_m1: s = "M1"; break; + case avm_m2: s = "M2"; break; + case avm_t1isa: s = "T1 ISA (HEMA)"; break; + case avm_t1pci: s = "T1 PCI"; break; + default: s = "???"; break; + } + len += sprintf(page+len, "%-16s %s\n", "type", s); + if (card->cardtype == avm_t1isa) + len += sprintf(page+len, "%-16s %d\n", "cardnr", card->cardnr); + if ((s = card->version[VER_DRIVER]) != 0) + len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); + if ((s = card->version[VER_CARDTYPE]) != 0) + len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); + if ((s = card->version[VER_SERIAL]) != 0) + len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); + + if (card->cardtype != avm_m1) { + flag = ((__u8 *)(ctrl->profile.manu))[3]; + if (flag) + len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n", + "protocol", + (flag & 0x01) ? " DSS1" : "", + (flag & 0x02) ? " CT1" : "", + (flag & 0x04) ? " VN3" : "", + (flag & 0x08) ? " NI1" : "", + (flag & 0x10) ? " AUSTEL" : "", + (flag & 0x20) ? " ESS" : "", + (flag & 0x40) ? " 1TR6" : "" + ); + } + if (card->cardtype != avm_m1) { + flag = ((__u8 *)(ctrl->profile.manu))[5]; + if (flag) + len += sprintf(page+len, "%-16s%s%s%s%s\n", + "linetype", + (flag & 0x01) ? " point to point" : "", + (flag & 0x02) ? " point to multipoint" : "", + (flag & 0x08) ? " leased line without D-channel" : "", + (flag & 0x04) ? " leased line with D-channel" : "" + ); + } + len += sprintf(page+len, "%-16s %s\n", "cardname", card->cardname); + + if (len < off) + return 0; + *eof = 1; + *start = page - off; + return ((count < len-off) ? count : len-off); + if (len < off) + return 0; + *eof = 1; + *start = page - off; + return ((count < len-off) ? count : len-off); +} + +/* ------------------------------------------------------------- */ + +EXPORT_SYMBOL(b1_irq_table); + +EXPORT_SYMBOL(b1_detect); +EXPORT_SYMBOL(b1_load_t4file); +EXPORT_SYMBOL(b1_load_config); +EXPORT_SYMBOL(b1_loaded); +EXPORT_SYMBOL(b1_load_firmware); +EXPORT_SYMBOL(b1_reset_ctr); +EXPORT_SYMBOL(b1_register_appl); +EXPORT_SYMBOL(b1_release_appl); +EXPORT_SYMBOL(b1_send_message); + +EXPORT_SYMBOL(b1_parse_version); +EXPORT_SYMBOL(b1_handle_interrupt); + +EXPORT_SYMBOL(b1ctl_read_proc); + +#ifdef MODULE +#define b1_init init_module +void cleanup_module(void); +#endif + +int b1_init(void) +{ + char *p; + char rev[10]; + + if ((p = strchr(revision, ':'))) { + strncpy(rev, p + 1, sizeof(rev)); + p = strchr(rev, '$'); + *p = 0; + } else + strcpy(rev, "1.0"); + + printk(KERN_INFO "b1: revision %s\n", rev); + + return 0; +} + +#ifdef MODULE +void cleanup_module(void) +{ +} +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/b1capi.c linux.pre11.3/drivers/isdn/avmb1/b1capi.c --- linux.vanilla/drivers/isdn/avmb1/b1capi.c Sun Nov 8 15:10:14 1998 +++ linux.pre11.3/drivers/isdn/avmb1/b1capi.c Mon Jul 19 23:59:32 1999 @@ -1,1141 +0,0 @@ -/* - * $Id: b1capi.c,v 1.10 1998/02/13 07:09:10 calle Exp $ - * - * CAPI 2.0 Module for AVM B1-card. - * - * (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log: b1capi.c,v $ - * Revision 1.10 1998/02/13 07:09:10 calle - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.9 1998/01/31 11:14:39 calle - * merged changes to 2.0 tree, prepare 2.1.82 to work. - * - * Revision 1.8 1997/12/10 20:00:46 calle - * get changes from 2.0 version - * - * Revision 1.4.2.5 1997/12/07 19:59:54 calle - * more changes for M1/T1/B1 + config - * - * Revision 1.4.2.4 1997/11/26 16:57:20 calle - * more changes for B1/M1/T1. - * - * Revision 1.7 1997/10/19 14:45:40 calle - * fixed capi_get_version. - * - * Revision 1.6 1997/10/01 09:21:09 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.5 1997/07/12 08:22:26 calle - * Correct bug in CARD_NR macro, so now more than one card will work. - * Allow card reset, even if card is in running state. - * - * - * Revision 1.4 1997/05/27 15:17:45 fritz - * Added changes for recent 2.1.x kernels: - * changed return type of isdn_close - * queue_task_* -> queue_task - * clear/set_bit -> test_and_... where apropriate. - * changed type of hard_header_cache parameter. - * - * Revision 1.3 1997/05/18 09:24:09 calle - * added verbose disconnect reason reporting to avmb1. - * some fixes in capi20 interface. - * changed info messages for B1-PCI - * - * Revision 1.2 1997/03/05 21:20:41 fritz - * Removed include of config.h (mkdep stated this is unneded). - * - * Revision 1.1 1997/03/04 21:50:27 calle - * Frirst version in isdn4linux - * - * Revision 2.2 1997/02/12 09:31:39 calle - * new version - * - * Revision 1.1 1997/01/31 10:32:20 calle - * Initial revision - * - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "compat.h" -#include "capicmd.h" -#include "capiutil.h" - -static char *revision = "$Revision: 1.10 $"; - -/* ------------------------------------------------------------- */ - -int showcapimsgs = 0; /* used in lli.c */ -int loaddebug = 0; - -MODULE_AUTHOR("Carsten Paeth "); -MODULE_PARM(showcapimsgs, "0-3i"); -MODULE_PARM(loaddebug, "0-1i"); - -/* ------------------------------------------------------------- */ - -struct msgidqueue { - struct msgidqueue *next; - __u16 msgid; -}; - -typedef struct avmb1_ncci { - struct avmb1_ncci *next; - __u16 applid; - __u32 ncci; - __u32 winsize; - struct msgidqueue *msgidqueue; - struct msgidqueue *msgidlast; - struct msgidqueue *msgidfree; - struct msgidqueue msgidpool[CAPI_MAXDATAWINDOW]; -} avmb1_ncci; - -typedef struct avmb1_appl { - __u16 applid; - capi_register_params rparam; - int releasing; - __u32 param; - void (*signal) (__u16 applid, __u32 param); - struct sk_buff_head recv_queue; - struct avmb1_ncci *nccilist; -} avmb1_appl; - -/* ------------------------------------------------------------- */ - -static struct capi_version driver_version = {2, 0, 1, 1<<4}; -static char driver_serial[CAPI_SERIAL_LEN] = "4711"; -static char capi_manufakturer[64] = "AVM Berlin"; - -#define APPL(a) (&applications[(a)-1]) -#define VALID_APPLID(a) ((a) && (a) <= CAPI_MAXAPPL && APPL(a)->applid == a) -#define APPL_IS_FREE(a) (APPL(a)->applid == 0) -#define APPL_MARK_FREE(a) do{ APPL(a)->applid=0; MOD_DEC_USE_COUNT; }while(0); -#define APPL_MARK_USED(a) do{ APPL(a)->applid=(a); MOD_INC_USE_COUNT; }while(0); - -#define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f) - -#define VALID_CARD(c) ((c) > 0 && (c) <= CAPI_MAXCONTR) -#define CARD(c) (&cards[(c)-1]) -#define CARDNR(cp) (((cp)-cards)+1) - -static avmb1_appl applications[CAPI_MAXAPPL]; -static avmb1_card cards[CAPI_MAXCONTR]; -static int ncards = 0; -static struct sk_buff_head recv_queue; -static struct capi_interface_user *capi_users = 0; -static long notify_up_set = 0; -static long notify_down_set = 0; - -static struct tq_struct tq_state_notify; -static struct tq_struct tq_recv_notify; - -/* -------- util functions ------------------------------------ */ - -static char *cardtype2str(int cardtype) -{ - switch (cardtype) { - default: - case AVM_CARDTYPE_B1: return "B1"; - case AVM_CARDTYPE_M1: return "M1"; - case AVM_CARDTYPE_M2: return "M2"; - case AVM_CARDTYPE_T1: return "T1"; - } -} - -static inline int capi_cmd_valid(__u8 cmd) -{ - switch (cmd) { - case CAPI_ALERT: - case CAPI_CONNECT: - case CAPI_CONNECT_ACTIVE: - case CAPI_CONNECT_B3_ACTIVE: - case CAPI_CONNECT_B3: - case CAPI_CONNECT_B3_T90_ACTIVE: - case CAPI_DATA_B3: - case CAPI_DISCONNECT_B3: - case CAPI_DISCONNECT: - case CAPI_FACILITY: - case CAPI_INFO: - case CAPI_LISTEN: - case CAPI_MANUFACTURER: - case CAPI_RESET_B3: - case CAPI_SELECT_B_PROTOCOL: - return 1; - } - return 0; -} - -static inline int capi_subcmd_valid(__u8 subcmd) -{ - switch (subcmd) { - case CAPI_REQ: - case CAPI_CONF: - case CAPI_IND: - case CAPI_RESP: - return 1; - } - return 0; -} - -/* -------- NCCI Handling ------------------------------------- */ - -static inline void mq_init(avmb1_ncci * np) -{ - int i; - np->msgidqueue = 0; - np->msgidlast = 0; - memset(np->msgidpool, 0, sizeof(np->msgidpool)); - np->msgidfree = &np->msgidpool[0]; - for (i = 1; i < np->winsize; i++) { - np->msgidpool[i].next = np->msgidfree; - np->msgidfree = &np->msgidpool[i]; - } -} - -static inline int mq_enqueue(avmb1_ncci * np, __u16 msgid) -{ - struct msgidqueue *mq; - if ((mq = np->msgidfree) == 0) - return 0; - np->msgidfree = mq->next; - mq->msgid = msgid; - mq->next = 0; - if (np->msgidlast) - np->msgidlast->next = mq; - np->msgidlast = mq; - if (!np->msgidqueue) - np->msgidqueue = mq; - return 1; -} - -static inline int mq_dequeue(avmb1_ncci * np, __u16 msgid) -{ - struct msgidqueue **pp; - for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) { - if ((*pp)->msgid == msgid) { - struct msgidqueue *mq = *pp; - *pp = mq->next; - if (mq == np->msgidlast) - np->msgidlast = 0; - mq->next = np->msgidfree; - np->msgidfree = mq; - return 1; - } - } - return 0; -} - -void avmb1_handle_new_ncci(avmb1_card * card, - __u16 appl, __u32 ncci, __u32 winsize) -{ - avmb1_ncci *np; - if (!VALID_APPLID(appl)) { - printk(KERN_ERR "avmb1_handle_new_ncci: illegal appl %d\n", appl); - return; - } - if ((np = (avmb1_ncci *) kmalloc(sizeof(avmb1_ncci), GFP_ATOMIC)) == 0) { - printk(KERN_ERR "avmb1_handle_new_ncci: alloc failed ncci 0x%x\n", ncci); - return; - } - if (winsize > CAPI_MAXDATAWINDOW) { - printk(KERN_ERR "avmb1_handle_new_ncci: winsize %d too big, set to %d\n", - winsize, CAPI_MAXDATAWINDOW); - winsize = CAPI_MAXDATAWINDOW; - } - np->applid = appl; - np->ncci = ncci; - np->winsize = winsize; - mq_init(np); - np->next = APPL(appl)->nccilist; - APPL(appl)->nccilist = np; - printk(KERN_INFO "b1capi: appl %d ncci 0x%x up\n", appl, ncci); - -} - -void avmb1_handle_free_ncci(avmb1_card * card, - __u16 appl, __u32 ncci) -{ - if (!VALID_APPLID(appl)) { - printk(KERN_ERR "avmb1_handle_free_ncci: illegal appl %d\n", appl); - return; - } - if (ncci != 0xffffffff) { - avmb1_ncci **pp; - for (pp = &APPL(appl)->nccilist; *pp; pp = &(*pp)->next) { - if ((*pp)->ncci == ncci) { - avmb1_ncci *np = *pp; - *pp = np->next; - kfree(np); - printk(KERN_INFO "b1capi: appl %d ncci 0x%x down\n", appl, ncci); - return; - } - } - printk(KERN_ERR "avmb1_handle_free_ncci: ncci 0x%x not found\n", ncci); - } else { - avmb1_ncci **pp, **nextpp; - for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) { - if (NCCI2CTRL((*pp)->ncci) == card->cnr) { - avmb1_ncci *np = *pp; - *pp = np->next; - printk(KERN_INFO "b1capi: appl %d ncci 0x%x down!\n", appl, np->ncci); - kfree(np); - nextpp = pp; - } else { - nextpp = &(*pp)->next; - } - } - APPL(appl)->releasing--; - if (APPL(appl)->releasing == 0) { - APPL(appl)->signal = 0; - APPL_MARK_FREE(appl); - printk(KERN_INFO "b1capi: appl %d down\n", appl); - } - } -} - -static avmb1_ncci *find_ncci(avmb1_appl * app, __u32 ncci) -{ - avmb1_ncci *np; - for (np = app->nccilist; np; np = np->next) { - if (np->ncci == ncci) - return np; - } - return 0; -} - - - -/* -------- Receiver ------------------------------------------ */ - - -static void recv_handler(void *dummy) -{ - struct sk_buff *skb; - - while ((skb = skb_dequeue(&recv_queue)) != 0) { - __u16 appl = CAPIMSG_APPID(skb->data); - struct avmb1_ncci *np; - if (!VALID_APPLID(appl)) { - printk(KERN_ERR "b1capi: recv_handler: applid %d ? (%s)\n", - appl, capi_message2str(skb->data)); - kfree_skb(skb); - continue; - } - if (APPL(appl)->signal == 0) { - printk(KERN_ERR "b1capi: recv_handler: applid %d has no signal function\n", - appl); - kfree_skb(skb); - continue; - } - if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3 - && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF - && (np = find_ncci(APPL(appl), CAPIMSG_NCCI(skb->data))) != 0 - && mq_dequeue(np, CAPIMSG_MSGID(skb->data)) == 0) { - printk(KERN_ERR "b1capi: msgid %hu ncci 0x%x not on queue\n", - CAPIMSG_MSGID(skb->data), np->ncci); - } - skb_queue_tail(&APPL(appl)->recv_queue, skb); - (APPL(appl)->signal) (APPL(appl)->applid, APPL(appl)->param); - } -} - - -void avmb1_handle_capimsg(avmb1_card * card, __u16 appl, struct sk_buff *skb) -{ - if (card->cardstate != CARD_RUNNING) { - printk(KERN_INFO "b1capi: controller %d not active, got: %s", - card->cnr, capi_message2str(skb->data)); - goto error; - return; - } - skb_queue_tail(&recv_queue, skb); - queue_task(&tq_recv_notify, &tq_immediate); - mark_bh(IMMEDIATE_BH); - return; - - error: - kfree_skb(skb); -} - -void avmb1_interrupt(int interrupt, void *devptr, struct pt_regs *regs) -{ - avmb1_card *card; - - card = (avmb1_card *) devptr; - - if (!card) { - printk(KERN_WARNING "avmb1_interrupt: wrong device\n"); - return; - } - if (card->interrupt) { - printk(KERN_ERR "avmb1_interrupt: reentering interrupt hander\n"); - return; - } - - card->interrupt = 1; - - B1_handle_interrupt(card); - - card->interrupt = 0; -} - -/* -------- Notifier ------------------------------------------ */ - -static void notify_up(__u16 contr) -{ - struct capi_interface_user *p; - - printk(KERN_NOTICE "b1capi: notify up contr %d\n", contr); - for (p = capi_users; p; p = p->next) { - if (p->callback) - (*p->callback) (KCI_CONTRUP, contr, - (capi_profile *) - CARD(contr)->version[VER_PROFILE]); - } -} - -static void notify_down(__u16 contr) -{ - struct capi_interface_user *p; - printk(KERN_NOTICE "b1capi: notify down contr %d\n", contr); - for (p = capi_users; p; p = p->next) { - if (p->callback) - (*p->callback) (KCI_CONTRDOWN, contr, 0); - } -} - -static void notify_handler(void *dummy) -{ - __u16 contr; - - for (contr=1; VALID_CARD(contr); contr++) - if (test_and_clear_bit(contr, ¬ify_up_set)) - notify_up(contr); - for (contr=1; VALID_CARD(contr); contr++) - if (test_and_clear_bit(contr, ¬ify_down_set)) - notify_down(contr); -} - -/* -------- card ready callback ------------------------------- */ - -void avmb1_card_ready(avmb1_card * card) -{ - struct capi_profile *profp = - (struct capi_profile *)card->version[VER_PROFILE]; - char *dversion = card->version[VER_DRIVER]; - __u16 appl; - char *cardname, cname[20]; - __u32 flag; - - card->cversion.majorversion = 2; - card->cversion.minorversion = 0; - card->cversion.majormanuversion = (((dversion[0] - '0') & 0xf) << 4); - card->cversion.majormanuversion |= ((dversion[2] - '0') & 0xf); - card->cversion.minormanuversion = (dversion[3] - '0') << 4; - card->cversion.minormanuversion |= - (dversion[5] - '0') * 10 + ((dversion[6] - '0') & 0xf); - card->cardstate = CARD_RUNNING; - - for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { - if (VALID_APPLID(appl) && !APPL(appl)->releasing) { - B1_send_register(card->port, appl, - 1024 * (APPL(appl)->rparam.level3cnt+1), - APPL(appl)->rparam.level3cnt, - APPL(appl)->rparam.datablkcnt, - APPL(appl)->rparam.datablklen); - } - } - - set_bit(CARDNR(card), ¬ify_up_set); - queue_task(&tq_state_notify, &tq_scheduler); - - flag = ((__u8 *)(profp->manu))[1]; - switch (flag) { - case 0: cardname = cardtype2str(card->cardtype); break; - case 3: cardname = "PCMCIA B"; break; - case 4: cardname = "PCMCIA M1"; break; - case 5: cardname = "PCMCIA M2"; break; - case 6: cardname = "B1 V3.0"; break; - case 7: cardname = "B1 PCI"; break; - default: cardname = cname; break; - sprintf(cname, "AVM?%u", (unsigned int)flag); - break; - } - printk(KERN_NOTICE "b1capi: card %d \"%s\" ready.\n", - CARDNR(card), cardname); - flag = ((__u8 *)(profp->manu))[3]; - if (flag) - printk(KERN_NOTICE "b1capi: card %d Protocol:%s%s%s%s%s%s%s\n", - CARDNR(card), - (flag & 0x01) ? " DSS1" : "", - (flag & 0x02) ? " CT1" : "", - (flag & 0x04) ? " VN3" : "", - (flag & 0x08) ? " NI1" : "", - (flag & 0x10) ? " AUSTEL" : "", - (flag & 0x20) ? " ESS" : "", - (flag & 0x40) ? " 1TR6" : "" - ); - flag = ((__u8 *)(profp->manu))[5]; - if (flag) - printk(KERN_NOTICE "b1capi: card %d Linetype:%s%s%s%s\n", - CARDNR(card), - (flag & 0x01) ? " point to point" : "", - (flag & 0x02) ? " point to multipoint" : "", - (flag & 0x08) ? " leased line without D-channel" : "", - (flag & 0x04) ? " leased line with D-channel" : "" - ); -} - -static void avmb1_card_down(avmb1_card * card, int notify) -{ - __u16 appl; - - card->cardstate = CARD_DETECTED; - - for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { - avmb1_ncci **pp, **nextpp; - for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) { - if (NCCI2CTRL((*pp)->ncci) == card->cnr) { - avmb1_ncci *np = *pp; - *pp = np->next; - printk(KERN_INFO "b1capi: appl %d ncci 0x%x forced down!\n", appl, np->ncci); - kfree(np); - nextpp = pp; - } else { - nextpp = &(*pp)->next; - } - } - } - set_bit(CARDNR(card), ¬ify_down_set); - queue_task(&tq_state_notify, &tq_scheduler); - printk(KERN_NOTICE "b1capi: card %d down.\n", CARDNR(card)); -} - -/* ------------------------------------------------------------- */ - - -int avmb1_registercard(int port, int irq, int cardtype, int allocio) -{ - struct avmb1_card *card; - int irqval,i; - - - for (i=0; i < CAPI_MAXCONTR && cards[i].cardstate != CARD_FREE; i++) ; - - if (i == CAPI_MAXCONTR) { - printk(KERN_ERR "b1capi: out of controller slots\n"); - return -ENFILE; - } - - card = &cards[i]; - memset(card, 0, sizeof(avmb1_card)); - sprintf(card->name, "avmb1-%d", CARDNR(card)); - - if (allocio) - request_region(port, AVMB1_PORTLEN, card->name); - - if ((irqval = request_irq(irq, avmb1_interrupt, - SA_SHIRQ, card->name, card)) != 0) { - printk(KERN_ERR "b1capi: unable to get IRQ %d (irqval=%d).\n", - irq, irqval); - release_region((unsigned short) port, AVMB1_PORTLEN); - return -EIO; - } - - card->cardstate = CARD_DETECTED; - ncards++; - card->cnr = CARDNR(card); - card->port = port; - card->irq = irq; - card->cardtype = cardtype; - return card->cnr; -} - -int avmb1_addcard(int port, int irq, int cardtype) -{ - return avmb1_registercard(port, irq, cardtype, 1); -} - -int avmb1_detectcard(int port, int irq, int cardtype) -{ - int rc; - - if (!B1_valid_irq(irq, cardtype)) { - printk(KERN_WARNING "b1capi: irq %d not valid for %s-card.\n", - irq, cardtype2str(cardtype)); - return -EIO; - } - if ((rc = B1_detect(port, cardtype)) != 0) { - printk(KERN_NOTICE "b1capi: NO %s-card at 0x%x (%d)\n", - cardtype2str(cardtype), port, rc); - return -EIO; - } - B1_reset(port); - switch (cardtype) { - default: - case AVM_CARDTYPE_M1: - case AVM_CARDTYPE_M2: - case AVM_CARDTYPE_B1: - printk(KERN_NOTICE "b1capi: AVM-%s-Controller detected at 0x%x\n", cardtype2str(cardtype), port); - break; - case AVM_CARDTYPE_T1: - printk(KERN_NOTICE "b1capi: AVM-%s-Controller may be at 0x%x\n", cardtype2str(cardtype), port); - break; - } - - return 0; -} - -int avmb1_probecard(int port, int irq, int cardtype) -{ - if (check_region((unsigned short) port, AVMB1_PORTLEN)) { - printk(KERN_WARNING - "b1capi: ports 0x%03x-0x%03x in use.\n", - port, port + AVMB1_PORTLEN); - return -EIO; - } - return avmb1_detectcard(port, irq, cardtype); -} - -int avmb1_unregistercard(int cnr, int freeio) -{ - avmb1_card * card; - if (!VALID_CARD(cnr)) - return -ESRCH; - card = CARD(cnr); - if (card->cardstate == CARD_FREE) - return -ESRCH; - if (card->cardstate == CARD_RUNNING) - avmb1_card_down(card, freeio); - - free_irq(card->irq, card); - if (freeio) - release_region(card->port, AVMB1_PORTLEN); - card->cardstate = CARD_FREE; - return 0; -} - -int avmb1_resetcard(int cnr) -{ - avmb1_card * card; - - if (!VALID_CARD(cnr)) - return -ESRCH; - card = CARD(cnr); - if (card->cardstate == CARD_FREE) - return -ESRCH; - - if (card->cardstate == CARD_RUNNING) - avmb1_card_down(card, 0); - - B1_reset(card->port); - B1_reset(card->port); - - card->cardstate = CARD_DETECTED; - - return 0; -} - -/* ------------------------------------------------------------- */ -/* -------- CAPI2.0 Interface ---------------------------------- */ -/* ------------------------------------------------------------- */ - -static int capi_installed(void) -{ - int i; - for (i = 0; i < CAPI_MAXCONTR; i++) { - if (cards[i].cardstate == CARD_RUNNING) - return 1; - } - return 0; -} - -static __u16 capi_register(capi_register_params * rparam, __u16 * applidp) -{ - int i; - int appl; - - if (rparam->datablklen < 128) - return CAPI_LOGBLKSIZETOSMALL; - - for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { - if (APPL_IS_FREE(appl)) - break; - } - if (appl > CAPI_MAXAPPL) - return CAPI_TOOMANYAPPLS; - - APPL_MARK_USED(appl); - skb_queue_head_init(&APPL(appl)->recv_queue); - - memcpy(&APPL(appl)->rparam, rparam, sizeof(capi_register_params)); - - for (i = 0; i < CAPI_MAXCONTR; i++) { - if (cards[i].cardstate != CARD_RUNNING) - continue; - B1_send_register(cards[i].port, appl, - 1024 * (APPL(appl)->rparam.level3cnt + 1), - APPL(appl)->rparam.level3cnt, - APPL(appl)->rparam.datablkcnt, - APPL(appl)->rparam.datablklen); - } - *applidp = appl; - printk(KERN_INFO "b1capi: appl %d up\n", appl); - - return CAPI_NOERROR; -} - -static __u16 capi_release(__u16 applid) -{ - struct sk_buff *skb; - int i; - - if (ncards == 0) - return CAPI_REGNOTINSTALLED; - if (!VALID_APPLID(applid) || APPL(applid)->releasing) - return CAPI_ILLAPPNR; - while ((skb = skb_dequeue(&APPL(applid)->recv_queue)) != 0) - kfree_skb(skb); - for (i = 0; i < CAPI_MAXCONTR; i++) { - if (cards[i].cardstate != CARD_RUNNING) { - continue; - } - APPL(applid)->releasing++; - B1_send_release(cards[i].port, applid); - } - if (APPL(applid)->releasing == 0) { - APPL(applid)->signal = 0; - APPL_MARK_FREE(applid); - printk(KERN_INFO "b1capi: appl %d down\n", applid); - } - return CAPI_NOERROR; -} - -static __u16 capi_put_message(__u16 applid, struct sk_buff *skb) -{ - avmb1_ncci *np; - int contr; - if (ncards == 0) - return CAPI_REGNOTINSTALLED; - if (!VALID_APPLID(applid)) - return CAPI_ILLAPPNR; - if (skb->len < 12 - || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data)) - || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data))) - return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; - contr = CAPIMSG_CONTROLLER(skb->data); - if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) { - contr = 1; - if (CARD(contr)->cardstate != CARD_RUNNING) - return CAPI_REGNOTINSTALLED; - } - if (CARD(contr)->blocked) - return CAPI_SENDQUEUEFULL; - - if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3 - && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_REQ - && (np = find_ncci(APPL(applid), CAPIMSG_NCCI(skb->data))) != 0 - && mq_enqueue(np, CAPIMSG_MSGID(skb->data)) == 0) - return CAPI_SENDQUEUEFULL; - - B1_send_message(CARD(contr)->port, skb); - return CAPI_NOERROR; -} - -static __u16 capi_get_message(__u16 applid, struct sk_buff **msgp) -{ - struct sk_buff *skb; - - if (!VALID_APPLID(applid)) - return CAPI_ILLAPPNR; - if ((skb = skb_dequeue(&APPL(applid)->recv_queue)) == 0) - return CAPI_RECEIVEQUEUEEMPTY; - *msgp = skb; - return CAPI_NOERROR; -} - -static __u16 capi_set_signal(__u16 applid, - void (*signal) (__u16 applid, __u32 param), - __u32 param) -{ - if (!VALID_APPLID(applid)) - return CAPI_ILLAPPNR; - APPL(applid)->signal = signal; - APPL(applid)->param = param; - return CAPI_NOERROR; -} - -static __u16 capi_get_manufacturer(__u16 contr, __u8 buf[CAPI_MANUFACTURER_LEN]) -{ - if (contr == 0) { - strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); - return CAPI_NOERROR; - } - if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) - return 0x2002; - - strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); - return CAPI_NOERROR; -} - -static __u16 capi_get_version(__u16 contr, struct capi_version *verp) -{ - if (contr == 0) { - *verp = driver_version; - return CAPI_NOERROR; - } - if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) - return 0x2002; - - memcpy((void *) verp, &CARD(contr)->cversion, - sizeof(capi_version)); - return CAPI_NOERROR; -} - -static __u16 capi_get_serial(__u16 contr, __u8 serial[CAPI_SERIAL_LEN]) -{ - if (contr == 0) { - strncpy(serial, driver_serial, 8); - return CAPI_NOERROR; - } - if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) - return 0x2002; - - memcpy((void *) serial, CARD(contr)->version[VER_SERIAL], - CAPI_SERIAL_LEN); - serial[CAPI_SERIAL_LEN - 1] = 0; - return CAPI_NOERROR; -} - -static __u16 capi_get_profile(__u16 contr, struct capi_profile *profp) -{ - if (contr == 0) { - profp->ncontroller = ncards; - return CAPI_NOERROR; - } - if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) - return 0x2002; - - memcpy((void *) profp, CARD(contr)->version[VER_PROFILE], - sizeof(struct capi_profile)); - return CAPI_NOERROR; -} - -static int capi_manufacturer(unsigned int cmd, void *data) -{ - unsigned long flags; - avmb1_loadandconfigdef ldef; - avmb1_extcarddef cdef; - avmb1_resetdef rdef; - avmb1_getdef gdef; - avmb1_card *card; - int rc; - - switch (cmd) { - case AVMB1_ADDCARD: - case AVMB1_ADDCARD_WITH_TYPE: - if (cmd == AVMB1_ADDCARD) { - if ((rc = copy_from_user((void *) &cdef, data, - sizeof(avmb1_carddef)))) - return rc; - cdef.cardtype = AVM_CARDTYPE_B1; - } else { - if ((rc = copy_from_user((void *) &cdef, data, - sizeof(avmb1_extcarddef)))) - return rc; - } - - if ((rc = avmb1_probecard(cdef.port, cdef.irq, cdef.cardtype)) != 0) - return rc; - - return avmb1_addcard(cdef.port, cdef.irq, cdef.cardtype); - - case AVMB1_LOAD: - case AVMB1_LOAD_AND_CONFIG: - - if (cmd == AVMB1_LOAD) { - if ((rc = copy_from_user((void *) &ldef, data, - sizeof(avmb1_loaddef)))) - return rc; - ldef.t4config.len = 0; - ldef.t4config.data = 0; - } else { - if ((rc = copy_from_user((void *) &ldef, data, - sizeof(avmb1_loadandconfigdef)))) - return rc; - } - if (!VALID_CARD(ldef.contr)) - return -ESRCH; - - if (ldef.t4file.len <= 0) { - if (loaddebug) - printk(KERN_DEBUG "b1capi: load: invalid parameter length of t4file is %d ?\n", ldef.t4file.len); - return -EINVAL; - } - - card = CARD(ldef.contr); - save_flags(flags); - cli(); - if (card->cardstate != CARD_DETECTED) { - restore_flags(flags); - if (loaddebug) - printk(KERN_DEBUG "b1capi: load: contr=%d not in detect state\n", ldef.contr); - return -EBUSY; - } - card->cardstate = CARD_LOADING; - restore_flags(flags); - - if (loaddebug) { - printk(KERN_DEBUG "b1capi: load: reseting contr %d\n", - ldef.contr); - } - - B1_reset(card->port); - if ((rc = B1_load_t4file(card->port, &ldef.t4file))) { - B1_reset(card->port); - printk(KERN_ERR "b1capi: failed to load t4file!!\n"); - card->cardstate = CARD_DETECTED; - return rc; - } - B1_disable_irq(card->port); - - if (ldef.t4config.len > 0) { /* load config */ - if (loaddebug) { - printk(KERN_DEBUG "b1capi: loading config to contr %d\n", - ldef.contr); - } - if ((rc = B1_load_config(card->port, &ldef.t4config))) { - B1_reset(card->port); - printk(KERN_ERR "b1capi: failed to load config!!\n"); - card->cardstate = CARD_DETECTED; - return rc; - } - } - - if (loaddebug) { - printk(KERN_DEBUG "b1capi: load: ready contr %d: checking\n", - ldef.contr); - } - - if (!B1_loaded(card->port)) { - card->cardstate = CARD_DETECTED; - printk(KERN_ERR "b1capi: failed to load t4file.\n"); - return -EIO; - } - /* - * enable interrupt - */ - - card->cardstate = CARD_INITSTATE; - save_flags(flags); - cli(); - B1_assign_irq(card->port, card->irq, card->cardtype); - B1_enable_irq(card->port); - restore_flags(flags); - - if (loaddebug) { - printk(KERN_DEBUG "b1capi: load: irq enabled contr %d\n", - ldef.contr); - } - - /* - * init card - */ - B1_send_init(card->port, AVM_NAPPS, AVM_NNCCI, card->cnr - 1); - - if (loaddebug) { - printk(KERN_DEBUG "b1capi: load: waiting for init reply contr %d\n", - ldef.contr); - } - - while (card->cardstate != CARD_RUNNING) { - - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); /* 0.1 sec */ - - if (signal_pending(current)) - return -EINTR; - } - return 0; - - case AVMB1_RESETCARD: - if ((rc = copy_from_user((void *) &rdef, data, - sizeof(avmb1_resetdef)))) - return rc; - - return avmb1_resetcard(rdef.contr); - - case AVMB1_GET_CARDINFO: - if ((rc = copy_from_user((void *) &gdef, data, - sizeof(avmb1_getdef)))) - return rc; - - if (!VALID_CARD(gdef.contr)) - return -ESRCH; - - card = CARD(gdef.contr); - - gdef.cardstate = card->cardstate; - gdef.cardtype = card->cardtype; - - if ((rc = copy_to_user(data, (void *) &gdef, - sizeof(avmb1_getdef)))) - return rc; - - return 0; - } - return -EINVAL; -} - -struct capi_interface avmb1_interface = -{ - capi_installed, - capi_register, - capi_release, - capi_put_message, - capi_get_message, - capi_set_signal, - capi_get_manufacturer, - capi_get_version, - capi_get_serial, - capi_get_profile, - capi_manufacturer -}; - -/* ------------------------------------------------------------- */ -/* -------- Exported Functions --------------------------------- */ -/* ------------------------------------------------------------- */ - -struct capi_interface *attach_capi_interface(struct capi_interface_user *userp) -{ - struct capi_interface_user *p; - - for (p = capi_users; p; p = p->next) { - if (p == userp) { - printk(KERN_ERR "b1capi: double attach from %s\n", - userp->name); - return 0; - } - } - userp->next = capi_users; - capi_users = userp; - MOD_INC_USE_COUNT; - - return &avmb1_interface; -} - -int detach_capi_interface(struct capi_interface_user *userp) -{ - struct capi_interface_user **pp; - - for (pp = &capi_users; *pp; pp = &(*pp)->next) { - if (*pp == userp) { - *pp = userp->next; - userp->next = 0; - MOD_DEC_USE_COUNT; - return 0; - } - } - printk(KERN_ERR "b1capi: double detach from %s\n", userp->name); - return -1; -} - -/* ------------------------------------------------------------- */ -/* -------- Init & Cleanup ------------------------------------- */ -/* ------------------------------------------------------------- */ - -EXPORT_SYMBOL(attach_capi_interface); -EXPORT_SYMBOL(detach_capi_interface); -EXPORT_SYMBOL(avmb1_addcard); -EXPORT_SYMBOL(avmb1_probecard); -EXPORT_SYMBOL(avmb1_registercard); -EXPORT_SYMBOL(avmb1_unregistercard); -EXPORT_SYMBOL(avmb1_resetcard); -EXPORT_SYMBOL(avmb1_detectcard); - - -/* - * init / exit functions - */ - -#ifdef MODULE -#define avmb1_init init_module -#endif - -int avmb1_init(void) -{ - char *p; - char rev[10]; - - skb_queue_head_init(&recv_queue); - /* init_bh(CAPI_BH, do_capi_bh); */ - - tq_state_notify.routine = notify_handler; - tq_state_notify.data = 0; - - tq_recv_notify.routine = recv_handler; - tq_recv_notify.data = 0; - - - if ((p = strchr(revision, ':'))) { - strcpy(rev, p + 1); - p = strchr(rev, '$'); - *p = 0; - } else - strcpy(rev, " ??? "); - -#ifdef MODULE - printk(KERN_NOTICE "AVM-B1-CAPI-driver Rev%s: loaded\n", rev); -#else - printk(KERN_NOTICE "AVM-B1-CAPI-driver Rev%s: started\n", rev); -#endif - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ - char rev[10]; - char *p; - int i; - - if ((p = strchr(revision, ':'))) { - strcpy(rev, p + 1); - p = strchr(rev, '$'); - *p = 0; - } else { - strcpy(rev, " ??? "); - } - - for (i = 0; i < CAPI_MAXCONTR; i++) { - if (cards[i].cardstate != CARD_FREE) { - /* - * disable card - */ - B1_disable_irq(cards[i].port); - avmb1_resetcard(i+1); - /* - * free kernel resources - */ - avmb1_unregistercard(i+1, 1); - } - } - schedule(); /* execute queued tasks .... */ - printk(KERN_NOTICE "AVM-B1-CAPI-driver Rev%s: unloaded\n", rev); -} -#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/b1isa.c linux.pre11.3/drivers/isdn/avmb1/b1isa.c --- linux.vanilla/drivers/isdn/avmb1/b1isa.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/avmb1/b1isa.c Mon Jul 19 23:59:32 1999 @@ -0,0 +1,238 @@ +/* + * $Id: b1isa.c,v 1.3 1999/07/09 15:05:40 keil Exp $ + * + * Module for AVM B1 ISA-card. + * + * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) + * + * $Log: b1isa.c,v $ + * Revision 1.3 1999/07/09 15:05:40 keil + * compat.h is now isdn_compat.h + * + * Revision 1.2 1999/07/05 15:09:49 calle + * - renamed "appl_release" to "appl_released". + * - version und profile data now cleared on controller reset + * - extended /proc interface, to allow driver and controller specific + * informations to include by driver hackers. + * + * Revision 1.1 1999/07/01 15:26:27 calle + * complete new version (I love it): + * + new hardware independed "capi_driver" interface that will make it easy to: + * - support other controllers with CAPI-2.0 (i.e. USB Controller) + * - write a CAPI-2.0 for the passive cards + * - support serial link CAPI-2.0 boxes. + * + wrote "capi_driver" for all supported cards. + * + "capi_driver" (supported cards) now have to be configured with + * make menuconfig, in the past all supported cards where included + * at once. + * + new and better informations in /proc/capi/ + * + new ioctl to switch trace of capi messages per controller + * using "avmcapictrl trace [contr] on|off|...." + * + complete testcircle with all supported cards and also the + * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "capicmd.h" +#include "capiutil.h" +#include "capilli.h" +#include "avmcard.h" + +static char *revision = "$Revision: 1.3 $"; + +/* ------------------------------------------------------------- */ + +MODULE_AUTHOR("Carsten Paeth "); + +/* ------------------------------------------------------------- */ + +static struct capi_driver_interface *di; + +/* ------------------------------------------------------------- */ + +static void b1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs) +{ + avmcard *card; + + card = (avmcard *) devptr; + + if (!card) { + printk(KERN_WARNING "b1_interrupt: wrong device\n"); + return; + } + if (card->interrupt) { + printk(KERN_ERR "b1_interrupt: reentering interrupt hander (%s)\n", card->name); + return; + } + + card->interrupt = 1; + + b1_handle_interrupt(card); + + card->interrupt = 0; +} +/* ------------------------------------------------------------- */ + +static void b1isa_remove_ctr(struct capi_ctr *ctrl) +{ + avmcard *card = (avmcard *)(ctrl->driverdata); + unsigned int port = card->port; + + b1_reset(port); + b1_reset(port); + + di->detach_ctr(ctrl); + free_irq(card->irq, card); + release_region(card->port, AVMB1_PORTLEN); + kfree(card); + + MOD_DEC_USE_COUNT; +} + +/* ------------------------------------------------------------- */ + +static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) +{ + avmcard *card; + int retval; + + card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); + + if (!card) { + printk(KERN_WARNING "b1isa: no memory.\n"); + return -ENOMEM; + } + memset(card, 0, sizeof(avmcard)); + sprintf(card->name, "b1isa-%x", p->port); + card->port = p->port; + card->irq = p->irq; + card->cardtype = avm_b1isa; + + if (check_region(card->port, AVMB1_PORTLEN)) { + printk(KERN_WARNING + "b1isa: ports 0x%03x-0x%03x in use.\n", + card->port, card->port + AVMB1_PORTLEN); + kfree(card); + return -EBUSY; + } + if (b1_irq_table[card->irq & 0xf] == 0) { + printk(KERN_WARNING "b1isa: irq %d not valid.\n", card->irq); + kfree(card); + return -EINVAL; + } + if ( card->port != 0x150 && card->port != 0x250 + && card->port != 0x300 && card->port != 0x340) { + printk(KERN_WARNING "b1isa: illegal port 0x%x.\n", card->port); + kfree(card); + return -EINVAL; + } + b1_reset(card->port); + if ((retval = b1_detect(card->port, card->cardtype)) != 0) { + printk(KERN_NOTICE "b1isa: NO card at 0x%x (%d)\n", + card->port, retval); + kfree(card); + return -EIO; + } + b1_reset(card->port); + + request_region(p->port, AVMB1_PORTLEN, card->name); + + retval = request_irq(card->irq, b1isa_interrupt, 0, card->name, card); + if (retval) { + printk(KERN_ERR "b1isa: unable to get IRQ %d.\n", card->irq); + release_region(card->port, AVMB1_PORTLEN); + kfree(card); + return -EBUSY; + } + + card->ctrl = di->attach_ctr(driver, card->name, card); + if (!card->ctrl) { + printk(KERN_ERR "b1isa: attach controller failed.\n"); + free_irq(card->irq, card); + release_region(card->port, AVMB1_PORTLEN); + kfree(card); + return -EBUSY; + } + + MOD_INC_USE_COUNT; + return 0; +} + +static char *b1isa_procinfo(struct capi_ctr *ctrl) +{ + avmcard *card = (avmcard *)(ctrl->driverdata); + if (!card) + return ""; + sprintf(card->infobuf, "%s %s 0x%x %d", + card->cardname[0] ? card->cardname : "-", + card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-", + card->port, card->irq + ); + return card->infobuf; +} + +/* ------------------------------------------------------------- */ + +static struct capi_driver b1isa_driver = { + "b1isa", + "0.0", + b1_load_firmware, + b1_reset_ctr, + b1isa_remove_ctr, + b1_register_appl, + b1_release_appl, + b1_send_message, + + b1isa_procinfo, + b1ctl_read_proc, + 0, /* use standard driver_read_proc */ + + b1isa_add_card, +}; + +#ifdef MODULE +#define b1isa_init init_module +void cleanup_module(void); +#endif + +int b1isa_init(void) +{ + struct capi_driver *driver = &b1isa_driver; + char *p; + + if ((p = strchr(revision, ':'))) { + strncpy(driver->revision, p + 1, sizeof(driver->revision)); + p = strchr(driver->revision, '$'); + *p = 0; + } + + printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision); + + di = attach_capi_driver(driver); + + if (!di) { + printk(KERN_ERR "%s: failed to attach capi_driver\n", + driver->name); + return -EIO; + } + return 0; +} + +#ifdef MODULE +void cleanup_module(void) +{ + detach_capi_driver(&b1isa_driver); +} +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/b1lli.c linux.pre11.3/drivers/isdn/avmb1/b1lli.c --- linux.vanilla/drivers/isdn/avmb1/b1lli.c Mon Dec 28 23:09:42 1998 +++ linux.pre11.3/drivers/isdn/avmb1/b1lli.c Mon Jul 19 23:59:32 1999 @@ -1,749 +0,0 @@ -/* - * $Id: b1lli.c,v 1.6 1998/02/13 07:09:11 calle Exp $ - * - * ISDN lowlevel-module for AVM B1-card. - * - * (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log: b1lli.c,v $ - * Revision 1.6 1998/02/13 07:09:11 calle - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.5 1998/01/31 11:14:41 calle - * merged changes to 2.0 tree, prepare 2.1.82 to work. - * - * Revision 1.4 1997/12/10 20:00:48 calle - * get changes from 2.0 version - * - * Revision 1.1.2.2 1997/11/26 10:46:55 calle - * prepared for M1 (Mobile) and T1 (PMX) cards. - * prepared to set configuration after load to support other D-channel - * protocols, point-to-point and leased lines. - * - * Revision 1.3 1997/10/01 09:21:13 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.2 1997/07/13 12:22:42 calle - * bug fix for more than one controller in connect_req. - * debugoutput now with contrnr. - * - * - * Revision 1.1 1997/03/04 21:50:28 calle - * Frirst version in isdn4linux - * - * Revision 2.2 1997/02/12 09:31:39 calle - * new version - * - * Revision 1.1 1997/01/31 10:32:20 calle - * Initial revision - * - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "compat.h" -#include "capicmd.h" -#include "capiutil.h" - -/* - * LLI Messages to the ISDN-ControllerISDN Controller - */ - -#define SEND_POLL 0x72 /* - * after load <- RECEIVE_POLL - */ -#define SEND_INIT 0x11 /* - * first message <- RECEIVE_INIT - * int32 NumApplications int32 - * NumNCCIs int32 BoardNumber - */ -#define SEND_REGISTER 0x12 /* - * register an application int32 - * ApplIDId int32 NumMessages - * int32 NumB3Connections int32 - * NumB3Blocks int32 B3Size - * - * AnzB3Connection != 0 && - * AnzB3Blocks >= 1 && B3Size >= 1 - */ -#define SEND_RELEASE 0x14 /* - * deregister an application int32 - * ApplID - */ -#define SEND_MESSAGE 0x15 /* - * send capi-message int32 length - * capi-data ... - */ -#define SEND_DATA_B3_REQ 0x13 /* - * send capi-data-message int32 - * MsgLength capi-data ... int32 - * B3Length data .... - */ - -#define SEND_CONFIG 0x21 /* - */ - -/* - * LLI Messages from the ISDN-ControllerISDN Controller - */ - -#define RECEIVE_POLL 0x32 /* - * <- after SEND_POLL - */ -#define RECEIVE_INIT 0x27 /* - * <- after SEND_INIT int32 length - * byte total length b1struct board - * driver revision b1struct card - * type b1struct reserved b1struct - * serial number b1struct driver - * capability b1struct d-channel - * protocol b1struct CAPI-2.0 - * profile b1struct capi version - */ -#define RECEIVE_MESSAGE 0x21 /* - * <- after SEND_MESSAGE int32 - * AppllID int32 Length capi-data - * .... - */ -#define RECEIVE_DATA_B3_IND 0x22 /* - * received data int32 AppllID - * int32 Length capi-data ... - * int32 B3Length data ... - */ -#define RECEIVE_START 0x23 /* - * Handshake - */ -#define RECEIVE_STOP 0x24 /* - * Handshake - */ -#define RECEIVE_NEW_NCCI 0x25 /* - * int32 AppllID int32 NCCI int32 - * WindowSize - */ -#define RECEIVE_FREE_NCCI 0x26 /* - * int32 AppllID int32 NCCI - */ -#define RECEIVE_RELEASE 0x26 /* - * int32 AppllID int32 0xffffffff - */ - -#define WRITE_REGISTER 0x00 -#define READ_REGISTER 0x01 - -/* - * port offsets - */ - -#define B1_READ 0x00 -#define B1_WRITE 0x01 -#define B1_INSTAT 0x02 -#define B1_OUTSTAT 0x03 -#define B1_RESET 0x10 -#define B1_ANALYSE 0x04 -#define B1_IDENT 0x17 /* Hema card T1 */ -#define B1_IRQ_MASTER 0x12 /* Hema card T1 */ - -#define B1_STAT0(cardtype) ((cardtype) == AVM_CARDTYPE_M1 ? 0x81200000l : 0x80A00000l) -#define B1_STAT1(cardtype) (0x80E00000l) - - -static inline unsigned char b1outp(unsigned short base, - unsigned short offset, - unsigned char value) -{ - outb(value, base + offset); - return inb(base + B1_ANALYSE); -} - -static inline int B1_rx_full(unsigned short base) -{ - return inb(base + B1_INSTAT) & 0x1; -} - -static inline unsigned char B1_get_byte(unsigned short base) -{ - unsigned long i = jiffies + 5 * HZ; /* maximum wait time 5 sec */ - while (!B1_rx_full(base) && time_before(jiffies, i)); - if (B1_rx_full(base)) - return inb(base + B1_READ); - printk(KERN_CRIT "b1lli: rx not full after 5 second\n"); - return 0; -} - -static inline unsigned int B1_get_word(unsigned short base) -{ - unsigned int val = 0; - val |= B1_get_byte(base); - val |= (B1_get_byte(base) << 8); - val |= (B1_get_byte(base) << 16); - val |= (B1_get_byte(base) << 24); - return val; -} - -static inline int B1_tx_empty(unsigned short base) -{ - return inb(base + B1_OUTSTAT) & 0x1; -} - -static inline void B1_put_byte(unsigned short base, unsigned char val) -{ - while (!B1_tx_empty(base)); - b1outp(base, B1_WRITE, val); -} - -static inline void B1_put_word(unsigned short base, unsigned int val) -{ - B1_put_byte(base, val & 0xff); - B1_put_byte(base, (val >> 8) & 0xff); - B1_put_byte(base, (val >> 16) & 0xff); - B1_put_byte(base, (val >> 24) & 0xff); -} - -static inline unsigned int B1_get_slice(unsigned short base, - unsigned char *dp) -{ - unsigned int len, i; - - len = i = B1_get_word(base); - while (i-- > 0) - *dp++ = B1_get_byte(base); - return len; -} - -static inline void B1_put_slice(unsigned short base, - unsigned char *dp, unsigned int len) -{ - B1_put_word(base, len); - while (len-- > 0) - B1_put_byte(base, *dp++); -} - -static void b1_wr_reg(unsigned short base, - unsigned int reg, - unsigned int value) -{ - B1_put_byte(base, WRITE_REGISTER); - B1_put_word(base, reg); - B1_put_word(base, value); -} - -static inline unsigned int b1_rd_reg(unsigned short base, - unsigned int reg) -{ - B1_put_byte(base, READ_REGISTER); - B1_put_word(base, reg); - return B1_get_word(base); - -} - -static inline void b1_set_test_bit(unsigned short base, - int cardtype, - int onoff) -{ - b1_wr_reg(base, B1_STAT0(cardtype), onoff ? 0x21 : 0x20); -} - -static inline int b1_get_test_bit(unsigned short base, - int cardtype) -{ - return (b1_rd_reg(base, B1_STAT0(cardtype)) & 0x01) != 0; -} - -static int irq_table[16] = -{0, - 0, - 0, - 192, /* irq 3 */ - 32, /* irq 4 */ - 160, /* irq 5 */ - 96, /* irq 6 */ - 224, /* irq 7 */ - 0, - 64, /* irq 9 */ - 80, /* irq 10 */ - 208, /* irq 11 */ - 48, /* irq 12 */ - 0, - 0, - 112, /* irq 15 */ -}; - -int B1_valid_irq(unsigned irq, int cardtype) -{ - switch (cardtype) { - default: - case AVM_CARDTYPE_M1: - case AVM_CARDTYPE_M2: - case AVM_CARDTYPE_B1: - return irq_table[irq] != 0; - case AVM_CARDTYPE_T1: - return irq == 5; - } -} - -unsigned char B1_assign_irq(unsigned short base, unsigned irq, int cardtype) -{ - switch (cardtype) { - case AVM_CARDTYPE_T1: - return b1outp(base, B1_IRQ_MASTER, 0x08); - default: - case AVM_CARDTYPE_M1: - case AVM_CARDTYPE_M2: - case AVM_CARDTYPE_B1: - return b1outp(base, B1_RESET, irq_table[irq]); - } -} - -unsigned char B1_enable_irq(unsigned short base) -{ - return b1outp(base, B1_INSTAT, 0x02); -} - -unsigned char B1_disable_irq(unsigned short base) -{ - return b1outp(base, B1_INSTAT, 0x00); -} - -void B1_reset(unsigned short base) -{ - b1outp(base, B1_RESET, 0); - udelay(55 * 2 * 1000); /* 2 TIC's */ - - b1outp(base, B1_RESET, 1); - udelay(55 * 2 * 1000); /* 2 TIC's */ - - b1outp(base, B1_RESET, 0); - udelay(55 * 2 * 1000); /* 2 TIC's */ -} - -int B1_detect(unsigned short base, int cardtype) -{ - int onoff, i; - - if (cardtype == AVM_CARDTYPE_T1) - return 0; - - /* - * Statusregister 0000 00xx - */ - if ((inb(base + B1_INSTAT) & 0xfc) - || (inb(base + B1_OUTSTAT) & 0xfc)) - return 1; - /* - * Statusregister 0000 001x - */ - b1outp(base, B1_INSTAT, 0x2); /* enable irq */ - /* b1outp(base, B1_OUTSTAT, 0x2); */ - if ((inb(base + B1_INSTAT) & 0xfe) != 0x2 - /* || (inb(base + B1_OUTSTAT) & 0xfe) != 0x2 */) - return 2; - /* - * Statusregister 0000 000x - */ - b1outp(base, B1_INSTAT, 0x0); /* disable irq */ - b1outp(base, B1_OUTSTAT, 0x0); - if ((inb(base + B1_INSTAT) & 0xfe) - || (inb(base + B1_OUTSTAT) & 0xfe)) - return 3; - - for (onoff = !0, i= 0; i < 10 ; i++) { - b1_set_test_bit(base, cardtype, onoff); - if (b1_get_test_bit(base, cardtype) != onoff) - return 4; - onoff = !onoff; - } - - if (cardtype == AVM_CARDTYPE_M1) - return 0; - - if ((b1_rd_reg(base, B1_STAT1(cardtype)) & 0x0f) != 0x01) - return 5; - - return 0; -} - - -extern int loaddebug; - -int B1_load_t4file(unsigned short base, avmb1_t4file * t4file) -{ - /* - * Data is in user space !!! - */ - unsigned char buf[256]; - unsigned char *dp; - int i, left, retval; - - - dp = t4file->data; - left = t4file->len; - while (left > sizeof(buf)) { - retval = copy_from_user(buf, dp, sizeof(buf)); - if (retval) - return -EFAULT; - if (loaddebug) - printk(KERN_DEBUG "b1capi: loading: %d bytes ..", sizeof(buf)); - for (i = 0; i < sizeof(buf); i++) - B1_put_byte(base, buf[i]); - if (loaddebug) - printk("ok\n"); - left -= sizeof(buf); - dp += sizeof(buf); - } - if (left) { - retval = copy_from_user(buf, dp, left); - if (retval) - return -EFAULT; - if (loaddebug) - printk(KERN_DEBUG "b1capi: loading: %d bytes ..", left); - for (i = 0; i < left; i++) - B1_put_byte(base, buf[i]); - if (loaddebug) - printk("ok\n"); - } - return 0; -} - -int B1_load_config(unsigned short base, avmb1_t4file * config) -{ - /* - * Data is in user space !!! - */ - unsigned char buf[256]; - unsigned char *dp; - int i, j, left, retval; - - - dp = config->data; - left = config->len; - if (left) { - B1_put_byte(base, SEND_CONFIG); - B1_put_word(base, 1); - B1_put_byte(base, SEND_CONFIG); - B1_put_word(base, left); - } - while (left > sizeof(buf)) { - retval = copy_from_user(buf, dp, sizeof(buf)); - if (retval) - return -EFAULT; - if (loaddebug) - printk(KERN_DEBUG "b1capi: conf load: %d bytes ..", sizeof(buf)); - for (i = 0; i < sizeof(buf); ) { - B1_put_byte(base, SEND_CONFIG); - for (j=0; j < 4; j++) { - B1_put_byte(base, buf[i++]); - } - } - if (loaddebug) - printk("ok\n"); - left -= sizeof(buf); - dp += sizeof(buf); - } - if (left) { - retval = copy_from_user(buf, dp, left); - if (retval) - return -EFAULT; - if (loaddebug) - printk(KERN_DEBUG "b1capi: conf load: %d bytes ..", left); - for (i = 0; i < left; ) { - B1_put_byte(base, SEND_CONFIG); - for (j=0; j < 4; j++) { - if (i < left) - B1_put_byte(base, buf[i++]); - else - B1_put_byte(base, 0); - } - } - if (loaddebug) - printk("ok\n"); - } - return 0; -} - -int B1_loaded(unsigned short base) -{ - int i; - unsigned char ans; - - if (loaddebug) - printk(KERN_DEBUG "b1capi: loaded: wait 1 ..\n"); - for (i = jiffies + 10 * HZ; time_before(jiffies, i);) { - if (B1_tx_empty(base)) - break; - } - if (!B1_tx_empty(base)) { - printk(KERN_ERR "b1lli: B1_loaded: timeout tx\n"); - return 0; - } - B1_put_byte(base, SEND_POLL); - printk(KERN_DEBUG "b1capi: loaded: wait 2 ..\n"); - for (i = jiffies + 10 * HZ; time_before(jiffies, i);) { - if (B1_rx_full(base)) { - if ((ans = B1_get_byte(base)) == RECEIVE_POLL) { - if (loaddebug) - printk(KERN_DEBUG "b1capi: loaded: ok\n"); - return 1; - } - printk(KERN_ERR "b1lli: B1_loaded: got 0x%x ???\n", ans); - return 0; - } - } - printk(KERN_ERR "b1lli: B1_loaded: timeout rx\n"); - return 0; -} - -/* - * ------------------------------------------------------------------- - */ -static inline void parse_version(avmb1_card * card) -{ - int i, j; - for (j = 0; j < AVM_MAXVERSION; j++) - card->version[j] = "\0\0" + 1; - for (i = 0, j = 0; - j < AVM_MAXVERSION && i < card->versionlen; - j++, i += card->versionbuf[i] + 1) - card->version[j] = &card->versionbuf[i + 1]; -} -/* - * ------------------------------------------------------------------- - */ - -void B1_send_init(unsigned short port, - unsigned int napps, unsigned int nncci, unsigned int cardnr) -{ - unsigned long flags; - - save_flags(flags); - cli(); - B1_put_byte(port, SEND_INIT); - B1_put_word(port, napps); - B1_put_word(port, nncci); - B1_put_word(port, cardnr); - restore_flags(flags); -} - -void B1_send_register(unsigned short port, - __u16 appid, __u32 nmsg, - __u32 nb3conn, __u32 nb3blocks, __u32 b3bsize) -{ - unsigned long flags; - - save_flags(flags); - cli(); - B1_put_byte(port, SEND_REGISTER); - B1_put_word(port, appid); - B1_put_word(port, nmsg); - B1_put_word(port, nb3conn); - B1_put_word(port, nb3blocks); - B1_put_word(port, b3bsize); - restore_flags(flags); -} - -void B1_send_release(unsigned short port, - __u16 appid) -{ - unsigned long flags; - - save_flags(flags); - cli(); - B1_put_byte(port, SEND_RELEASE); - B1_put_word(port, appid); - restore_flags(flags); -} - -extern int showcapimsgs; - -void B1_send_message(unsigned short port, struct sk_buff *skb) -{ - unsigned long flags; - __u16 len = CAPIMSG_LEN(skb->data); - __u8 cmd = CAPIMSG_COMMAND(skb->data); - __u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data); - __u32 contr = CAPIMSG_CONTROL(skb->data); - - if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { - __u16 dlen = CAPIMSG_DATALEN(skb->data); - - if (showcapimsgs > 2) { - if (showcapimsgs & 1) { - printk(KERN_DEBUG "b1lli: Put [0x%lx] id#%d %s len=%u\n", - (unsigned long) contr, - CAPIMSG_APPID(skb->data), - capi_cmd2str(cmd, subcmd), len); - } else { - printk(KERN_DEBUG "b1lli: Put [0x%lx] %s\n", - (unsigned long) contr, - capi_message2str(skb->data)); - } - - } - save_flags(flags); - cli(); - B1_put_byte(port, SEND_DATA_B3_REQ); - B1_put_slice(port, skb->data, len); - B1_put_slice(port, skb->data + len, dlen); - restore_flags(flags); - } else { - if (showcapimsgs) { - - if (showcapimsgs & 1) { - printk(KERN_DEBUG "b1lli: Put [0x%lx] id#%d %s len=%u\n", - (unsigned long) contr, - CAPIMSG_APPID(skb->data), - capi_cmd2str(cmd, subcmd), len); - } else { - printk(KERN_DEBUG "b1lli: Put [0x%lx] %s\n", (unsigned long)contr, capi_message2str(skb->data)); - } - } - save_flags(flags); - cli(); - B1_put_byte(port, SEND_MESSAGE); - B1_put_slice(port, skb->data, len); - restore_flags(flags); - } - dev_kfree_skb(skb); -} - -/* - * ------------------------------------------------------------------- - */ - -void B1_handle_interrupt(avmb1_card * card) -{ - unsigned char b1cmd; - struct sk_buff *skb; - - unsigned ApplId; - unsigned MsgLen; - unsigned DataB3Len; - unsigned NCCI; - unsigned WindowSize; - - if (!B1_rx_full(card->port)) - return; - - b1cmd = B1_get_byte(card->port); - - switch (b1cmd) { - - case RECEIVE_DATA_B3_IND: - - ApplId = (unsigned) B1_get_word(card->port); - MsgLen = B1_get_slice(card->port, card->msgbuf); - DataB3Len = B1_get_slice(card->port, card->databuf); - - if (showcapimsgs > 2) { - __u8 cmd = CAPIMSG_COMMAND(card->msgbuf); - __u8 subcmd = CAPIMSG_SUBCOMMAND(card->msgbuf); - __u32 contr = CAPIMSG_CONTROL(card->msgbuf); - CAPIMSG_SETDATA(card->msgbuf, card->databuf); - if (showcapimsgs & 1) { - printk(KERN_DEBUG "b1lli: Got [0x%lx] id#%d %s len=%u/%u\n", - (unsigned long) contr, - CAPIMSG_APPID(card->msgbuf), - capi_cmd2str(cmd, subcmd), - MsgLen, DataB3Len); - } else { - printk(KERN_DEBUG "b1lli: Got [0x%lx] %s\n", (unsigned long)contr, capi_message2str(card->msgbuf)); - } - } - if (!(skb = dev_alloc_skb(DataB3Len + MsgLen))) { - printk(KERN_ERR "b1lli: incoming packet dropped\n"); - } else { - memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); - memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len); - CAPIMSG_SETDATA(skb->data, skb->data + MsgLen); - avmb1_handle_capimsg(card, ApplId, skb); - } - break; - - case RECEIVE_MESSAGE: - - ApplId = (unsigned) B1_get_word(card->port); - MsgLen = B1_get_slice(card->port, card->msgbuf); - if (showcapimsgs) { - __u8 cmd = CAPIMSG_COMMAND(card->msgbuf); - __u8 subcmd = CAPIMSG_SUBCOMMAND(card->msgbuf); - __u32 contr = CAPIMSG_CONTROL(card->msgbuf); - if (showcapimsgs & 1) { - printk(KERN_DEBUG "b1lli: Got [0x%lx] id#%d %s len=%u\n", - (unsigned long) contr, - CAPIMSG_APPID(card->msgbuf), - capi_cmd2str(cmd, subcmd), - MsgLen); - } else { - printk(KERN_DEBUG "b1lli: Got [0x%lx] %s\n", - (unsigned long) contr, - capi_message2str(card->msgbuf)); - } - - } - if (!(skb = dev_alloc_skb(MsgLen))) { - printk(KERN_ERR "b1lli: incoming packet dropped\n"); - } else { - memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); - avmb1_handle_capimsg(card, ApplId, skb); - } - break; - - case RECEIVE_NEW_NCCI: - - ApplId = B1_get_word(card->port); - NCCI = B1_get_word(card->port); - WindowSize = B1_get_word(card->port); - - if (showcapimsgs) - printk(KERN_DEBUG "b1lli: NEW_NCCI app %u ncci 0x%x\n", ApplId, NCCI); - - avmb1_handle_new_ncci(card, ApplId, NCCI, WindowSize); - - break; - - case RECEIVE_FREE_NCCI: - - ApplId = B1_get_word(card->port); - NCCI = B1_get_word(card->port); - - if (showcapimsgs) - printk(KERN_DEBUG "b1lli: FREE_NCCI app %u ncci 0x%x\n", ApplId, NCCI); - - avmb1_handle_free_ncci(card, ApplId, NCCI); - break; - - case RECEIVE_START: - if (card->blocked) - printk(KERN_DEBUG "b1lli: RESTART\n"); - card->blocked = 0; - break; - - case RECEIVE_STOP: - printk(KERN_DEBUG "b1lli: STOP\n"); - card->blocked = 1; - break; - - case RECEIVE_INIT: - - card->versionlen = B1_get_slice(card->port, card->versionbuf); - card->cardstate = CARD_ACTIVE; - parse_version(card); - printk(KERN_INFO "b1lli: %s-card (%s) now active\n", - card->version[VER_CARDTYPE], - card->version[VER_DRIVER]); - avmb1_card_ready(card); - break; - default: - printk(KERN_ERR "b1lli: B1_handle_interrupt: 0x%x ???\n", b1cmd); - break; - } -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/b1pci.c linux.pre11.3/drivers/isdn/avmb1/b1pci.c --- linux.vanilla/drivers/isdn/avmb1/b1pci.c Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/avmb1/b1pci.c Mon Jul 19 23:59:32 1999 @@ -1,40 +1,59 @@ /* - * $Id: b1pci.c,v 1.5 1998/01/31 11:14:43 calle Exp $ + * $Id: b1pci.c,v 1.14 1999/07/09 15:05:41 keil Exp $ * * Module for AVM B1 PCI-card. * - * (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) + * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1pci.c,v $ - * Revision 1.5 1998/01/31 11:14:43 calle - * merged changes to 2.0 tree, prepare 2.1.82 to work. + * Revision 1.14 1999/07/09 15:05:41 keil + * compat.h is now isdn_compat.h * - * Revision 1.4 1997/12/10 20:00:50 calle - * get changes from 2.0 version + * Revision 1.13 1999/07/05 15:09:50 calle + * - renamed "appl_release" to "appl_released". + * - version und profile data now cleared on controller reset + * - extended /proc interface, to allow driver and controller specific + * informations to include by driver hackers. * - * Revision 1.3 1997/10/01 09:21:14 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. + * Revision 1.12 1999/07/01 15:26:29 calle + * complete new version (I love it): + * + new hardware independed "capi_driver" interface that will make it easy to: + * - support other controllers with CAPI-2.0 (i.e. USB Controller) + * - write a CAPI-2.0 for the passive cards + * - support serial link CAPI-2.0 boxes. + * + wrote "capi_driver" for all supported cards. + * + "capi_driver" (supported cards) now have to be configured with + * make menuconfig, in the past all supported cards where included + * at once. + * + new and better informations in /proc/capi/ + * + new ioctl to switch trace of capi messages per controller + * using "avmcapictrl trace [contr] on|off|...." + * + complete testcircle with all supported cards and also the + * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. * - * Revision 1.2 1997/05/18 09:24:13 calle - * added verbose disconnect reason reporting to avmb1. - * some fixes in capi20 interface. - * changed info messages for B1-PCI - * - * Revision 1.1 1997/03/30 17:10:42 calle - * added support for AVM-B1-PCI card. * */ #include #include #include -#include #include -#include "compat.h" +#include +#include +#include +#include +#include #include -#include +#include +#include +#include "capicmd.h" +#include "capiutil.h" +#include "capilli.h" +#include "avmcard.h" + +static char *revision = "$Revision: 1.14 $"; + +/* ------------------------------------------------------------- */ #ifndef PCI_VENDOR_ID_AVM #define PCI_VENDOR_ID_AVM 0x1244 @@ -44,65 +63,213 @@ #define PCI_DEVICE_ID_AVM_B1 0x700 #endif -static char *revision = "$Revision: 1.5 $"; - /* ------------------------------------------------------------- */ MODULE_AUTHOR("Carsten Paeth "); /* ------------------------------------------------------------- */ +static struct capi_driver_interface *di; + /* ------------------------------------------------------------- */ -/* -------- Init & Cleanup ------------------------------------- */ + +static void b1pci_interrupt(int interrupt, void *devptr, struct pt_regs *regs) +{ + avmcard *card; + + card = (avmcard *) devptr; + + if (!card) { + printk(KERN_WARNING "b1_interrupt: wrong device\n"); + return; + } + if (card->interrupt) { + printk(KERN_ERR "b1_interrupt: reentering interrupt hander (%s)\n", card->name); + return; + } + + card->interrupt = 1; + + b1_handle_interrupt(card); + + card->interrupt = 0; +} /* ------------------------------------------------------------- */ -/* - * init / exit functions - */ +static void b1pci_remove_ctr(struct capi_ctr *ctrl) +{ + avmcard *card = (avmcard *)(ctrl->driverdata); + unsigned int port = card->port; + + b1_reset(port); + b1_reset(port); + + di->detach_ctr(ctrl); + free_irq(card->irq, card); + release_region(card->port, AVMB1_PORTLEN); + ctrl->driverdata = 0; + kfree(card); + + MOD_DEC_USE_COUNT; +} + +/* ------------------------------------------------------------- */ + +static char *b1pci_procinfo(struct capi_ctr *ctrl) +{ + avmcard *card = (avmcard *)(ctrl->driverdata); + if (!card) + return ""; + sprintf(card->infobuf, "%s %s 0x%x %d", + card->cardname[0] ? card->cardname : "-", + card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-", + card->port, card->irq + ); + return card->infobuf; +} + +/* ------------------------------------------------------------- */ + +static int b1pci_add_card(struct capi_driver *driver, struct capicardparams *p) +{ + avmcard *card; + int retval; + + card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); + + if (!card) { + printk(KERN_WARNING "b1pci: no memory.\n"); + return -ENOMEM; + } + memset(card, 0, sizeof(avmcard)); + sprintf(card->name, "b1pci-%x", p->port); + card->port = p->port; + card->irq = p->irq; + card->cardtype = avm_b1pci; + + if (check_region(card->port, AVMB1_PORTLEN)) { + printk(KERN_WARNING + "b1pci: ports 0x%03x-0x%03x in use.\n", + card->port, card->port + AVMB1_PORTLEN); + kfree(card); + return -EBUSY; + } + b1_reset(card->port); + if ((retval = b1_detect(card->port, card->cardtype)) != 0) { + printk(KERN_NOTICE "b1pci: NO card at 0x%x (%d)\n", + card->port, retval); + kfree(card); + return -EIO; + } + b1_reset(card->port); + + request_region(p->port, AVMB1_PORTLEN, card->name); + + retval = request_irq(card->irq, b1pci_interrupt, 0, card->name, card); + if (retval) { + printk(KERN_ERR "b1pci: unable to get IRQ %d.\n", card->irq); + release_region(card->port, AVMB1_PORTLEN); + kfree(card); + return -EBUSY; + } + + card->ctrl = di->attach_ctr(driver, card->name, card); + if (!card->ctrl) { + printk(KERN_ERR "b1pci: attach controller failed.\n"); + free_irq(card->irq, card); + release_region(card->port, AVMB1_PORTLEN); + kfree(card); + return -EBUSY; + } + + MOD_INC_USE_COUNT; + + return 0; +} + +/* ------------------------------------------------------------- */ + +static struct capi_driver b1pci_driver = { + "b1pci", + "0.0", + b1_load_firmware, + b1_reset_ctr, + b1pci_remove_ctr, + b1_register_appl, + b1_release_appl, + b1_send_message, + + b1pci_procinfo, + b1ctl_read_proc, + 0, /* use standard driver_read_proc */ + + 0, /* no add_card function */ +}; #ifdef MODULE #define b1pci_init init_module +void cleanup_module(void); #endif +static int ncards = 0; + int b1pci_init(void) { - char *p; - char rev[10]; - int rc; + struct capi_driver *driver = &b1pci_driver; struct pci_dev *dev = NULL; + char *p; + int retval; if ((p = strchr(revision, ':'))) { - strcpy(rev, p + 1); - p = strchr(rev, '$'); + strncpy(driver->revision, p + 1, sizeof(driver->revision)); + p = strchr(driver->revision, '$'); *p = 0; - } else - strcpy(rev, " ??? "); + } + + printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision); + + di = attach_capi_driver(driver); + if (!di) { + printk(KERN_ERR "%s: failed to attach capi_driver\n", + driver->name); + return -EIO; + } #ifdef CONFIG_PCI if (!pci_present()) { - printk(KERN_ERR "b1pci: no PCI bus present\n"); + printk(KERN_ERR "%s: no PCI bus present\n", driver->name); + detach_capi_driver(driver); return -EIO; } - printk(KERN_INFO "b1pci: revision %s\n", rev); - while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, dev))) { - unsigned int ioaddr = dev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK; - unsigned int irq = dev->irq; + struct capicardparams param; + + param.port = dev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK; + param.irq = dev->irq; printk(KERN_INFO - "b1pci: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n", - ioaddr, irq); - if ((rc = avmb1_probecard(ioaddr, irq, AVM_CARDTYPE_B1)) != 0) { + "%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n", + driver->name, param.port, param.irq); + retval = b1pci_add_card(driver, ¶m); + if (retval != 0) { printk(KERN_ERR - "b1pci: no AVM-B1 at i/o %#x, irq %d detected\n", - ioaddr, irq); - return rc; + "%s: no AVM-B1 at i/o %#x, irq %d detected\n", + driver->name, param.port, param.irq); +#ifdef MODULE + cleanup_module(); +#endif + return retval; } - if ((rc = avmb1_addcard(ioaddr, irq, AVM_CARDTYPE_B1)) < 0) - return rc; + ncards++; } - return 0; + if (ncards) { + printk(KERN_INFO "%s: %d B1-PCI card(s) detected\n", + driver->name, ncards); + return 0; + } + printk(KERN_ERR "%s: NO B1-PCI card detected\n", driver->name); + return -ESRCH; #else printk(KERN_ERR "b1pci: kernel not compiled with PCI.\n"); return -EIO; @@ -112,5 +279,6 @@ #ifdef MODULE void cleanup_module(void) { + detach_capi_driver(&b1pci_driver); } #endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/b1pcmcia.c linux.pre11.3/drivers/isdn/avmb1/b1pcmcia.c --- linux.vanilla/drivers/isdn/avmb1/b1pcmcia.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/avmb1/b1pcmcia.c Mon Jul 19 23:59:32 1999 @@ -0,0 +1,267 @@ +/* + * $Id: b1pcmcia.c,v 1.3 1999/07/09 15:05:41 keil Exp $ + * + * Module for AVM B1/M1/M2 PCMCIA-card. + * + * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) + * + * $Log: b1pcmcia.c,v $ + * Revision 1.3 1999/07/09 15:05:41 keil + * compat.h is now isdn_compat.h + * + * Revision 1.2 1999/07/05 15:09:51 calle + * - renamed "appl_release" to "appl_released". + * - version und profile data now cleared on controller reset + * - extended /proc interface, to allow driver and controller specific + * informations to include by driver hackers. + * + * Revision 1.1 1999/07/01 15:26:30 calle + * complete new version (I love it): + * + new hardware independed "capi_driver" interface that will make it easy to: + * - support other controllers with CAPI-2.0 (i.e. USB Controller) + * - write a CAPI-2.0 for the passive cards + * - support serial link CAPI-2.0 boxes. + * + wrote "capi_driver" for all supported cards. + * + "capi_driver" (supported cards) now have to be configured with + * make menuconfig, in the past all supported cards where included + * at once. + * + new and better informations in /proc/capi/ + * + new ioctl to switch trace of capi messages per controller + * using "avmcapictrl trace [contr] on|off|...." + * + complete testcircle with all supported cards and also the + * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "capicmd.h" +#include "capiutil.h" +#include "capilli.h" +#include "avmcard.h" + +static char *revision = "$Revision: 1.3 $"; + +/* ------------------------------------------------------------- */ + +MODULE_AUTHOR("Carsten Paeth "); + +/* ------------------------------------------------------------- */ + +static struct capi_driver_interface *di; + +/* ------------------------------------------------------------- */ + +static void b1pcmcia_interrupt(int interrupt, void *devptr, struct pt_regs *regs) +{ + avmcard *card; + + card = (avmcard *) devptr; + + if (!card) { + printk(KERN_WARNING "b1_interrupt: wrong device\n"); + return; + } + if (card->interrupt) { + printk(KERN_ERR "b1_interrupt: reentering interrupt hander (%s)\n", card->name); + return; + } + + card->interrupt = 1; + + b1_handle_interrupt(card); + + card->interrupt = 0; +} +/* ------------------------------------------------------------- */ + +static void b1pcmcia_remove_ctr(struct capi_ctr *ctrl) +{ + avmcard *card = (avmcard *)(ctrl->driverdata); + unsigned int port = card->port; + + b1_reset(port); + b1_reset(port); + + di->detach_ctr(ctrl); + free_irq(card->irq, card); + /* io addrsses managent by CardServices + * release_region(card->port, AVMB1_PORTLEN); + */ + kfree(card); + + MOD_DEC_USE_COUNT; +} + +/* ------------------------------------------------------------- */ + +static int b1pcmcia_add_card(struct capi_driver *driver, + unsigned int port, + unsigned irq, + enum avmcardtype cardtype) +{ + avmcard *card; + int retval; + + card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); + + if (!card) { + printk(KERN_WARNING "b1pcmcia: no memory.\n"); + return -ENOMEM; + } + memset(card, 0, sizeof(avmcard)); + switch (cardtype) { + case avm_m1: sprintf(card->name, "m1-%x", port); break; + case avm_m2: sprintf(card->name, "m2-%x", port); break; + default: sprintf(card->name, "b1pcmcia-%x", port); break; + } + card->port = port; + card->irq = irq; + card->cardtype = cardtype; + + b1_reset(card->port); + if ((retval = b1_detect(card->port, card->cardtype)) != 0) { + printk(KERN_NOTICE "b1pcmcia: NO card at 0x%x (%d)\n", + card->port, retval); + kfree(card); + return -EIO; + } + b1_reset(card->port); + + retval = request_irq(card->irq, b1pcmcia_interrupt, 0, card->name, card); + if (retval) { + printk(KERN_ERR "b1pcmcia: unable to get IRQ %d.\n", card->irq); + kfree(card); + return -EBUSY; + } + + card->ctrl = di->attach_ctr(driver, card->name, card); + if (!card->ctrl) { + printk(KERN_ERR "b1pcmcia: attach controller failed.\n"); + free_irq(card->irq, card); + kfree(card); + return -EBUSY; + } + + MOD_INC_USE_COUNT; + return card->ctrl->cnr; +} + +/* ------------------------------------------------------------- */ + +static char *b1pcmcia_procinfo(struct capi_ctr *ctrl) +{ + avmcard *card = (avmcard *)(ctrl->driverdata); + if (!card) + return ""; + sprintf(card->infobuf, "%s %s 0x%x %d", + card->cardname[0] ? card->cardname : "-", + card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-", + card->port, card->irq + ); + return card->infobuf; +} + +/* ------------------------------------------------------------- */ + +static struct capi_driver b1pcmcia_driver = { + "b1pcmcia", + "0.0", + b1_load_firmware, + b1_reset_ctr, + b1pcmcia_remove_ctr, + b1_register_appl, + b1_release_appl, + b1_send_message, + + b1pcmcia_procinfo, + b1ctl_read_proc, + 0, /* use standard driver_read_proc */ + + 0, +}; + +/* ------------------------------------------------------------- */ + +int b1pcmcia_addcard_b1(unsigned int port, unsigned irq) +{ + return b1pcmcia_add_card(&b1pcmcia_driver, port, irq, avm_b1pcmcia); +} + +int b1pcmcia_addcard_m1(unsigned int port, unsigned irq) +{ + return b1pcmcia_add_card(&b1pcmcia_driver, port, irq, avm_m1); +} + +int b1pcmcia_addcard_m2(unsigned int port, unsigned irq) +{ + return b1pcmcia_add_card(&b1pcmcia_driver, port, irq, avm_m2); +} + +int b1pcmcia_delcard(unsigned int port, unsigned irq) +{ + struct capi_ctr *ctrl; + avmcard *card; + + for (ctrl = b1pcmcia_driver.controller; ctrl; ctrl = ctrl->next) { + card = (avmcard *)(ctrl->driverdata); + if (card->port == port && card->irq == irq) { + b1pcmcia_remove_ctr(ctrl); + return 0; + } + } + return -ESRCH; +} + +EXPORT_SYMBOL(b1pcmcia_addcard_b1); +EXPORT_SYMBOL(b1pcmcia_addcard_m1); +EXPORT_SYMBOL(b1pcmcia_addcard_m2); +EXPORT_SYMBOL(b1pcmcia_delcard); + +/* ------------------------------------------------------------- */ + +#ifdef MODULE +#define b1pcmcia_init init_module +void cleanup_module(void); +#endif + +int b1pcmcia_init(void) +{ + struct capi_driver *driver = &b1pcmcia_driver; + char *p; + + if ((p = strchr(revision, ':'))) { + strncpy(driver->revision, p + 1, sizeof(driver->revision)); + p = strchr(driver->revision, '$'); + *p = 0; + } + + printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision); + + di = attach_capi_driver(driver); + + if (!di) { + printk(KERN_ERR "%s: failed to attach capi_driver\n", + driver->name); + return -EIO; + } + return 0; +} + +#ifdef MODULE +void cleanup_module(void) +{ + detach_capi_driver(&b1pcmcia_driver); +} +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/capi.c linux.pre11.3/drivers/isdn/avmb1/capi.c --- linux.vanilla/drivers/isdn/avmb1/capi.c Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/avmb1/capi.c Mon Jul 19 23:59:32 1999 @@ -1,11 +1,55 @@ /* - * $Id: capi.c,v 1.10 1998/02/13 07:09:13 calle Exp $ + * $Id: capi.c,v 1.19 1999/07/09 15:05:42 keil Exp $ * * CAPI 2.0 Interface for Linux * * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capi.c,v $ + * Revision 1.19 1999/07/09 15:05:42 keil + * compat.h is now isdn_compat.h + * + * Revision 1.18 1999/07/06 07:42:01 calle + * - changes in /proc interface + * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb. + * + * Revision 1.17 1999/07/01 15:26:30 calle + * complete new version (I love it): + * + new hardware independed "capi_driver" interface that will make it easy to: + * - support other controllers with CAPI-2.0 (i.e. USB Controller) + * - write a CAPI-2.0 for the passive cards + * - support serial link CAPI-2.0 boxes. + * + wrote "capi_driver" for all supported cards. + * + "capi_driver" (supported cards) now have to be configured with + * make menuconfig, in the past all supported cards where included + * at once. + * + new and better informations in /proc/capi/ + * + new ioctl to switch trace of capi messages per controller + * using "avmcapictrl trace [contr] on|off|...." + * + complete testcircle with all supported cards and also the + * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. + * + * Revision 1.16 1999/07/01 08:22:57 keil + * compatibility macros now in + * + * Revision 1.15 1999/06/21 15:24:11 calle + * extend information in /proc. + * + * Revision 1.14 1999/06/10 16:51:03 calle + * Bugfix: open/release of control device was not handled correct. + * + * Revision 1.13 1998/08/28 04:32:25 calle + * Added patch send by Michael.Mueller4@post.rwth-aachen.de, to get AVM B1 + * driver running with 2.1.118. + * + * Revision 1.12 1998/05/26 22:39:34 he + * sync'ed with 2.1.102 where appropriate (CAPABILITY changes) + * concap typo + * cleared dev.tbusy in isdn_net BCONN status callback + * + * Revision 1.11 1998/03/09 17:46:37 he + * merged in 2.1.89 changes + * * Revision 1.10 1998/02/13 07:09:13 calle * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * @@ -68,11 +112,12 @@ #include #include #include +#include #include #include #include -#include "compat.h" +#include #include "capiutil.h" #include "capicmd.h" #include "capidev.h" @@ -166,7 +211,10 @@ } copied = skb->len; - + if (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3 + && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) + cdev->nrecvdatapkt++; + else cdev->nrecvctlpkt++; kfree_skb(skb); return copied; @@ -195,7 +243,7 @@ skb = alloc_skb(count, GFP_USER); if ((retval = copy_from_user(skb_put(skb, count), buf, count))) { - dev_kfree_skb(skb); + kfree_skb(skb); return retval; } cmd = CAPIMSG_COMMAND(skb->data); @@ -204,11 +252,11 @@ if (cmd == CAPI_DATA_B3 && subcmd == CAPI_REQ) { __u16 dlen = CAPIMSG_DATALEN(skb->data); if (mlen + dlen != count) { - dev_kfree_skb(skb); + kfree_skb(skb); return -EINVAL; } } else if (mlen != count) { - dev_kfree_skb(skb); + kfree_skb(skb); return -EINVAL; } CAPIMSG_SETAPPID(skb->data, cdev->applid); @@ -216,9 +264,12 @@ cdev->errcode = (*capifuncs->capi_put_message) (cdev->applid, skb); if (cdev->errcode) { - dev_kfree_skb(skb); + kfree_skb(skb); return -EIO; } + if (cmd == CAPI_DATA_B3 && subcmd == CAPI_REQ) + cdev->nsentdatapkt++; + else cdev->nsentctlpkt++; return count; } @@ -237,6 +288,9 @@ return POLLERR; cdev = &capidevs[minor]; +#if (LINUX_VERSION_CODE < 0x020159) /* 2.1.89 */ +#define poll_wait(f,wq,w) poll_wait((wq),(w)) +#endif poll_wait(file, &(cdev->recv_wait), wait); mask = POLLOUT | POLLWRNORM; if (!skb_queue_empty(&cdev->recv_queue)) @@ -411,16 +465,13 @@ capidevs[minor].is_open = 1; skb_queue_head_init(&capidevs[minor].recv_queue); MOD_INC_USE_COUNT; + capidevs[minor].nopen++; } else { - - if (!capidevs[minor].is_open) { - capidevs[minor].is_open = 1; - MOD_INC_USE_COUNT; - } + capidevs[minor].is_open++; + MOD_INC_USE_COUNT; } - return 0; } @@ -445,10 +496,13 @@ cdev->is_registered = 0; cdev->applid = 0; - while ((skb = skb_dequeue(&cdev->recv_queue)) != 0) + while ((skb = skb_dequeue(&cdev->recv_queue)) != 0) { kfree_skb(skb); + } + cdev->is_open = 0; + } else { + cdev->is_open--; } - cdev->is_open = 0; MOD_DEC_USE_COUNT; return 0; @@ -464,13 +518,90 @@ capi_ioctl, NULL, /* capi_mmap */ capi_open, - NULL, /* flush */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,118) + NULL, /* capi_flush */ +#endif capi_release, NULL, /* capi_fsync */ NULL, /* capi_fasync */ }; +/* -------- /proc functions ----------------------------------- */ +/* + * /proc/capi/capi20: + * minor opencount nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt + */ +static int proc_capidev_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct capidev *cp; + int i; + int len = 0; + off_t begin = 0; + + for (i=0; i < CAPI_MAXMINOR; i++) { + cp = &capidevs[i+1]; + if (cp->nopen == 0) continue; + len += sprintf(page+len, "%d %lu %lu %lu %lu %lu\n", + i+1, + cp->nopen, + cp->nrecvctlpkt, + cp->nrecvdatapkt, + cp->nsentctlpkt, + cp->nsentdatapkt); + if (len+begin > off+count) + goto endloop; + if (len+begin < off) { + begin += len; + len = 0; + } + } +endloop: + if (i >= CAPI_MAXMINOR) + *eof = 1; + if (off >= len+begin) + return 0; + *start = page + (begin-off); + return ((count < begin+len-off) ? count : begin+len-off); +} + +static struct procfsentries { + char *name; + mode_t mode; + int (*read_proc)(char *page, char **start, off_t off, + int count, int *eof, void *data); + struct proc_dir_entry *procent; +} procfsentries[] = { + /* { "capi", S_IFDIR, 0 }, */ + { "capi/capi20", 0 , proc_capidev_read_proc }, +}; + +static void proc_init(void) +{ + int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); + int i; + + for (i=0; i < nelem; i++) { + struct procfsentries *p = procfsentries + i; + p->procent = create_proc_entry(p->name, p->mode, 0); + if (p->procent) p->procent->read_proc = p->read_proc; + } +} + +static void proc_exit(void) +{ + int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); + int i; + + for (i=nelem-1; i >= 0; i--) { + struct procfsentries *p = procfsentries + i; + if (p->procent) { + remove_proc_entry(p->name, 0); + p->procent = 0; + } + } +} /* -------- init function and module interface ---------------------- */ #ifdef MODULE @@ -484,7 +615,16 @@ int capi_init(void) { +#ifdef COMPAT_HAS_NEW_WAITQ + int j; +#endif + memset(capidevs, 0, sizeof(capidevs)); +#ifdef COMPAT_HAS_NEW_WAITQ + for ( j = 0; j < CAPI_MAXMINOR+1; j++ ) { + init_waitqueue_head(&capidevs[j].recv_wait); + } +#endif if (register_chrdev(capi_major, "capi20", &capi_fops)) { printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); @@ -496,12 +636,14 @@ unregister_chrdev(capi_major, "capi20"); return -EIO; } + (void)proc_init(); return 0; } #ifdef MODULE void cleanup_module(void) { + (void)proc_exit(); unregister_chrdev(capi_major, "capi20"); (void) detach_capi_interface(&cuser); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/capidev.h linux.pre11.3/drivers/isdn/avmb1/capidev.h --- linux.vanilla/drivers/isdn/avmb1/capidev.h Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/avmb1/capidev.h Mon Jul 19 23:59:32 1999 @@ -1,11 +1,33 @@ /* - * $Id: capidev.h,v 1.1 1997/03/04 21:50:30 calle Exp $ + * $Id: capidev.h,v 1.4 1999/07/01 15:26:32 calle Exp $ * * CAPI 2.0 Interface for Linux * * (c) Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capidev.h,v $ + * Revision 1.4 1999/07/01 15:26:32 calle + * complete new version (I love it): + * + new hardware independed "capi_driver" interface that will make it easy to: + * - support other controllers with CAPI-2.0 (i.e. USB Controller) + * - write a CAPI-2.0 for the passive cards + * - support serial link CAPI-2.0 boxes. + * + wrote "capi_driver" for all supported cards. + * + "capi_driver" (supported cards) now have to be configured with + * make menuconfig, in the past all supported cards where included + * at once. + * + new and better informations in /proc/capi/ + * + new ioctl to switch trace of capi messages per controller + * using "avmcapictrl trace [contr] on|off|...." + * + complete testcircle with all supported cards and also the + * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. + * + * Revision 1.3 1999/07/01 08:22:58 keil + * compatibility macros now in + * + * Revision 1.2 1999/06/21 15:24:13 calle + * extend information in /proc. + * * Revision 1.1 1997/03/04 21:50:30 calle * Frirst version in isdn4linux * @@ -22,8 +44,18 @@ int is_registered; __u16 applid; struct sk_buff_head recv_queue; +#ifdef COMPAT_HAS_NEW_WAITQ + wait_queue_head_t recv_wait; +#else struct wait_queue *recv_wait; +#endif __u16 errcode; + /* Statistic */ + unsigned long nopen; + unsigned long nrecvctlpkt; + unsigned long nrecvdatapkt; + unsigned long nsentctlpkt; + unsigned long nsentdatapkt; }; #define CAPI_MAXMINOR CAPI_MAXAPPL diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/capidrv.c linux.pre11.3/drivers/isdn/avmb1/capidrv.c --- linux.vanilla/drivers/isdn/avmb1/capidrv.c Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/avmb1/capidrv.c Mon Jul 19 23:59:32 1999 @@ -1,11 +1,83 @@ /* - * $Id: capidrv.c,v 1.11 1998/02/13 07:09:15 calle Exp $ + * $Id: capidrv.c,v 1.23 1999/07/09 15:05:44 keil Exp $ * * ISDN4Linux Driver, using capi20 interface (kernelcapi) * * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capidrv.c,v $ + * Revision 1.23 1999/07/09 15:05:44 keil + * compat.h is now isdn_compat.h + * + * Revision 1.22 1999/07/06 07:24:14 calle + * Bugfix: call to kfree_skb in capidrv_signal was too early, + * thanks to Lars Heete . + * + * Revision 1.21 1999/07/01 15:26:34 calle + * complete new version (I love it): + * + new hardware independed "capi_driver" interface that will make it easy to: + * - support other controllers with CAPI-2.0 (i.e. USB Controller) + * - write a CAPI-2.0 for the passive cards + * - support serial link CAPI-2.0 boxes. + * + wrote "capi_driver" for all supported cards. + * + "capi_driver" (supported cards) now have to be configured with + * make menuconfig, in the past all supported cards where included + * at once. + * + new and better informations in /proc/capi/ + * + new ioctl to switch trace of capi messages per controller + * using "avmcapictrl trace [contr] on|off|...." + * + complete testcircle with all supported cards and also the + * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. + * + * Revision 1.20 1999/07/01 08:22:59 keil + * compatibility macros now in + * + * Revision 1.19 1999/06/29 16:16:54 calle + * Let ISDN_CMD_UNLOAD work with open isdn devices without crash again. + * Also right unlocking (ISDN_CMD_UNLOCK) is done now. + * isdnlog should check returncode of read(2) calls. + * + * Revision 1.18 1999/06/21 15:24:15 calle + * extend information in /proc. + * + * Revision 1.17 1999/06/10 16:53:55 calle + * Removing of module b1pci will now remove card from lower level. + * + * Revision 1.16 1999/05/31 11:50:33 calle + * Bugfix: In if_sendbuf, skb_push'ed DATA_B3 header was not skb_pull'ed + * on failure, result in data block with DATA_B3 header transmitted + * + * Revision 1.15 1999/05/25 21:26:16 calle + * Include CAPI-Channelallocation (leased lines) from the 2.0 tree. + * + * Revision 1.14 1999/05/22 07:55:06 calle + * Added *V110* to AVM B1 driver. + * + * Revision 1.13 1998/06/26 15:12:55 fritz + * Added handling of STAT_ICALL with incomplete CPN. + * Added AT&L for ttyI emulator. + * Added more locking stuff in tty_write. + * + * Revision 1.12 1998/03/29 16:06:03 calle + * changes from 2.0 tree merged. + * + * Revision 1.3.2.10 1998/03/20 14:38:24 calle + * capidrv: prepared state machines for suspend/resume/hold + * capidrv: fix bug in state machine if B1/T1 is out of nccis + * b1capi: changed some errno returns. + * b1capi: detect if you try to add same T1 to different io address. + * b1capi: change number of nccis depending on number of channels. + * b1lli: cosmetics + * + * Revision 1.3.2.9 1998/03/20 09:01:12 calle + * Changes capi_register handling to get full support for 30 bchannels. + * + * Revision 1.3.2.8 1998/03/18 17:51:28 calle + * added controller number to error messages + * + * Revision 1.3.2.7 1998/02/27 15:40:47 calle + * T1 running with slow link. bugfix in capi_release. + * * Revision 1.11 1998/02/13 07:09:15 calle * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * @@ -71,15 +143,18 @@ #include #include #include +#include #include #include +#include +#include -#include "compat.h" +#include #include "capiutil.h" #include "capicmd.h" #include "capidrv.h" -static char *revision = "$Revision: 1.11 $"; +static char *revision = "$Revision: 1.23 $"; int debugmode = 0; MODULE_AUTHOR("Carsten Paeth "); @@ -135,6 +210,7 @@ __u16 msgid; /* to identfy CONNECT_CONF */ int chan; int state; + int leasedline; struct capidrv_ncci { struct capidrv_ncci *next; struct capidrv_plci *plcip; @@ -169,6 +245,12 @@ __u16 appid; int ncontr; struct capidrv_contr *contr_list; + + /* statistic */ + unsigned long nrecvctlpkt; + unsigned long nrecvdatapkt; + unsigned long nsentctlpkt; + unsigned long nsentdatapkt; }; typedef struct capidrv_plci capidrv_plci; @@ -199,6 +281,10 @@ return 0; case ISDN_PROTO_L2_TRANS: return 1; + case ISDN_PROTO_L2_V11096: + case ISDN_PROTO_L2_V11019: + case ISDN_PROTO_L2_V11038: + return 2; } } @@ -212,6 +298,9 @@ return 0; case ISDN_PROTO_L2_HDLC: case ISDN_PROTO_L2_TRANS: + case ISDN_PROTO_L2_V11096: + case ISDN_PROTO_L2_V11019: + case ISDN_PROTO_L2_V11038: return 1; } } @@ -224,8 +313,43 @@ case ISDN_PROTO_L2_X75BUI: case ISDN_PROTO_L2_HDLC: case ISDN_PROTO_L2_TRANS: + case ISDN_PROTO_L2_V11096: + case ISDN_PROTO_L2_V11019: + case ISDN_PROTO_L2_V11038: + default: + return 0; + } +} + +static _cstruct b1config_sync_v110(__u16 rate) +{ + /* CAPI-Spec "B1 Configuration" */ + static unsigned char buf[9]; + buf[0] = 8; /* len */ + /* maximum bitrate */ + buf[1] = rate & 0xff; buf[2] = (rate >> 8) & 0xff; + buf[3] = buf[4] = 0; /* reserved, bits per character */ + buf[5] = buf[6] = 0; /* reserved, parity */ + buf[7] = buf[9] = 0; /* reserved, stop bits */ + return buf; +} + +static _cstruct b1config(int l2, int l3) +{ + switch (l2) { + case ISDN_PROTO_L2_X75I: + case ISDN_PROTO_L2_X75UI: + case ISDN_PROTO_L2_X75BUI: + case ISDN_PROTO_L2_HDLC: + case ISDN_PROTO_L2_TRANS: default: return 0; + case ISDN_PROTO_L2_V11096: + return b1config_sync_v110(9600); + case ISDN_PROTO_L2_V11019: + return b1config_sync_v110(19200); + case ISDN_PROTO_L2_V11038: + return b1config_sync_v110(38400); } } @@ -378,8 +502,8 @@ return; } } - printk(KERN_ERR "capidrv: free_plci %p (0x%x) not found, Huh?\n", - plcip, plcip->plci); + printk(KERN_ERR "capidrv-%d: free_plci %p (0x%x) not found, Huh?\n", + card->contrnr, plcip, plcip->plci); } /* -------- ncci management ------------------------------------------ */ @@ -497,9 +621,10 @@ size_t len; capi_cmsg2message(cmsg, cmsg->buf); len = CAPIMSG_LEN(cmsg->buf); - skb = dev_alloc_skb(len); + skb = alloc_skb(len, GFP_ATOMIC); memcpy(skb_put(skb, len), cmsg->buf, len); (*capifuncs->capi_put_message) (global.appid, skb); + global.nsentctlpkt++; } /* -------- state machine -------------------------------------------- */ @@ -512,15 +637,15 @@ static struct listenstatechange listentable[] = { - {ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ}, - {ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ}, - {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR}, - {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR}, - {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY}, - {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY}, - {ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK}, - {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK}, - {}, + {ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ}, + {ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ}, + {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR}, + {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR}, + {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY}, + {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY}, + {ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK}, + {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK}, + {}, }; static void listen_change_state(capidrv_contr * card, int event) @@ -529,15 +654,15 @@ while (p->event) { if (card->state == p->actstate && p->event == event) { if (debugmode) - printk(KERN_DEBUG "capidrv: listen_change_state %d -> %d\n", - card->state, p->nextstate); + printk(KERN_DEBUG "capidrv-%d: listen_change_state %d -> %d\n", + card->contrnr, card->state, p->nextstate); card->state = p->nextstate; return; } p++; } - printk(KERN_ERR "capidrv: listen_change_state state=%d event=%d ????\n", - card->state, event); + printk(KERN_ERR "capidrv-%d: listen_change_state state=%d event=%d ????\n", + card->contrnr, card->state, event); } @@ -567,46 +692,57 @@ static struct plcistatechange plcitable[] = { /* P-0 */ - {ST_PLCI_NONE, ST_PLCI_OUTGOING, EV_PLCI_CONNECT_REQ, 0}, - {ST_PLCI_NONE, ST_PLCI_ALLOCATED, EV_PLCI_FACILITY_IND_UP, 0}, - {ST_PLCI_NONE, ST_PLCI_INCOMING, EV_PLCI_CONNECT_IND, 0}, + {ST_PLCI_NONE, ST_PLCI_OUTGOING, EV_PLCI_CONNECT_REQ, 0}, + {ST_PLCI_NONE, ST_PLCI_ALLOCATED, EV_PLCI_FACILITY_IND_UP, 0}, + {ST_PLCI_NONE, ST_PLCI_INCOMING, EV_PLCI_CONNECT_IND, 0}, + {ST_PLCI_NONE, ST_PLCI_RESUMEING, EV_PLCI_RESUME_REQ, 0}, /* P-0.1 */ - {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0}, - {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, 0}, - {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, - {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, + {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0}, + {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, 0}, + {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, + {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, /* P-1 */ - {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0}, - {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, -{ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, - {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, + {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0}, + {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, + {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, + {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, /* P-ACT */ - {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, - {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, - {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, + {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, + {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, + {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, + {ST_PLCI_ACTIVE, ST_PLCI_HELD, EV_PLCI_HOLD_IND, 0}, + {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_SUSPEND_IND, 0}, /* P-2 */ - {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0}, - {ST_PLCI_INCOMING, ST_PLCI_FACILITY_IND, EV_PLCI_FACILITY_IND_UP, 0}, - {ST_PLCI_INCOMING, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_RESP, 0}, - {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, - {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, - {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, + {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0}, + {ST_PLCI_INCOMING, ST_PLCI_FACILITY_IND, EV_PLCI_FACILITY_IND_UP, 0}, + {ST_PLCI_INCOMING, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_RESP, 0}, + {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, + {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, + {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, + {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CD_IND, 0}, /* P-3 */ -{ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0}, -{ST_PLCI_FACILITY_IND, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_ACTIVE_IND, 0}, -{ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, - {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, - {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, + {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0}, + {ST_PLCI_FACILITY_IND, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_ACTIVE_IND, 0}, + {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, + {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, + {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, /* P-4 */ - {ST_PLCI_ACCEPTING, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0}, - {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, -{ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, - {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, + {ST_PLCI_ACCEPTING, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0}, + {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, + {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, + {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, /* P-5 */ -{ST_PLCI_DISCONNECTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, + {ST_PLCI_DISCONNECTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, /* P-6 */ - {ST_PLCI_DISCONNECTED, ST_PLCI_NONE, EV_PLCI_DISCONNECT_RESP, p0}, - {}, + {ST_PLCI_DISCONNECTED, ST_PLCI_NONE, EV_PLCI_DISCONNECT_RESP, p0}, + /* P-0.Res */ + {ST_PLCI_RESUMEING, ST_PLCI_NONE, EV_PLCI_RESUME_CONF_ERROR, p0}, + {ST_PLCI_RESUMEING, ST_PLCI_RESUME, EV_PLCI_RESUME_CONF_OK, 0}, + /* P-RES */ + {ST_PLCI_RESUME, ST_PLCI_ACTIVE, EV_PLCI_RESUME_IND, 0}, + /* P-HELD */ + {ST_PLCI_HELD, ST_PLCI_ACTIVE, EV_PLCI_RETRIEVE_IND, 0}, + {}, }; static void plci_change_state(capidrv_contr * card, capidrv_plci * plci, int event) @@ -615,8 +751,8 @@ while (p->event) { if (plci->state == p->actstate && p->event == event) { if (debugmode) - printk(KERN_DEBUG "capidrv: plci_change_state:0x%x %d -> %d\n", - plci->plci, plci->state, p->nextstate); + printk(KERN_DEBUG "capidrv-%d: plci_change_state:0x%x %d -> %d\n", + card->contrnr, plci->plci, plci->state, p->nextstate); plci->state = p->nextstate; if (p->changefunc) p->changefunc(card, plci); @@ -624,8 +760,8 @@ } p++; } - printk(KERN_ERR "capidrv: plci_change_state:0x%x state=%d event=%d ????\n", - plci->plci, plci->state, event); + printk(KERN_ERR "capidrv-%d: plci_change_state:0x%x state=%d event=%d ????\n", + card->contrnr, plci->plci, plci->state, event); } /* ------------------------------------------------------------------ */ @@ -642,7 +778,7 @@ ncci->plcip->plci, 0, /* BChannelinformation */ 0, /* Keypadfacility */ - 0, /* Useruserdata */ + 0, /* Useruserdata */ /* $$$$ */ 0 /* Facilitydataarray */ ); send_message(card, &cmsg); @@ -667,34 +803,35 @@ static struct nccistatechange nccitable[] = { /* N-0 */ - {ST_NCCI_NONE, ST_NCCI_OUTGOING, EV_NCCI_CONNECT_B3_REQ, 0}, - {ST_NCCI_NONE, ST_NCCI_INCOMING, EV_NCCI_CONNECT_B3_IND, 0}, + {ST_NCCI_NONE, ST_NCCI_OUTGOING, EV_NCCI_CONNECT_B3_REQ, 0}, + {ST_NCCI_NONE, ST_NCCI_INCOMING, EV_NCCI_CONNECT_B3_IND, 0}, /* N-0.1 */ - {ST_NCCI_OUTGOING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_CONF_OK, 0}, - {ST_NCCI_OUTGOING, ST_NCCI_NONE, EV_NCCI_CONNECT_B3_CONF_ERROR, 0}, + {ST_NCCI_OUTGOING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_CONF_OK, 0}, + {ST_NCCI_OUTGOING, ST_NCCI_NONE, EV_NCCI_CONNECT_B3_CONF_ERROR, n0}, /* N-1 */ - {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_CONNECT_B3_REJECT, 0}, - {ST_NCCI_INCOMING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_RESP, 0}, + {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_CONNECT_B3_REJECT, 0}, + {ST_NCCI_INCOMING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_RESP, 0}, {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0}, - {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0}, + {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0}, /* N-2 */ - {ST_NCCI_ALLOCATED, ST_NCCI_ACTIVE, EV_NCCI_CONNECT_B3_ACTIVE_IND, 0}, - {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0}, -{ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0}, + {ST_NCCI_ALLOCATED, ST_NCCI_ACTIVE, EV_NCCI_CONNECT_B3_ACTIVE_IND, 0}, + {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0}, + {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0}, /* N-ACT */ - {ST_NCCI_ACTIVE, ST_NCCI_RESETING, EV_NCCI_RESET_B3_REQ, 0}, - {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0}, - {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0}, + {ST_NCCI_ACTIVE, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0}, + {ST_NCCI_ACTIVE, ST_NCCI_RESETING, EV_NCCI_RESET_B3_REQ, 0}, + {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0}, + {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0}, /* N-3 */ - {ST_NCCI_RESETING, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0}, + {ST_NCCI_RESETING, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0}, {ST_NCCI_RESETING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0}, - {ST_NCCI_RESETING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0}, + {ST_NCCI_RESETING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0}, /* N-4 */ - {ST_NCCI_DISCONNECTING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0}, - {ST_NCCI_DISCONNECTING, ST_NCCI_PREVIOUS, EV_NCCI_DISCONNECT_B3_CONF_ERROR, 0}, + {ST_NCCI_DISCONNECTING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0}, + {ST_NCCI_DISCONNECTING, ST_NCCI_PREVIOUS, EV_NCCI_DISCONNECT_B3_CONF_ERROR,0}, /* N-5 */ - {ST_NCCI_DISCONNECTED, ST_NCCI_NONE, EV_NCCI_DISCONNECT_B3_RESP, n0}, - {}, + {ST_NCCI_DISCONNECTED, ST_NCCI_NONE, EV_NCCI_DISCONNECT_B3_RESP, n0}, + {}, }; static void ncci_change_state(capidrv_contr * card, capidrv_ncci * ncci, int event) @@ -703,8 +840,8 @@ while (p->event) { if (ncci->state == p->actstate && p->event == event) { if (debugmode) - printk(KERN_DEBUG "capidrv: ncci_change_state:0x%x %d -> %d\n", - ncci->ncci, ncci->state, p->nextstate); + printk(KERN_DEBUG "capidrv-%d: ncci_change_state:0x%x %d -> %d\n", + card->contrnr, ncci->ncci, ncci->state, p->nextstate); if (p->nextstate == ST_NCCI_PREVIOUS) { ncci->state = ncci->oldstate; ncci->oldstate = p->actstate; @@ -718,8 +855,8 @@ } p++; } - printk(KERN_ERR "capidrv: ncci_change_state:0x%x state=%d event=%d ????\n", - ncci->ncci, ncci->state, event); + printk(KERN_ERR "capidrv-%d: ncci_change_state:0x%x state=%d event=%d ????\n", + card->contrnr, ncci->ncci, ncci->state, event); } /* ------------------------------------------------------------------- */ @@ -752,8 +889,8 @@ case CAPI_LISTEN_CONF: /* Controller */ if (debugmode) - printk(KERN_DEBUG "capidrv: listenconf Info=0x%4x (%s) cipmask=0x%x\n", - cmsg->Info, capi_info2str(cmsg->Info), card->cipmask); + printk(KERN_DEBUG "capidrv-%d: listenconf Info=0x%4x (%s) cipmask=0x%x\n", + card->contrnr, cmsg->Info, capi_info2str(cmsg->Info), card->cipmask); if (cmsg->Info) { listen_change_state(card, EV_LISTEN_CONF_ERROR); } else if (card->cipmask == 0) { @@ -789,7 +926,8 @@ handle_dtrace_data(card, direction, 0, data, len); break; } - printk(KERN_INFO "capidrv: %s from controller 0x%x layer 0x%x, ignored\n", + printk(KERN_INFO "capidrv-%d: %s from controller 0x%x layer 0x%x, ignored\n", + card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrController, layer); break; @@ -805,7 +943,8 @@ default: s = "unkown error"; break; } if (s) - printk(KERN_INFO "capidrv: %s from controller 0x%x function %d: %s\n", + printk(KERN_INFO "capidrv-%d: %s from controller 0x%x function %d: %s\n", + card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrController, cmsg->Function, s); @@ -822,14 +961,16 @@ goto ignored; default: - printk(KERN_ERR "capidrv: got %s from controller 0x%x ???", + printk(KERN_ERR "capidrv-%d: got %s from controller 0x%x ???", + card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrController); } return; ignored: - printk(KERN_INFO "capidrv: %s from controller 0x%x ignored\n", + printk(KERN_INFO "capidrv-%d: %s from controller 0x%x ignored\n", + card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrController); } @@ -842,12 +983,12 @@ int chan; if ((chan = new_bchan(card)) == -1) { - printk(KERN_ERR "capidrv: incoming call on not existing bchan ?\n"); + printk(KERN_ERR "capidrv-%d: incoming call on not existing bchan ?\n", card->contrnr); return; } bchan = &card->bchans[chan]; if ((plcip = new_plci(card, chan)) == 0) { - printk(KERN_ERR "capidrv: incoming call: no memory, sorry.\n"); + printk(KERN_ERR "capidrv-%d: incoming call: no memory, sorry.\n", card->contrnr); return; } bchan->incoming = 1; @@ -869,7 +1010,8 @@ cmd.parm.setup.plan = cmsg->CallingPartyNumber[1]; cmd.parm.setup.screen = cmsg->CallingPartyNumber[2]; - printk(KERN_INFO "capidrv: incoming call %s,%d,%d,%s\n", + printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s\n", + card->contrnr, cmd.parm.setup.phone, cmd.parm.setup.si1, cmd.parm.setup.si2, @@ -877,6 +1019,7 @@ switch (card->interface.statcallb(&cmd)) { case 0: + case 3: /* No device matching this call. * and isdn_common.c has send a HANGUP command * which is ignored in state ST_PLCI_INCOMING, @@ -886,7 +1029,8 @@ cmsg->Reject = 1; /* ignore */ send_message(card, cmsg); plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT); - printk(KERN_INFO "capidrv: incoming call %s,%d,%d,%s ignored\n", + printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignored\n", + card->contrnr, cmd.parm.setup.phone, cmd.parm.setup.si1, cmd.parm.setup.si2, @@ -903,7 +1047,8 @@ * and CONNECT_RESP already sent. */ if (plcip->state == ST_PLCI_INCOMING) { - printk(KERN_INFO "capidrv: incoming call %s,%d,%d,%s tty alerting\n", + printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s tty alerting\n", + card->contrnr, cmd.parm.setup.phone, cmd.parm.setup.si1, cmd.parm.setup.si2, @@ -920,7 +1065,8 @@ plcip->msgid = cmsg->Messagenumber; send_message(card, cmsg); } else { - printk(KERN_INFO "capidrv: incoming call %s,%d,%d,%s on netdev\n", + printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s on netdev\n", + card->contrnr, cmd.parm.setup.phone, cmd.parm.setup.si1, cmd.parm.setup.si2, @@ -963,7 +1109,8 @@ case CAPI_DISCONNECT_IND: /* plci */ if (cmsg->Reason) { - printk(KERN_INFO "capidrv: %s reason 0x%x (%s) for plci 0x%x\n", + printk(KERN_INFO "capidrv-%d: %s reason 0x%x (%s) for plci 0x%x\n", + card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->Reason, capi_info2str(cmsg->Reason), cmsg->adr.adrPLCI); } @@ -981,7 +1128,8 @@ case CAPI_DISCONNECT_CONF: /* plci */ if (cmsg->Info) { - printk(KERN_INFO "capidrv: %s info 0x%x (%s) for plci 0x%x\n", + printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n", + card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->Info, capi_info2str(cmsg->Info), cmsg->adr.adrPLCI); @@ -994,7 +1142,8 @@ case CAPI_ALERT_CONF: /* plci */ if (cmsg->Info) { - printk(KERN_INFO "capidrv: %s info 0x%x (%s) for plci 0x%x\n", + printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n", + card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->Info, capi_info2str(cmsg->Info), cmsg->adr.adrPLCI); @@ -1007,7 +1156,8 @@ case CAPI_CONNECT_CONF: /* plci */ if (cmsg->Info) { - printk(KERN_INFO "capidrv: %s info 0x%x (%s) for plci 0x%x\n", + printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n", + card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->Info, capi_info2str(cmsg->Info), cmsg->adr.adrPLCI); @@ -1040,7 +1190,7 @@ nccip = new_ncci(card, plcip, cmsg->adr.adrPLCI); if (!nccip) { - printk(KERN_ERR "capidrv: no mem for ncci, sorry\n"); + printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr); break; /* $$$$ */ } capi_fill_CONNECT_B3_REQ(cmsg, @@ -1080,7 +1230,8 @@ break; } } - printk(KERN_ERR "capidrv: %s\n", capi_cmsg2str(cmsg)); + printk(KERN_ERR "capidrv-%d: %s\n", + card->contrnr, capi_cmsg2str(cmsg)); break; case CAPI_CONNECT_ACTIVE_CONF: /* plci */ @@ -1096,18 +1247,21 @@ goto ignored; default: - printk(KERN_ERR "capidrv: got %s for plci 0x%x ???", + printk(KERN_ERR "capidrv-%d: got %s for plci 0x%x ???", + card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrPLCI); } return; ignored: - printk(KERN_INFO "capidrv: %s for plci 0x%x ignored\n", + printk(KERN_INFO "capidrv-%d: %s for plci 0x%x ignored\n", + card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrPLCI); return; notfound: - printk(KERN_ERR "capidrv: %s: plci 0x%x not found\n", + printk(KERN_ERR "capidrv-%d: %s: plci 0x%x not found\n", + card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrPLCI); return; @@ -1142,8 +1296,8 @@ cmd.arg = nccip->chan; card->interface.statcallb(&cmd); - printk(KERN_INFO "capidrv: chan %d up with ncci 0x%x\n", - nccip->chan, nccip->ncci); + printk(KERN_INFO "capidrv-%d: chan %d up with ncci 0x%x\n", + card->contrnr, nccip->chan, nccip->ncci); break; case CAPI_CONNECT_B3_ACTIVE_CONF: /* ncci */ @@ -1167,9 +1321,10 @@ ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP); break; } - printk(KERN_ERR "capidrv: no mem for ncci, sorry\n"); + printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr); } else { - printk(KERN_ERR "capidrv: %s: plci for ncci 0x%x not found\n", + printk(KERN_ERR "capidrv-%d: %s: plci for ncci 0x%x not found\n", + card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrNCCI); } @@ -1192,7 +1347,8 @@ nccip->ncci = cmsg->adr.adrNCCI; if (cmsg->Info) { - printk(KERN_INFO "capidrv: %s info 0x%x (%s) for ncci 0x%x\n", + printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n", + card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->Info, capi_info2str(cmsg->Info), cmsg->adr.adrNCCI); @@ -1242,7 +1398,8 @@ if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) goto notfound; if (cmsg->Info) { - printk(KERN_INFO "capidrv: %s info 0x%x (%s) for ncci 0x%x\n", + printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n", + card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->Info, capi_info2str(cmsg->Info), cmsg->adr.adrNCCI); @@ -1251,6 +1408,9 @@ break; case CAPI_RESET_B3_IND: /* ncci */ + if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) + goto notfound; + ncci_change_state(card, nccip, EV_NCCI_RESET_B3_IND); capi_cmsg_answer(cmsg); send_message(card, cmsg); break; @@ -1264,18 +1424,21 @@ goto ignored; default: - printk(KERN_ERR "capidrv: got %s for ncci 0x%x ???", + printk(KERN_ERR "capidrv-%d: got %s for ncci 0x%x ???", + card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrNCCI); } return; ignored: - printk(KERN_INFO "capidrv: %s for ncci 0x%x ignored\n", + printk(KERN_INFO "capidrv-%d: %s for ncci 0x%x ignored\n", + card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrNCCI); return; notfound: - printk(KERN_ERR "capidrv: %s: ncci 0x%x not found\n", + printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n", + card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrNCCI); } @@ -1290,10 +1453,12 @@ printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n", capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrController & 0x7f); + kfree_skb(skb); return; } if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) { - printk(KERN_ERR "capidrv: %s: ncci 0x%x not found\n", + printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n", + card->contrnr, capi_cmd2str(cmsg->Command, cmsg->Subcommand), cmsg->adr.adrNCCI); kfree_skb(skb); @@ -1313,21 +1478,29 @@ while ((*capifuncs->capi_get_message) (global.appid, &skb) == CAPI_NOERROR) { capi_message2cmsg(&s_cmsg, skb->data); - if (debugmode > 1) - printk(KERN_DEBUG "capidrv_signal: %s\n", capi_cmsg2str(&s_cmsg)); + if (debugmode > 2) + printk(KERN_DEBUG "capidrv_signal: applid=%d %s\n", + applid, capi_cmsg2str(&s_cmsg)); if (s_cmsg.Command == CAPI_DATA_B3 && s_cmsg.Subcommand == CAPI_IND) { handle_data(&s_cmsg, skb); + global.nrecvdatapkt++; continue; } - kfree_skb(skb); if ((s_cmsg.adr.adrController & 0xffffff00) == 0) handle_controller(&s_cmsg); else if ((s_cmsg.adr.adrPLCI & 0xffff0000) == 0) handle_plci(&s_cmsg); else handle_ncci(&s_cmsg); + /* + * data of skb used in s_cmsg, + * free data when s_cmsg is not used again + * thanks to Lars Heete + */ + kfree_skb(skb); + global.nrecvctlpkt++; } } @@ -1348,7 +1521,8 @@ isdn_ctrl cmd; if (!len) { - printk(KERN_DEBUG "avmb1_q931_data: len == %d\n", len); + printk(KERN_DEBUG "capidrv-%d: avmb1_q931_data: len == %d\n", + card->contrnr, len); return; } @@ -1392,18 +1566,116 @@ static int capidrv_ioctl(isdn_ctrl * c, capidrv_contr * card) { switch (c->arg) { + case 1: + debugmode = (int)(*((unsigned int *)c->parm.num)); + printk(KERN_DEBUG "capidrv-%d: debugmode=%d\n", + card->contrnr, debugmode); + return 0; default: - printk(KERN_DEBUG "capidrv: capidrv_ioctl(%ld) called ??\n", c->arg); + printk(KERN_DEBUG "capidrv-%d: capidrv_ioctl(%ld) called ??\n", + card->contrnr, c->arg); return -EINVAL; } return -EINVAL; } +/* + * Handle leased lines (CAPI-Bundling) + */ + +struct internal_bchannelinfo { + unsigned short channelalloc; + unsigned short operation; + unsigned char cmask[31]; +}; + +static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep) +{ + unsigned long bmask = 0; + int active = !0; + char *s; + int i; + + if (strncmp(teln, "FV:", 3) != 0) + return 1; + s = teln + 3; + while (*s && *s == ' ') s++; + if (!*s) return -2; + if (*s == 'p' || *s == 'P') { + active = 0; + s++; + } + if (*s == 'a' || *s == 'A') { + active = !0; + s++; + } + while (*s) { + int digit1 = 0; + int digit2 = 0; + if (!isdigit(*s)) return -3; + while (isdigit(*s)) { digit1 = digit1*10 + (*s - '0'); s++; } + if (digit1 <= 0 && digit1 > 30) return -4; + if (*s == 0 || *s == ',' || *s == ' ') { + bmask |= (1 << digit1); + digit1 = 0; + if (*s) s++; + continue; + } + if (*s != '-') return -5; + s++; + if (!isdigit(*s)) return -3; + while (isdigit(*s)) { digit2 = digit2*10 + (*s - '0'); s++; } + if (digit2 <= 0 && digit2 > 30) return -4; + if (*s == 0 || *s == ',' || *s == ' ') { + if (digit1 > digit2) + for (i = digit2; i <= digit1 ; i++) + bmask |= (1 << i); + else + for (i = digit1; i <= digit2 ; i++) + bmask |= (1 << i); + digit1 = digit2 = 0; + if (*s) s++; + continue; + } + return -6; + } + if (activep) *activep = active; + if (bmaskp) *bmaskp = bmask; + return 0; +} + +static int FVteln2capi20(char *teln, __u8 AdditionalInfo[1+2+2+31]) +{ + unsigned long bmask; + int active; + int rc, i; + + rc = decodeFVteln(teln, &bmask, &active); + if (rc) return rc; + /* Length */ + AdditionalInfo[0] = 2+2+31; + /* Channel: 3 => use channel allocation */ + AdditionalInfo[1] = 3; AdditionalInfo[2] = 0; + /* Operation: 0 => DTE mode, 1 => DCE mode */ + if (active) { + AdditionalInfo[3] = 0; AdditionalInfo[4] = 0; + } else { + AdditionalInfo[3] = 1; AdditionalInfo[4] = 0; + } + /* Channel mask array */ + AdditionalInfo[5] = 0; /* no D-Channel */ + for (i=1; i <= 30; i++) + AdditionalInfo[5+i] = (bmask & (1 << i)) ? 0xff : 0; + return 0; +} + static int capidrv_command(isdn_ctrl * c, capidrv_contr * card) { isdn_ctrl cmd; struct capidrv_bchan *bchan; struct capidrv_plci *plcip; + __u8 AdditionalInfo[1+2+2+31]; + int rc, isleasedline = 0; if (c->command == ISDN_CMD_IOCTL) return capidrv_ioctl(c, card); @@ -1414,7 +1686,8 @@ __u8 called[ISDN_MSNLEN + 2]; if (debugmode) - printk(KERN_DEBUG "capidrv: ISDN_CMD_DIAL(ch=%ld,\"%s,%d,%d,%s\")\n", + printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_DIAL(ch=%ld,\"%s,%d,%d,%s\")\n", + card->contrnr, c->arg, c->parm.setup.phone, c->parm.setup.si1, @@ -1424,7 +1697,8 @@ bchan = &card->bchans[c->arg % card->nbchan]; if (bchan->plcip) { - printk(KERN_ERR "capidrv: dail ch=%ld,\"%s,%d,%d,%s\" in use (plci=0x%x)\n", + printk(KERN_ERR "capidrv-%d: dail ch=%ld,\"%s,%d,%d,%s\" in use (plci=0x%x)\n", + card->contrnr, c->arg, c->parm.setup.phone, c->parm.setup.si1, @@ -1438,15 +1712,25 @@ strncpy(bchan->num, c->parm.setup.phone, sizeof(bchan->num)); strncpy(bchan->mynum, c->parm.setup.eazmsn, sizeof(bchan->mynum)); - - calling[0] = strlen(bchan->mynum) + 2; - calling[1] = 0; - calling[2] = 0x80; - strncpy(calling + 3, bchan->mynum, ISDN_MSNLEN); - - called[0] = strlen(bchan->num) + 1; - called[1] = 0x80; - strncpy(called + 2, bchan->num, ISDN_MSNLEN); + rc = FVteln2capi20(bchan->num, AdditionalInfo); + isleasedline = (rc == 0); + if (rc < 0) + printk(KERN_ERR "capidrv-%d: WARNING: illegal leased linedefinition \"%s\"\n", card->contrnr, bchan->num); + + if (isleasedline) { + calling[0] = 0; + called[0] = 0; + if (debugmode) + printk(KERN_DEBUG "capidrv-%d: connecting leased line\n", card->contrnr); + } else { + calling[0] = strlen(bchan->mynum) + 2; + calling[1] = 0; + calling[2] = 0x80; + strncpy(calling + 3, bchan->mynum, ISDN_MSNLEN); + called[0] = strlen(bchan->num) + 1; + called[1] = 0x80; + strncpy(called + 2, bchan->num, ISDN_MSNLEN); + } capi_fill_CONNECT_REQ(&cmdcmsg, global.appid, @@ -1460,13 +1744,14 @@ b1prot(bchan->l2, bchan->l3), /* B1protocol */ b2prot(bchan->l2, bchan->l3), /* B2protocol */ b3prot(bchan->l2, bchan->l3), /* B3protocol */ - 0, /* B1configuration */ + b1config(bchan->l2, bchan->l3), /* B1configuration */ 0, /* B2configuration */ 0, /* B3configuration */ 0, /* BC */ 0, /* LLC */ 0, /* HLC */ - 0, /* BChannelinformation */ + /* BChannelinformation */ + isleasedline ? AdditionalInfo : 0, 0, /* Keypadfacility */ 0, /* Useruserdata */ 0 /* Facilitydataarray */ @@ -1479,6 +1764,7 @@ return -1; } plcip->msgid = cmdcmsg.Messagenumber; + plcip->leasedline = isleasedline; plci_change_state(card, plcip, EV_PLCI_CONNECT_REQ); send_message(card, &cmdcmsg); return 0; @@ -1486,10 +1772,11 @@ case ISDN_CMD_ACCEPTD: - if (debugmode) - printk(KERN_DEBUG "capidrv: ISDN_CMD_ACCEPTD(ch=%ld)\n", - c->arg); bchan = &card->bchans[c->arg % card->nbchan]; + if (debugmode) + printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTD(ch=%ld) l2=%d l3=%d\n", + card->contrnr, + c->arg, bchan->l2, bchan->l3); capi_fill_CONNECT_RESP(&cmdcmsg, global.appid, @@ -1499,7 +1786,7 @@ b1prot(bchan->l2, bchan->l3), /* B1protocol */ b2prot(bchan->l2, bchan->l3), /* B2protocol */ b3prot(bchan->l2, bchan->l3), /* B3protocol */ - 0, /* B1configuration */ + b1config(bchan->l2, bchan->l3), /* B1configuration */ 0, /* B2configuration */ 0, /* B3configuration */ 0, /* ConnectedNumber */ @@ -1517,19 +1804,22 @@ case ISDN_CMD_ACCEPTB: if (debugmode) - printk(KERN_DEBUG "capidrv: ISDN_CMD_ACCEPTB(ch=%ld)\n", + printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTB(ch=%ld)\n", + card->contrnr, c->arg); return -ENOSYS; case ISDN_CMD_HANGUP: if (debugmode) - printk(KERN_DEBUG "capidrv: ISDN_CMD_HANGUP(ch=%ld)\n", + printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_HANGUP(ch=%ld)\n", + card->contrnr, c->arg); bchan = &card->bchans[c->arg % card->nbchan]; if (bchan->disconnecting) { if (debugmode) - printk(KERN_DEBUG "capidrv: chan %ld already disconnecting ...\n", + printk(KERN_DEBUG "capidrv-%d: chan %ld already disconnecting ...\n", + card->contrnr, c->arg); return 0; } @@ -1568,23 +1858,26 @@ case ISDN_CMD_SETL2: if (debugmode) - printk(KERN_DEBUG "capidrv: set L2 on chan %ld to %ld\n", + printk(KERN_DEBUG "capidrv-%d: set L2 on chan %ld to %ld\n", + card->contrnr, (c->arg & 0xff), (c->arg >> 8)); - bchan = &card->bchans[c->arg % card->nbchan]; + bchan = &card->bchans[(c->arg & 0xff) % card->nbchan]; bchan->l2 = (c->arg >> 8); return 0; case ISDN_CMD_SETL3: if (debugmode) - printk(KERN_DEBUG "capidrv: set L3 on chan %ld to %ld\n", + printk(KERN_DEBUG "capidrv-%d: set L3 on chan %ld to %ld\n", + card->contrnr, (c->arg & 0xff), (c->arg >> 8)); - bchan = &card->bchans[c->arg % card->nbchan]; + bchan = &card->bchans[(c->arg & 0xff) % card->nbchan]; bchan->l3 = (c->arg >> 8); return 0; case ISDN_CMD_SETEAZ: if (debugmode) - printk(KERN_DEBUG "capidrv: set EAZ \"%s\" on chan %ld\n", + printk(KERN_DEBUG "capidrv-%d: set EAZ \"%s\" on chan %ld\n", + card->contrnr, c->parm.num, c->arg); bchan = &card->bchans[c->arg % card->nbchan]; strncpy(bchan->msn, c->parm.num, ISDN_MSNLEN); @@ -1592,46 +1885,54 @@ case ISDN_CMD_CLREAZ: if (debugmode) - printk(KERN_DEBUG "capidrv: clearing EAZ on chan %ld\n", c->arg); + printk(KERN_DEBUG "capidrv-%d: clearing EAZ on chan %ld\n", + card->contrnr, c->arg); bchan = &card->bchans[c->arg % card->nbchan]; bchan->msn[0] = 0; return 0; case ISDN_CMD_LOCK: if (debugmode > 1) - printk(KERN_DEBUG "capidrv: ISDN_CMD_LOCK (%ld)\n", c->arg); + printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_LOCK (%ld)\n", card->contrnr, c->arg); MOD_INC_USE_COUNT; break; case ISDN_CMD_UNLOCK: if (debugmode > 1) - printk(KERN_DEBUG "capidrv: ISDN_CMD_UNLOCK (%ld)\n", c->arg); + printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_UNLOCK (%ld)\n", + card->contrnr, c->arg); MOD_DEC_USE_COUNT; break; /* never called */ case ISDN_CMD_GETL2: if (debugmode) - printk(KERN_DEBUG "capidrv: ISDN_CMD_GETL2\n"); + printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL2\n", + card->contrnr); return -ENODEV; case ISDN_CMD_GETL3: if (debugmode) - printk(KERN_DEBUG "capidrv: ISDN_CMD_GETL3\n"); + printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL3\n", + card->contrnr); return -ENODEV; case ISDN_CMD_GETEAZ: if (debugmode) - printk(KERN_DEBUG "capidrv: ISDN_CMD_GETEAZ\n"); + printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETEAZ\n", + card->contrnr); return -ENODEV; case ISDN_CMD_SETSIL: if (debugmode) - printk(KERN_DEBUG "capidrv: ISDN_CMD_SETSIL\n"); + printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_SETSIL\n", + card->contrnr); return -ENODEV; case ISDN_CMD_GETSIL: if (debugmode) - printk(KERN_DEBUG "capidrv: ISDN_CMD_GETSIL\n"); + printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETSIL\n", + card->contrnr); return -ENODEV; default: - printk(KERN_ERR "capidrv: ISDN_CMD_%d, Huh?\n", c->command); + printk(KERN_ERR "capidrv-%d: ISDN_CMD_%d, Huh?\n", + card->contrnr, c->command); return -EINVAL; } return 0; @@ -1645,8 +1946,8 @@ return capidrv_command(c, card); printk(KERN_ERR - "capidrv: if_command %d called with invalid driverId %d!\n", - c->command, c->driver); + "capidrv-%d: if_command %d called with invalid driverId %d!\n", + card->contrnr, c->command, c->driver); return -ENODEV; } @@ -1663,15 +1964,18 @@ __u16 datahandle; if (!card) { - printk(KERN_ERR "capidrv: if_sendbuf called with invalid driverId %d!\n", - id); + printk(KERN_ERR "capidrv-%d: if_sendbuf called with invalid driverId %d!\n", + card->contrnr, id); return 0; } + if (debugmode > 1) + printk(KERN_DEBUG "capidrv-%d: sendbuf len=%d skb=%p doack=%d\n", + card->contrnr, len, skb, doack); bchan = &card->bchans[channel % card->nbchan]; nccip = bchan->nccip; if (!nccip || nccip->state != ST_NCCI_ACTIVE) { - printk(KERN_ERR "capidrv: if_sendbuf: %s:%d: chan not up!\n", - card->name, channel); + printk(KERN_ERR "capidrv-%d: if_sendbuf: %s:%d: chan not up!\n", + card->contrnr, card->name, channel); return 0; } datahandle = nccip->datahandle; @@ -1689,22 +1993,23 @@ capi_cmsg2message(&sendcmsg, sendcmsg.buf); msglen = CAPIMSG_LEN(sendcmsg.buf); if (skb_headroom(skb) < msglen) { - struct sk_buff *nskb = dev_alloc_skb(msglen + skb->len); + struct sk_buff *nskb = skb_realloc_headroom(skb, msglen); if (!nskb) { - printk(KERN_ERR "capidrv: if_sendbuf: no memory\n"); + printk(KERN_ERR "capidrv-%d: if_sendbuf: no memory\n", + card->contrnr); (void)capidrv_del_ack(nccip, datahandle); return 0; } -#if 0 - printk(KERN_DEBUG "capidrv: only %d bytes headroom\n", - skb_headroom(skb)); +#if 1 + printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom, need %d\n", + card->contrnr, skb_headroom(skb), msglen); #endif - memcpy(skb_put(nskb, msglen), sendcmsg.buf, msglen); - memcpy(skb_put(nskb, skb->len), skb->data, skb->len); + memcpy(skb_push(nskb, msglen), sendcmsg.buf, msglen); errcode = (*capifuncs->capi_put_message) (global.appid, nskb); if (errcode == CAPI_NOERROR) { dev_kfree_skb(skb); nccip->datahandle++; + global.nsentdatapkt++; return len; } (void)capidrv_del_ack(nccip, datahandle); @@ -1715,8 +2020,10 @@ errcode = (*capifuncs->capi_put_message) (global.appid, skb); if (errcode == CAPI_NOERROR) { nccip->datahandle++; + global.nsentdatapkt++; return len; } + skb_pull(skb, msglen); (void)capidrv_del_ack(nccip, datahandle); return errcode == CAPI_SENDQUEUEFULL ? 0 : -1; } @@ -1729,8 +2036,8 @@ __u8 *p; if (!card) { - printk(KERN_ERR "capidrv: if_readstat called with invalid driverId %d!\n", - id); + printk(KERN_ERR "capidrv-%d: if_readstat called with invalid driverId %d!\n", + card->contrnr, id); return -ENODEV; } @@ -1761,8 +2068,8 @@ return; } if (strstr(manufacturer, "AVM") == 0) { - printk(KERN_ERR "%s: not from AVM, no d-channel trace possible\n", - card->name); + printk(KERN_ERR "%s: not from AVM, no d-channel trace possible (%s)\n", + card->name, manufacturer); return; } errcode = (*capifuncs->capi_get_version)(contr, &version); @@ -1776,7 +2083,7 @@ avmversion[1] |= (version.minormanuversion >> 4) & 0x0f; avmversion[2] |= version.minormanuversion & 0x0f; - if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 5)) { + if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 6)) { printk(KERN_INFO "%s: D2 trace enabled\n", card->name); capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid, card->msgid++, @@ -1798,6 +2105,51 @@ send_message(card, &cmdcmsg); } +static void disable_dchannel_trace(capidrv_contr *card) +{ + __u8 manufacturer[CAPI_MANUFACTURER_LEN]; + capi_version version; + __u16 contr = card->contrnr; + __u16 errcode; + __u16 avmversion[3]; + + errcode = (*capifuncs->capi_get_manufacturer)(contr, manufacturer); + if (errcode != CAPI_NOERROR) { + printk(KERN_ERR "%s: can't get manufacturer (0x%x)\n", + card->name, errcode); + return; + } + if (strstr(manufacturer, "AVM") == 0) { + printk(KERN_ERR "%s: not from AVM, no d-channel trace possible (%s)\n", + card->name, manufacturer); + return; + } + errcode = (*capifuncs->capi_get_version)(contr, &version); + if (errcode != CAPI_NOERROR) { + printk(KERN_ERR "%s: can't get version (0x%x)\n", + card->name, errcode); + return; + } + avmversion[0] = (version.majormanuversion >> 4) & 0x0f; + avmversion[1] = (version.majormanuversion << 4) & 0xf0; + avmversion[1] |= (version.minormanuversion >> 4) & 0x0f; + avmversion[2] |= version.minormanuversion & 0x0f; + + if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 6)) { + printk(KERN_INFO "%s: D2 trace disabled\n", card->name); + } else { + printk(KERN_INFO "%s: D3 trace disabled\n", card->name); + } + capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid, + card->msgid++, + contr, + 0x214D5641, /* ManuID */ + 0, /* Class */ + 1, /* Function */ + (_cstruct)"\004\000\000\000\000"); + send_message(card, &cmdcmsg); +} + static int capidrv_addcontr(__u16 contr, struct capi_profile *profp) { capidrv_contr *card; @@ -1834,6 +2186,9 @@ ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L2_TRANS | ISDN_FEATURE_L3_TRANS | + ISDN_FEATURE_L2_V11096 | + ISDN_FEATURE_L2_V11019 | + ISDN_FEATURE_L2_V11038 | ISDN_FEATURE_P_UNKNOWN; card->interface.hl_hdrlen = 22; /* len of DATA_B3_REQ */ strncpy(card->interface.id, id, sizeof(card->interface.id) - 1); @@ -1878,7 +2233,7 @@ printk(KERN_INFO "%s: now up (%d B channels)\n", card->name, card->nbchan); - enable_dchannel_trace(card); + enable_dchannel_trace(card); return 0; } @@ -1898,6 +2253,15 @@ return -1; } card = *pp; + + if (debugmode) + printk(KERN_DEBUG "capidrv-%d: id=%d unloading\n", + card->contrnr, card->myid); + + cmd.command = ISDN_STAT_UNLOAD; + cmd.driver = card->myid; + card->interface.statcallb(&cmd); + *pp = (*pp)->next; global.ncontr--; @@ -1911,10 +2275,6 @@ } kfree(card->bchans); - cmd.command = ISDN_STAT_UNLOAD; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - printk(KERN_INFO "%s: now down.\n", card->name); kfree(card); @@ -1925,16 +2285,77 @@ static void lower_callback(unsigned int cmd, __u16 contr, void *data) { + switch (cmd) { case KCI_CONTRUP: + printk(KERN_INFO "capidrv: controller %hu up\n", contr); (void) capidrv_addcontr(contr, (capi_profile *) data); break; case KCI_CONTRDOWN: + printk(KERN_INFO "capidrv: controller %hu down\n", contr); (void) capidrv_delcontr(contr); break; } } +/* + * /proc/capi/capidrv: + * nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt + */ +static int proc_capidrv_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = 0; + + len += sprintf(page+len, "%lu %lu %lu %lu\n", + global.nrecvctlpkt, + global.nrecvdatapkt, + global.nsentctlpkt, + global.nsentdatapkt); + if (len < off) + return 0; + *eof = 1; + *start = page -off; + return ((count < len-off) ? count : len-off); +} + +static struct procfsentries { + char *name; + mode_t mode; + int (*read_proc)(char *page, char **start, off_t off, + int count, int *eof, void *data); + struct proc_dir_entry *procent; +} procfsentries[] = { + /* { "capi", S_IFDIR, 0 }, */ + { "capi/capidrv", 0 , proc_capidrv_read_proc }, +}; + +static void proc_init(void) +{ + int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); + int i; + + for (i=0; i < nelem; i++) { + struct procfsentries *p = procfsentries + i; + p->procent = create_proc_entry(p->name, p->mode, 0); + if (p->procent) p->procent->read_proc = p->read_proc; + } +} + +static void proc_exit(void) +{ + int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); + int i; + + for (i=nelem-1; i >= 0; i--) { + struct procfsentries *p = procfsentries + i; + if (p->procent) { + remove_proc_entry(p->name, 0); + p->procent = 0; + } + } +} + static struct capi_interface_user cuser = { "capidrv", lower_callback @@ -1965,8 +2386,8 @@ } else strcpy(rev, " ??? "); - rparam.level3cnt = 2; - rparam.datablkcnt = 8; + rparam.level3cnt = -2; /* number of bchannels twice */ + rparam.datablkcnt = 16; rparam.datablklen = 2048; errcode = (*capifuncs->capi_register) (&rparam, &global.appid); if (errcode) { @@ -1990,6 +2411,7 @@ continue; (void) capidrv_addcontr(contr, &profile); } + proc_init(); return 0; } @@ -2011,11 +2433,13 @@ for (card = global.contr_list; card; card = next) { next = card->next; + disable_dchannel_trace(card); capidrv_delcontr(card->contrnr); } (void) (*capifuncs->capi_release) (global.appid); detach_capi_interface(&cuser); + proc_exit(); printk(KERN_NOTICE "capidrv: Rev%s: unloaded\n", rev); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/capidrv.h linux.pre11.3/drivers/isdn/avmb1/capidrv.h --- linux.vanilla/drivers/isdn/avmb1/capidrv.h Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/avmb1/capidrv.h Mon Jul 19 23:59:32 1999 @@ -1,11 +1,22 @@ /* - * $Id: capidrv.h,v 1.1 1997/03/04 21:50:33 calle Exp $ + * $Id: capidrv.h,v 1.2 1998/03/29 16:06:06 calle Exp $ * * ISDN4Linux Driver, using capi20 interface (kernelcapi) * * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capidrv.h,v $ + * Revision 1.2 1998/03/29 16:06:06 calle + * changes from 2.0 tree merged. + * + * Revision 1.1.2.1 1998/03/20 14:38:28 calle + * capidrv: prepared state machines for suspend/resume/hold + * capidrv: fix bug in state machine if B1/T1 is out of nccis + * b1capi: changed some errno returns. + * b1capi: detect if you try to add same T1 to different io address. + * b1capi: change number of nccis depending on number of channels. + * b1lli: cosmetics + * * Revision 1.1 1997/03/04 21:50:33 calle * Frirst version in isdn4linux * @@ -49,34 +60,70 @@ #define ST_PLCI_ACCEPTING 6 /* P-4 */ #define ST_PLCI_DISCONNECTING 7 /* P-5 */ #define ST_PLCI_DISCONNECTED 8 /* P-6 */ +#define ST_PLCI_RESUMEING 9 /* P-0.Res */ +#define ST_PLCI_RESUME 10 /* P-Res */ +#define ST_PLCI_HELD 11 /* P-HELD */ -#define EV_PLCI_CONNECT_REQ 1 /* P-0 -> P-0.1 */ -#define EV_PLCI_CONNECT_CONF_ERROR 2 /* P-0.1 -> P-0 */ -#define EV_PLCI_CONNECT_CONF_OK 3 /* P-0.1 -> P-1 */ -#define EV_PLCI_FACILITY_IND_UP 4 /* P-0 -> P-1 */ -#define EV_PLCI_CONNECT_IND 5 /* P-0 -> P-2 */ -#define EV_PLCI_CONNECT_ACTIVE_IND 6 /* P-1 -> P-ACT */ +#define EV_PLCI_CONNECT_REQ 1 /* P-0 -> P-0.1 + */ +#define EV_PLCI_CONNECT_CONF_ERROR 2 /* P-0.1 -> P-0 + */ +#define EV_PLCI_CONNECT_CONF_OK 3 /* P-0.1 -> P-1 + */ +#define EV_PLCI_FACILITY_IND_UP 4 /* P-0 -> P-1 + */ +#define EV_PLCI_CONNECT_IND 5 /* P-0 -> P-2 + */ +#define EV_PLCI_CONNECT_ACTIVE_IND 6 /* P-1 -> P-ACT + */ #define EV_PLCI_CONNECT_REJECT 7 /* P-2 -> P-5 - P-3 -> P-5 */ + P-3 -> P-5 + */ #define EV_PLCI_DISCONNECT_REQ 8 /* P-1 -> P-5 P-2 -> P-5 P-3 -> P-5 P-4 -> P-5 - P-ACT -> P-5 */ + P-ACT -> P-5 + P-Res -> P-5 (*) + P-HELD -> P-5 (*) + */ #define EV_PLCI_DISCONNECT_IND 9 /* P-1 -> P-6 P-2 -> P-6 P-3 -> P-6 P-4 -> P-6 P-5 -> P-6 - P-ACT -> P-6 */ + P-ACT -> P-6 + P-Res -> P-6 (*) + P-HELD -> P-6 (*) + */ #define EV_PLCI_FACILITY_IND_DOWN 10 /* P-0.1 -> P-5 P-1 -> P-5 P-ACT -> P-5 P-2 -> P-5 P-3 -> P-5 - P-4 -> P-5 */ -#define EV_PLCI_DISCONNECT_RESP 11 /* P-6 -> P-0 */ -#define EV_PLCI_CONNECT_RESP 12 /* P-6 -> P-0 */ + P-4 -> P-5 + */ +#define EV_PLCI_DISCONNECT_RESP 11 /* P-6 -> P-0 + */ +#define EV_PLCI_CONNECT_RESP 12 /* P-6 -> P-0 + */ + +#define EV_PLCI_RESUME_REQ 13 /* P-0 -> P-0.Res + */ +#define EV_PLCI_RESUME_CONF_OK 14 /* P-0.Res -> P-Res + */ +#define EV_PLCI_RESUME_CONF_ERROR 15 /* P-0.Res -> P-0 + */ +#define EV_PLCI_RESUME_IND 16 /* P-Res -> P-ACT + */ +#define EV_PLCI_HOLD_IND 17 /* P-ACT -> P-HELD + */ +#define EV_PLCI_RETRIEVE_IND 18 /* P-HELD -> P-ACT + */ +#define EV_PLCI_SUSPEND_IND 19 /* P-ACT -> P-5 + */ +#define EV_PLCI_CD_IND 20 /* P-2 -> P-5 + */ /* * per ncci state machine diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/capilli.h linux.pre11.3/drivers/isdn/avmb1/capilli.h --- linux.vanilla/drivers/isdn/avmb1/capilli.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/avmb1/capilli.h Mon Jul 19 23:59:32 1999 @@ -0,0 +1,109 @@ +/* + * $Id: capilli.h,v 1.2 1999/07/05 15:09:52 calle Exp $ + * + * Kernel CAPI 2.0 Driver Interface for Linux + * + * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) + * + */ +#ifndef __CAPILLI_H__ +#define __CAPILLI_H__ + +typedef struct capiloaddatapart { + int user; /* data in userspace ? */ + int len; + unsigned char *data; +} capiloaddatapart; + +typedef struct capiloaddata { + capiloaddatapart firmware; + capiloaddatapart configuration; +} capiloaddata; + +typedef struct capicardparams { + unsigned int port; + unsigned irq; + int cardtype; + int cardnr; +} capicardparams; + +struct capi_driver; + +struct capi_ctr { + struct capi_ctr *next; /* next ctr of same driver */ + struct capi_driver *driver; + int cnr; /* controller number */ + char name[32]; /* name of controller */ + volatile unsigned short cardstate; /* controller state */ + volatile int blocked; /* output blocked */ + int traceflag; /* capi trace */ + + void *driverdata; /* driver specific */ + + /* filled before calling ready callback */ + __u8 manu[CAPI_MANUFACTURER_LEN]; /* CAPI_GET_MANUFACTURER */ + capi_version version; /* CAPI_GET_VERSION */ + capi_profile profile; /* CAPI_GET_PROFILE */ + __u8 serial[CAPI_SERIAL_LEN]; /* CAPI_GET_SERIAL */ + + /* functions */ + void (*ready)(struct capi_ctr * card); + void (*reseted)(struct capi_ctr * card); + void (*suspend_output)(struct capi_ctr * card); + void (*resume_output)(struct capi_ctr * card); + void (*handle_capimsg)(struct capi_ctr * card, + __u16 appl, struct sk_buff *skb); + void (*appl_registered)(struct capi_ctr * card, __u16 appl); + void (*appl_released)(struct capi_ctr * card, __u16 appl); + + void (*new_ncci)(struct capi_ctr * card, + __u16 appl, __u32 ncci, __u32 winsize); + void (*free_ncci)(struct capi_ctr * card, __u16 appl, __u32 ncci); + + /* management information for kcapi */ + + unsigned long nrecvctlpkt; + unsigned long nrecvdatapkt; + unsigned long nsentctlpkt; + unsigned long nsentdatapkt; + + struct proc_dir_entry *procent; + char procfn[128]; +}; + +struct capi_driver_interface { + struct capi_ctr *(*attach_ctr)(struct capi_driver *driver, char *name, void *data); + int (*detach_ctr)(struct capi_ctr *); +}; + +struct capi_driver { + char name[32]; /* driver name */ + char revision[32]; + int (*load_firmware)(struct capi_ctr *, capiloaddata *); + void (*reset_ctr)(struct capi_ctr *); + void (*remove_ctr)(struct capi_ctr *); + void (*register_appl)(struct capi_ctr *, __u16 appl, + capi_register_params *); + void (*release_appl)(struct capi_ctr *, __u16 appl); + void (*send_message)(struct capi_ctr *, struct sk_buff *skb); + + char *(*procinfo)(struct capi_ctr *); + int (*ctr_read_proc)(char *page, char **start, off_t off, + int count, int *eof, struct capi_ctr *card); + int (*driver_read_proc)(char *page, char **start, off_t off, + int count, int *eof, struct capi_driver *driver); + + int (*add_card)(struct capi_driver *driver, capicardparams *data); + + /* intitialized by kcapi */ + struct capi_ctr *controller; /* list of controllers */ + struct capi_driver *next; + int ncontroller; + struct proc_dir_entry *procent; + char procfn[128]; +}; + +struct capi_driver_interface *attach_capi_driver(struct capi_driver *driver); +void detach_capi_driver(struct capi_driver *driver); + +#endif /* __CAPILLI_H__ */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/capiutil.c linux.pre11.3/drivers/isdn/avmb1/capiutil.c --- linux.vanilla/drivers/isdn/avmb1/capiutil.c Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/avmb1/capiutil.c Mon Jul 19 23:59:32 1999 @@ -1,5 +1,5 @@ /* - * $Id: capiutil.c,v 1.6 1997/11/04 06:12:12 calle Exp $ + * $Id: capiutil.c,v 1.9 1999/07/09 15:05:46 keil Exp $ * * CAPI 2.0 convert capi message to capi message struct * @@ -7,6 +7,28 @@ * Rewritten for Linux 1996 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capiutil.c,v $ + * Revision 1.9 1999/07/09 15:05:46 keil + * compat.h is now isdn_compat.h + * + * Revision 1.8 1999/07/01 15:26:37 calle + * complete new version (I love it): + * + new hardware independed "capi_driver" interface that will make it easy to: + * - support other controllers with CAPI-2.0 (i.e. USB Controller) + * - write a CAPI-2.0 for the passive cards + * - support serial link CAPI-2.0 boxes. + * + wrote "capi_driver" for all supported cards. + * + "capi_driver" (supported cards) now have to be configured with + * make menuconfig, in the past all supported cards where included + * at once. + * + new and better informations in /proc/capi/ + * + new ioctl to switch trace of capi messages per controller + * using "avmcapictrl trace [contr] on|off|...." + * + complete testcircle with all supported cards and also the + * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. + * + * Revision 1.7 1999/07/01 08:23:01 keil + * compatibility macros now in + * * Revision 1.6 1997/11/04 06:12:12 calle * capi.c: new read/write in file_ops since 2.1.60 * capidrv.c: prepared isdnlog interface for d2-trace in newer firmware. @@ -48,7 +70,7 @@ #include #include -#include "compat.h" +#include #include "capiutil.h" /* from CAPI2.0 DDK AVM Berlin GmbH */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/compat.h linux.pre11.3/drivers/isdn/avmb1/compat.h --- linux.vanilla/drivers/isdn/avmb1/compat.h Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/avmb1/compat.h Mon Jul 19 23:59:32 1999 @@ -1,41 +0,0 @@ -/* - * $Id: compat.h,v 1.3 1997/11/04 06:12:15 calle Exp $ - * - * Headerfile for Compartibility between different kernel versions - * - * (c) Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log: compat.h,v $ - * Revision 1.3 1997/11/04 06:12:15 calle - * capi.c: new read/write in file_ops since 2.1.60 - * capidrv.c: prepared isdnlog interface for d2-trace in newer firmware. - * capiutil.c: needs config.h (CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON) - * compat.h: added #define LinuxVersionCode - * - * Revision 1.2 1997/10/01 09:21:22 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.1 1997/03/04 21:50:36 calle - * Frirst version in isdn4linux - * - * Revision 2.2 1997/02/12 09:31:39 calle - * new version - * - * Revision 1.1 1997/01/31 10:32:20 calle - * Initial revision - * - * - */ -#ifndef __COMPAT_H__ -#define __COMPAT_H__ - -#include -#include - -#ifndef LinuxVersionCode -#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) -#endif - -#endif /* __COMPAT_H__ */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/kcapi.c linux.pre11.3/drivers/isdn/avmb1/kcapi.c --- linux.vanilla/drivers/isdn/avmb1/kcapi.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/avmb1/kcapi.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,1522 @@ +/* + * $Id: kcapi.c,v 1.5 1999/07/09 15:05:48 keil Exp $ + * + * Kernel CAPI 2.0 Module + * + * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) + * + * $Log: kcapi.c,v $ + * Revision 1.5 1999/07/09 15:05:48 keil + * compat.h is now isdn_compat.h + * + * Revision 1.4 1999/07/08 14:15:17 calle + * Forgot to count down ncards in drivercb_detach_ctr. + * + * Revision 1.3 1999/07/06 07:42:02 calle + * - changes in /proc interface + * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb. + * + * Revision 1.2 1999/07/05 15:09:52 calle + * - renamed "appl_release" to "appl_released". + * - version und profile data now cleared on controller reset + * - extended /proc interface, to allow driver and controller specific + * informations to include by driver hackers. + * + * Revision 1.1 1999/07/01 15:26:42 calle + * complete new version (I love it): + * + new hardware independed "capi_driver" interface that will make it easy to: + * - support other controllers with CAPI-2.0 (i.e. USB Controller) + * - write a CAPI-2.0 for the passive cards + * - support serial link CAPI-2.0 boxes. + * + wrote "capi_driver" for all supported cards. + * + "capi_driver" (supported cards) now have to be configured with + * make menuconfig, in the past all supported cards where included + * at once. + * + new and better informations in /proc/capi/ + * + new ioctl to switch trace of capi messages per controller + * using "avmcapictrl trace [contr] on|off|...." + * + complete testcircle with all supported cards and also the + * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. + * + */ +#define CONFIG_AVMB1_COMPAT + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "capicmd.h" +#include "capiutil.h" +#include "capilli.h" +#ifdef CONFIG_AVMB1_COMPAT +#include +#endif + +static char *revision = "$Revision: 1.5 $"; + +/* ------------------------------------------------------------- */ + +#define CARD_FREE 0 +#define CARD_DETECTED 1 +#define CARD_LOADING 2 +#define CARD_RUNNING 3 + +/* ------------------------------------------------------------- */ + +int showcapimsgs = 0; + +MODULE_AUTHOR("Carsten Paeth "); +MODULE_PARM(showcapimsgs, "0-4i"); + +/* ------------------------------------------------------------- */ + +struct msgidqueue { + struct msgidqueue *next; + __u16 msgid; +}; + +struct capi_ncci { + struct capi_ncci *next; + __u16 applid; + __u32 ncci; + __u32 winsize; + int nmsg; + struct msgidqueue *msgidqueue; + struct msgidqueue *msgidlast; + struct msgidqueue *msgidfree; + struct msgidqueue msgidpool[CAPI_MAXDATAWINDOW]; +}; + +struct capi_appl { + __u16 applid; + capi_register_params rparam; + int releasing; + __u32 param; + void (*signal) (__u16 applid, __u32 param); + struct sk_buff_head recv_queue; + int nncci; + struct capi_ncci *nccilist; + + unsigned long nrecvctlpkt; + unsigned long nrecvdatapkt; + unsigned long nsentctlpkt; + unsigned long nsentdatapkt; +}; + +/* ------------------------------------------------------------- */ + +static struct capi_version driver_version = {2, 0, 1, 1<<4}; +static char driver_serial[CAPI_SERIAL_LEN] = "4711"; +static char capi_manufakturer[64] = "AVM Berlin"; + +#define APPL(a) (&applications[(a)-1]) +#define VALID_APPLID(a) ((a) && (a) <= CAPI_MAXAPPL && APPL(a)->applid == a) +#define APPL_IS_FREE(a) (APPL(a)->applid == 0) +#define APPL_MARK_FREE(a) do{ APPL(a)->applid=0; MOD_DEC_USE_COUNT; }while(0); +#define APPL_MARK_USED(a) do{ APPL(a)->applid=(a); MOD_INC_USE_COUNT; }while(0); + +#define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f) + +#define VALID_CARD(c) ((c) > 0 && (c) <= CAPI_MAXCONTR) +#define CARD(c) (&cards[(c)-1]) +#define CARDNR(cp) (((cp)-cards)+1) + +static struct capi_appl applications[CAPI_MAXAPPL]; +static struct capi_ctr cards[CAPI_MAXCONTR]; +static int ncards = 0; +static struct sk_buff_head recv_queue; +static struct capi_interface_user *capi_users = 0; +static struct capi_driver *drivers; +#ifdef CONFIG_AVMB1_COMPAT +static struct capi_driver *b1isa_driver; +static struct capi_driver *t1isa_driver; +#endif +static long notify_up_set = 0; +static long notify_down_set = 0; + +static struct tq_struct tq_state_notify; +static struct tq_struct tq_recv_notify; + +/* -------- util functions ------------------------------------ */ + +static char *cardstate2str(unsigned short cardstate) +{ + switch (cardstate) { + default: + case CARD_FREE: return "free"; + case CARD_DETECTED: return "detected"; + case CARD_LOADING: return "loading"; + case CARD_RUNNING: return "running"; + } +} + +static inline int capi_cmd_valid(__u8 cmd) +{ + switch (cmd) { + case CAPI_ALERT: + case CAPI_CONNECT: + case CAPI_CONNECT_ACTIVE: + case CAPI_CONNECT_B3_ACTIVE: + case CAPI_CONNECT_B3: + case CAPI_CONNECT_B3_T90_ACTIVE: + case CAPI_DATA_B3: + case CAPI_DISCONNECT_B3: + case CAPI_DISCONNECT: + case CAPI_FACILITY: + case CAPI_INFO: + case CAPI_LISTEN: + case CAPI_MANUFACTURER: + case CAPI_RESET_B3: + case CAPI_SELECT_B_PROTOCOL: + return 1; + } + return 0; +} + +static inline int capi_subcmd_valid(__u8 subcmd) +{ + switch (subcmd) { + case CAPI_REQ: + case CAPI_CONF: + case CAPI_IND: + case CAPI_RESP: + return 1; + } + return 0; +} + +/* -------- /proc functions ----------------------------------- */ +/* + * /proc/capi/applications: + * applid l3cnt dblkcnt dblklen #ncci recvqueuelen + */ +static int proc_applications_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct capi_appl *ap; + int i; + int len = 0; + off_t begin = 0; + + for (i=0; i < CAPI_MAXAPPL; i++) { + ap = &applications[i]; + if (ap->applid == 0) continue; + len += sprintf(page+len, "%u %d %d %d %d %d\n", + ap->applid, + ap->rparam.level3cnt, + ap->rparam.datablkcnt, + ap->rparam.datablklen, + ap->nncci, + skb_queue_len(&ap->recv_queue)); + if (len+begin > off+count) + goto endloop; + if (len+begin < off) { + begin += len; + len = 0; + } + } +endloop: + if (i >= CAPI_MAXAPPL) + *eof = 1; + if (off >= len+begin) + return 0; + *start = page + (begin-off); + return ((count < begin+len-off) ? count : begin+len-off); +} + +/* + * /proc/capi/ncci: + * applid ncci winsize nblk + */ +static int proc_ncci_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct capi_appl *ap; + struct capi_ncci *np; + int i; + int len = 0; + off_t begin = 0; + + for (i=0; i < CAPI_MAXAPPL; i++) { + ap = &applications[i]; + if (ap->applid == 0) continue; + for (np = ap->nccilist; np; np = np->next) { + len += sprintf(page+len, "%d 0x%x %d %d\n", + np->applid, + np->ncci, + np->winsize, + np->nmsg); + if (len+begin > off+count) + goto endloop; + if (len+begin < off) { + begin += len; + len = 0; + } + } + } +endloop: + if (i >= CAPI_MAXAPPL) + *eof = 1; + if (off >= len+begin) + return 0; + *start = page + (begin-off); + return ((count < begin+len-off) ? count : begin+len-off); +} + +/* + * /proc/capi/driver: + * driver ncontroller + */ +static int proc_driver_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct capi_driver *driver; + int len = 0; + off_t begin = 0; + + for (driver = drivers; driver; driver = driver->next) { + len += sprintf(page+len, "%-32s %d %s\n", + driver->name, + driver->ncontroller, + driver->revision); + if (len+begin > off+count) + goto endloop; + if (len+begin < off) { + begin += len; + len = 0; + } + } +endloop: + if (!driver) + *eof = 1; + if (off >= len+begin) + return 0; + *start = page + (begin-off); + return ((count < begin+len-off) ? count : begin+len-off); +} + +/* + * /proc/capi/users: + * name + */ +static int proc_users_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct capi_interface_user *cp; + int len = 0; + off_t begin = 0; + + for (cp = capi_users; cp ; cp = cp->next) { + len += sprintf(page+len, "%s\n", cp->name); + if (len+begin > off+count) + goto endloop; + if (len+begin < off) { + begin += len; + len = 0; + } + } +endloop: + if (cp == 0) + *eof = 1; + if (off >= len+begin) + return 0; + *start = page + (begin-off); + return ((count < begin+len-off) ? count : begin+len-off); +} + +/* + * /proc/capi/controller: + * cnr driver cardstate name driverinfo + */ +static int proc_controller_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct capi_ctr *cp; + int i; + int len = 0; + off_t begin = 0; + + for (i=0; i < CAPI_MAXCONTR; i++) { + cp = &cards[i]; + if (cp->cardstate == CARD_FREE) continue; + len += sprintf(page+len, "%d %-10s %-8s %-16s %s\n", + cp->cnr, cp->driver->name, + cardstate2str(cp->cardstate), + cp->name, + cp->driver->procinfo ? cp->driver->procinfo(cp) : "" + ); + if (len+begin > off+count) + goto endloop; + if (len+begin < off) { + begin += len; + len = 0; + } + } +endloop: + if (i >= CAPI_MAXCONTR) + *eof = 1; + if (off >= len+begin) + return 0; + *start = page + (begin-off); + return ((count < begin+len-off) ? count : begin+len-off); +} + +/* + * /proc/capi/applstats: + * applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt + */ +static int proc_applstats_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct capi_appl *ap; + int i; + int len = 0; + off_t begin = 0; + + for (i=0; i < CAPI_MAXAPPL; i++) { + ap = &applications[i]; + if (ap->applid == 0) continue; + len += sprintf(page+len, "%u %lu %lu %lu %lu\n", + ap->applid, + ap->nrecvctlpkt, + ap->nrecvdatapkt, + ap->nsentctlpkt, + ap->nsentdatapkt); + if (len+begin > off+count) + goto endloop; + if (len+begin < off) { + begin += len; + len = 0; + } + } +endloop: + if (i >= CAPI_MAXAPPL) + *eof = 1; + if (off >= len+begin) + return 0; + *start = page + (begin-off); + return ((count < begin+len-off) ? count : begin+len-off); +} + +/* + * /proc/capi/contrstats: + * cnr nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt + */ +static int proc_contrstats_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct capi_ctr *cp; + int i; + int len = 0; + off_t begin = 0; + + for (i=0; i < CAPI_MAXCONTR; i++) { + cp = &cards[i]; + if (cp->cardstate == CARD_FREE) continue; + len += sprintf(page+len, "%d %lu %lu %lu %lu\n", + cp->cnr, + cp->nrecvctlpkt, + cp->nrecvdatapkt, + cp->nsentctlpkt, + cp->nsentdatapkt); + if (len+begin > off+count) + goto endloop; + if (len+begin < off) { + begin += len; + len = 0; + } + } +endloop: + if (i >= CAPI_MAXCONTR) + *eof = 1; + if (off >= len+begin) + return 0; + *start = page + (begin-off); + return ((count < begin+len-off) ? count : begin+len-off); +} + +static struct procfsentries { + char *name; + mode_t mode; + int (*read_proc)(char *page, char **start, off_t off, + int count, int *eof, void *data); + struct proc_dir_entry *procent; +} procfsentries[] = { + { "capi", S_IFDIR, 0 }, + { "capi/applications", 0 , proc_applications_read_proc }, + { "capi/ncci", 0 , proc_ncci_read_proc }, + { "capi/driver", 0 , proc_driver_read_proc }, + { "capi/users", 0 , proc_users_read_proc }, + { "capi/controller", 0 , proc_controller_read_proc }, + { "capi/applstats", 0 , proc_applstats_read_proc }, + { "capi/contrstats", 0 , proc_contrstats_read_proc }, + { "capi/drivers", S_IFDIR, 0 }, + { "capi/controllers", S_IFDIR, 0 }, +}; + +static void proc_capi_init(void) +{ + int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); + int i; + + for (i=0; i < nelem; i++) { + struct procfsentries *p = procfsentries + i; + p->procent = create_proc_entry(p->name, p->mode, 0); + if (p->procent) p->procent->read_proc = p->read_proc; + } +} + +static void proc_capi_exit(void) +{ + int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); + int i; + + for (i=nelem-1; i >= 0; i--) { + struct procfsentries *p = procfsentries + i; + if (p->procent) { + remove_proc_entry(p->name, 0); + p->procent = 0; + } + } +} + +/* -------- NCCI Handling ------------------------------------- */ + +static inline void mq_init(struct capi_ncci * np) +{ + int i; + np->msgidqueue = 0; + np->msgidlast = 0; + np->nmsg = 0; + memset(np->msgidpool, 0, sizeof(np->msgidpool)); + np->msgidfree = &np->msgidpool[0]; + for (i = 1; i < np->winsize; i++) { + np->msgidpool[i].next = np->msgidfree; + np->msgidfree = &np->msgidpool[i]; + } +} + +static inline int mq_enqueue(struct capi_ncci * np, __u16 msgid) +{ + struct msgidqueue *mq; + if ((mq = np->msgidfree) == 0) + return 0; + np->msgidfree = mq->next; + mq->msgid = msgid; + mq->next = 0; + if (np->msgidlast) + np->msgidlast->next = mq; + np->msgidlast = mq; + if (!np->msgidqueue) + np->msgidqueue = mq; + np->nmsg++; + return 1; +} + +static inline int mq_dequeue(struct capi_ncci * np, __u16 msgid) +{ + struct msgidqueue **pp; + for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) { + if ((*pp)->msgid == msgid) { + struct msgidqueue *mq = *pp; + *pp = mq->next; + if (mq == np->msgidlast) + np->msgidlast = 0; + mq->next = np->msgidfree; + np->msgidfree = mq; + np->nmsg--; + return 1; + } + } + return 0; +} + +static void controllercb_appl_registered(struct capi_ctr * card, __u16 appl) +{ +} + +static void controllercb_appl_released(struct capi_ctr * card, __u16 appl) +{ + struct capi_ncci **pp, **nextpp; + for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) { + if (NCCI2CTRL((*pp)->ncci) == card->cnr) { + struct capi_ncci *np = *pp; + *pp = np->next; + printk(KERN_INFO "kcapi: appl %d ncci 0x%x down!\n", appl, np->ncci); + kfree(np); + APPL(appl)->nncci--; + nextpp = pp; + } else { + 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); + } +} +/* + * ncci managment + */ + +static void controllercb_new_ncci(struct capi_ctr * card, + __u16 appl, __u32 ncci, __u32 winsize) +{ + struct capi_ncci *np; + if (!VALID_APPLID(appl)) { + printk(KERN_ERR "avmb1_handle_new_ncci: illegal appl %d\n", appl); + return; + } + if ((np = (struct capi_ncci *) kmalloc(sizeof(struct capi_ncci), GFP_ATOMIC)) == 0) { + printk(KERN_ERR "capi_new_ncci: alloc failed ncci 0x%x\n", ncci); + return; + } + if (winsize > CAPI_MAXDATAWINDOW) { + printk(KERN_ERR "capi_new_ncci: winsize %d too big, set to %d\n", + winsize, CAPI_MAXDATAWINDOW); + winsize = CAPI_MAXDATAWINDOW; + } + np->applid = appl; + np->ncci = ncci; + np->winsize = winsize; + mq_init(np); + np->next = APPL(appl)->nccilist; + APPL(appl)->nccilist = np; + APPL(appl)->nncci++; + printk(KERN_INFO "kcapi: appl %d ncci 0x%x up\n", appl, ncci); + +} + +static void controllercb_free_ncci(struct capi_ctr * card, + __u16 appl, __u32 ncci) +{ + struct capi_ncci **pp; + if (!VALID_APPLID(appl)) { + printk(KERN_ERR "free_ncci: illegal appl %d\n", appl); + return; + } + for (pp = &APPL(appl)->nccilist; *pp; pp = &(*pp)->next) { + if ((*pp)->ncci == ncci) { + struct capi_ncci *np = *pp; + *pp = np->next; + kfree(np); + APPL(appl)->nncci--; + printk(KERN_INFO "kcapi: appl %d ncci 0x%x down\n", appl, ncci); + return; + } + } + printk(KERN_ERR "free_ncci: ncci 0x%x not found\n", ncci); +} + + +static struct capi_ncci *find_ncci(struct capi_appl * app, __u32 ncci) +{ + struct capi_ncci *np; + for (np = app->nccilist; np; np = np->next) { + if (np->ncci == ncci) + return np; + } + return 0; +} + +/* -------- Receiver ------------------------------------------ */ + +static void recv_handler(void *dummy) +{ + struct sk_buff *skb; + + while ((skb = skb_dequeue(&recv_queue)) != 0) { + __u16 appl = CAPIMSG_APPID(skb->data); + struct capi_ncci *np; + if (!VALID_APPLID(appl)) { + printk(KERN_ERR "kcapi: recv_handler: applid %d ? (%s)\n", + appl, capi_message2str(skb->data)); + kfree_skb(skb); + continue; + } + if (APPL(appl)->signal == 0) { + printk(KERN_ERR "kcapi: recv_handler: applid %d has no signal function\n", + appl); + kfree_skb(skb); + continue; + } + if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3 + && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF + && (np = find_ncci(APPL(appl), CAPIMSG_NCCI(skb->data))) != 0 + && mq_dequeue(np, CAPIMSG_MSGID(skb->data)) == 0) { + printk(KERN_ERR "kcapi: msgid %hu ncci 0x%x not on queue\n", + CAPIMSG_MSGID(skb->data), np->ncci); + } + if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3 + && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) { + APPL(appl)->nrecvdatapkt++; + } else { + APPL(appl)->nrecvctlpkt++; + } + skb_queue_tail(&APPL(appl)->recv_queue, skb); + (APPL(appl)->signal) (APPL(appl)->applid, APPL(appl)->param); + } +} + +static void controllercb_handle_capimsg(struct capi_ctr * card, + __u16 appl, struct sk_buff *skb) +{ + int showctl = 0; + __u8 cmd, subcmd; + + if (card->cardstate != CARD_RUNNING) { + printk(KERN_INFO "kcapi: controller %d not active, got: %s", + card->cnr, capi_message2str(skb->data)); + goto error; + } + cmd = CAPIMSG_COMMAND(skb->data); + subcmd = CAPIMSG_SUBCOMMAND(skb->data); + if (cmd == CAPI_DATA_B3 && subcmd == CAPI_IND) { + card->nrecvdatapkt++; + if (card->traceflag > 2) showctl |= 2; + if (card->traceflag) showctl |= 2; + } else { + card->nrecvctlpkt++; + } + showctl |= (card->traceflag & 1); + if (showctl & 2) { + if (showctl & 1) { + printk(KERN_DEBUG "kcapi: got [0x%lx] id#%d %s len=%u\n", + (unsigned long) card->cnr, + CAPIMSG_APPID(skb->data), + capi_cmd2str(cmd, subcmd), + CAPIMSG_LEN(skb->data)); + } else { + printk(KERN_DEBUG "kcapi: got [0x%lx] %s\n", + (unsigned long) card->cnr, + capi_message2str(skb->data)); + } + + } + skb_queue_tail(&recv_queue, skb); + queue_task(&tq_recv_notify, &tq_immediate); + mark_bh(IMMEDIATE_BH); + return; + +error: + kfree_skb(skb); +} + +/* -------- Notifier ------------------------------------------ */ + +static void notify_up(__u16 contr) +{ + struct capi_interface_user *p; + + printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr); + for (p = capi_users; p; p = p->next) { + if (!p->callback) continue; + (*p->callback) (KCI_CONTRUP, contr, &CARD(contr)->profile); + } +} + +static void notify_down(__u16 contr) +{ + struct capi_interface_user *p; + printk(KERN_NOTICE "kcapi: notify down contr %d\n", contr); + for (p = capi_users; p; p = p->next) { + if (!p->callback) continue; + (*p->callback) (KCI_CONTRDOWN, contr, 0); + } +} + +static void notify_handler(void *dummy) +{ + __u16 contr; + + for (contr=1; VALID_CARD(contr); contr++) + if (test_and_clear_bit(contr, ¬ify_up_set)) + notify_up(contr); + for (contr=1; VALID_CARD(contr); contr++) + if (test_and_clear_bit(contr, ¬ify_down_set)) + notify_down(contr); +} + + +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); + } + + set_bit(CARDNR(card), ¬ify_up_set); + queue_task(&tq_state_notify, &tq_scheduler); + + printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n", + CARDNR(card), card->name); +} + +static void controllercb_reseted(struct capi_ctr * card) +{ + __u16 appl; + + if (card->cardstate == CARD_FREE) + return; + if (card->cardstate == CARD_DETECTED) + return; + + card->cardstate = CARD_DETECTED; + + memset(card->manu, 0, sizeof(card->manu)); + memset(&card->version, 0, sizeof(card->version)); + memset(&card->profile, 0, sizeof(card->profile)); + memset(card->serial, 0, sizeof(card->serial)); + + for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { + struct capi_ncci **pp, **nextpp; + for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) { + if (NCCI2CTRL((*pp)->ncci) == card->cnr) { + struct capi_ncci *np = *pp; + *pp = np->next; + printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down!\n", appl, np->ncci); + kfree(np); + nextpp = pp; + } else { + nextpp = &(*pp)->next; + } + } + } + set_bit(CARDNR(card), ¬ify_down_set); + queue_task(&tq_state_notify, &tq_scheduler); + printk(KERN_NOTICE "kcapi: card %d down.\n", CARDNR(card)); +} + +static void controllercb_suspend_output(struct capi_ctr *card) +{ + if (!card->blocked) { + printk(KERN_DEBUG "kcapi: card %d suspend\n", CARDNR(card)); + card->blocked = 1; + } +} + +static void controllercb_resume_output(struct capi_ctr *card) +{ + if (card->blocked) { + printk(KERN_DEBUG "kcapi: card %d resume\n", CARDNR(card)); + card->blocked = 0; + } +} + +/* ------------------------------------------------------------- */ + + +struct capi_ctr * +drivercb_attach_ctr(struct capi_driver *driver, char *name, void *driverdata) +{ + struct capi_ctr *card, **pp; + int i; + + for (i=0; i < CAPI_MAXCONTR && cards[i].cardstate != CARD_FREE; i++) ; + + if (i == CAPI_MAXCONTR) { + printk(KERN_ERR "kcapi: out of controller slots\n"); + return 0; + } + card = &cards[i]; + memset(card, 0, sizeof(struct capi_ctr)); + card->driver = driver; + card->cnr = CARDNR(card); + strncpy(card->name, name, sizeof(card->name)); + card->cardstate = CARD_DETECTED; + card->blocked = 0; + card->driverdata = driverdata; + card->traceflag = showcapimsgs; + + card->ready = controllercb_ready; + card->reseted = controllercb_reseted; + card->suspend_output = controllercb_suspend_output; + card->resume_output = controllercb_resume_output; + card->handle_capimsg = controllercb_handle_capimsg; + card->appl_registered = controllercb_appl_registered; + card->appl_released = controllercb_appl_released; + card->new_ncci = controllercb_new_ncci; + card->free_ncci = controllercb_free_ncci; + + for (pp = &driver->controller; *pp; pp = &(*pp)->next) ; + card->next = 0; + *pp = card; + driver->ncontroller++; + sprintf(card->procfn, "capi/controllers/%d", card->cnr); + card->procent = create_proc_entry(card->procfn, 0, 0); + if (card->procent) { + card->procent->read_proc = + (int (*)(char *,char **,off_t,int,int *,void *)) + driver->ctr_read_proc; + card->procent->data = card; + } + + ncards++; + printk(KERN_NOTICE "kcapi: Controller %d: %s attached\n", + card->cnr, card->name); + return card; +} + +static int drivercb_detach_ctr(struct capi_ctr *card) +{ + struct capi_driver *driver = card->driver; + struct capi_ctr **pp; + + if (card->cardstate == CARD_FREE) + return 0; + if (card->cardstate != CARD_DETECTED) + controllercb_reseted(card); + for (pp = &driver->controller; *pp ; pp = &(*pp)->next) { + if (*pp == card) { + *pp = card->next; + driver->ncontroller--; + ncards--; + break; + } + } + if (card->procent) { + remove_proc_entry(card->procfn, 0); + card->procent = 0; + } + card->cardstate = CARD_FREE; + printk(KERN_NOTICE "kcapi: Controller %d: %s unregistered\n", + card->cnr, card->name); + return 0; +} + +/* ------------------------------------------------------------- */ + +/* fallback if no driver read_proc function defined by driver */ + +static int driver_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct capi_driver *driver = (struct capi_driver *)data; + int len = 0; + + len += sprintf(page+len, "%-16s %s\n", "name", driver->name); + len += sprintf(page+len, "%-16s %s\n", "revision", driver->revision); + + if (len < off) + return 0; + *eof = 1; + *start = page - off; + return ((count < len-off) ? count : len-off); +} + +/* ------------------------------------------------------------- */ + +static struct capi_driver_interface di = { + drivercb_attach_ctr, + drivercb_detach_ctr, +}; + +struct capi_driver_interface *attach_capi_driver(struct capi_driver *driver) +{ + struct capi_driver **pp; + + for (pp = &drivers; *pp; pp = &(*pp)->next) ; + driver->next = 0; + *pp = driver; + printk(KERN_NOTICE "kcapi: driver %s attached\n", driver->name); +#ifdef CONFIG_AVMB1_COMPAT + if (strcmp(driver->name, "b1isa") == 0 && driver->add_card) + b1isa_driver = driver; + if (strcmp(driver->name, "t1isa") == 0 && driver->add_card) + t1isa_driver = driver; +#endif + sprintf(driver->procfn, "capi/drivers/%s", driver->name); + driver->procent = create_proc_entry(driver->procfn, 0, 0); + if (driver->procent) { + if (driver->driver_read_proc) { + driver->procent->read_proc = + (int (*)(char *,char **,off_t,int,int *,void *)) + driver->driver_read_proc; + } else { + driver->procent->read_proc = driver_read_proc; + } + driver->procent->data = driver; + } + return &di; +} + +void detach_capi_driver(struct capi_driver *driver) +{ + struct capi_driver **pp; + for (pp = &drivers; *pp && *pp != driver; pp = &(*pp)->next) ; + if (*pp) { + *pp = (*pp)->next; +#ifdef CONFIG_AVMB1_COMPAT + if (driver == b1isa_driver) b1isa_driver = 0; + if (driver == t1isa_driver) t1isa_driver = 0; +#endif + printk(KERN_NOTICE "kcapi: driver %s detached\n", driver->name); + } else { + printk(KERN_ERR "kcapi: driver %s double detach ?\n", driver->name); + } + if (driver->procent) { + remove_proc_entry(driver->procfn, 0); + driver->procent = 0; + } +} + +/* ------------------------------------------------------------- */ +/* -------- CAPI2.0 Interface ---------------------------------- */ +/* ------------------------------------------------------------- */ + +static int capi_installed(void) +{ + int i; + for (i = 0; i < CAPI_MAXCONTR; i++) { + if (cards[i].cardstate == CARD_RUNNING) + return 1; + } + return 0; +} + +static __u16 capi_register(capi_register_params * rparam, __u16 * applidp) +{ + int appl; + int i; + + if (rparam->datablklen < 128) + return CAPI_LOGBLKSIZETOSMALL; + + for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { + if (APPL_IS_FREE(appl)) + break; + } + if (appl > CAPI_MAXAPPL) + return CAPI_TOOMANYAPPLS; + + APPL_MARK_USED(appl); + skb_queue_head_init(&APPL(appl)->recv_queue); + APPL(appl)->nncci = 0; + + memcpy(&APPL(appl)->rparam, rparam, sizeof(capi_register_params)); + + for (i = 0; i < CAPI_MAXCONTR; i++) { + if (cards[i].cardstate != CARD_RUNNING) + continue; + cards[i].driver->register_appl(&cards[i], appl, + &APPL(appl)->rparam); + } + *applidp = appl; + printk(KERN_INFO "kcapi: appl %d up\n", appl); + + return CAPI_NOERROR; +} + +static __u16 capi_release(__u16 applid) +{ + struct sk_buff *skb; + int i; + + if (!VALID_APPLID(applid) || APPL(applid)->releasing) + return CAPI_ILLAPPNR; + while ((skb = skb_dequeue(&APPL(applid)->recv_queue)) != 0) + kfree_skb(skb); + for (i = 0; i < CAPI_MAXCONTR; i++) { + if (cards[i].cardstate != CARD_RUNNING) + continue; + APPL(applid)->releasing++; + cards[i].driver->release_appl(&cards[i], applid); + } + if (APPL(applid)->releasing <= 0) { + APPL(applid)->signal = 0; + APPL_MARK_FREE(applid); + printk(KERN_INFO "kcapi: appl %d down\n", applid); + } + return CAPI_NOERROR; +} + +static __u16 capi_put_message(__u16 applid, struct sk_buff *skb) +{ + struct capi_ncci *np; + int contr; + int showctl = 0; + __u8 cmd, subcmd; + + if (ncards == 0) + return CAPI_REGNOTINSTALLED; + if (!VALID_APPLID(applid)) + return CAPI_ILLAPPNR; + if (skb->len < 12 + || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data)) + || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data))) + return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; + contr = CAPIMSG_CONTROLLER(skb->data); + if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) { + contr = 1; + if (CARD(contr)->cardstate != CARD_RUNNING) + return CAPI_REGNOTINSTALLED; + } + if (CARD(contr)->blocked) + return CAPI_SENDQUEUEFULL; + + cmd = CAPIMSG_COMMAND(skb->data); + subcmd = CAPIMSG_SUBCOMMAND(skb->data); + + if (cmd == CAPI_DATA_B3 && subcmd== CAPI_REQ) { + if ((np = find_ncci(APPL(applid), CAPIMSG_NCCI(skb->data))) != 0 + && mq_enqueue(np, CAPIMSG_MSGID(skb->data)) == 0) + return CAPI_SENDQUEUEFULL; + CARD(contr)->nsentdatapkt++; + APPL(applid)->nsentdatapkt++; + if (CARD(contr)->traceflag > 2) showctl |= 2; + } else { + CARD(contr)->nsentctlpkt++; + APPL(applid)->nsentctlpkt++; + if (CARD(contr)->traceflag) showctl |= 2; + } + showctl |= (CARD(contr)->traceflag & 1); + if (showctl & 2) { + if (showctl & 1) { + printk(KERN_DEBUG "kcapi: put [0x%lx] id#%d %s len=%u\n", + (unsigned long) contr, + CAPIMSG_APPID(skb->data), + capi_cmd2str(cmd, subcmd), + CAPIMSG_LEN(skb->data)); + } else { + printk(KERN_DEBUG "kcapi: put [0x%lx] %s\n", + (unsigned long) contr, + capi_message2str(skb->data)); + } + + } + CARD(contr)->driver->send_message(CARD(contr), skb); + return CAPI_NOERROR; +} + +static __u16 capi_get_message(__u16 applid, struct sk_buff **msgp) +{ + struct sk_buff *skb; + + if (!VALID_APPLID(applid)) + return CAPI_ILLAPPNR; + if ((skb = skb_dequeue(&APPL(applid)->recv_queue)) == 0) + return CAPI_RECEIVEQUEUEEMPTY; + *msgp = skb; + return CAPI_NOERROR; +} + +static __u16 capi_set_signal(__u16 applid, + void (*signal) (__u16 applid, __u32 param), + __u32 param) +{ + if (!VALID_APPLID(applid)) + return CAPI_ILLAPPNR; + APPL(applid)->signal = signal; + APPL(applid)->param = param; + return CAPI_NOERROR; +} + +static __u16 capi_get_manufacturer(__u16 contr, __u8 buf[CAPI_MANUFACTURER_LEN]) +{ + if (contr == 0) { + strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); + return CAPI_NOERROR; + } + if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) + return 0x2002; + + strncpy(buf, CARD(contr)->manu, CAPI_MANUFACTURER_LEN); + return CAPI_NOERROR; +} + +static __u16 capi_get_version(__u16 contr, struct capi_version *verp) +{ + if (contr == 0) { + *verp = driver_version; + return CAPI_NOERROR; + } + if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) + return 0x2002; + + memcpy((void *) verp, &CARD(contr)->version, sizeof(capi_version)); + return CAPI_NOERROR; +} + +static __u16 capi_get_serial(__u16 contr, __u8 serial[CAPI_SERIAL_LEN]) +{ + if (contr == 0) { + strncpy(serial, driver_serial, CAPI_SERIAL_LEN); + return CAPI_NOERROR; + } + if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) + return 0x2002; + + strncpy((void *) serial, CARD(contr)->serial, CAPI_SERIAL_LEN); + return CAPI_NOERROR; +} + +static __u16 capi_get_profile(__u16 contr, struct capi_profile *profp) +{ + if (contr == 0) { + profp->ncontroller = ncards; + return CAPI_NOERROR; + } + if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) + return 0x2002; + + memcpy((void *) profp, &CARD(contr)->profile, + sizeof(struct capi_profile)); + return CAPI_NOERROR; +} + +#ifdef CONFIG_AVMB1_COMPAT +static int old_capi_manufacturer(unsigned int cmd, void *data) +{ + avmb1_loadandconfigdef ldef; + avmb1_extcarddef cdef; + avmb1_resetdef rdef; + avmb1_getdef gdef; + struct capi_driver *driver; + struct capi_ctr *card; + capicardparams cparams; + capiloaddata ldata; + int retval; + + switch (cmd) { + case AVMB1_ADDCARD: + case AVMB1_ADDCARD_WITH_TYPE: + if (cmd == AVMB1_ADDCARD) { + if ((retval = copy_from_user((void *) &cdef, data, + sizeof(avmb1_carddef)))) + return retval; + cdef.cardtype = AVM_CARDTYPE_B1; + } else { + if ((retval = copy_from_user((void *) &cdef, data, + sizeof(avmb1_extcarddef)))) + return retval; + } + cparams.port = cdef.port; + cparams.irq = cdef.irq; + cparams.cardnr = cdef.cardnr; + + switch (cdef.cardtype) { + case AVM_CARDTYPE_B1: driver = b1isa_driver; break; + case AVM_CARDTYPE_T1: driver = t1isa_driver; break; + default: driver = 0; + } + if (!driver || !driver->add_card) { + return -EIO; + } + + return driver->add_card(driver, &cparams); + + case AVMB1_LOAD: + case AVMB1_LOAD_AND_CONFIG: + + if (cmd == AVMB1_LOAD) { + if ((retval = copy_from_user((void *) &ldef, data, + sizeof(avmb1_loaddef)))) + return retval; + ldef.t4config.len = 0; + ldef.t4config.data = 0; + } else { + if ((retval = copy_from_user((void *) &ldef, data, + sizeof(avmb1_loadandconfigdef)))) + return retval; + } + if (!VALID_CARD(ldef.contr)) + return -ESRCH; + + card = CARD(ldef.contr); + if (card->cardstate == CARD_FREE) + return -ESRCH; + + if (ldef.t4file.len <= 0) { + printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len); + return -EINVAL; + } + if (ldef.t4file.data == 0) { + printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n"); + return -EINVAL; + } + + ldata.firmware.user = 1; + ldata.firmware.data = ldef.t4file.data; + ldata.firmware.len = ldef.t4file.len; + ldata.configuration.user = 1; + ldata.configuration.data = ldef.t4config.data; + ldata.configuration.len = ldef.t4config.len; + + if (card->cardstate != CARD_DETECTED) { + printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr); + return -EBUSY; + } + card->cardstate = CARD_LOADING; + + retval = card->driver->load_firmware(card, &ldata); + + if (retval) { + card->cardstate = CARD_DETECTED; + return retval; + } + + while (card->cardstate != CARD_RUNNING) { + + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ/10); /* 0.1 sec */ + + if (signal_pending(current)) + return -EINTR; + } + return 0; + + case AVMB1_RESETCARD: + if ((retval = copy_from_user((void *) &rdef, data, + sizeof(avmb1_resetdef)))) + return retval; + if (!VALID_CARD(rdef.contr)) + return -ESRCH; + card = CARD(rdef.contr); + + if (card->cardstate == CARD_FREE) + return -ESRCH; + if (card->cardstate == CARD_DETECTED) + return 0; + + card->driver->reset_ctr(card); + + while (card->cardstate > CARD_DETECTED) { + + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ/10); /* 0.1 sec */ + + if (signal_pending(current)) + return -EINTR; + } + return 0; + + case AVMB1_GET_CARDINFO: + if ((retval = copy_from_user((void *) &gdef, data, + sizeof(avmb1_getdef)))) + return retval; + + if (!VALID_CARD(gdef.contr)) + return -ESRCH; + + card = CARD(gdef.contr); + + if (card->cardstate == CARD_FREE) + return -ESRCH; + + gdef.cardstate = card->cardstate; + if (card->driver == b1isa_driver) + gdef.cardtype = AVM_CARDTYPE_B1; + else if (card->driver == t1isa_driver) + gdef.cardtype = AVM_CARDTYPE_T1; + else gdef.cardtype = AVM_CARDTYPE_B1; + + if ((retval = copy_to_user(data, (void *) &gdef, + sizeof(avmb1_getdef)))) + return retval; + + return 0; + + case AVMB1_REMOVECARD: + if ((retval = copy_from_user((void *) &rdef, data, + sizeof(avmb1_resetdef)))) + return retval; + + if (!VALID_CARD(rdef.contr)) + return -ESRCH; + card = CARD(rdef.contr); + + if (card->cardstate == CARD_FREE) + return -ESRCH; + + if (card->cardstate != CARD_DETECTED) + return -EBUSY; + + card->driver->remove_ctr(card); + + while (card->cardstate != CARD_FREE) { + + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ/10); /* 0.1 sec */ + + if (signal_pending(current)) + return -EINTR; + } + return 0; + } + return -EINVAL; +} +#endif + +static int capi_manufacturer(unsigned int cmd, void *data) +{ + struct capi_ctr *card; + kcapi_flagdef fdef; + int retval; + + switch (cmd) { +#ifdef CONFIG_AVMB1_COMPAT + case AVMB1_ADDCARD: + case AVMB1_ADDCARD_WITH_TYPE: + case AVMB1_LOAD: + case AVMB1_LOAD_AND_CONFIG: + case AVMB1_RESETCARD: + case AVMB1_GET_CARDINFO: + case AVMB1_REMOVECARD: + return old_capi_manufacturer(cmd, data); +#endif + case KCAPI_CMD_TRACE: + if ((retval = copy_from_user((void *) &fdef, data, + sizeof(kcapi_flagdef)))) + return retval; + + if (!VALID_CARD(fdef.contr)) + return -ESRCH; + card = CARD(fdef.contr); + if (card->cardstate == CARD_FREE) + return -ESRCH; + card->traceflag = fdef.flag; + printk(KERN_INFO "kcapi: contr %d set trace=%d\n", + card->cnr, card->traceflag); + return 0; + } + return -EINVAL; +} + +struct capi_interface avmb1_interface = +{ + capi_installed, + capi_register, + capi_release, + capi_put_message, + capi_get_message, + capi_set_signal, + capi_get_manufacturer, + capi_get_version, + capi_get_serial, + capi_get_profile, + capi_manufacturer +}; + +/* ------------------------------------------------------------- */ +/* -------- Exported Functions --------------------------------- */ +/* ------------------------------------------------------------- */ + +struct capi_interface *attach_capi_interface(struct capi_interface_user *userp) +{ + struct capi_interface_user *p; + + for (p = capi_users; p; p = p->next) { + if (p == userp) { + printk(KERN_ERR "kcapi: double attach from %s\n", + userp->name); + return 0; + } + } + userp->next = capi_users; + capi_users = userp; + MOD_INC_USE_COUNT; + printk(KERN_NOTICE "kcapi: %s attached\n", userp->name); + + return &avmb1_interface; +} + +int detach_capi_interface(struct capi_interface_user *userp) +{ + struct capi_interface_user **pp; + + for (pp = &capi_users; *pp; pp = &(*pp)->next) { + if (*pp == userp) { + *pp = userp->next; + userp->next = 0; + MOD_DEC_USE_COUNT; + printk(KERN_NOTICE "kcapi: %s detached\n", userp->name); + return 0; + } + } + printk(KERN_ERR "kcapi: double detach from %s\n", userp->name); + return -1; +} + +/* ------------------------------------------------------------- */ +/* -------- Init & Cleanup ------------------------------------- */ +/* ------------------------------------------------------------- */ + +EXPORT_SYMBOL(attach_capi_interface); +EXPORT_SYMBOL(detach_capi_interface); +EXPORT_SYMBOL(attach_capi_driver); +EXPORT_SYMBOL(detach_capi_driver); + +/* + * init / exit functions + */ + +#ifdef MODULE +#define kcapi_init init_module +#endif + +int kcapi_init(void) +{ + char *p; + char rev[10]; + + skb_queue_head_init(&recv_queue); + /* init_bh(CAPI_BH, do_capi_bh); */ + + tq_state_notify.routine = notify_handler; + tq_state_notify.data = 0; + + tq_recv_notify.routine = recv_handler; + tq_recv_notify.data = 0; + + proc_capi_init(); + + if ((p = strchr(revision, ':'))) { + strcpy(rev, p + 1); + p = strchr(rev, '$'); + *p = 0; + } else + strcpy(rev, "1.0"); + +#ifdef MODULE + printk(KERN_NOTICE "CAPI-driver Rev%s: loaded\n", rev); +#else + printk(KERN_NOTICE "CAPI-driver Rev%s: started\n", rev); +#endif + return 0; +} + +#ifdef MODULE +void cleanup_module(void) +{ + char rev[10]; + char *p; + + if ((p = strchr(revision, ':'))) { + strcpy(rev, p + 1); + p = strchr(rev, '$'); + *p = 0; + } else { + strcpy(rev, "1.0"); + } + + schedule(); /* execute queued tasks .... */ + proc_capi_exit(); + printk(KERN_NOTICE "CAPI-driver Rev%s: unloaded\n", rev); +} +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/t1isa.c linux.pre11.3/drivers/isdn/avmb1/t1isa.c --- linux.vanilla/drivers/isdn/avmb1/t1isa.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/avmb1/t1isa.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,545 @@ +/* + * $Id: t1isa.c,v 1.4 1999/07/09 15:05:50 keil Exp $ + * + * Module for AVM T1 HEMA-card. + * + * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) + * + * $Log: t1isa.c,v $ + * Revision 1.4 1999/07/09 15:05:50 keil + * compat.h is now isdn_compat.h + * + * Revision 1.3 1999/07/06 07:42:04 calle + * - changes in /proc interface + * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb. + * + * Revision 1.2 1999/07/05 15:09:54 calle + * - renamed "appl_release" to "appl_released". + * - version und profile data now cleared on controller reset + * - extended /proc interface, to allow driver and controller specific + * informations to include by driver hackers. + * + * Revision 1.1 1999/07/01 15:26:44 calle + * complete new version (I love it): + * + new hardware independed "capi_driver" interface that will make it easy to: + * - support other controllers with CAPI-2.0 (i.e. USB Controller) + * - write a CAPI-2.0 for the passive cards + * - support serial link CAPI-2.0 boxes. + * + wrote "capi_driver" for all supported cards. + * + "capi_driver" (supported cards) now have to be configured with + * make menuconfig, in the past all supported cards where included + * at once. + * + new and better informations in /proc/capi/ + * + new ioctl to switch trace of capi messages per controller + * using "avmcapictrl trace [contr] on|off|...." + * + complete testcircle with all supported cards and also the + * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "capicmd.h" +#include "capiutil.h" +#include "capilli.h" +#include "avmcard.h" + +static char *revision = "$Revision: 1.4 $"; + +/* ------------------------------------------------------------- */ + +MODULE_AUTHOR("Carsten Paeth "); + +/* ------------------------------------------------------------- */ + +static struct capi_driver_interface *di; + +/* ------------------------------------------------------------- */ + +static int hema_irq_table[16] = +{0, + 0, + 0, + 0x80, /* irq 3 */ + 0, + 0x90, /* irq 5 */ + 0, + 0xA0, /* irq 7 */ + 0, + 0xB0, /* irq 9 */ + 0xC0, /* irq 10 */ + 0xD0, /* irq 11 */ + 0xE0, /* irq 12 */ + 0, + 0, + 0xF0, /* irq 15 */ +}; + +static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr) +{ + unsigned char cregs[8]; + unsigned char reverse_cardnr; + unsigned long flags; + unsigned char dummy; + int i; + + reverse_cardnr = ((cardnr & 0x01) << 3) | ((cardnr & 0x02) << 1) + | ((cardnr & 0x04) >> 1) | ((cardnr & 0x08) >> 3); + cregs[0] = (HEMA_VERSION_ID << 4) | (reverse_cardnr & 0xf); + cregs[1] = 0x00; /* fast & slow link connected to CON1 */ + cregs[2] = 0x05; /* fast link 20MBit, slow link 20 MBit */ + cregs[3] = 0; + cregs[4] = 0x11; /* zero wait state */ + cregs[5] = hema_irq_table[irq & 0xf]; + cregs[6] = 0; + cregs[7] = 0; + + save_flags(flags); + cli(); + /* board reset */ + t1outp(base, T1_RESETBOARD, 0xf); + udelay(100 * 1000); + dummy = t1inp(base, T1_FASTLINK+T1_OUTSTAT); /* first read */ + + /* write config */ + dummy = (base >> 4) & 0xff; + for (i=1;i<=0xf;i++) t1outp(base, i, dummy); + t1outp(base, HEMA_PAL_ID & 0xf, dummy); + t1outp(base, HEMA_PAL_ID >> 4, cregs[0]); + for(i=1;i<7;i++) t1outp(base, 0, cregs[i]); + t1outp(base, ((base >> 4)) & 0x3, cregs[7]); + restore_flags(flags); + + udelay(100 * 1000); + t1outp(base, T1_FASTLINK+T1_RESETLINK, 0); + t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0); + udelay(10 * 1000); + t1outp(base, T1_FASTLINK+T1_RESETLINK, 1); + t1outp(base, T1_SLOWLINK+T1_RESETLINK, 1); + udelay(100 * 1000); + t1outp(base, T1_FASTLINK+T1_RESETLINK, 0); + t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0); + udelay(10 * 1000); + t1outp(base, T1_FASTLINK+T1_ANALYSE, 0); + udelay(5 * 1000); + t1outp(base, T1_SLOWLINK+T1_ANALYSE, 0); + + if (t1inp(base, T1_FASTLINK+T1_OUTSTAT) != 0x1) /* tx empty */ + return 1; + if (t1inp(base, T1_FASTLINK+T1_INSTAT) != 0x0) /* rx empty */ + return 2; + if (t1inp(base, T1_FASTLINK+T1_IRQENABLE) != 0x0) + return 3; + if ((t1inp(base, T1_FASTLINK+T1_FIFOSTAT) & 0xf0) != 0x70) + return 4; + if ((t1inp(base, T1_FASTLINK+T1_IRQMASTER) & 0x0e) != 0) + return 5; + if ((t1inp(base, T1_FASTLINK+T1_IDENT) & 0x7d) != 1) + return 6; + if (t1inp(base, T1_SLOWLINK+T1_OUTSTAT) != 0x1) /* tx empty */ + return 7; + if ((t1inp(base, T1_SLOWLINK+T1_IRQMASTER) & 0x0e) != 0) + return 8; + if ((t1inp(base, T1_SLOWLINK+T1_IDENT) & 0x7d) != 0) + return 9; + return 0; +} + +static void t1_handle_interrupt(avmcard * card) +{ + struct capi_ctr *ctrl = card->ctrl; + unsigned char b1cmd; + struct sk_buff *skb; + + unsigned ApplId; + unsigned MsgLen; + unsigned DataB3Len; + unsigned NCCI; + unsigned WindowSize; + + while (b1_rx_full(card->port)) { + + b1cmd = b1_get_byte(card->port); + + switch (b1cmd) { + + case RECEIVE_DATA_B3_IND: + + ApplId = (unsigned) b1_get_word(card->port); + MsgLen = t1_get_slice(card->port, card->msgbuf); + DataB3Len = t1_get_slice(card->port, card->databuf); + + if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) { + printk(KERN_ERR "t1isa: incoming packet dropped\n"); + } else { + memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); + memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len); + CAPIMSG_SETDATA(skb->data, skb->data + MsgLen); + ctrl->handle_capimsg(ctrl, ApplId, skb); + } + break; + + case RECEIVE_MESSAGE: + + ApplId = (unsigned) b1_get_word(card->port); + MsgLen = t1_get_slice(card->port, card->msgbuf); + if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { + printk(KERN_ERR "t1isa: incoming packet dropped\n"); + } else { + memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); + ctrl->handle_capimsg(ctrl, ApplId, skb); + } + break; + + case RECEIVE_NEW_NCCI: + + ApplId = b1_get_word(card->port); + NCCI = b1_get_word(card->port); + WindowSize = b1_get_word(card->port); + + ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize); + + break; + + case RECEIVE_FREE_NCCI: + + ApplId = b1_get_word(card->port); + NCCI = b1_get_word(card->port); + + if (NCCI != 0xffffffff) + ctrl->free_ncci(ctrl, ApplId, NCCI); + else ctrl->appl_released(ctrl, ApplId); + break; + + case RECEIVE_START: + b1_put_byte(card->port, SEND_POLLACK); + ctrl->resume_output(ctrl); + break; + + case RECEIVE_STOP: + ctrl->suspend_output(ctrl); + break; + + case RECEIVE_INIT: + + card->versionlen = t1_get_slice(card->port, card->versionbuf); + b1_parse_version(card); + printk(KERN_INFO "%s: %s-card (%s) now active\n", + card->name, + card->version[VER_CARDTYPE], + card->version[VER_DRIVER]); + ctrl->ready(ctrl); + break; + + case RECEIVE_TASK_READY: + ApplId = (unsigned) b1_get_word(card->port); + MsgLen = t1_get_slice(card->port, card->msgbuf); + card->msgbuf[MsgLen--] = 0; + while ( MsgLen >= 0 + && ( card->msgbuf[MsgLen] == '\n' + || card->msgbuf[MsgLen] == '\r')) + card->msgbuf[MsgLen--] = 0; + printk(KERN_INFO "%s: task %d \"%s\" ready.\n", + card->name, ApplId, card->msgbuf); + break; + + case RECEIVE_DEBUGMSG: + MsgLen = t1_get_slice(card->port, card->msgbuf); + card->msgbuf[MsgLen--] = 0; + while ( MsgLen >= 0 + && ( card->msgbuf[MsgLen] == '\n' + || card->msgbuf[MsgLen] == '\r')) + card->msgbuf[MsgLen--] = 0; + printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf); + break; + + case 0xff: + printk(KERN_ERR "%s: card reseted ?\n", card->name); + return; + default: + printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n", + card->name, b1cmd); + return; + } + } +} + +/* ------------------------------------------------------------- */ + +static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs) +{ + avmcard *card; + + card = (avmcard *) devptr; + + if (!card) { + printk(KERN_WARNING "t1_interrupt: wrong device\n"); + return; + } + if (card->interrupt) { + printk(KERN_ERR "t1_interrupt: reentering interrupt hander (%s)\n", card->name); + return; + } + + card->interrupt = 1; + + t1_handle_interrupt(card); + + card->interrupt = 0; +} +/* ------------------------------------------------------------- */ + +static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) +{ + avmcard *card = (avmcard *)(ctrl->driverdata); + unsigned int port = card->port; + unsigned long flags; + int retval; + + t1_disable_irq(port); + b1_reset(port); + + if ((retval = b1_load_t4file(port, &data->firmware))) { + b1_reset(port); + printk(KERN_ERR "%s: failed to load t4file!!\n", + card->name); + return retval; + } + + if (data->configuration.len > 0 && data->configuration.data) { + if ((retval = b1_load_config(port, &data->configuration))) { + b1_reset(port); + printk(KERN_ERR "%s: failed to load config!!\n", + card->name); + return retval; + } + } + + if (!b1_loaded(port)) { + printk(KERN_ERR "%s: failed to load t4file.\n", card->name); + return -EIO; + } + + save_flags(flags); + cli(); + b1_setinterrupt(port, card->irq, card->cardtype); + b1_put_byte(port, SEND_INIT); + b1_put_word(port, AVM_NAPPS); + b1_put_word(port, AVM_NCCI_PER_CHANNEL*30); + b1_put_word(port, ctrl->cnr - 1); + restore_flags(flags); + + return 0; +} + +void t1isa_reset_ctr(struct capi_ctr *ctrl) +{ + avmcard *card = (avmcard *)(ctrl->driverdata); + unsigned int port = card->port; + + t1_disable_irq(port); + b1_reset(port); + b1_reset(port); + + memset(card->version, 0, sizeof(card->version)); + ctrl->reseted(ctrl); +} + +static void t1isa_remove_ctr(struct capi_ctr *ctrl) +{ + avmcard *card = (avmcard *)(ctrl->driverdata); + unsigned int port = card->port; + + t1_disable_irq(port); + b1_reset(port); + b1_reset(port); + t1_reset(port); + + di->detach_ctr(ctrl); + free_irq(card->irq, card); + release_region(card->port, AVMB1_PORTLEN); + kfree(card); + + MOD_DEC_USE_COUNT; +} + +/* ------------------------------------------------------------- */ + +static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p) +{ + struct capi_ctr *ctrl; + avmcard *card; + int retval; + + card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); + + if (!card) { + printk(KERN_WARNING "t1isa: no memory.\n"); + return -ENOMEM; + } + memset(card, 0, sizeof(avmcard)); + sprintf(card->name, "t1isa-%x", p->port); + card->port = p->port; + card->irq = p->irq; + card->cardtype = avm_t1isa; + card->cardnr = p->cardnr; + + if (!(((card->port & 0x7) == 0) && ((card->port & 0x30) != 0x30))) { + printk(KERN_WARNING "t1isa: illegal port 0x%x.\n", card->port); + kfree(card); + return -EINVAL; + } + + if (check_region(card->port, AVMB1_PORTLEN)) { + printk(KERN_WARNING + "t1isa: ports 0x%03x-0x%03x in use.\n", + card->port, card->port + AVMB1_PORTLEN); + kfree(card); + return -EBUSY; + } + if (hema_irq_table[card->irq & 0xf] == 0) { + printk(KERN_WARNING "t1isa: irq %d not valid.\n", card->irq); + kfree(card); + return -EINVAL; + } + for (ctrl = driver->controller; ctrl; ctrl = ctrl->next) { + if (((avmcard *)(ctrl->driverdata))->cardnr == card->cardnr) { + printk(KERN_WARNING "t1isa: card with number %d already installed.\n", card->cardnr); + kfree(card); + return -EBUSY; + } + } + if ((retval = t1_detectandinit(card->port, card->irq, card->cardnr)) != 0) { + printk(KERN_NOTICE "t1isa: NO card at 0x%x (%d)\n", + card->port, retval); + kfree(card); + return -EIO; + } + t1_disable_irq(card->port); + b1_reset(card->port); + + request_region(p->port, AVMB1_PORTLEN, card->name); + + retval = request_irq(card->irq, t1isa_interrupt, 0, card->name, card); + if (retval) { + printk(KERN_ERR "t1isa: unable to get IRQ %d.\n", card->irq); + release_region(card->port, AVMB1_PORTLEN); + kfree(card); + return -EBUSY; + } + + card->ctrl = di->attach_ctr(driver, card->name, card); + if (!card->ctrl) { + printk(KERN_ERR "t1isa: attach controller failed.\n"); + free_irq(card->irq, card); + release_region(card->port, AVMB1_PORTLEN); + kfree(card); + return -EBUSY; + } + + MOD_INC_USE_COUNT; + return 0; +} + +static void t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) +{ + avmcard *card = (avmcard *)(ctrl->driverdata); + unsigned int port = card->port; + unsigned long flags; + __u16 len = CAPIMSG_LEN(skb->data); + __u8 cmd = CAPIMSG_COMMAND(skb->data); + __u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data); + + save_flags(flags); + cli(); + if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { + __u16 dlen = CAPIMSG_DATALEN(skb->data); + b1_put_byte(port, SEND_DATA_B3_REQ); + t1_put_slice(port, skb->data, len); + t1_put_slice(port, skb->data + len, dlen); + } else { + b1_put_byte(port, SEND_MESSAGE); + t1_put_slice(port, skb->data, len); + } + restore_flags(flags); + dev_kfree_skb(skb); +} +/* ------------------------------------------------------------- */ + +static char *t1isa_procinfo(struct capi_ctr *ctrl) +{ + avmcard *card = (avmcard *)(ctrl->driverdata); + if (!card) + return ""; + sprintf(card->infobuf, "%s %s 0x%x %d %d", + card->cardname[0] ? card->cardname : "-", + card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-", + card->port, card->irq, card->cardnr + ); + return card->infobuf; +} + + +/* ------------------------------------------------------------- */ + +static struct capi_driver t1isa_driver = { + "t1isa", + "0.0", + t1isa_load_firmware, + t1isa_reset_ctr, + t1isa_remove_ctr, + b1_register_appl, + b1_release_appl, + t1isa_send_message, + + t1isa_procinfo, + b1ctl_read_proc, + 0, /* use standard driver_read_proc */ + + t1isa_add_card, +}; + +#ifdef MODULE +#define t1isa_init init_module +void cleanup_module(void); +#endif + +int t1isa_init(void) +{ + struct capi_driver *driver = &t1isa_driver; + char *p; + + if ((p = strchr(revision, ':'))) { + strncpy(driver->revision, p + 1, sizeof(driver->revision)); + p = strchr(driver->revision, '$'); + *p = 0; + } + + printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision); + + di = attach_capi_driver(driver); + + if (!di) { + printk(KERN_ERR "%s: failed to attach capi_driver\n", + driver->name); + return -EIO; + } + return 0; +} + +#ifdef MODULE +void cleanup_module(void) +{ + detach_capi_driver(&t1isa_driver); +} +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/divert/Makefile linux.pre11.3/drivers/isdn/divert/Makefile --- linux.vanilla/drivers/isdn/divert/Makefile Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/divert/Makefile Mon Jul 19 23:59:33 1999 @@ -0,0 +1,21 @@ +L_OBJS := +LX_OBJS := +M_OBJS := +MX_OBJS := +O_OBJS := +OX_OBJS := +L_TARGET := +O_TARGET := + +O_OBJS += isdn_divert.o divert_procfs.o +O_TARGET := dss1_divert.o +M_OBJS += dss1_divert.o +OX_OBJS += divert_init.o + +include $(TOPDIR)/Rules.make + + + + + + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/divert/divert_init.c linux.pre11.3/drivers/isdn/divert/divert_init.c --- linux.vanilla/drivers/isdn/divert/divert_init.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/divert/divert_init.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,105 @@ +/* + * $Id: divert_init.c,v 1.3 1999/07/05 20:21:39 werner Exp $ + * + * Module init for DSS1 diversion services for i4l. + * + * Copyright 1999 by Werner Cornelius (werner@isdn4linux.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, 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. + * + * $Log: divert_init.c,v $ + * Revision 1.3 1999/07/05 20:21:39 werner + * changes to use diversion sources for all kernel versions. + * removed static device, only proc filesystem used + * + * Revision 1.2 1999/07/04 21:37:30 werner + * Ported from kernel version 2.0 + * + * + * + */ + +#include +#include +#include +#include "isdn_divert.h" + +/********************/ +/* needed externals */ +/********************/ +extern int printk(const char *fmt,...); + +/****************************************/ +/* structure containing interface to hl */ +/****************************************/ +isdn_divert_if divert_if = + { DIVERT_IF_MAGIC, /* magic value */ + DIVERT_CMD_REG, /* register cmd */ + ll_callback, /* callback routine from ll */ + NULL, /* command still not specified */ + NULL, /* drv_to_name */ + NULL, /* name_to_drv */ + }; + +/*************************/ +/* Module interface code */ +/* no cmd line parms */ +/*************************/ +int init_module(void) +{ int i; + + if (divert_dev_init()) + { printk(KERN_WARNING "dss1_divert: cannot install device, not loaded\n"); + return(-EIO); + } + if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) + { divert_dev_deinit(); + printk(KERN_WARNING "dss1_divert: error %d registering module, not loaded\n",i); + return(-EIO); + } +#if (LINUX_VERSION_CODE < 0x020111) + register_symtab(0); +#endif + printk(KERN_INFO "dss1_divert module successfully installed\n"); + return(0); +} /* init_module */ + +/**********************/ +/* Module deinit code */ +/**********************/ +void cleanup_module(void) +{ int flags; + int i; + + save_flags(flags); + cli(); + divert_if.cmd = DIVERT_CMD_REL; /* release */ + if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) + { printk(KERN_WARNING "dss1_divert: error %d releasing module\n",i); + restore_flags(flags); + return; + } + if (divert_dev_deinit()) + { printk(KERN_WARNING "dss1_divert: device busy, remove cancelled\n"); + restore_flags(flags); + return; + } + restore_flags(flags); + deleterule(-1); /* delete all rules and free mem */ + deleteprocs(); + printk(KERN_INFO "dss1_divert module successfully removed \n"); +} /* cleanup_module */ + + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/divert/divert_procfs.c linux.pre11.3/drivers/isdn/divert/divert_procfs.c --- linux.vanilla/drivers/isdn/divert/divert_procfs.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/divert/divert_procfs.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,444 @@ +/* + * $Id: divert_procfs.c,v 1.3 1999/07/05 20:21:41 werner Exp $ + * + * Filesystem handling for the diversion supplementary services. + * + * Copyright 1998 by Werner Cornelius (werner@isdn4linux.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, 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. + * + * $Log: divert_procfs.c,v $ + * Revision 1.3 1999/07/05 20:21:41 werner + * changes to use diversion sources for all kernel versions. + * removed static device, only proc filesystem used + * + * Revision 1.2 1999/07/04 21:37:31 werner + * Ported from kernel version 2.0 + * + * + * + */ + +#include +#define __NO_VERSION__ +#include +#include +#if (LINUX_VERSION_CODE >= 0x020117) +#include +#endif +#ifdef CONFIG_PROC_FS + #include +#else + #include +#endif +#include +#include "isdn_divert.h" + +/*********************************/ +/* Variables for interface queue */ +/*********************************/ +ulong if_used = 0; /* number of interface users */ +static struct divert_info *divert_info_head = NULL; /* head of queue */ +static struct divert_info *divert_info_tail = NULL; /* pointer to last entry */ +static struct wait_queue *rd_queue = 0; /* Queue IO */ + +/*********************************/ +/* put an info buffer into queue */ +/*********************************/ +void put_info_buffer(char *cp) +{ struct divert_info *ib; + int flags; + + if (if_used <= 0) return; + if (!cp) return; + if (!*cp) return; + if (!(ib = (struct divert_info *) kmalloc(sizeof(struct divert_info)+strlen(cp), GFP_ATOMIC))) return; /* no memory */ + strcpy(ib->info_start,cp); /* set output string */ + ib->next = NULL; + save_flags(flags); + cli(); + ib->usage_cnt = if_used; + if (!divert_info_head) + divert_info_head = ib; /* new head */ + else + divert_info_tail->next = ib; /* follows existing messages */ + divert_info_tail = ib; /* new tail */ + restore_flags(flags); + + /* delete old entrys */ + while (divert_info_head->next) + { if ((divert_info_head->usage_cnt <= 0) && + (divert_info_head->next->usage_cnt <= 0)) + { ib = divert_info_head; + divert_info_head = divert_info_head->next; + kfree(ib); + } + else break; + } /* divert_info_head->next */ + wake_up_interruptible(&(rd_queue)); +} /* put_info_buffer */ + +/**********************************/ +/* deflection device read routine */ +/**********************************/ +#if (LINUX_VERSION_CODE < 0x020117) +static int isdn_divert_read(struct inode *inode, struct file *file, char *buf, RWARG count) +#else +static ssize_t isdn_divert_read(struct file *file, char *buf, size_t count, loff_t *off) +#endif +{ struct divert_info *inf; + int len; + + if (!*((struct divert_info **)file->private_data)) + { if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + interruptible_sleep_on(&(rd_queue)); + } + if (!(inf = *((struct divert_info **)file->private_data))) return(0); + + inf->usage_cnt--; /* new usage count */ + (struct divert_info **)file->private_data = &inf->next; /* next structure */ + if ((len = strlen(inf->info_start)) <= count) + { if (copy_to_user(buf, inf->info_start, len)) + return -EFAULT; + file->f_pos += len; + return(len); + } + return(0); +} /* isdn_divert_read */ + +/**********************************/ +/* deflection device write routine */ +/**********************************/ +#if (LINUX_VERSION_CODE < 0x020117) +static int isdn_divert_write(struct inode *inode, struct file *file, const char *buf, RWARG count) +#else +static ssize_t isdn_divert_write(struct file *file, const char *buf, size_t count, loff_t *off) +#endif +{ + return(-ENODEV); +} /* isdn_divert_write */ + + +/***************************************/ +/* select routines for various kernels */ +/***************************************/ +#if (LINUX_VERSION_CODE < 0x020117) +static int isdn_divert_select(struct inode *inode, struct file *file, int type, select_table * st) +{ + if (*((struct divert_info **)file->private_data)) + return 1; + else + { if (st) select_wait(&(rd_queue), st); + return 0; + } +} /* isdn_divert_select */ +#else +static unsigned int isdn_divert_poll(struct file *file, poll_table * wait) +{ unsigned int mask = 0; + + poll_wait(file, &(rd_queue), wait); + /* mask = POLLOUT | POLLWRNORM; */ + if (*((struct divert_info **)file->private_data)) + { mask |= POLLIN | POLLRDNORM; + } + return mask; +} /* isdn_divert_poll */ +#endif + +/****************/ +/* Open routine */ +/****************/ +static int isdn_divert_open(struct inode *ino, struct file *filep) +{ int flags; + + MOD_INC_USE_COUNT; + save_flags(flags); + cli(); + if_used++; + if (divert_info_head) + (struct divert_info **)filep->private_data = &(divert_info_tail->next); + else + (struct divert_info **)filep->private_data = &divert_info_head; + restore_flags(flags); + /* start_divert(); */ + return(0); +} /* isdn_divert_open */ + +/*******************/ +/* close routine */ +/*******************/ +#if (LINUX_VERSION_CODE < 0x020117) +static void isdn_divert_close(struct inode *ino, struct file *filep) +#else +static int isdn_divert_close(struct inode *ino, struct file *filep) +#endif +{ struct divert_info *inf; + int flags; + + save_flags(flags); + cli(); + if_used--; + inf = *((struct divert_info **)filep->private_data); + while (inf) + { inf->usage_cnt--; + inf = inf->next; + } + restore_flags(flags); + if (if_used <= 0) + while (divert_info_head) + { inf = divert_info_head; + divert_info_head = divert_info_head->next; + kfree(inf); + } + MOD_DEC_USE_COUNT; +#if (LINUX_VERSION_CODE < 0x020117) +#else + return(0); +#endif +} /* isdn_divert_close */ + +/*********/ +/* IOCTL */ +/*********/ +static int isdn_divert_ioctl(struct inode *inode, struct file *file, + uint cmd, ulong arg) +{ divert_ioctl dioctl; + int i, flags; + divert_rule *rulep; + char *cp; + + if ((i = copy_from_user(&dioctl,(char *) arg, sizeof(dioctl)))) + return(i); + + switch (cmd) + { + case IIOCGETVER: + dioctl.drv_version = DIVERT_IIOC_VERSION ; /* set version */ + break; + + case IIOCGETDRV: + if ((dioctl.getid.drvid = divert_if.name_to_drv(dioctl.getid.drvnam)) < 0) + return(-EINVAL); + break; + + case IIOCGETNAM: + cp = divert_if.drv_to_name(dioctl.getid.drvid); + if (!cp) return(-EINVAL); + if (!*cp) return(-EINVAL); + strcpy(dioctl.getid.drvnam,cp); + break; + + case IIOCGETRULE: + if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx))) + return(-EINVAL); + dioctl.getsetrule.rule = *rulep; /* copy data */ + break; + + case IIOCMODRULE: + if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx))) + return(-EINVAL); + save_flags(flags); + cli(); + *rulep = dioctl.getsetrule.rule; /* copy data */ + restore_flags(flags); + return(0); /* no copy required */ + break; + + case IIOCINSRULE: + return(insertrule(dioctl.getsetrule.ruleidx,&dioctl.getsetrule.rule)); + break; + + case IIOCDELRULE: + return(deleterule(dioctl.getsetrule.ruleidx)); + break; + + case IIOCDODFACT: + return(deflect_extern_action(dioctl.fwd_ctrl.subcmd, + dioctl.fwd_ctrl.callid, + dioctl.fwd_ctrl.to_nr)); + + case IIOCDOCFACT: + case IIOCDOCFDIS: + case IIOCDOCFINT: + if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid)) + return(-EINVAL); /* invalid driver */ + if ((i = cf_command(dioctl.cf_ctrl.drvid, + (cmd == IIOCDOCFACT) ? 1: (cmd == IIOCDOCFDIS) ? 0:2, + dioctl.cf_ctrl.cfproc, + dioctl.cf_ctrl.msn, + dioctl.cf_ctrl.service, + dioctl.cf_ctrl.fwd_nr, + &dioctl.cf_ctrl.procid))) + return(i); + break; + + default: + return(-EINVAL); + } /* switch cmd */ + return(copy_to_user((char *) arg, &dioctl, sizeof(dioctl))); /* success */ +} /* isdn_divert_ioctl */ + + +#ifdef CONFIG_PROC_FS +#if (LINUX_VERSION_CODE < 0x020117) +static LSTYPE +isdn_divert_lseek(struct inode *inode, struct file *file, LSARG offset, int orig) +#else +static loff_t +isdn_divert_lseek(struct file *file, loff_t offset, int orig) +#endif +{ + return -ESPIPE; +} + +#if (LINUX_VERSION_CODE < 0x020117) +static struct file_operations isdn_fops = +{ + isdn_divert_lseek, + isdn_divert_read, + isdn_divert_write, + NULL, /* isdn_readdir */ + isdn_divert_select, /* isdn_select */ + isdn_divert_ioctl, /* isdn_ioctl */ + NULL, /* isdn_mmap */ + isdn_divert_open, + isdn_divert_close, + NULL /* fsync */ +}; + +#else + +static struct file_operations isdn_fops = +{ + isdn_divert_lseek, + isdn_divert_read, + isdn_divert_write, + NULL, /* isdn_readdir */ + isdn_divert_poll, /* isdn_poll */ + isdn_divert_ioctl, /* isdn_ioctl */ + NULL, /* isdn_mmap */ + isdn_divert_open, + NULL, /* flush */ + isdn_divert_close, + NULL /* fsync */ +}; +#endif /* kernel >= 2.1 */ + + +/* + * proc directories can do almost nothing.. + */ +struct inode_operations proc_isdn_inode_ops = { + &isdn_fops, /* isdn divert special file-ops */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ + NULL, /* bmap */ + NULL, /* truncate */ + NULL /* permission */ +}; + +/****************************/ +/* isdn subdir in /proc/net */ +/****************************/ +static struct proc_dir_entry isdn_proc_entry = + { 0, 4, "isdn", S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, 0, + &proc_dir_inode_operations,NULL,NULL,NULL,NULL,NULL + }; + +static struct proc_dir_entry isdn_divert_entry = +{ 0, 6, "divert",S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_isdn_inode_ops, + NULL + }; + +/*****************************************************************/ +/* variables used for automatic determining existence of proc fs */ +/*****************************************************************/ +static int (*proc_reg_dynamic)(struct proc_dir_entry *, struct proc_dir_entry *) = NULL; +static int (*proc_unreg)(struct proc_dir_entry *, int) = NULL; + +#endif CONFIG_PROC_FS + +/***************************************************************************/ +/* divert_dev_init must be called before the proc filesystem may be used */ +/***************************************************************************/ +int divert_dev_init(void) +{ int i; + +#ifdef CONFIG_PROC_FS +#if (LINUX_VERSION_CODE < 0x020117) + (void *) proc_reg_dynamic = get_module_symbol("","proc_register_dynamic"); + (void *) proc_unreg = get_module_symbol("","proc_unregister"); + if (proc_unreg) + { i = proc_reg_dynamic(&proc_net,&isdn_proc_entry); + if (i) return(i); + i = proc_reg_dynamic(&isdn_proc_entry,&isdn_divert_entry); + if (i) + { proc_unreg(&proc_net,isdn_proc_entry.low_ino); + return(i); + } + } /* proc exists */ +#else + (void *) proc_reg_dynamic = get_module_symbol("","proc_register"); + (void *) proc_unreg = get_module_symbol("","proc_unregister"); + if (proc_unreg) + { i = proc_reg_dynamic(proc_net,&isdn_proc_entry); + if (i) return(i); + i = proc_reg_dynamic(&isdn_proc_entry,&isdn_divert_entry); + if (i) + { proc_unreg(proc_net,isdn_proc_entry.low_ino); + return(i); + } + } /* proc exists */ +#endif +#endif CONFIG_PROC_FS + + return(0); +} /* divert_dev_init */ + +/***************************************************************************/ +/* divert_dev_deinit must be called before leaving isdn when included as */ +/* a module. */ +/***************************************************************************/ +int divert_dev_deinit(void) +{ int i; + +#ifdef CONFIG_PROC_FS + if (proc_unreg) + { i = proc_unreg(&isdn_proc_entry,isdn_divert_entry.low_ino); + if (i) return(i); +#if (LINUX_VERSION_CODE < 0x020117) + i = proc_unreg(&proc_net,isdn_proc_entry.low_ino); +#else + i = proc_unreg(proc_net,isdn_proc_entry.low_ino); +#endif + if (i) return(i); + } /* proc exists */ +#endif CONFIG_PROC_FS + + return(0); +} /* divert_dev_deinit */ + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/divert/isdn_divert.c linux.pre11.3/drivers/isdn/divert/isdn_divert.c --- linux.vanilla/drivers/isdn/divert/isdn_divert.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/divert/isdn_divert.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,902 @@ +/* + * $Id: isdn_divert.c,v 1.2 1999/07/04 21:37:32 werner Exp $ + * + * DSS1 main diversion supplementary handling for i4l. + * + * Copyright 1999 by Werner Cornelius (werner@isdn4linux.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, 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. + * + * $Log: isdn_divert.c,v $ + * Revision 1.2 1999/07/04 21:37:32 werner + * Ported from kernel version 2.0 + * + * + * + */ + + + +#include +#define __NO_VERSION__ +#include +#include +#include +#include "isdn_divert.h" + +/**********************************/ +/* structure keeping calling info */ +/**********************************/ +struct call_struc + { isdn_ctrl ics; /* delivered setup + driver parameters */ + ulong divert_id; /* Id delivered to user */ + unsigned char akt_state; /* actual state */ + char deflect_dest[35]; /* deflection destination */ + struct timer_list timer; /* timer control structure */ + char info[90]; /* device info output */ + struct call_struc *next; /* pointer to next entry */ + struct call_struc *prev; + }; + + +/********************************************/ +/* structure keeping deflection table entry */ +/********************************************/ +struct deflect_struc + { struct deflect_struc *next,*prev; + divert_rule rule; /* used rule */ + }; + + +/*****************************************/ +/* variables for main diversion services */ +/*****************************************/ +/* diversion/deflection processes */ +static struct call_struc *divert_head = NULL; /* head of remembered entrys */ +static ulong next_id = 1; /* next info id */ +static struct deflect_struc *table_head = NULL; +static struct deflect_struc *table_tail = NULL; +static unsigned char extern_wait_max = 4; /* maximum wait in s for external process */ + +/***************************/ +/* timer callback function */ +/***************************/ +static void deflect_timer_expire(ulong arg) +{ int flags; + struct call_struc *cs = (struct call_struc *) arg; + + save_flags(flags); + cli(); + del_timer(&cs->timer); /* delete active timer */ + restore_flags(flags); + + switch(cs->akt_state) + { case DEFLECT_PROCEED: + cs->ics.command = ISDN_CMD_HANGUP; /* cancel action */ + divert_if.ll_cmd(&cs->ics); + save_flags(flags); + cli(); + cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ + cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); + add_timer(&cs->timer); + restore_flags(flags); + break; + + case DEFLECT_ALERT: + cs->ics.command = ISDN_CMD_REDIR; /* protocol */ + strcpy(cs->ics.parm.setup.phone,cs->deflect_dest); + strcpy(cs->ics.parm.setup.eazmsn,"Testtext delayed"); + divert_if.ll_cmd(&cs->ics); + save_flags(flags); + cli(); + cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ + cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); + add_timer(&cs->timer); + restore_flags(flags); + break; + + case DEFLECT_AUTODEL: + default: + save_flags(flags); + cli(); + if (cs->prev) + cs->prev->next = cs->next; /* forward link */ + else + divert_head = cs->next; + if (cs->next) + cs->next->prev = cs->prev; /* back link */ + restore_flags(flags); + kfree(cs); + return; + + } /* switch */ +} /* deflect_timer_func */ + + +/*****************************************/ +/* handle call forwarding de/activations */ +/* 0 = deact, 1 = act, 2 = interrogate */ +/*****************************************/ +int cf_command(int drvid, int mode, + u_char proc, char *msn, + u_char service, char *fwd_nr, ulong *procid) +{ int retval,msnlen,flags; + int fwd_len; + char *p,*ielenp,tmp[60]; + struct call_struc *cs; + + if (strchr(msn,'.')) return(-EINVAL); /* subaddress not allowed in msn */ + if ((proc & 0x7F) > 2) return(-EINVAL); + proc &= 3; + p = tmp; + *p++ = 0x30; /* enumeration */ + ielenp = p++; /* remember total length position */ + *p++ = 0xa; /* proc tag */ + *p++ = 1; /* length */ + *p++ = proc & 0x7F; /* procedure to de/activate/interrogate */ + *p++ = 0xa; /* service tag */ + *p++ = 1; /* length */ + *p++ = service; /* service to handle */ + + if (mode == 1) + { if (!*fwd_nr) return(-EINVAL); /* destination missing */ + if (strchr(fwd_nr,'.')) return(-EINVAL); /* subaddress not allowed */ + fwd_len = strlen(fwd_nr); + *p++ = 0x30; /* number enumeration */ + *p++ = fwd_len + 2; /* complete forward to len */ + *p++ = 0x80; /* fwd to nr */ + *p++ = fwd_len; /* length of number */ + strcpy(p,fwd_nr); /* copy number */ + p += fwd_len; /* pointer beyond fwd */ + } /* activate */ + + msnlen = strlen(msn); + *p++ = 0x80; /* msn number */ + if (msnlen > 1) + { *p++ = msnlen; /* length */ + strcpy(p,msn); + p += msnlen; + } + else *p++ = 0; + + *ielenp = p - ielenp - 1; /* set total IE length */ + + /* allocate mem for information struct */ + if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) + return(-ENOMEM); /* no memory */ + init_timer(&cs->timer); + cs->info[0] = '\0'; + cs->timer.function = deflect_timer_expire; + cs->timer.data = (ulong) cs; /* pointer to own structure */ + cs->ics.driver = drvid; + cs->ics.command = ISDN_CMD_PROT_IO; /* protocol specific io */ + cs->ics.arg = DSS1_CMD_INVOKE; /* invoke supplementary service */ + cs->ics.parm.dss1_io.proc = (mode == 1) ? 7: (mode == 2) ? 11:8; /* operation */ + cs->ics.parm.dss1_io.timeout = 4000; /* from ETS 300 207-1 */ + cs->ics.parm.dss1_io.datalen = p - tmp; /* total len */ + cs->ics.parm.dss1_io.data = tmp; /* start of buffer */ + + save_flags(flags); + cli(); + cs->ics.parm.dss1_io.ll_id = next_id++; /* id for callback */ + restore_flags(flags); + *procid = cs->ics.parm.dss1_io.ll_id; + + sprintf(cs->info,"%d 0x%lx %s%s 0 %s %0x %d%s%s\n", + (!mode ) ? DIVERT_DEACTIVATE : (mode == 1) ? DIVERT_ACTIVATE : DIVERT_REPORT, + cs->ics.parm.dss1_io.ll_id, + (mode != 2) ? "" : "0 ", + divert_if.drv_to_name(cs->ics.driver), + msn, + service & 0xFF, + proc, + (mode != 1) ? "" : " 0 ", + (mode != 1) ? "" : fwd_nr); + + retval = divert_if.ll_cmd(&cs->ics); /* excute command */ + + if (!retval) + { cs->prev = NULL; + save_flags(flags); + cli(); + cs->next = divert_head; + divert_head = cs; + restore_flags(flags); + } + else + kfree(cs); + return(retval); +} /* cf_command */ + + +/****************************************/ +/* handle a external deflection command */ +/****************************************/ +int deflect_extern_action(u_char cmd, ulong callid, char *to_nr) +{ struct call_struc *cs; + isdn_ctrl ic; + int flags; + int i; + + if ((cmd & 0x7F) > 2) return(-EINVAL); /* invalid command */ + cs = divert_head; /* start of parameter list */ + while (cs) + { if (cs->divert_id == callid) break; /* found */ + cs = cs->next; + } /* search entry */ + if (!cs) return(-EINVAL); /* invalid callid */ + + ic.driver = cs->ics.driver; + ic.arg = cs->ics.arg; + i = -EINVAL; + if (cs->akt_state == DEFLECT_AUTODEL) return(i); /* no valid call */ + switch (cmd & 0x7F) + { case 0: /* hangup */ + del_timer(&cs->timer); + ic.command = ISDN_CMD_HANGUP; + i = divert_if.ll_cmd(&ic); + save_flags(flags); + cli(); + cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ + cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); + add_timer(&cs->timer); + restore_flags(flags); + break; + + case 1: /* alert */ + if (cs->akt_state == DEFLECT_ALERT) return(0); + cmd &= 0x7F; /* never wait */ + del_timer(&cs->timer); + ic.command = ISDN_CMD_ALERT; + if ((i = divert_if.ll_cmd(&ic))) + { save_flags(flags); + cli(); + cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ + cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); + add_timer(&cs->timer); + restore_flags(flags); + } + else + cs->akt_state = DEFLECT_ALERT; + break; + + case 2: /* redir */ + del_timer(&cs->timer); + strcpy(cs->ics.parm.setup.phone, to_nr); + strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual"); + ic.command = ISDN_CMD_REDIR; + if ((i = divert_if.ll_cmd(&ic))) + { save_flags(flags); + cli(); + cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ + cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); + add_timer(&cs->timer); + restore_flags(flags); + } + else + cs->akt_state = DEFLECT_ALERT; + break; + + } /* switch */ + return(i); +} /* deflect_extern_action */ + +/********************************/ +/* insert a new rule before idx */ +/********************************/ +int insertrule(int idx, divert_rule *newrule) +{ struct deflect_struc *ds,*ds1; + int flags; + + if (!(ds = (struct deflect_struc *) kmalloc(sizeof(struct deflect_struc), + GFP_KERNEL))) + return(-ENOMEM); /* no memory */ + + ds->rule = *newrule; /* set rule */ + + save_flags(flags); + cli(); + + if (idx >= 0) + { ds1 = table_head; + while ((ds1) && (idx > 0)) + { idx--; + ds1 = ds1->next; + } + if (!ds1) idx = -1; + } + + if (idx < 0) + { ds->prev = table_tail; /* previous entry */ + ds->next = NULL; /* end of chain */ + if (ds->prev) + ds->prev->next = ds; /* last forward */ + else + table_head = ds; /* is first entry */ + table_tail = ds; /* end of queue */ + } + else + { ds->next = ds1; /* next entry */ + ds->prev = ds1->prev; /* prev entry */ + ds1->prev = ds; /* backward chain old element */ + if (!ds->prev) + table_head = ds; /* first element */ + } + + restore_flags(flags); + return(0); +} /* insertrule */ + +/***********************************/ +/* delete the rule at position idx */ +/***********************************/ +int deleterule(int idx) +{ struct deflect_struc *ds,*ds1; + int flags; + + if (idx < 0) + { save_flags(flags); + cli(); + ds = table_head; + table_head = NULL; + table_tail = NULL; + restore_flags(flags); + while (ds) + { ds1 = ds; + ds = ds->next; + kfree(ds1); + } + return(0); + } + + save_flags(flags); + cli(); + ds = table_head; + + while ((ds) && (idx > 0)) + { idx--; + ds = ds->next; + } + + if (!ds) + { restore_flags(flags); + return(-EINVAL); + } + + if (ds->next) + ds->next->prev = ds->prev; /* backward chain */ + else + table_tail = ds->prev; /* end of chain */ + + if (ds->prev) + ds->prev->next = ds->next; /* forward chain */ + else + table_head = ds->next; /* start of chain */ + + restore_flags(flags); + kfree(ds); + return(0); +} /* deleterule */ + +/*******************************************/ +/* get a pointer to a specific rule number */ +/*******************************************/ +divert_rule *getruleptr(int idx) +{ struct deflect_struc *ds = table_head; + + if (idx < 0) return(NULL); + while ((ds) && (idx >= 0)) + { if (!(idx--)) + { return(&ds->rule); + break; + } + ds = ds->next; + } + return(NULL); +} /* getruleptr */ + +/*************************************************/ +/* called from common module on an incoming call */ +/*************************************************/ +int isdn_divert_icall(isdn_ctrl *ic) +{ int retval = 0; + int flags; + struct call_struc *cs = NULL; + struct deflect_struc *dv; + char *p,*p1; + u_char accept; + + /* first check the internal deflection table */ + for (dv = table_head; dv ; dv = dv->next ) + { /* scan table */ + if (((dv->rule.callopt == 1) && (ic->command == ISDN_STAT_ICALLW)) || + ((dv->rule.callopt == 2) && (ic->command == ISDN_STAT_ICALL))) + continue; /* call option check */ + if (!(dv->rule.drvid & (1L << ic->driver))) + continue; /* driver not matching */ + if ((dv->rule.si1) && (dv->rule.si1 != ic->parm.setup.si1)) + continue; /* si1 not matching */ + if ((dv->rule.si2) && (dv->rule.si2 != ic->parm.setup.si2)) + continue; /* si2 not matching */ + + p = dv->rule.my_msn; + p1 = ic->parm.setup.eazmsn; + accept = 0; + while (*p) + { /* complete compare */ + if (*p == '-') + { accept = 1; /* call accepted */ + break; + } + if (*p++ != *p1++) + break; /* not accepted */ + if ((!*p) && (!*p1)) + accept = 1; + } /* complete compare */ + if (!accept) continue; /* not accepted */ + + if ((strcmp(dv->rule.caller,"0")) || (ic->parm.setup.phone[0])) + { p = dv->rule.caller; + p1 = ic->parm.setup.phone; + accept = 0; + while (*p) + { /* complete compare */ + if (*p == '-') + { accept = 1; /* call accepted */ + break; + } + if (*p++ != *p1++) + break; /* not accepted */ + if ((!*p) && (!*p1)) + accept = 1; + } /* complete compare */ + if (!accept) continue; /* not accepted */ + } + + switch (dv->rule.action) + { case DEFLECT_IGNORE: + return(0); + break; + + case DEFLECT_ALERT: + case DEFLECT_PROCEED: + case DEFLECT_REPORT: + case DEFLECT_REJECT: + if (dv->rule.action == DEFLECT_PROCEED) + if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime))) + return(0); /* no external deflection needed */ + if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) + return(0); /* no memory */ + init_timer(&cs->timer); + cs->info[0] = '\0'; + cs->timer.function = deflect_timer_expire; + cs->timer.data = (ulong) cs; /* pointer to own structure */ + + cs->ics = *ic; /* copy incoming data */ + if (!cs->ics.parm.setup.phone[0]) strcpy(cs->ics.parm.setup.phone,"0"); + if (!cs->ics.parm.setup.eazmsn[0]) strcpy(cs->ics.parm.setup.eazmsn,"0"); + cs->ics.parm.setup.screen = dv->rule.screen; + if (dv->rule.waittime) + cs->timer.expires = jiffies + (HZ * dv->rule.waittime); + else + if (dv->rule.action == DEFLECT_PROCEED) + cs->timer.expires = jiffies + (HZ * extern_wait_max); + else + cs->timer.expires = 0; + cs->akt_state = dv->rule.action; + save_flags(flags); + cli(); + cs->divert_id = next_id++; /* new sequence number */ + restore_flags(flags); + cs->prev = NULL; + if (cs->akt_state == DEFLECT_ALERT) + { strcpy(cs->deflect_dest,dv->rule.to_nr); + if (!cs->timer.expires) + { strcpy(ic->parm.setup.eazmsn,"Testtext direkt"); + ic->parm.setup.screen = dv->rule.screen; + strcpy(ic->parm.setup.phone,dv->rule.to_nr); + cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ + cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); + retval = 4; + } + else + retval = 1; /* alerting */ + } + else + { cs->deflect_dest[0] = '\0'; + retval = 3; /* only proceed */ + } + sprintf(cs->info,"%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n", + cs->akt_state, + cs->divert_id, + divert_if.drv_to_name(cs->ics.driver), + (ic->command == ISDN_STAT_ICALLW) ? "1":"0", + cs->ics.parm.setup.phone, + cs->ics.parm.setup.eazmsn, + cs->ics.parm.setup.si1, + cs->ics.parm.setup.si2, + cs->ics.parm.setup.screen, + dv->rule.waittime, + cs->deflect_dest); + if ((dv->rule.action == DEFLECT_REPORT) || + (dv->rule.action == DEFLECT_REJECT)) + { put_info_buffer(cs->info); + kfree(cs); /* remove */ + return((dv->rule.action == DEFLECT_REPORT) ? 0:2); /* nothing to do */ + } + break; + + default: + return(0); /* ignore call */ + break; + } /* switch action */ + break; + } /* scan_table */ + + if (cs) + { cs->prev = NULL; + save_flags(flags); + cli(); + cs->next = divert_head; + divert_head = cs; + if (cs->timer.expires) add_timer(&cs->timer); + restore_flags(flags); + + put_info_buffer(cs->info); + return(retval); + } + else + return(0); +} /* isdn_divert_icall */ + + +void deleteprocs(void) +{ struct call_struc *cs, *cs1; + int flags; + + save_flags(flags); + cli(); + cs = divert_head; + divert_head = NULL; + while (cs) + { del_timer(&cs->timer); + cs1 = cs; + cs = cs->next; + kfree(cs1); + } + restore_flags(flags); +} /* deleteprocs */ + +/****************************************************/ +/* put a address including address type into buffer */ +/****************************************************/ +int put_address(char *st, u_char *p, int len) +{ u_char retval = 0; + u_char adr_typ = 0; /* network standard */ + + if (len < 2) return(retval); + if (*p == 0xA1) + { retval = *(++p) + 2; /* total length */ + if (retval > len) return(0); /* too short */ + len = retval - 2; /* remaining length */ + if (len < 3) return(0); + if ((*(++p) != 0x0A) || (*(++p) != 1)) return(0); + adr_typ = *(++p); + len -= 3; + p++; + if (len < 2) return(0); + if (*p++ != 0x12) return(0); + if (*p > len) return(0); /* check number length */ + len = *p++; + } + else + if (*p == 0x80) + { retval = *(++p) + 2; /* total length */ + if (retval > len) return(0); + len = retval - 2; + p++; + } + else + return(0); /* invalid address information */ + + sprintf(st,"%d ",adr_typ); + st += strlen(st); + if (!len) + *st++ = '-'; + else + while (len--) + *st++ = *p++; + *st = '\0'; + return(retval); +} /* put_address */ + +/*************************************/ +/* report a succesfull interrogation */ +/*************************************/ +int interrogate_success(isdn_ctrl *ic, struct call_struc *cs) +{ char *src = ic->parm.dss1_io.data; + int restlen = ic->parm.dss1_io.datalen; + int cnt = 1; + u_char n,n1; + char st[90], *p, *stp; + + if (restlen < 2) return(-100); /* frame too short */ + if (*src++ != 0x30) return(-101); + if ((n = *src++) > 0x81) return(-102); /* invalid length field */ + restlen -= 2; /* remaining bytes */ + if (n == 0x80) + { if (restlen < 2) return(-103); + if ((*(src+restlen-1)) || (*(src+restlen-2))) return(-104); + restlen -= 2; + } + else + if ( n == 0x81) + { n = *src++; + restlen--; + if (n > restlen) return(-105); + restlen = n; + } + else + if (n > restlen) return(-106); + else + restlen = n; /* standard format */ + if (restlen < 3) return(-107); /* no procedure */ + if ((*src++ != 2) || (*src++ != 1) || (*src++ != 0x0B)) return(-108); + restlen -= 3; + if (restlen < 2) return(-109); /* list missing */ + if (*src == 0x31) + { src++; + if ((n = *src++) > 0x81) return(-110); /* invalid length field */ + restlen -= 2; /* remaining bytes */ + if (n == 0x80) + { if (restlen < 2) return(-111); + if ((*(src+restlen-1)) || (*(src+restlen-2))) return(-112); + restlen -= 2; + } + else + if ( n == 0x81) + { n = *src++; + restlen--; + if (n > restlen) return(-113); + restlen = n; + } + else + if (n > restlen) return(-114); + else + restlen = n; /* standard format */ + } /* result list header */ + + while (restlen >= 2) + { stp = st; + sprintf(stp,"%d 0x%lx %d %s ",DIVERT_REPORT, ic->parm.dss1_io.ll_id, + cnt++,divert_if.drv_to_name(ic->driver)); + stp += strlen(stp); + if (*src++ != 0x30) return(-115); /* invalid enum */ + n = *src++; + restlen -= 2; + if (n > restlen) return(-116); /* enum length wrong */ + restlen -= n; + p = src; /* one entry */ + src += n; + if (!(n1 = put_address(stp,p,n & 0xFF))) continue; + stp += strlen(stp); + p += n1; + n -= n1; + if (n < 6) continue; /* no service and proc */ + if ((*p++ != 0x0A) || (*p++ != 1)) continue; + sprintf(stp," 0x%02x ",(*p++) & 0xFF); + stp += strlen(stp); + if ((*p++ != 0x0A) || (*p++ != 1)) continue; + sprintf(stp,"%d ",(*p++) & 0xFF); + stp += strlen(stp); + n -= 6; + if (n > 2) + { if (*p++ != 0x30) continue; + if (*p > (n-2)) continue; + n = *p++; + if (!(n1 = put_address(stp,p,n & 0xFF))) continue; + stp += strlen(stp); + } + sprintf(stp,"\n"); + put_info_buffer(st); + } /* while restlen */ + if (restlen) return(-117); + return(0); +} /* interrogate_success */ + +/*********************************************/ +/* callback for protocol specific extensions */ +/*********************************************/ +int prot_stat_callback(isdn_ctrl *ic) +{ struct call_struc *cs, *cs1; + int i,flags; + + cs = divert_head; /* start of list */ + cs1 = NULL; + while (cs) + { if (ic->driver == cs->ics.driver) + { switch (cs->ics.arg) + { case DSS1_CMD_INVOKE: + if ((cs->ics.parm.dss1_io.ll_id == ic->parm.dss1_io.ll_id) && + (cs->ics.parm.dss1_io.hl_id == ic->parm.dss1_io.hl_id)) + { switch (ic->arg) + { case DSS1_STAT_INVOKE_ERR: + sprintf(cs->info,"128 0x%lx 0x%x\n", + ic->parm.dss1_io.ll_id, + ic->parm.dss1_io.timeout); + put_info_buffer(cs->info); + break; + + case DSS1_STAT_INVOKE_RES: + switch (cs->ics.parm.dss1_io.proc) + { case 7: + case 8: + put_info_buffer(cs->info); + break; + + case 11: + i = interrogate_success(ic,cs); + if (i) + sprintf(cs->info,"%d 0x%lx %d\n",DIVERT_REPORT, + ic->parm.dss1_io.ll_id,i); + put_info_buffer(cs->info); + break; + + default: + printk(KERN_WARNING "dss1_divert: unknown proc %d\n",cs->ics.parm.dss1_io.proc); + break; + } + + +#if 0 + sprintf(st, "0x%lx 0x%lx",ic->arg, ic->parm.dss1_io.ll_id); + p = st + strlen(st); + p1 = ic->parm.dss1_io.data; + i = ic->parm.dss1_io.datalen; + while ((i > 0) && (p - st < 530)) + { p += sprintf(p," %02x",(*p1++) & 0xFF); + i--; + } + sprintf(p, "\n"); + put_info_buffer(st); +#endif + break; + + default: + printk(KERN_WARNING "dss1_divert unknown invoke answer %lx\n",ic->arg); + break; + } + cs1 = cs; /* remember structure */ + cs = NULL; + continue; /* abort search */ + } /* id found */ + break; + + case DSS1_CMD_INVOKE_ABORT: + printk(KERN_WARNING "dss1_divert unhandled invoke abort\n"); + break; + + default: + printk(KERN_WARNING "dss1_divert unknown cmd 0x%lx\n",cs->ics.arg); + break; + } /* switch ics.arg */ + cs = cs->next; + } /* driver ok */ + } + + if (!cs1) + { printk(KERN_WARNING "dss1_divert unhandled process\n"); + return(0); + } + + if (cs1->ics.driver == -1) + { save_flags(flags); + cli(); + del_timer(&cs1->timer); + if (cs1->prev) + cs1->prev->next = cs1->next; /* forward link */ + else + divert_head = cs1->next; + if (cs1->next) + cs1->next->prev = cs1->prev; /* back link */ + restore_flags(flags); + kfree(cs1); + } + + return(0); +} /* prot_stat_callback */ + + +/***************************/ +/* status callback from HL */ +/***************************/ +int isdn_divert_stat_callback(isdn_ctrl *ic) +{ struct call_struc *cs, *cs1; + int flags, retval; + + retval = -1; + cs = divert_head; /* start of list */ + while (cs) + { if ((ic->driver == cs->ics.driver) && (ic->arg == cs->ics.arg)) + { switch (ic->command) + { case ISDN_STAT_DHUP: + sprintf(cs->info,"129 0x%lx\n",cs->divert_id); + del_timer(&cs->timer); + cs->ics.driver = -1; + break; + + case ISDN_STAT_CAUSE: + sprintf(cs->info,"130 0x%lx %s\n",cs->divert_id,ic->parm.num); + break; + + case ISDN_STAT_REDIR: + sprintf(cs->info,"131 0x%lx\n",cs->divert_id); + del_timer(&cs->timer); + cs->ics.driver = -1; + break; + + default: + sprintf(cs->info,"999 0x%lx 0x%x\n",cs->divert_id,(int)(ic->command)); + break; + } + put_info_buffer(cs->info); + retval = 0; + } + cs1 = cs; + cs = cs->next; + if (cs1->ics.driver == -1) + { + save_flags(flags); + cli(); + if (cs1->prev) + cs1->prev->next = cs1->next; /* forward link */ + else + divert_head = cs1->next; + if (cs1->next) + cs1->next->prev = cs1->prev; /* back link */ + restore_flags(flags); + kfree(cs1); + } + } + return(retval); /* not found */ +} /* isdn_divert_stat_callback */ + + +/********************/ +/* callback from ll */ +/********************/ +int ll_callback(isdn_ctrl *ic) +{ + switch (ic->command) + { case ISDN_STAT_ICALL: + case ISDN_STAT_ICALLW: + return(isdn_divert_icall(ic)); + break; + + case ISDN_STAT_PROT: + if ((ic->arg & 0xFF) == ISDN_PTYPE_EURO) + { if (ic->arg != DSS1_STAT_INVOKE_BRD) + return(prot_stat_callback(ic)); + else + return(0); /* DSS1 invoke broadcast */ + } + else + return(-1); /* protocol not euro */ + + default: + return(isdn_divert_stat_callback(ic)); + } +} /* ll_callback */ + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/divert/isdn_divert.h linux.pre11.3/drivers/isdn/divert/isdn_divert.h --- linux.vanilla/drivers/isdn/divert/isdn_divert.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/divert/isdn_divert.h Mon Jul 19 23:59:33 1999 @@ -0,0 +1,159 @@ +/* + * $Id: isdn_divert.h,v 1.2 1999/07/04 21:37:33 werner Exp $ + * + * Header for the diversion supplementary ioctl interface. + * + * Copyright 1998 by Werner Cornelius (werner@ikt.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, 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. + * + * $Log: isdn_divert.h,v $ + * Revision 1.2 1999/07/04 21:37:33 werner + * Ported from kernel version 2.0 + * + * + * + */ + + + +#include +#include +#include + +/******************************************/ +/* IOCTL codes for interface to user prog */ +/******************************************/ +#define DIVERT_IIOC_VERSION 0x01 /* actual version */ +#define IIOCGETVER _IO('I', 1) /* get version of interface */ +#define IIOCGETDRV _IO('I', 2) /* get driver number */ +#define IIOCGETNAM _IO('I', 3) /* get driver name */ +#define IIOCGETRULE _IO('I', 4) /* read one rule */ +#define IIOCMODRULE _IO('I', 5) /* modify/replace a rule */ +#define IIOCINSRULE _IO('I', 6) /* insert/append one rule */ +#define IIOCDELRULE _IO('I', 7) /* delete a rule */ +#define IIOCDODFACT _IO('I', 8) /* hangup/reject/alert/immediately deflect a call */ +#define IIOCDOCFACT _IO('I', 9) /* activate control forwarding in PBX */ +#define IIOCDOCFDIS _IO('I',10) /* deactivate control forwarding in PBX */ +#define IIOCDOCFINT _IO('I',11) /* interrogate control forwarding in PBX */ + +/*************************************/ +/* states reported through interface */ +/*************************************/ +#define DEFLECT_IGNORE 0 /* ignore incoming call */ +#define DEFLECT_REPORT 1 /* only report */ +#define DEFLECT_PROCEED 2 /* deflect when externally triggered */ +#define DEFLECT_ALERT 3 /* alert and deflect after delay */ +#define DEFLECT_REJECT 4 /* reject immediately */ +#define DIVERT_ACTIVATE 5 /* diversion activate */ +#define DIVERT_DEACTIVATE 6 /* diversion deactivate */ +#define DIVERT_REPORT 7 /* interrogation result */ +#define DEFLECT_AUTODEL 255 /* only for internal use */ + +#define DEFLECT_ALL_IDS 0xFFFFFFFF /* all drivers selected */ + +typedef struct + { ulong drvid; /* driver ids, bit mapped */ + char my_msn[35]; /* desired msn, subaddr allowed */ + char caller[35]; /* caller id, partial string with * + subaddr allowed */ + char to_nr[35]; /* deflected to number incl. subaddress */ + u_char si1,si2; /* service indicators, si1=bitmask, si1+2 0 = all */ + u_char screen; /* screening: 0 = no info, 1 = info, 2 = nfo with nr */ + u_char callopt; /* option for call handling: + 0 = all calls + 1 = only non waiting calls + 2 = only waiting calls */ + u_char action; /* desired action: + 0 = don't report call -> ignore + 1 = report call, do not allow/proceed for deflection + 2 = report call, send proceed, wait max waittime secs + 3 = report call, alert and deflect after waittime + 4 = report call, reject immediately + actions 1-2 only take place if interface is opened + */ + u_char waittime; /* maximum wait time for proceeding */ + } divert_rule; + +typedef union + { int drv_version; /* return of driver version */ + struct + { int drvid; /* id of driver */ + char drvnam[30]; /* name of driver */ + } getid; + struct + { int ruleidx; /* index of rule */ + divert_rule rule; /* rule parms */ + } getsetrule; + struct + { u_char subcmd; /* 0 = hangup/reject, + 1 = alert, + 2 = deflect */ + ulong callid; /* id of call delivered by ascii output */ + char to_nr[35]; /* destination when deflect, + else uus1 string (maxlen 31), + data from rule used if empty */ + } fwd_ctrl; + struct + { int drvid; /* id of driver */ + u_char cfproc; /* cfu = 0, cfb = 1, cfnr = 2 */ + ulong procid; /* process id returned when no error */ + u_char service; /* basically coded service, 0 = all */ + char msn[25]; /* desired msn, empty = all */ + char fwd_nr[35];/* forwarded to number + subaddress */ + } cf_ctrl; + } divert_ioctl; + +#ifdef __KERNEL__ + +#include +#include + +#define AUTODEL_TIME 30 /* timeout in s to delete internal entrys */ + +/**************************************************/ +/* structure keeping ascii info for device output */ +/**************************************************/ +struct divert_info + { struct divert_info *next; + ulong usage_cnt; /* number of files still to work */ + char info_start[2]; /* info string start */ + }; + + +/**************/ +/* Prototypes */ +/**************/ +extern ulong if_used; /* number of interface users */ +extern int divert_dev_deinit(void); +extern int divert_dev_init(void); +extern void put_info_buffer(char *); +extern int ll_callback(isdn_ctrl *); +extern isdn_divert_if divert_if; +extern divert_rule *getruleptr(int); +extern int insertrule(int, divert_rule *); +extern int deleterule(int); +extern void deleteprocs(void); +extern int deflect_extern_action(u_char, ulong, char *); +extern int cf_command(int, int, u_char, char *, u_char, char *, ulong *); + +#endif __KERNEL__ + + + + + + + + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/Makefile linux.pre11.3/drivers/isdn/eicon/Makefile --- linux.vanilla/drivers/isdn/eicon/Makefile Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/eicon/Makefile Mon Jul 19 23:59:33 1999 @@ -0,0 +1,13 @@ +L_OBJS := +M_OBJS := +O_OBJS := eicon_mod.o eicon_isa.o eicon_pci.o eicon_idi.o eicon_io.o + +O_TARGET := +ifeq ($(CONFIG_ISDN_DRV_EICON),y) + O_TARGET += eicon.o +else + O_TARGET += eicon.o + M_OBJS = eicon.o +endif + +include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon.h linux.pre11.3/drivers/isdn/eicon/eicon.h --- linux.vanilla/drivers/isdn/eicon/eicon.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/eicon/eicon.h Mon Jul 19 23:59:33 1999 @@ -0,0 +1,544 @@ +/* $Id: eicon.h,v 1.7 1999/07/11 17:16:23 armin Exp $ + * + * ISDN low-level module for Eicon.Diehl active ISDN-Cards. + * + * Copyright 1998 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1998,99 by Armin Schindler (mac@melware.de) + * Copyright 1999 Cytronics & Melware (info@melware.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, 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. + * + * $Log: eicon.h,v $ + * Revision 1.7 1999/07/11 17:16:23 armin + * Bugfixes in queue handling. + * Added DSP-DTMF decoder functions. + * Reorganized ack_handler. + * + * Revision 1.6 1999/06/09 19:31:24 armin + * Wrong PLX size for request_region() corrected. + * Added first MCA code from Erik Weber. + * + * Revision 1.5 1999/03/29 11:19:41 armin + * I/O stuff now in seperate file (eicon_io.c) + * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. + * + * Revision 1.4 1999/03/02 12:37:42 armin + * Added some important checks. + * Analog Modem with DSP. + * Channels will be added to Link-Level after loading firmware. + * + * Revision 1.3 1999/01/24 20:14:07 armin + * Changed and added debug stuff. + * Better data sending. (still problems with tty's flip buffer) + * + * Revision 1.2 1999/01/10 18:46:04 armin + * Bug with wrong values in HLC fixed. + * Bytes to send are counted and limited now. + * + * Revision 1.1 1999/01/01 18:09:41 armin + * First checkin of new eicon driver. + * DIVA-Server BRI/PCI and PRI/PCI are supported. + * Old diehl code is obsolete. + * + * + */ + + +#ifndef eicon_h +#define eicon_h + +#define EICON_IOCTL_SETMMIO 0 +#define EICON_IOCTL_GETMMIO 1 +#define EICON_IOCTL_SETIRQ 2 +#define EICON_IOCTL_GETIRQ 3 +#define EICON_IOCTL_LOADBOOT 4 +#define EICON_IOCTL_ADDCARD 5 +#define EICON_IOCTL_GETTYPE 6 +#define EICON_IOCTL_LOADPCI 7 +#define EICON_IOCTL_LOADISA 8 +#define EICON_IOCTL_GETVER 9 + +#define EICON_IOCTL_MANIF 90 + +#define EICON_IOCTL_FREEIT 97 +#define EICON_IOCTL_TEST 98 +#define EICON_IOCTL_DEBUGVAR 99 + +/* Bus types */ +#define EICON_BUS_ISA 1 +#define EICON_BUS_MCA 2 +#define EICON_BUS_PCI 3 + +/* Constants for describing Card-Type */ +#define EICON_CTYPE_S 0 +#define EICON_CTYPE_SX 1 +#define EICON_CTYPE_SCOM 2 +#define EICON_CTYPE_QUADRO 3 +#define EICON_CTYPE_S2M 4 +#define EICON_CTYPE_MAESTRA 5 +#define EICON_CTYPE_MAESTRAQ 6 +#define EICON_CTYPE_MAESTRAQ_U 7 +#define EICON_CTYPE_MAESTRAP 8 +#define EICON_CTYPE_ISABRI 0x10 +#define EICON_CTYPE_ISAPRI 0x20 +#define EICON_CTYPE_MASK 0x0f +#define EICON_CTYPE_QUADRO_NR(n) (n<<4) + +#define MAX_HEADER_LEN 10 + +/* Struct for adding new cards */ +typedef struct eicon_cdef { + int membase; + int irq; + char id[10]; +} eicon_cdef; + +#define EICON_ISA_BOOT_MEMCHK 1 +#define EICON_ISA_BOOT_NORMAL 2 + +/* Struct for downloading protocol via ioctl for ISA cards */ +/* same struct for downloading protocol via ioctl for MCA cards */ +typedef struct { + /* start-up parameters */ + unsigned char tei; + unsigned char nt2; + unsigned char skip1; + unsigned char WatchDog; + unsigned char Permanent; + unsigned char XInterface; + unsigned char StableL2; + unsigned char NoOrderCheck; + unsigned char HandsetType; + unsigned char skip2; + unsigned char LowChannel; + unsigned char ProtVersion; + unsigned char Crc4; + unsigned char Loopback; + unsigned char oad[32]; + unsigned char osa[32]; + unsigned char spid[32]; + unsigned char boot_opt; + unsigned long bootstrap_len; + unsigned long firmware_len; + unsigned char code[1]; /* Rest (bootstrap- and firmware code) will be allocated */ +} eicon_isa_codebuf; + +/* Struct for downloading protocol via ioctl for PCI cards */ +typedef struct { + /* start-up parameters */ + unsigned char tei; + unsigned char nt2; + unsigned char WatchDog; + unsigned char Permanent; + unsigned char XInterface; + unsigned char StableL2; + unsigned char NoOrderCheck; + unsigned char HandsetType; + unsigned char LowChannel; + unsigned char ProtVersion; + unsigned char Crc4; + unsigned char NoHscx30Mode; /* switch PRI into No HSCX30 test mode */ + unsigned char Loopback; /* switch card into Loopback mode */ + struct q931_link_s + { + unsigned char oad[32]; + unsigned char osa[32]; + unsigned char spid[32]; + } l[2]; + unsigned long protocol_len; + unsigned int dsp_code_num; + unsigned long dsp_code_len[9]; + unsigned char code[1]; /* Rest (protocol- and dsp code) will be allocated */ +} eicon_pci_codebuf; + +/* Data for downloading protocol via ioctl */ +typedef union { + eicon_isa_codebuf isa; + eicon_isa_codebuf mca; + eicon_pci_codebuf pci; +} eicon_codebuf; + +/* Data for Management interface */ +typedef struct { + int count; + int pos; + int length[50]; + unsigned char data[700]; +} eicon_manifbuf; + + +#ifdef __KERNEL__ + +/* Kernel includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +typedef struct { + __u16 length __attribute__ ((packed)); /* length of data/parameter field */ + __u8 P[1]; /* data/parameter field */ +} eicon_PBUFFER; + +#include "eicon_isa.h" + +/* Macro for delay via schedule() */ +#define SLEEP(j) { \ + current->state = TASK_INTERRUPTIBLE; \ + schedule_timeout(j); \ +} + +#endif /* KERNEL */ + + +#define DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE 48 +#define DSP_COMBIFILE_FORMAT_VERSION_BCD 0x0100 + +#define DSP_FILE_FORMAT_IDENTIFICATION_SIZE 48 +#define DSP_FILE_FORMAT_VERSION_BCD 0x0100 + +typedef struct tag_dsp_combifile_header +{ + char format_identification[DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE] __attribute__ ((packed)); + __u16 format_version_bcd __attribute__ ((packed)); + __u16 header_size __attribute__ ((packed)); + __u16 combifile_description_size __attribute__ ((packed)); + __u16 directory_entries __attribute__ ((packed)); + __u16 directory_size __attribute__ ((packed)); + __u16 download_count __attribute__ ((packed)); + __u16 usage_mask_size __attribute__ ((packed)); +} t_dsp_combifile_header; + +typedef struct tag_dsp_combifile_directory_entry +{ + __u16 card_type_number __attribute__ ((packed)); + __u16 file_set_number __attribute__ ((packed)); +} t_dsp_combifile_directory_entry; + +typedef struct tag_dsp_file_header +{ + char format_identification[DSP_FILE_FORMAT_IDENTIFICATION_SIZE] __attribute__ ((packed)); + __u16 format_version_bcd __attribute__ ((packed)); + __u16 download_id __attribute__ ((packed)); + __u16 download_flags __attribute__ ((packed)); + __u16 required_processing_power __attribute__ ((packed)); + __u16 interface_channel_count __attribute__ ((packed)); + __u16 header_size __attribute__ ((packed)); + __u16 download_description_size __attribute__ ((packed)); + __u16 memory_block_table_size __attribute__ ((packed)); + __u16 memory_block_count __attribute__ ((packed)); + __u16 segment_table_size __attribute__ ((packed)); + __u16 segment_count __attribute__ ((packed)); + __u16 symbol_table_size __attribute__ ((packed)); + __u16 symbol_count __attribute__ ((packed)); + __u16 total_data_size_dm __attribute__ ((packed)); + __u16 data_block_count_dm __attribute__ ((packed)); + __u16 total_data_size_pm __attribute__ ((packed)); + __u16 data_block_count_pm __attribute__ ((packed)); +} t_dsp_file_header; + +typedef struct tag_dsp_memory_block_desc +{ + __u16 alias_memory_block; + __u16 memory_type; + __u16 address; + __u16 size; /* DSP words */ +} t_dsp_memory_block_desc; + +typedef struct tag_dsp_segment_desc +{ + __u16 memory_block; + __u16 attributes; + __u16 base; + __u16 size; + __u16 alignment; /* ==0 -> no other legal start address than base */ +} t_dsp_segment_desc; + +typedef struct tag_dsp_symbol_desc +{ + __u16 symbol_id; + __u16 segment; + __u16 offset; + __u16 size; /* DSP words */ +} t_dsp_symbol_desc; + +typedef struct tag_dsp_data_block_header +{ + __u16 attributes; + __u16 segment; + __u16 offset; + __u16 size; /* DSP words */ +} t_dsp_data_block_header; + +typedef struct tag_dsp_download_desc /* be sure to keep native alignment for MAESTRA's */ +{ + __u16 download_id; + __u16 download_flags; + __u16 required_processing_power; + __u16 interface_channel_count; + __u16 excess_header_size; + __u16 memory_block_count; + __u16 segment_count; + __u16 symbol_count; + __u16 data_block_count_dm; + __u16 data_block_count_pm; + __u8 * p_excess_header_data __attribute__ ((packed)); + char * p_download_description __attribute__ ((packed)); + t_dsp_memory_block_desc *p_memory_block_table __attribute__ ((packed)); + t_dsp_segment_desc *p_segment_table __attribute__ ((packed)); + t_dsp_symbol_desc *p_symbol_table __attribute__ ((packed)); + __u16 * p_data_blocks_dm __attribute__ ((packed)); + __u16 * p_data_blocks_pm __attribute__ ((packed)); +} t_dsp_download_desc; + + +#ifdef __KERNEL__ + +typedef struct { + __u8 Req; /* pending request */ + __u8 Rc; /* return code received */ + __u8 Ind; /* indication received */ + __u8 ReqCh; /* channel of current Req */ + __u8 RcCh; /* channel of current Rc */ + __u8 IndCh; /* channel of current Ind */ + __u8 D3Id; /* ID used by this entity */ + __u8 B2Id; /* ID used by this entity */ + __u8 GlobalId; /* reserved field */ + __u8 XNum; /* number of X-buffers */ + __u8 RNum; /* number of R-buffers */ + struct sk_buff_head X; /* X-buffer queue */ + struct sk_buff_head R; /* R-buffer queue */ + __u8 RNR; /* receive not ready flag */ + __u8 complete; /* receive complete status */ + __u8 busy; /* busy flag */ + __u16 ref; /* saved reference */ +} entity; + + +typedef struct { + int No; /* Channel Number */ + unsigned short callref; /* Call Reference */ + unsigned short fsm_state; /* Current D-Channel state */ + unsigned short eazmask; /* EAZ-Mask for this Channel */ + int queued; /* User-Data Bytes in TX queue */ + int waitq; /* User-Data Bytes in wait queue */ + int waitpq; /* User-Data Bytes in packet queue */ + unsigned short plci; + unsigned short ncci; + unsigned char l2prot; /* Layer 2 protocol */ + unsigned char l3prot; /* Layer 3 protocol */ + entity e; /* Entity */ + char cpn[32]; /* remember cpn */ + char oad[32]; /* remember oad */ + unsigned char cause[2]; /* Last Cause */ + unsigned char si1; + unsigned char si2; +} eicon_chan; + +typedef struct { + eicon_chan *ptr; +} eicon_chan_ptr; + +#include "eicon_pci.h" + +#define EICON_FLAGS_RUNNING 1 /* Cards driver activated */ +#define EICON_FLAGS_PVALID 2 /* Cards port is valid */ +#define EICON_FLAGS_IVALID 4 /* Cards irq is valid */ +#define EICON_FLAGS_MVALID 8 /* Cards membase is valid */ +#define EICON_FLAGS_LOADED 8 /* Firmware loaded */ + +#define EICON_BCH 2 /* # of channels per card */ + +/* D-Channel states */ +#define EICON_STATE_NULL 0 +#define EICON_STATE_ICALL 1 +#define EICON_STATE_OCALL 2 +#define EICON_STATE_IWAIT 3 +#define EICON_STATE_OWAIT 4 +#define EICON_STATE_IBWAIT 5 +#define EICON_STATE_OBWAIT 6 +#define EICON_STATE_BWAIT 7 +#define EICON_STATE_BHWAIT 8 +#define EICON_STATE_BHWAIT2 9 +#define EICON_STATE_DHWAIT 10 +#define EICON_STATE_DHWAIT2 11 +#define EICON_STATE_BSETUP 12 +#define EICON_STATE_ACTIVE 13 +#define EICON_STATE_ICALLW 14 +#define EICON_STATE_LISTEN 15 +#define EICON_STATE_WMCONN 16 + +#define EICON_MAX_QUEUED 8000 /* 2 * maxbuff */ + +#define EICON_LOCK_TX 0 +#define EICON_LOCK_RX 1 + +typedef union { + eicon_isa_card isa; + eicon_pci_card pci; + eicon_isa_card mca; +} eicon_hwif; + +typedef struct { + __u8 ret; + __u8 id; + __u8 ch; +} eicon_ack; + +typedef struct { + __u8 code; + __u8 id; + __u8 ch; +} eicon_req; + +typedef struct { + __u8 ret; + __u8 id; + __u8 ch; + __u8 more; +} eicon_indhdr; + +typedef struct msn_entry { + char eaz; + char msn[16]; + struct msn_entry * next; +} msn_entry; + +/* + * Per card driver data + */ +typedef struct eicon_card { + eicon_hwif hwif; /* Hardware dependant interface */ + u_char ptype; /* Protocol type (1TR6 or Euro) */ + u_char bus; /* Bustype (ISA, MCA, PCI) */ + u_char type; /* Cardtype (EICON_CTYPE_...) */ + struct eicon_card *qnext; /* Pointer to next quadro adapter */ + int Feature; /* Protocol Feature Value */ + struct eicon_card *next; /* Pointer to next device struct */ + int myid; /* Driver-Nr. assigned by linklevel */ + unsigned long flags; /* Statusflags */ + unsigned long ilock; /* Semaphores for IRQ-Routines */ + struct sk_buff_head rcvq; /* Receive-Message queue */ + struct sk_buff_head sndq; /* Send-Message queue */ + struct sk_buff_head rackq; /* Req-Ack-Message queue */ + struct sk_buff_head sackq; /* Data-Ack-Message queue */ + u_char *ack_msg; /* Ptr to User Data in User skb */ + __u16 need_b3ack; /* Flag: Need ACK for current skb */ + struct sk_buff *sbuf; /* skb which is currently sent */ + struct tq_struct snd_tq; /* Task struct for xmit bh */ + struct tq_struct rcv_tq; /* Task struct for rcv bh */ + struct tq_struct ack_tq; /* Task struct for ack bh */ + msn_entry *msn_list; + unsigned short msgnum; /* Message number for sending */ + eicon_chan* IdTable[256]; /* Table to find entity */ + __u16 ref_in; + __u16 ref_out; + int nchannels; /* Number of B-Channels */ + int ReadyInt; /* Ready Interrupt */ + eicon_chan *bch; /* B-Channel status/control */ + char status_buf[256]; /* Buffer for status messages */ + char *status_buf_read; + char *status_buf_write; + char *status_buf_end; + isdn_if interface; /* Interface to upper layer */ + char regname[35]; /* Name used for request_region */ +#ifdef CONFIG_MCA + int mca_slot; /* # of cards MCA slot */ +#endif +} eicon_card; + +/* -----------------------------------------------------------** +** The PROTOCOL_FEATURE_STRING ** +** defines capabilities and ** +** features of the actual protocol code. It's used as a bit ** +** mask. ** +** The following Bits are defined: ** +** -----------------------------------------------------------*/ +#define PROTCAP_TELINDUS 0x0001 /* Telindus Variant of protocol code */ +#define PROTCAP_MANIF 0x0002 /* Management interface implemented */ +#define PROTCAP_V_42 0x0004 /* V42 implemented */ +#define PROTCAP_V90D 0x0008 /* V.90D (implies up to 384k DSP code) */ +#define PROTCAP_EXTD_FAX 0x0010 /* Extended FAX (ECM, 2D, T6, Polling) */ +#define PROTCAP_FREE4 0x0020 /* not used */ +#define PROTCAP_FREE5 0x0040 /* not used */ +#define PROTCAP_FREE6 0x0080 /* not used */ +#define PROTCAP_FREE7 0x0100 /* not used */ +#define PROTCAP_FREE8 0x0200 /* not used */ +#define PROTCAP_FREE9 0x0400 /* not used */ +#define PROTCAP_FREE10 0x0800 /* not used */ +#define PROTCAP_FREE11 0x1000 /* not used */ +#define PROTCAP_FREE12 0x2000 /* not used */ +#define PROTCAP_FREE13 0x4000 /* not used */ +#define PROTCAP_EXTENSION 0x8000 /* used for future extentions */ + +#include "eicon_idi.h" + +extern eicon_card *cards; +extern char *eicon_ctype_name[]; + + +extern __inline__ void eicon_schedule_tx(eicon_card *card) +{ + queue_task(&card->snd_tq, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +extern __inline__ void eicon_schedule_rx(eicon_card *card) +{ + queue_task(&card->rcv_tq, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +extern __inline__ void eicon_schedule_ack(eicon_card *card) +{ + queue_task(&card->ack_tq, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +extern char *eicon_find_eaz(eicon_card *, char); +extern int eicon_addcard(int, int, int, char *); +extern void eicon_io_transmit(eicon_card *card); +extern void eicon_irq(int irq, void *dev_id, struct pt_regs *regs); +extern void eicon_io_rcv_dispatch(eicon_card *ccard); +extern void eicon_io_ack_dispatch(eicon_card *ccard); +#ifdef CONFIG_MCA +extern int eicon_mca_find_card(int, int, int, char *); +extern int eicon_mca_probe(int, int, int, int, char *); +extern int eicon_info(char *, int , void *); +#endif /* CONFIG_MCA */ + +extern ulong DebugVar; + +#endif /* __KERNEL__ */ + +#endif /* eicon_h */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon_dsp.h linux.pre11.3/drivers/isdn/eicon/eicon_dsp.h --- linux.vanilla/drivers/isdn/eicon/eicon_dsp.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/eicon/eicon_dsp.h Mon Jul 19 23:59:33 1999 @@ -0,0 +1,313 @@ +/* $Id: eicon_dsp.h,v 1.3 1999/07/11 17:16:24 armin Exp $ + * + * ISDN lowlevel-module for Eicon.Diehl active cards. + * DSP definitions + * + * Copyright 1999 by Armin Schindler (mac@melware.de) + * Copyright 1999 Cytronics & Melware (info@melware.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, 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. + * + * $Log: eicon_dsp.h,v $ + * Revision 1.3 1999/07/11 17:16:24 armin + * Bugfixes in queue handling. + * Added DSP-DTMF decoder functions. + * Reorganized ack_handler. + * + * Revision 1.2 1999/03/29 11:19:42 armin + * I/O stuff now in seperate file (eicon_io.c) + * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. + * + * Revision 1.1 1999/03/02 12:18:54 armin + * First checkin of DSP defines for audio features. + * + * + */ + +#ifndef DSP_H +#define DSP_H + +#define DSP_UDATA_REQUEST_RECONFIGURE 0 +/* +parameters: + reconfigure delay (in 8kHz samples) + reconfigure code + reconfigure hdlc preamble flags +*/ + +#define DSP_RECONFIGURE_TX_FLAG 0x8000 +#define DSP_RECONFIGURE_SHORT_TRAIN_FLAG 0x4000 +#define DSP_RECONFIGURE_ECHO_PROTECT_FLAG 0x2000 +#define DSP_RECONFIGURE_HDLC_FLAG 0x1000 +#define DSP_RECONFIGURE_SYNC_FLAG 0x0800 +#define DSP_RECONFIGURE_PROTOCOL_MASK 0x00ff +#define DSP_RECONFIGURE_IDLE 0 +#define DSP_RECONFIGURE_V25 1 +#define DSP_RECONFIGURE_V21_CH2 2 +#define DSP_RECONFIGURE_V27_2400 3 +#define DSP_RECONFIGURE_V27_4800 4 +#define DSP_RECONFIGURE_V29_7200 5 +#define DSP_RECONFIGURE_V29_9600 6 +#define DSP_RECONFIGURE_V33_12000 7 +#define DSP_RECONFIGURE_V33_14400 8 +#define DSP_RECONFIGURE_V17_7200 9 +#define DSP_RECONFIGURE_V17_9600 10 +#define DSP_RECONFIGURE_V17_12000 11 +#define DSP_RECONFIGURE_V17_14400 12 + +/* +data indications if transparent framer + data 0 + data 1 + ... + +data indications if HDLC framer + data 0 + data 1 + ... + CRC 0 + CRC 1 + preamble flags +*/ + +#define DSP_UDATA_REQUEST_SWITCH_FRAMER 1 +/* +parameters: + transmit framer type + receive framer type +*/ + +#define DSP_REQUEST_SWITCH_FRAMER_HDLC 0 +#define DSP_REQUEST_SWITCH_FRAMER_TRANSPARENT 1 +#define DSP_REQUEST_SWITCH_FRAMER_ASYNC 2 + + +#define DSP_UDATA_REQUEST_CLEARDOWN 2 +/* +parameters: + - none - +*/ + + +#define DSP_UDATA_REQUEST_TX_CONFIRMATION_ON 3 +/* +parameters: + - none - +*/ + + +#define DSP_UDATA_REQUEST_TX_CONFIRMATION_OFF 4 +/* +parameters: + - none - +*/ + + +#define DSP_UDATA_INDICATION_SYNC 0 +/* +returns: + time of sync (sampled from counter at 8kHz) +*/ + +#define DSP_UDATA_INDICATION_DCD_OFF 1 +/* +returns: + time of DCD off (sampled from counter at 8kHz) +*/ + +#define DSP_UDATA_INDICATION_DCD_ON 2 +/* +returns: + time of DCD on (sampled from counter at 8kHz) + connected norm + connected options + connected speed (bit/s, max of tx and rx speed) + roundtrip delay (ms) + connected speed tx (bit/s) + connected speed rx (bit/s) +*/ + +#define DSP_UDATA_INDICATION_CTS_OFF 3 +/* +returns: + time of CTS off (sampled from counter at 8kHz) +*/ + +#define DSP_UDATA_INDICATION_CTS_ON 4 +/* +returns: + time of CTS on (sampled from counter at 8kHz) + connected norm + connected options + connected speed (bit/s, max of tx and rx speed) + roundtrip delay (ms) + connected speed tx (bit/s) + connected speed rx (bit/s) +*/ + +typedef struct eicon_dsp_ind { + __u16 time __attribute__ ((packed)); + __u8 norm __attribute__ ((packed)); + __u16 options __attribute__ ((packed)); + __u32 speed __attribute__ ((packed)); + __u16 delay __attribute__ ((packed)); + __u32 txspeed __attribute__ ((packed)); + __u32 rxspeed __attribute__ ((packed)); +} eicon_dsp_ind; + +#define DSP_CONNECTED_NORM_UNSPECIFIED 0 +#define DSP_CONNECTED_NORM_V21 1 +#define DSP_CONNECTED_NORM_V23 2 +#define DSP_CONNECTED_NORM_V22 3 +#define DSP_CONNECTED_NORM_V22_BIS 4 +#define DSP_CONNECTED_NORM_V32_BIS 5 +#define DSP_CONNECTED_NORM_V34 6 +#define DSP_CONNECTED_NORM_V8 7 +#define DSP_CONNECTED_NORM_BELL_212A 8 +#define DSP_CONNECTED_NORM_BELL_103 9 +#define DSP_CONNECTED_NORM_V29_LEASED_LINE 10 +#define DSP_CONNECTED_NORM_V33_LEASED_LINE 11 +#define DSP_CONNECTED_NORM_V90 12 +#define DSP_CONNECTED_NORM_V21_CH2 13 +#define DSP_CONNECTED_NORM_V27_TER 14 +#define DSP_CONNECTED_NORM_V29 15 +#define DSP_CONNECTED_NORM_V33 16 +#define DSP_CONNECTED_NORM_V17 17 + +#define DSP_CONNECTED_OPTION_TRELLIS 0x0001 +#define DSP_CONNECTED_OPTION_V42_TRANS 0x0002 +#define DSP_CONNECTED_OPTION_V42_LAPM 0x0004 +#define DSP_CONNECTED_OPTION_SHORT_TRAIN 0x0008 +#define DSP_CONNECTED_OPTION_TALKER_ECHO_PROTECT 0x0010 + + +#define DSP_UDATA_INDICATION_DISCONNECT 5 +/* +returns: + cause +*/ + +#define DSP_DISCONNECT_CAUSE_NONE 0x00 +#define DSP_DISCONNECT_CAUSE_BUSY_TONE 0x01 +#define DSP_DISCONNECT_CAUSE_CONGESTION_TONE 0x02 +#define DSP_DISCONNECT_CAUSE_INCOMPATIBILITY 0x03 +#define DSP_DISCONNECT_CAUSE_CLEARDOWN 0x04 +#define DSP_DISCONNECT_CAUSE_TRAINING_TIMEOUT 0x05 + + +#define DSP_UDATA_INDICATION_TX_CONFIRMATION 6 +/* +returns: + confirmation number +*/ + + +#define DSP_UDATA_REQUEST_SEND_DTMF_DIGITS 16 +/* +parameters: + tone duration (ms) + gap duration (ms) + digit 0 tone code + ... + digit n tone code +*/ + +#define DSP_SEND_DTMF_DIGITS_HEADER_LENGTH 5 + +#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_697_HZ 0x00 +#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_770_HZ 0x01 +#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_852_HZ 0x02 +#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_941_HZ 0x03 +#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_MASK 0x03 +#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1209_HZ 0x00 +#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1336_HZ 0x04 +#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1477_HZ 0x08 +#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1633_HZ 0x0c +#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_MASK 0x0c + +#define DSP_DTMF_DIGIT_TONE_CODE_0 0x07 +#define DSP_DTMF_DIGIT_TONE_CODE_1 0x00 +#define DSP_DTMF_DIGIT_TONE_CODE_2 0x04 +#define DSP_DTMF_DIGIT_TONE_CODE_3 0x08 +#define DSP_DTMF_DIGIT_TONE_CODE_4 0x01 +#define DSP_DTMF_DIGIT_TONE_CODE_5 0x05 +#define DSP_DTMF_DIGIT_TONE_CODE_6 0x09 +#define DSP_DTMF_DIGIT_TONE_CODE_7 0x02 +#define DSP_DTMF_DIGIT_TONE_CODE_8 0x06 +#define DSP_DTMF_DIGIT_TONE_CODE_9 0x0a +#define DSP_DTMF_DIGIT_TONE_CODE_STAR 0x03 +#define DSP_DTMF_DIGIT_TONE_CODE_HASHMARK 0x0b +#define DSP_DTMF_DIGIT_TONE_CODE_A 0x0c +#define DSP_DTMF_DIGIT_TONE_CODE_B 0x0d +#define DSP_DTMF_DIGIT_TONE_CODE_C 0x0e +#define DSP_DTMF_DIGIT_TONE_CODE_D 0x0f + + +#define DSP_UDATA_INDICATION_DTMF_DIGITS_SENT 16 +/* +returns: + - none - + One indication will be sent for every request. +*/ + + +#define DSP_UDATA_REQUEST_ENABLE_DTMF_RECEIVER 17 +/* +parameters: + tone duration (ms) + gap duration (ms) +*/ +typedef struct enable_dtmf_s { + __u16 tone; + __u16 gap; +} enable_dtmf_s; + +#define DSP_UDATA_REQUEST_DISABLE_DTMF_RECEIVER 18 +/* +parameters: + - none - +*/ + +#define DSP_UDATA_INDICATION_DTMF_DIGITS_RECEIVED 17 +/* +returns: + digit 0 tone code + ... + digit n tone code +*/ + +#define DSP_DTMF_DIGITS_RECEIVED_HEADER_LENGTH 1 + + +#define DSP_UDATA_INDICATION_MODEM_CALLING_TONE 18 +/* +returns: + - none - +*/ + +#define DSP_UDATA_INDICATION_FAX_CALLING_TONE 19 +/* +returns: + - none - +*/ + +#define DSP_UDATA_INDICATION_ANSWER_TONE 20 +/* +returns: + - none - +*/ + +#endif /* DSP_H */ + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon_idi.c linux.pre11.3/drivers/isdn/eicon/eicon_idi.c --- linux.vanilla/drivers/isdn/eicon/eicon_idi.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/eicon/eicon_idi.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,1638 @@ +/* $Id: eicon_idi.c,v 1.10 1999/07/11 17:16:24 armin Exp $ + * + * ISDN lowlevel-module for Eicon.Diehl active cards. + * IDI interface + * + * Copyright 1998,99 by Armin Schindler (mac@melware.de) + * Copyright 1999 Cytronics & Melware (info@melware.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, 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. + * + * $Log: eicon_idi.c,v $ + * Revision 1.10 1999/07/11 17:16:24 armin + * Bugfixes in queue handling. + * Added DSP-DTMF decoder functions. + * Reorganized ack_handler. + * + * Revision 1.9 1999/03/29 11:19:42 armin + * I/O stuff now in seperate file (eicon_io.c) + * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. + * + * Revision 1.8 1999/03/02 12:37:43 armin + * Added some important checks. + * Analog Modem with DSP. + * Channels will be added to Link-Level after loading firmware. + * + * Revision 1.7 1999/02/03 18:34:35 armin + * Channel selection for outgoing calls w/o CHI. + * Added channel # in debug messages. + * L2 Transparent should work with 800 byte/packet now. + * + * Revision 1.6 1999/01/26 07:18:59 armin + * Bug with wrong added CPN fixed. + * + * Revision 1.5 1999/01/24 20:14:11 armin + * Changed and added debug stuff. + * Better data sending. (still problems with tty's flip buffer) + * + * Revision 1.4 1999/01/10 18:46:05 armin + * Bug with wrong values in HLC fixed. + * Bytes to send are counted and limited now. + * + * Revision 1.3 1999/01/05 14:49:34 armin + * Added experimental usage of full BC and HLC for + * speech, 3.1kHz audio, fax gr.2/3 + * + * Revision 1.2 1999/01/04 13:19:29 armin + * Channel status with listen-request wrong - fixed. + * + * Revision 1.1 1999/01/01 18:09:41 armin + * First checkin of new eicon driver. + * DIVA-Server BRI/PCI and PRI/PCI are supported. + * Old diehl code is obsolete. + * + * + */ + +#define __NO_VERSION__ +#include "eicon.h" +#include "eicon_idi.h" +#include "eicon_dsp.h" + +#undef EICON_FULL_SERVICE_OKTETT + +char *eicon_idi_revision = "$Revision: 1.10 $"; + +eicon_manifbuf *manbuf; + +static char BC_Speech[3] = { 0x80, 0x90, 0xa3 }; +static char BC_31khz[3] = { 0x90, 0x90, 0xa3 }; +static char BC_64k[2] = { 0x88, 0x90 }; +static char BC_video[3] = { 0x91, 0x90, 0xa5 }; + +#ifdef EICON_FULL_SERVICE_OKTETT +/* +static char HLC_telephony[2] = { 0x91, 0x81 }; +*/ +static char HLC_faxg3[2] = { 0x91, 0x84 }; +#endif + +int eicon_idi_manage_assign(eicon_card *card); +int eicon_idi_manage_remove(eicon_card *card); + +int +idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan) +{ + int l = 0; + int tmp; + + tmp = 0; + if (!signet) { + /* Signal Layer */ + reqbuf->XBuffer.P[l++] = CAI; + reqbuf->XBuffer.P[l++] = 1; + reqbuf->XBuffer.P[l++] = 0; + reqbuf->XBuffer.P[l++] = KEY; + reqbuf->XBuffer.P[l++] = 3; + reqbuf->XBuffer.P[l++] = 'I'; + reqbuf->XBuffer.P[l++] = '4'; + reqbuf->XBuffer.P[l++] = 'L'; + reqbuf->XBuffer.P[l++] = SHIFT|6; + reqbuf->XBuffer.P[l++] = SIN; + reqbuf->XBuffer.P[l++] = 2; + reqbuf->XBuffer.P[l++] = 0; + reqbuf->XBuffer.P[l++] = 0; + reqbuf->XBuffer.P[l++] = 0; /* end */ + reqbuf->Req = ASSIGN; + reqbuf->ReqCh = 0; + reqbuf->ReqId = 0; + reqbuf->XBuffer.length = l; + reqbuf->Reference = 0; /* Sig Entity */ + } + else { + /* Network Layer */ + reqbuf->XBuffer.P[l++] = CAI; + reqbuf->XBuffer.P[l++] = 1; + reqbuf->XBuffer.P[l++] = chan->e.D3Id; + reqbuf->XBuffer.P[l++] = LLC; + reqbuf->XBuffer.P[l++] = 2; + switch(chan->l2prot) { + case ISDN_PROTO_L2_HDLC: + reqbuf->XBuffer.P[l++] = 2; + break; + case ISDN_PROTO_L2_X75I: + case ISDN_PROTO_L2_X75UI: + case ISDN_PROTO_L2_X75BUI: + reqbuf->XBuffer.P[l++] = 5; + break; + case ISDN_PROTO_L2_TRANS: + case ISDN_PROTO_L2_MODEM: + reqbuf->XBuffer.P[l++] = 2; + break; + default: + reqbuf->XBuffer.P[l++] = 1; + } + switch(chan->l3prot) { + case ISDN_PROTO_L3_TRANS: + default: + reqbuf->XBuffer.P[l++] = 4; + } + reqbuf->XBuffer.P[l++] = 0; /* end */ + reqbuf->Req = ASSIGN; + reqbuf->ReqCh = 0; + reqbuf->ReqId = 0x20; + reqbuf->XBuffer.length = l; + reqbuf->Reference = 1; /* Net Entity */ + } + return(0); +} + +int +idi_put_req(eicon_REQ *reqbuf, int rq, int signet) +{ + reqbuf->Req = rq; + reqbuf->ReqCh = 0; + reqbuf->ReqId = 1; + reqbuf->XBuffer.length = 1; + reqbuf->XBuffer.P[0] = 0; + reqbuf->Reference = signet; + return(0); +} + +int +idi_call_res_req(eicon_REQ *reqbuf, eicon_chan *chan) +{ + int l = 9; + reqbuf->Req = CALL_RES; + reqbuf->ReqCh = 0; + reqbuf->ReqId = 1; + reqbuf->XBuffer.P[0] = CAI; + reqbuf->XBuffer.P[1] = 6; + reqbuf->XBuffer.P[2] = 9; + reqbuf->XBuffer.P[3] = 0; + reqbuf->XBuffer.P[4] = 0; + reqbuf->XBuffer.P[5] = 0; + reqbuf->XBuffer.P[6] = 32; + reqbuf->XBuffer.P[7] = 3; + switch(chan->l2prot) { + case ISDN_PROTO_L2_X75I: + case ISDN_PROTO_L2_X75UI: + case ISDN_PROTO_L2_X75BUI: + case ISDN_PROTO_L2_HDLC: + reqbuf->XBuffer.P[1] = 1; + reqbuf->XBuffer.P[2] = 0x05; + l = 4; + break; + case ISDN_PROTO_L2_V11096: + reqbuf->XBuffer.P[2] = 0x0d; + reqbuf->XBuffer.P[3] = 5; + reqbuf->XBuffer.P[4] = 0; + break; + case ISDN_PROTO_L2_V11019: + reqbuf->XBuffer.P[2] = 0x0d; + reqbuf->XBuffer.P[3] = 6; + reqbuf->XBuffer.P[4] = 0; + break; + case ISDN_PROTO_L2_V11038: + reqbuf->XBuffer.P[2] = 0x0d; + reqbuf->XBuffer.P[3] = 7; + reqbuf->XBuffer.P[4] = 0; + break; + case ISDN_PROTO_L2_MODEM: + reqbuf->XBuffer.P[2] = 0x11; + reqbuf->XBuffer.P[3] = 7; + reqbuf->XBuffer.P[4] = 0; + reqbuf->XBuffer.P[5] = 0; + reqbuf->XBuffer.P[6] = 128; + reqbuf->XBuffer.P[7] = 0; + break; + case ISDN_PROTO_L2_TRANS: + switch(chan->l3prot) { + case ISDN_PROTO_L3_TRANSDSP: + reqbuf->XBuffer.P[2] = 22; /* DTMF, audio events on */ + } + break; + } + reqbuf->XBuffer.P[8] = 0; + reqbuf->XBuffer.length = l; + reqbuf->Reference = 0; /* Sig Entity */ + if (DebugVar & 8) + printk(KERN_DEBUG"idi_req: Ch%d: Call_Res\n", chan->No); + return(0); +} + +int +idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer) +{ + struct sk_buff *skb; + struct sk_buff *skb2; + eicon_REQ *reqbuf; + eicon_chan_ptr *chan2; + + skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC); + skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); + + if ((!skb) || (!skb2)) { + if (DebugVar & 1) + printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No); + return -ENOMEM; + } + + chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); + chan2->ptr = chan; + + reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ)); + if (DebugVar & 8) + printk(KERN_DEBUG "idi_req: Ch%d: 0x%02x (%s)\n", chan->No, cmd, (layer)?"Net":"Sig"); + if (layer) cmd |= 0x700; + switch(cmd) { + case ASSIGN: + case ASSIGN|0x700: + idi_assign_req(reqbuf, layer, chan); + break; + case REMOVE: + case REMOVE|0x700: + idi_put_req(reqbuf, REMOVE, layer); + break; + case INDICATE_REQ: + idi_put_req(reqbuf, INDICATE_REQ, 0); + break; + case HANGUP: + idi_put_req(reqbuf, HANGUP, 0); + break; + case REJECT: + idi_put_req(reqbuf, REJECT, 0); + break; + case CALL_ALERT: + idi_put_req(reqbuf, CALL_ALERT, 0); + break; + case CALL_RES: + idi_call_res_req(reqbuf, chan); + break; + case IDI_N_CONNECT|0x700: + idi_put_req(reqbuf, IDI_N_CONNECT, 1); + break; + case IDI_N_CONNECT_ACK|0x700: + idi_put_req(reqbuf, IDI_N_CONNECT_ACK, 1); + break; + case IDI_N_DISC|0x700: + idi_put_req(reqbuf, IDI_N_DISC, 1); + break; + case IDI_N_DISC_ACK|0x700: + idi_put_req(reqbuf, IDI_N_DISC_ACK, 1); + break; + default: + if (DebugVar & 1) + printk(KERN_ERR "idi_req: Ch%d: Unknown request\n", chan->No); + return(-1); + } + + skb_queue_tail(&chan->e.X, skb); + skb_queue_tail(&card->sndq, skb2); + eicon_schedule_tx(card); + return(0); +} + +int +eicon_idi_listen_req(eicon_card *card, eicon_chan *chan) +{ + if (DebugVar & 16) + printk(KERN_DEBUG"idi_req: Ch%d: Listen_Req eazmask=0x%x\n",chan->No, chan->eazmask); + if (!chan->e.D3Id) { + idi_do_req(card, chan, ASSIGN, 0); + } + if (chan->fsm_state == EICON_STATE_NULL) { + idi_do_req(card, chan, INDICATE_REQ, 0); + chan->fsm_state = EICON_STATE_LISTEN; + } + return(0); +} + +unsigned char +idi_si2bc(int si1, int si2, char *bc, char *hlc) +{ + hlc[0] = 0; + switch(si1) { + case 1: + bc[0] = 0x90; /* 3,1 kHz audio */ + bc[1] = 0x90; /* 64 kbit/s */ + bc[2] = 0xa3; /* G.711 A-law */ +#ifdef EICON_FULL_SERVICE_OKTETT + if (si2 == 1) { + bc[0] = 0x80; /* Speech */ + hlc[0] = 0x02; /* hlc len */ + hlc[1] = 0x91; /* first hic */ + hlc[2] = 0x81; /* Telephony */ + } +#endif + return(3); + case 2: + bc[0] = 0x90; /* 3,1 kHz audio */ + bc[1] = 0x90; /* 64 kbit/s */ + bc[2] = 0xa3; /* G.711 A-law */ +#ifdef EICON_FULL_SERVICE_OKTETT + if (si2 == 2) { + hlc[0] = 0x02; /* hlc len */ + hlc[1] = 0x91; /* first hic */ + hlc[2] = 0x84; /* Fax Gr.2/3 */ + } +#endif + return(3); + case 5: + case 7: + default: + bc[0] = 0x88; + bc[1] = 0x90; + return(2); + } + return (0); +} + +int +idi_hangup(eicon_card *card, eicon_chan *chan) +{ + if ((chan->fsm_state == EICON_STATE_ACTIVE) || + (chan->fsm_state == EICON_STATE_WMCONN)) { + if (chan->e.B2Id) idi_do_req(card, chan, IDI_N_DISC, 1); + } + if (chan->e.B2Id) idi_do_req(card, chan, REMOVE, 1); + idi_do_req(card, chan, HANGUP, 0); + chan->fsm_state = EICON_STATE_NULL; + if (DebugVar & 8) + printk(KERN_DEBUG"idi_req: Ch%d: Hangup\n", chan->No); + return(0); +} + +int +idi_connect_res(eicon_card *card, eicon_chan *chan) +{ + chan->fsm_state = EICON_STATE_IWAIT; + idi_do_req(card, chan, CALL_RES, 0); + idi_do_req(card, chan, ASSIGN, 1); + return(0); +} + +int +idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone, + char *eazmsn, int si1, int si2) +{ + int l = 0; + int i; + unsigned char tmp; + unsigned char bc[5]; + unsigned char hlc[5]; + struct sk_buff *skb; + struct sk_buff *skb2; + eicon_REQ *reqbuf; + eicon_chan_ptr *chan2; + + skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC); + skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); + + if ((!skb) || (!skb2)) { + if (DebugVar & 1) + printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No); + return -ENOMEM; + } + + chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); + chan2->ptr = chan; + + reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ)); + reqbuf->Req = CALL_REQ; + reqbuf->ReqCh = 0; + reqbuf->ReqId = 1; + + reqbuf->XBuffer.P[l++] = CPN; + reqbuf->XBuffer.P[l++] = strlen(phone) + 1; + reqbuf->XBuffer.P[l++] = 0xc1; + for(i=0; iXBuffer.P[l++] = phone[i]; + + reqbuf->XBuffer.P[l++] = OAD; + reqbuf->XBuffer.P[l++] = strlen(eazmsn) + 2; + reqbuf->XBuffer.P[l++] = 0x01; + reqbuf->XBuffer.P[l++] = 0x81; + for(i=0; iXBuffer.P[l++] = eazmsn[i]; + + if ((tmp = idi_si2bc(si1, si2, bc, hlc)) > 0) { + reqbuf->XBuffer.P[l++] = BC; + reqbuf->XBuffer.P[l++] = tmp; + for(i=0; iXBuffer.P[l++] = bc[i]; + if ((tmp=hlc[0])) { + reqbuf->XBuffer.P[l++] = HLC; + reqbuf->XBuffer.P[l++] = tmp; + for(i=1; i<=tmp;i++) + reqbuf->XBuffer.P[l++] = hlc[i]; + } + } + reqbuf->XBuffer.P[l++] = CAI; + reqbuf->XBuffer.P[l++] = 6; + reqbuf->XBuffer.P[l++] = 0x09; + reqbuf->XBuffer.P[l++] = 0; + reqbuf->XBuffer.P[l++] = 0; + reqbuf->XBuffer.P[l++] = 0; + reqbuf->XBuffer.P[l++] = 32; + reqbuf->XBuffer.P[l++] = 3; + switch(chan->l2prot) { + case ISDN_PROTO_L2_X75I: + case ISDN_PROTO_L2_X75UI: + case ISDN_PROTO_L2_X75BUI: + case ISDN_PROTO_L2_HDLC: + reqbuf->XBuffer.P[l-6] = 5; + reqbuf->XBuffer.P[l-7] = 1; + l -= 5; + break; + case ISDN_PROTO_L2_V11096: + reqbuf->XBuffer.P[l-7] = 3; + reqbuf->XBuffer.P[l-6] = 0x0d; + reqbuf->XBuffer.P[l-5] = 5; + reqbuf->XBuffer.P[l-4] = 0; + l -= 3; + break; + case ISDN_PROTO_L2_V11019: + reqbuf->XBuffer.P[l-7] = 3; + reqbuf->XBuffer.P[l-6] = 0x0d; + reqbuf->XBuffer.P[l-5] = 6; + reqbuf->XBuffer.P[l-4] = 0; + l -= 3; + break; + case ISDN_PROTO_L2_V11038: + reqbuf->XBuffer.P[l-7] = 3; + reqbuf->XBuffer.P[l-6] = 0x0d; + reqbuf->XBuffer.P[l-5] = 7; + reqbuf->XBuffer.P[l-4] = 0; + l -= 3; + break; + case ISDN_PROTO_L2_MODEM: + reqbuf->XBuffer.P[l-6] = 0x11; + reqbuf->XBuffer.P[l-5] = 7; + reqbuf->XBuffer.P[l-4] = 0; + reqbuf->XBuffer.P[l-3] = 0; + reqbuf->XBuffer.P[l-2] = 128; + reqbuf->XBuffer.P[l-1] = 0; + break; + case ISDN_PROTO_L2_TRANS: + switch(chan->l3prot) { + case ISDN_PROTO_L3_TRANSDSP: + reqbuf->XBuffer.P[l-6] = 22; /* DTMF, audio events on */ + } + break; + } + + reqbuf->XBuffer.P[l++] = 0; /* end */ + reqbuf->XBuffer.length = l; + reqbuf->Reference = 0; /* Sig Entity */ + + skb_queue_tail(&chan->e.X, skb); + skb_queue_tail(&card->sndq, skb2); + eicon_schedule_tx(card); + + if (DebugVar & 8) + printk(KERN_DEBUG"idi_req: Ch%d: Conn_Req %s -> %s\n",chan->No, eazmsn, phone); + return(0); +} + + +void +idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsigned char *buffer, int len) +{ + int i,j; + int pos = 0; + int codeset = 0; + int wlen = 0; + int lock = 0; + __u8 w; + __u16 code; + isdn_ctrl cmd; + + memset(message, 0, sizeof(idi_ind_message)); + + if ((!len) || (!buffer[pos])) return; + while(pos <= len) { + w = buffer[pos++]; + if (!w) return; + if (w & 0x80) { + wlen = 0; + } + else { + wlen = buffer[pos++]; + } + + if (pos > len) return; + + if (lock & 0x80) lock &= 0x7f; + else codeset = lock; + + if((w&0xf0) == SHIFT) { + codeset = w; + if(!(codeset & 0x08)) lock = codeset & 7; + codeset &= 7; + lock |= 0x80; + } + else { + if (w==ESC && wlen >=2) { + code = buffer[pos++]|0x800; + wlen--; + } + else code = w; + code |= (codeset<<8); + + switch(code) { + case OAD: + j = 1; + if (wlen) { + message->plan = buffer[pos++]; + if (message->plan &0x80) + message->screen = 0; + else { + message->screen = buffer[pos++]; + j = 2; + } + } + for(i=0; i < wlen-j; i++) + message->oad[i] = buffer[pos++]; + if (DebugVar & 2) + printk(KERN_DEBUG"idi_inf: Ch%d: OAD=(0x%02x,0x%02x) %s\n", chan->No, + message->plan, message->screen, message->oad); + break; + case RDN: + j = 1; + if (wlen) { + if (!(buffer[pos++] & 0x80)) { + pos++; + j = 2; + } + } + for(i=0; i < wlen-j; i++) + message->rdn[i] = buffer[pos++]; + if (DebugVar & 2) + printk(KERN_DEBUG"idi_inf: Ch%d: RDN= %s\n", chan->No, + message->rdn); + break; + case CPN: + for(i=0; i < wlen; i++) + message->cpn[i] = buffer[pos++]; + if (DebugVar & 2) + printk(KERN_DEBUG"idi_inf: Ch%d: CPN=(0x%02x) %s\n", chan->No, + (__u8)message->cpn[0], message->cpn + 1); + break; + case DSA: + pos++; + for(i=0; i < wlen-1; i++) + message->dsa[i] = buffer[pos++]; + if (DebugVar & 2) + printk(KERN_DEBUG"idi_inf: Ch%d: DSA=%s\n", chan->No, message->dsa); + break; + case OSA: + pos++; + for(i=0; i < wlen-1; i++) + message->osa[i] = buffer[pos++]; + if (DebugVar & 2) + printk(KERN_DEBUG"idi_inf: Ch%d: OSA=%s\n", chan->No, message->osa); + break; + case BC: + for(i=0; i < wlen; i++) + message->bc[i] = buffer[pos++]; + if (DebugVar & 4) + printk(KERN_DEBUG"idi_inf: Ch%d: BC = 0x%02x 0x%02x 0x%02x\n", chan->No, + message->bc[0],message->bc[1],message->bc[2]); + break; + case 0x800|BC: + for(i=0; i < wlen; i++) + message->e_bc[i] = buffer[pos++]; + if (DebugVar & 4) + printk(KERN_DEBUG"idi_inf: Ch%d: ESC/BC=%d\n", chan->No, message->bc[0]); + break; + case LLC: + for(i=0; i < wlen; i++) + message->llc[i] = buffer[pos++]; + if (DebugVar & 4) + printk(KERN_DEBUG"idi_inf: Ch%d: LLC=%d %d %d %d\n", chan->No, message->llc[0], + message->llc[1],message->llc[2],message->llc[3]); + break; + case HLC: + for(i=0; i < wlen; i++) + message->hlc[i] = buffer[pos++]; + if (DebugVar & 4) + printk(KERN_DEBUG"idi_inf: Ch%d: HLC=%x %x %x %x %x\n", chan->No, + message->hlc[0], message->hlc[1], + message->hlc[2], message->hlc[3], message->hlc[4]); + break; + case DSP: + case 0x600|DSP: + for(i=0; i < wlen; i++) + message->display[i] = buffer[pos++]; + if (DebugVar & 4) + printk(KERN_DEBUG"idi_inf: Ch%d: Display: %s\n", chan->No, + message->display); + break; + case 0x600|KEY: + for(i=0; i < wlen; i++) + message->keypad[i] = buffer[pos++]; + if (DebugVar & 4) + printk(KERN_DEBUG"idi_inf: Ch%d: Keypad: %s\n", chan->No, + message->keypad); + break; + case NI: + case 0x600|NI: + if (wlen) { + if (DebugVar & 4) { + switch(buffer[pos] & 127) { + case 0: + printk(KERN_DEBUG"idi_inf: Ch%d: User suspended.\n", chan->No); + break; + case 1: + printk(KERN_DEBUG"idi_inf: Ch%d: User resumed.\n", chan->No); + break; + case 2: + printk(KERN_DEBUG"idi_inf: Ch%d: Bearer service change.\n", chan->No); + break; + default: + printk(KERN_DEBUG"idi_inf: Ch%d: Unknown Notification %x.\n", + chan->No, buffer[pos] & 127); + } + } + pos += wlen; + } + break; + case PI: + case 0x600|PI: + if (wlen > 1) { + if (DebugVar & 4) { + switch(buffer[pos+1] & 127) { + case 1: + printk(KERN_DEBUG"idi_inf: Ch%d: Call is not end-to-end ISDN.\n", chan->No); + break; + case 2: + printk(KERN_DEBUG"idi_inf: Ch%d: Destination address is non ISDN.\n", chan->No); + break; + case 3: + printk(KERN_DEBUG"idi_inf: Ch%d: Origination address is non ISDN.\n", chan->No); + break; + case 4: + printk(KERN_DEBUG"idi_inf: Ch%d: Call has returned to the ISDN.\n", chan->No); + break; + case 5: + printk(KERN_DEBUG"idi_inf: Ch%d: Interworking has occurred.\n", chan->No); + break; + case 8: + printk(KERN_DEBUG"idi_inf: Ch%d: In-band information available.\n", chan->No); + break; + default: + printk(KERN_DEBUG"idi_inf: Ch%d: Unknown Progress %x.\n", + chan->No, buffer[pos+1] & 127); + } + } + } + pos += wlen; + break; + case CAU: + for(i=0; i < wlen; i++) + message->cau[i] = buffer[pos++]; + memcpy(&chan->cause, &message->cau, 2); + if (DebugVar & 4) + printk(KERN_DEBUG"idi_inf: Ch%d: CAU=%d %d\n", chan->No, + message->cau[0],message->cau[1]); + break; + case 0x800|CAU: + for(i=0; i < wlen; i++) + message->e_cau[i] = buffer[pos++]; + if (DebugVar & 4) + printk(KERN_DEBUG"idi_inf: Ch%d: ECAU=%d %d\n", chan->No, + message->e_cau[0],message->e_cau[1]); + break; + case 0x800|CHI: + for(i=0; i < wlen; i++) + message->e_chi[i] = buffer[pos++]; + if (DebugVar & 4) + printk(KERN_DEBUG"idi_inf: Ch%d: ESC/CHI=%d\n", chan->No, + message->e_cau[0]); + break; + case 0x800|0x7a: + pos ++; + message->e_mt=buffer[pos++]; + if (DebugVar & 2) + printk(KERN_DEBUG"idi_inf: Ch%d: EMT=0x%x\n", chan->No, message->e_mt); + break; + case DT: + for(i=0; i < wlen; i++) + message->dt[i] = buffer[pos++]; + if (DebugVar & 4) + printk(KERN_DEBUG"idi_inf: Ch%d: DT: %02d.%02d.%02d %02d:%02d:%02d\n", chan->No, + message->dt[2], message->dt[1], message->dt[0], + message->dt[3], message->dt[4], message->dt[5]); + break; + case 0x600|SIN: + for(i=0; i < wlen; i++) + message->sin[i] = buffer[pos++]; + if (DebugVar & 2) + printk(KERN_DEBUG"idi_inf: Ch%d: SIN=%d %d\n", chan->No, + message->sin[0],message->sin[1]); + break; + case 0x600|CPS: + if (DebugVar & 2) + printk(KERN_DEBUG"idi_inf: Ch%d: Called Party Status in ind\n", chan->No); + pos += wlen; + break; + case 0x600|CIF: + for (i = 0; i < wlen; i++) + if (buffer[pos + i] != '0') break; + memcpy(&cmd.parm.num, &buffer[pos + i], wlen - i); + cmd.parm.num[wlen - i] = 0; + if (DebugVar & 2) + printk(KERN_DEBUG"idi_inf: Ch%d: CIF=%s\n", chan->No, cmd.parm.num); + pos += wlen; + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_CINF; + cmd.arg = chan->No; + ccard->interface.statcallb(&cmd); + break; + case 0x600|DATE: + if (DebugVar & 2) + printk(KERN_DEBUG"idi_inf: Ch%d: Date in ind\n", chan->No); + pos += wlen; + break; + case 0xe08: + case 0xe7a: + case 0xe04: + case 0xe00: + /* *** TODO *** */ + case CHA: + /* Charge advice */ + case FTY: + case 0x600|FTY: + case CHI: + case 0x800: + /* Not yet interested in this */ + pos += wlen; + break; + case 0x880: + /* Managment Information Element */ + if (!manbuf) { + if (DebugVar & 1) + printk(KERN_WARNING"idi_err: manbuf not allocated\n"); + } + else { + memcpy(&manbuf->data[manbuf->pos], &buffer[pos], wlen); + manbuf->length[manbuf->count] = wlen; + manbuf->count++; + manbuf->pos += wlen; + } + pos += wlen; + break; + default: + pos += wlen; + if (DebugVar & 6) + printk(KERN_WARNING"idi_inf: Ch%d: unknown information element 0x%x in ind, len:%x\n", + chan->No, code, wlen); + } + } + } +} + +void +idi_bc2si(unsigned char *bc, unsigned char *hlc, unsigned char *si1, unsigned char *si2) +{ + si1[0] = 0; + si2[0] = 0; + if (memcmp(bc, BC_Speech, 3) == 0) { /* Speech */ + si1[0] = 1; +#ifdef EICON_FULL_SERVICE_OKTETT + si2[0] = 1; +#endif + } + if (memcmp(bc, BC_31khz, 3) == 0) { /* 3.1kHz audio */ + si1[0] = 1; +#ifdef EICON_FULL_SERVICE_OKTETT + si2[0] = 2; + if (memcmp(hlc, HLC_faxg3, 2) == 0) { /* Fax Gr.2/3 */ + si1[0] = 2; + } +#endif + } + if (memcmp(bc, BC_64k, 2) == 0) { /* unrestricted 64 kbits */ + si1[0] = 7; + } + if (memcmp(bc, BC_video, 3) == 0) { /* video */ + si1[0] = 4; + } +} + +int +idi_send_udata(eicon_card *card, eicon_chan *chan, int UReq, u_char *buffer, int len) +{ + struct sk_buff *skb; + struct sk_buff *skb2; + eicon_REQ *reqbuf; + eicon_chan_ptr *chan2; + + if ((chan->fsm_state == EICON_STATE_NULL) || (chan->fsm_state == EICON_STATE_LISTEN)) { + if (DebugVar & 1) + printk(KERN_DEBUG"idi_snd: Ch%d: send udata on state %d !\n", chan->No, chan->fsm_state); + return -ENODEV; + } + if (DebugVar & 8) + printk(KERN_DEBUG"idi_snd: Ch%d: udata 0x%x: %d %d %d %d\n", chan->No, + UReq, buffer[0], buffer[1], buffer[2], buffer[3]); + + skb = alloc_skb(sizeof(eicon_REQ) + len + 1, GFP_ATOMIC); + skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); + + if ((!skb) || (!skb2)) { + if (DebugVar & 1) + printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No); + return -ENOMEM; + } + + chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); + chan2->ptr = chan; + + reqbuf = (eicon_REQ *)skb_put(skb, 1 + len + sizeof(eicon_REQ)); + + reqbuf->Req = IDI_N_UDATA; + reqbuf->ReqCh = 0; + reqbuf->ReqId = 1; + + reqbuf->XBuffer.length = len + 1; + reqbuf->XBuffer.P[0] = UReq; + memcpy(&reqbuf->XBuffer.P[1], buffer, len); + reqbuf->Reference = 1; /* Net Entity */ + + skb_queue_tail(&chan->e.X, skb); + skb_queue_tail(&card->sndq, skb2); + eicon_schedule_tx(card); + return (0); +} + +void +idi_audio_cmd(eicon_card *ccard, eicon_chan *chan, int cmd, u_char *value) +{ + u_char buf[6]; + struct enable_dtmf_s *dtmf_buf = (struct enable_dtmf_s *)buf; + + memset(buf, 0, 6); + switch(cmd) { + case ISDN_AUDIO_SETDD: + if (value[0]) { + dtmf_buf->tone = (__u16) (value[1] * 5); + dtmf_buf->gap = (__u16) (value[1] * 5); + idi_send_udata(ccard, chan, + DSP_UDATA_REQUEST_ENABLE_DTMF_RECEIVER, + buf, 4); + } else { + idi_send_udata(ccard, chan, + DSP_UDATA_REQUEST_DISABLE_DTMF_RECEIVER, + buf, 0); + } + break; + } +} + +void +idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int len) +{ + isdn_ctrl cmd; + eicon_dsp_ind *p = (eicon_dsp_ind *) (&buffer[1]); + static char *connmsg[] = + {"", "V.21", "V.23", "V.22", "V.22bis", "V.32bis", "V.34", + "V.8", "Bell 212A", "Bell 103", "V.29 Leased", "V.33 Leased", "V.90", + "V.21 CH2", "V.27ter", "V.29", "V.33", "V.17"}; + static u_char dtmf_code[] = { + '1','4','7','*','2','5','8','0','3','6','9','#','A','B','C','D' + }; + + switch (buffer[0]) { + case DSP_UDATA_INDICATION_SYNC: + if (DebugVar & 16) + printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_SYNC time %d\n", chan->No, p->time); + break; + case DSP_UDATA_INDICATION_DCD_OFF: + if (DebugVar & 8) + printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DCD_OFF time %d\n", chan->No, p->time); + break; + case DSP_UDATA_INDICATION_DCD_ON: + if ((chan->l2prot == ISDN_PROTO_L2_MODEM) && + (chan->fsm_state == EICON_STATE_WMCONN)) { + chan->fsm_state = EICON_STATE_ACTIVE; + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_BCONN; + cmd.arg = chan->No; + sprintf(cmd.parm.num, "%d/%s", p->speed, connmsg[p->norm]); + ccard->interface.statcallb(&cmd); + } + if (DebugVar & 8) { + printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DCD_ON time %d\n", chan->No, p->time); + printk(KERN_DEBUG"idi_ind: Ch%d: %d %d %d %d\n", chan->No, + p->norm, p->options, p->speed, p->delay); + } + break; + case DSP_UDATA_INDICATION_CTS_OFF: + if (DebugVar & 8) + printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_CTS_OFF time %d\n", chan->No, p->time); + break; + case DSP_UDATA_INDICATION_CTS_ON: + if (DebugVar & 8) { + printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_CTS_ON time %d\n", chan->No, p->time); + printk(KERN_DEBUG"idi_ind: Ch%d: %d %d %d %d\n", chan->No, + p->norm, p->options, p->speed, p->delay); + } + break; + case DSP_UDATA_INDICATION_DISCONNECT: + if (DebugVar & 8) + printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DISCONNECT cause %d\n", chan->No, buffer[1]); + break; + case DSP_UDATA_INDICATION_DTMF_DIGITS_RECEIVED: + if (DebugVar & 8) + printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DTMF_REC '%c'\n", chan->No, + dtmf_code[buffer[1]]); + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_AUDIO; + cmd.parm.num[0] = ISDN_AUDIO_DTMF; + cmd.parm.num[1] = dtmf_code[buffer[1]]; + cmd.arg = chan->No; + ccard->interface.statcallb(&cmd); + break; + default: + if (DebugVar & 8) + printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED UDATA Indication 0x%02x\n", chan->No, buffer[0]); + } +} + +void +idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) +{ + int tmp; + int free_buff; + struct sk_buff *skb2; + eicon_IND *ind = (eicon_IND *)skb->data; + eicon_chan *chan; + idi_ind_message message; + isdn_ctrl cmd; + + if ((chan = ccard->IdTable[ind->IndId]) == NULL) { + dev_kfree_skb(skb); + return; + } + + if ((DebugVar & 128) || + ((DebugVar & 16) && (ind->Ind != 8))) { + printk(KERN_DEBUG "idi_hdl: Ch%d: Ind=%d Id=%d Ch=%d MInd=%d MLen=%d Len=%d\n", chan->No, + ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length); + } + + free_buff = 1; + /* Signal Layer */ + if (chan->e.D3Id == ind->IndId) { + idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length); + switch(ind->Ind) { + case HANGUP: + if (DebugVar & 8) + printk(KERN_DEBUG"idi_ind: Ch%d: Hangup\n", chan->No); + while((skb2 = skb_dequeue(&chan->e.X))) { + dev_kfree_skb(skb2); + } + chan->e.busy = 0; + chan->queued = 0; + chan->waitq = 0; + chan->waitpq = 0; + chan->fsm_state = EICON_STATE_NULL; + if (message.e_cau[0] & 0x7f) { + cmd.driver = ccard->myid; + cmd.arg = chan->No; + sprintf(cmd.parm.num,"E%02x%02x", + chan->cause[0]&0x7f, message.e_cau[0]&0x7f); + cmd.command = ISDN_STAT_CAUSE; + ccard->interface.statcallb(&cmd); + } + chan->cause[0] = 0; + cmd.driver = ccard->myid; + cmd.arg = chan->No; + cmd.command = ISDN_STAT_DHUP; + ccard->interface.statcallb(&cmd); + eicon_idi_listen_req(ccard, chan); + break; + case INDICATE_IND: + if (DebugVar & 8) + printk(KERN_DEBUG"idi_ind: Ch%d: Indicate_Ind\n", chan->No); + chan->fsm_state = EICON_STATE_ICALL; + idi_bc2si(message.bc, message.hlc, &chan->si1, &chan->si2); + strcpy(chan->cpn, message.cpn + 1); + if (strlen(message.dsa)) { + strcat(chan->cpn, "."); + strcat(chan->cpn, message.dsa); + } + strcpy(chan->oad, message.oad); + try_stat_icall_again: + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_ICALL; + cmd.arg = chan->No; + cmd.parm.setup.si1 = chan->si1; + cmd.parm.setup.si2 = chan->si2; + strcpy(cmd.parm.setup.eazmsn, chan->cpn); + strcpy(cmd.parm.setup.phone, chan->oad); + cmd.parm.setup.plan = message.plan; + cmd.parm.setup.screen = message.screen; + tmp = ccard->interface.statcallb(&cmd); + switch(tmp) { + case 0: /* no user responding */ + idi_do_req(ccard, chan, HANGUP, 0); + break; + case 1: /* alert */ + if (DebugVar & 8) + printk(KERN_DEBUG"idi_req: Ch%d: Call Alert\n", chan->No); + if ((chan->fsm_state == EICON_STATE_ICALL) || (chan->fsm_state == EICON_STATE_ICALLW)) { + chan->fsm_state = EICON_STATE_ICALL; + idi_do_req(ccard, chan, CALL_ALERT, 0); + } + break; + case 2: /* reject */ + if (DebugVar & 8) + printk(KERN_DEBUG"idi_req: Ch%d: Call Reject\n", chan->No); + idi_do_req(ccard, chan, REJECT, 0); + break; + case 3: /* incomplete number */ + if (DebugVar & 8) + printk(KERN_DEBUG"idi_req: Ch%d: Incomplete Number\n", chan->No); + switch(ccard->type) { + case EICON_CTYPE_MAESTRAP: + case EICON_CTYPE_S2M: + /* TODO (other protocols) */ + chan->fsm_state = EICON_STATE_ICALLW; + break; + default: + idi_do_req(ccard, chan, HANGUP, 0); + } + break; + } + break; + case INFO_IND: + if (DebugVar & 8) + printk(KERN_DEBUG"idi_ind: Ch%d: Info_Ind\n", chan->No); + if ((chan->fsm_state == EICON_STATE_ICALLW) && + (message.cpn[0])) { + strcat(chan->cpn, message.cpn + 1); + goto try_stat_icall_again; + } + break; + case CALL_IND: + if (DebugVar & 8) + printk(KERN_DEBUG"idi_ind: Ch%d: Call_Ind\n", chan->No); + if ((chan->fsm_state == EICON_STATE_ICALL) || (chan->fsm_state == EICON_STATE_IWAIT)) { + chan->fsm_state = EICON_STATE_IBWAIT; + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_DCONN; + cmd.arg = chan->No; + ccard->interface.statcallb(&cmd); + idi_do_req(ccard, chan, IDI_N_CONNECT, 1); + } else + idi_hangup(ccard, chan); + break; + case CALL_CON: + if (DebugVar & 8) + printk(KERN_DEBUG"idi_ind: Ch%d: Call_Con\n", chan->No); + if (chan->fsm_state == EICON_STATE_OCALL) { + chan->fsm_state = EICON_STATE_OBWAIT; + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_DCONN; + cmd.arg = chan->No; + ccard->interface.statcallb(&cmd); + idi_do_req(ccard, chan, ASSIGN, 1); + idi_do_req(ccard, chan, IDI_N_CONNECT, 1); + } else + idi_hangup(ccard, chan); + break; + case AOC_IND: + if (DebugVar & 8) + printk(KERN_DEBUG"idi_ind: Ch%d: Advice of Charge\n", chan->No); + break; + default: + if (DebugVar & 8) + printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED SigIndication 0x%02x\n", chan->No, ind->Ind); + } + } + /* Network Layer */ + else if (chan->e.B2Id == ind->IndId) { + + if (chan->No == ccard->nchannels) { + /* Management Indication */ + idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length); + chan->fsm_state = 1; + } + else + switch(ind->Ind) { + case IDI_N_CONNECT_ACK: + if (DebugVar & 16) + printk(KERN_DEBUG"idi_ind: Ch%d: N_Connect_Ack\n", chan->No); + if (chan->l2prot == ISDN_PROTO_L2_MODEM) { + chan->fsm_state = EICON_STATE_WMCONN; + break; + } + chan->fsm_state = EICON_STATE_ACTIVE; + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_BCONN; + cmd.arg = chan->No; + ccard->interface.statcallb(&cmd); + break; + case IDI_N_CONNECT: + if (DebugVar & 16) + printk(KERN_DEBUG"idi_ind: Ch%d: N_Connect\n", chan->No); + if (chan->e.B2Id) idi_do_req(ccard, chan, IDI_N_CONNECT_ACK, 1); + if (chan->l2prot == ISDN_PROTO_L2_MODEM) { + chan->fsm_state = EICON_STATE_WMCONN; + break; + } + chan->fsm_state = EICON_STATE_ACTIVE; + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_BCONN; + cmd.arg = chan->No; + ccard->interface.statcallb(&cmd); + break; + case IDI_N_DISC: + if (DebugVar & 16) + printk(KERN_DEBUG"idi_ind: Ch%d: N_DISC\n", chan->No); + if (chan->e.B2Id) { + idi_do_req(ccard, chan, IDI_N_DISC_ACK, 1); + idi_do_req(ccard, chan, REMOVE, 1); + } + chan->queued = 0; + chan->waitq = 0; + chan->waitpq = 0; + if (chan->fsm_state == EICON_STATE_ACTIVE) { + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_BHUP; + cmd.arg = chan->No; + ccard->interface.statcallb(&cmd); + } + break; + case IDI_N_DISC_ACK: + if (DebugVar & 16) + printk(KERN_DEBUG"idi_ind: Ch%d: N_DISC_ACK\n", chan->No); + break; + case IDI_N_DATA_ACK: + if (DebugVar & 16) + printk(KERN_DEBUG"idi_ind: Ch%d: N_DATA_ACK\n", chan->No); + break; + case IDI_N_DATA: + skb_pull(skb, sizeof(eicon_IND) - 1); + if (DebugVar & 128) + printk(KERN_DEBUG"idi_rcv: Ch%d: %d bytes\n", chan->No, skb->len); + ccard->interface.rcvcallb_skb(ccard->myid, chan->No, skb); + free_buff = 0; + break; + case IDI_N_UDATA: + idi_parse_udata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length); + break; + default: + if (DebugVar & 8) + printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED NetIndication 0x%02x\n", chan->No, ind->Ind); + } + } + else { + if (DebugVar & 1) + printk(KERN_ERR "idi_ind: Ch%d: Ind is neither SIG nor NET !\n", chan->No); + } + if (free_buff) dev_kfree_skb(skb); +} + +void +idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack) +{ + isdn_ctrl cmd; + + if (ack->RcId != ((chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id)) { + /* I dont know why this happens, just ignoring this RC */ + if (DebugVar & 16) + printk(KERN_DEBUG "idi_ack: Ch%d: RcId %d not equal to last %d\n", chan->No, + ack->RcId, (chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id); + return; + } + + /* Management Interface */ + if (chan->No == ccard->nchannels) { + /* Managementinterface: changing state */ + if (chan->e.Req == 0x04) + chan->fsm_state = 1; + } + + /* Remove an Id */ + if (chan->e.Req == REMOVE) { + if (ack->Reference == chan->e.ref) { + ccard->IdTable[ack->RcId] = NULL; + if (DebugVar & 16) + printk(KERN_DEBUG "idi_ack: Ch%d: Removed : Id=%d Ch=%d (%s)\n", chan->No, + ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig"); + if (!chan->e.ReqCh) + chan->e.D3Id = 0; + else + chan->e.B2Id = 0; + } + else { + if (DebugVar & 1) + printk(KERN_DEBUG "idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan->No, + ack->Reference, chan->e.ref); + } + return; + } + + /* Signal layer */ + if (!chan->e.ReqCh) { + if (DebugVar & 16) + printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%d Ch=%d (ref:%d)\n", chan->No, + ack->RcId, ack->RcCh, ack->Reference); + } else { + /* Network layer */ + switch(chan->e.Req & 0x0f) { + case IDI_N_MDATA: + case IDI_N_DATA: + if ((chan->e.Req & 0x0f) == IDI_N_DATA) { + if (chan->queued) { + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_BSENT; + cmd.arg = chan->No; + cmd.parm.length = chan->waitpq; + ccard->interface.statcallb(&cmd); + } + chan->waitpq = 0; + } + chan->queued -= chan->waitq; + if (chan->queued < 0) chan->queued = 0; + break; + default: + if (DebugVar & 16) + printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%d Ch=%d (ref:%d)\n", chan->No, + ack->RcId, ack->RcCh, ack->Reference); + } + } +} + +void +idi_handle_ack(eicon_card *ccard, struct sk_buff *skb) +{ + int j; + eicon_RC *ack = (eicon_RC *)skb->data; + eicon_chan *chan; + isdn_ctrl cmd; + int dCh = -1; + + if ((chan = ccard->IdTable[ack->RcId]) != NULL) + dCh = chan->No; + + + switch (ack->Rc) { + case OK_FC: + case N_FLOW_CONTROL: + case ASSIGN_RC: + if (DebugVar & 1) + printk(KERN_ERR "idi_ack: Ch%d: unhandled RC 0x%x\n", + dCh, ack->Rc); + case READY_INT: + case TIMER_INT: + /* we do nothing here */ + break; + + case OK: + if (!chan) { + if (DebugVar & 1) + printk(KERN_ERR "idi_ack: Ch%d: OK on chan without Id\n", dCh); + break; + } + idi_handle_ack_ok(ccard, chan, ack); + break; + + case ASSIGN_OK: + if (chan) { + if (DebugVar & 1) + printk(KERN_ERR "idi_ack: Ch%d: ASSIGN-OK on chan already assigned (%d,%d)\n", + chan->No, chan->e.D3Id, chan->e.B2Id); + } + for(j = 0; j < ccard->nchannels + 1; j++) { + if (ccard->bch[j].e.ref == ack->Reference) { + if (!ccard->bch[j].e.ReqCh) + ccard->bch[j].e.D3Id = ack->RcId; + else + ccard->bch[j].e.B2Id = ack->RcId; + ccard->IdTable[ack->RcId] = &ccard->bch[j]; + ccard->bch[j].e.busy = 0; + ccard->bch[j].e.ref = 0; + if (DebugVar & 16) + printk(KERN_DEBUG"idi_ack: Ch%d: Id %d assigned (%s)\n", j, + ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig"); + break; + } + } + if (j > ccard->nchannels) { + if (DebugVar & 24) + printk(KERN_DEBUG"idi_ack: Ch??: ref %d not found for Id %d\n", + ack->Reference, ack->RcId); + } + break; + + case OUT_OF_RESOURCES: + case UNKNOWN_COMMAND: + case WRONG_COMMAND: + case WRONG_ID: + case WRONG_CH: + case UNKNOWN_IE: + case WRONG_IE: + default: + chan->e.busy = 0; + if (DebugVar & 24) + printk(KERN_ERR "eicon_ack: Ch%d: Not OK: Rc=%d Id=%d Ch=%d\n", dCh, + ack->Rc, ack->RcId, ack->RcCh); + if (dCh == ccard->nchannels) { /* Management */ + chan->fsm_state = 2; + } else if (dCh >= 0) { + /* any other channel */ + /* card reports error: we hangup */ + idi_hangup(ccard, chan); + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_DHUP; + cmd.arg = chan->No; + ccard->interface.statcallb(&cmd); + } + } + if (chan) + chan->e.busy = 0; + dev_kfree_skb(skb); + eicon_schedule_tx(ccard); +} + +int +idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que) +{ + struct sk_buff *xmit_skb; + struct sk_buff *skb2; + eicon_REQ *reqbuf; + eicon_chan_ptr *chan2; + int len, plen = 0, offset = 0; + unsigned long flags; + + if (chan->fsm_state != EICON_STATE_ACTIVE) { + if (DebugVar & 1) + printk(KERN_DEBUG"idi_snd: Ch%d: send bytes on state %d !\n", chan->No, chan->fsm_state); + return -ENODEV; + } + + len = skb->len; + if (len > 2138) /* too much for the shared memory */ + return -1; + if (!len) + return 0; + if (chan->queued + len > ((chan->l2prot == ISDN_PROTO_L2_TRANS) ? 4000 : EICON_MAX_QUEUED)) + return 0; + if (DebugVar & 128) + printk(KERN_DEBUG"idi_snd: Ch%d: %d bytes\n", chan->No, len); + + save_flags(flags); + cli(); + while(offset < len) { + + plen = ((len - offset) > 270) ? 270 : len - offset; + + xmit_skb = alloc_skb(plen + sizeof(eicon_REQ), GFP_ATOMIC); + skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); + + if ((!skb) || (!skb2)) { + restore_flags(flags); + if (DebugVar & 1) + printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No); + return -ENOMEM; + } + + chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); + chan2->ptr = chan; + + reqbuf = (eicon_REQ *)skb_put(xmit_skb, plen + sizeof(eicon_REQ)); + if (((len - offset) > 270) && + (chan->l2prot != ISDN_PROTO_L2_TRANS)) { + reqbuf->Req = IDI_N_MDATA; + } else { + reqbuf->Req = IDI_N_DATA; + if (ack) reqbuf->Req |= N_D_BIT; + } + reqbuf->ReqCh = 0; + reqbuf->ReqId = 1; + memcpy(&reqbuf->XBuffer.P, skb->data + offset, plen); + reqbuf->XBuffer.length = plen; + reqbuf->Reference = 1; /* Net Entity */ + + skb_queue_tail(&chan->e.X, xmit_skb); + skb_queue_tail(&card->sndq, skb2); + + offset += plen; + } + if (que) + chan->queued += len; + restore_flags(flags); + eicon_schedule_tx(card); + dev_kfree_skb(skb); + return len; +} + + + +int +eicon_idi_manage_assign(eicon_card *card) +{ + struct sk_buff *skb; + struct sk_buff *skb2; + eicon_REQ *reqbuf; + eicon_chan *chan; + eicon_chan_ptr *chan2; + + chan = &(card->bch[card->nchannels]); + + skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC); + skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); + + if ((!skb) || (!skb2)) { + if (DebugVar & 1) + printk(KERN_WARNING "idi_err: alloc_skb failed\n"); + return -ENOMEM; + } + + chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); + chan2->ptr = chan; + + reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ)); + + reqbuf->XBuffer.P[0] = 0; + reqbuf->Req = ASSIGN; + reqbuf->ReqCh = 0; + reqbuf->ReqId = 0xe0; + reqbuf->XBuffer.length = 1; + reqbuf->Reference = 2; /* Man Entity */ + + skb_queue_tail(&chan->e.X, skb); + skb_queue_tail(&card->sndq, skb2); + eicon_schedule_tx(card); + return(0); +} + + +int +eicon_idi_manage_remove(eicon_card *card) +{ + struct sk_buff *skb; + struct sk_buff *skb2; + eicon_REQ *reqbuf; + eicon_chan *chan; + eicon_chan_ptr *chan2; + + chan = &(card->bch[card->nchannels]); + + skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC); + skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); + + if ((!skb) || (!skb2)) { + if (DebugVar & 1) + printk(KERN_WARNING "idi_err: alloc_skb failed\n"); + return -ENOMEM; + } + + chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); + chan2->ptr = chan; + + reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ)); + + reqbuf->Req = REMOVE; + reqbuf->ReqCh = 0; + reqbuf->ReqId = 1; + reqbuf->XBuffer.length = 0; + reqbuf->Reference = 2; /* Man Entity */ + + skb_queue_tail(&chan->e.X, skb); + skb_queue_tail(&card->sndq, skb2); + eicon_schedule_tx(card); + return(0); +} + + +int +eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb) +{ + int l = 0; + int ret = 0; + int timeout; + int i; + struct sk_buff *skb; + struct sk_buff *skb2; + eicon_REQ *reqbuf; + eicon_chan *chan; + eicon_chan_ptr *chan2; + + chan = &(card->bch[card->nchannels]); + + if (chan->e.D3Id) return -EBUSY; + chan->e.D3Id = 1; + while((skb2 = skb_dequeue(&chan->e.X))) + dev_kfree_skb(skb2); + chan->e.busy = 0; + + if ((ret = eicon_idi_manage_assign(card))) { + chan->e.D3Id = 0; + return(ret); + } + + timeout = jiffies + 50; + while (timeout > jiffies) { + if (chan->e.B2Id) break; + SLEEP(10); + } + if (!chan->e.B2Id) { + chan->e.D3Id = 0; + return -EIO; + } + + chan->fsm_state = 0; + + if (!(manbuf = kmalloc(sizeof(eicon_manifbuf), GFP_KERNEL))) { + if (DebugVar & 1) + printk(KERN_WARNING "idi_err: alloc_manifbuf failed\n"); + chan->e.D3Id = 0; + return -ENOMEM; + } + if (copy_from_user(manbuf, mb, sizeof(eicon_manifbuf))) { + chan->e.D3Id = 0; + return -EFAULT; + } + + skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC); + skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); + + if ((!skb) || (!skb2)) { + if (DebugVar & 1) + printk(KERN_WARNING "idi_err_manif: alloc_skb failed\n"); + kfree(manbuf); + chan->e.D3Id = 0; + return -ENOMEM; + } + + chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); + chan2->ptr = chan; + + reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ)); + + reqbuf->XBuffer.P[l++] = ESC; + reqbuf->XBuffer.P[l++] = 6; + reqbuf->XBuffer.P[l++] = 0x80; + for (i = 0; i < manbuf->length[0]; i++) + reqbuf->XBuffer.P[l++] = manbuf->data[i]; + reqbuf->XBuffer.P[1] = manbuf->length[0] + 1; + + reqbuf->XBuffer.P[l++] = 0; + reqbuf->Req = (manbuf->count) ? manbuf->count : 0x02; /* Request */ + reqbuf->ReqCh = 0; + reqbuf->ReqId = 1; + reqbuf->XBuffer.length = l; + reqbuf->Reference = 2; /* Man Entity */ + + skb_queue_tail(&chan->e.X, skb); + skb_queue_tail(&card->sndq, skb2); + + manbuf->count = 0; + manbuf->pos = 0; + + eicon_schedule_tx(card); + + timeout = jiffies + 50; + while (timeout > jiffies) { + if (chan->fsm_state) break; + SLEEP(10); + } + if ((!chan->fsm_state) || (chan->fsm_state == 2)) { + eicon_idi_manage_remove(card); + kfree(manbuf); + chan->e.D3Id = 0; + return -EIO; + } + + if ((ret = eicon_idi_manage_remove(card))) { + chan->e.D3Id = 0; + return(ret); + } + + if (copy_to_user(mb, manbuf, sizeof(eicon_manifbuf))) { + chan->e.D3Id = 0; + return -EFAULT; + } + + kfree(manbuf); + chan->e.D3Id = 0; + return(0); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon_idi.h linux.pre11.3/drivers/isdn/eicon/eicon_idi.h --- linux.vanilla/drivers/isdn/eicon/eicon_idi.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/eicon/eicon_idi.h Mon Jul 19 23:59:33 1999 @@ -0,0 +1,260 @@ +/* $Id: eicon_idi.h,v 1.5 1999/07/11 17:16:26 armin Exp $ + * + * ISDN lowlevel-module for the Eicon.Diehl active cards. + * IDI-Interface + * + * Copyright 1998,99 by Armin Schindler (mac@melware.de) + * Copyright 1999 Cytronics & Melware (info@melware.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, 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. + * + * $Log: eicon_idi.h,v $ + * Revision 1.5 1999/07/11 17:16:26 armin + * Bugfixes in queue handling. + * Added DSP-DTMF decoder functions. + * Reorganized ack_handler. + * + * Revision 1.4 1999/03/29 11:19:44 armin + * I/O stuff now in seperate file (eicon_io.c) + * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. + * + * Revision 1.3 1999/03/02 12:37:45 armin + * Added some important checks. + * Analog Modem with DSP. + * Channels will be added to Link-Level after loading firmware. + * + * Revision 1.2 1999/01/24 20:14:18 armin + * Changed and added debug stuff. + * Better data sending. (still problems with tty's flip buffer) + * + * Revision 1.1 1999/01/01 18:09:42 armin + * First checkin of new eicon driver. + * DIVA-Server BRI/PCI and PRI/PCI are supported. + * Old diehl code is obsolete. + * + * + */ + +#ifndef IDI_H +#define IDI_H + + +#define ASSIGN 0x01 +#define REMOVE 0xff + +#define CALL_REQ 1 /* call request */ +#define CALL_CON 1 /* call confirmation */ +#define CALL_IND 2 /* incoming call connected */ +#define LISTEN_REQ 2 /* listen request */ +#define HANGUP 3 /* hangup request/indication */ +#define SUSPEND 4 /* call suspend request/confirm */ +#define RESUME 5 /* call resume request/confirm */ +#define SUSPEND_REJ 6 /* suspend rejected indication */ +#define USER_DATA 8 /* user data for user to user signaling */ +#define CONGESTION 9 /* network congestion indication */ +#define INDICATE_REQ 10 /* request to indicate an incoming call */ +#define INDICATE_IND 10 /* indicates that there is an incoming call */ +#define CALL_RES 11 /* accept an incoming call */ +#define CALL_ALERT 12 /* send ALERT for incoming call */ +#define INFO_REQ 13 /* INFO request */ +#define INFO_IND 13 /* INFO indication */ +#define REJECT 14 /* reject an incoming call */ +#define RESOURCES 15 /* reserve B-Channel hardware resources */ +#define TEL_CTRL 16 /* Telephone control request/indication */ +#define STATUS_REQ 17 /* Request D-State (returned in INFO_IND) */ +#define FAC_REG_REQ 18 /* connection idependent fac registration */ +#define FAC_REG_ACK 19 /* fac registration acknowledge */ +#define FAC_REG_REJ 20 /* fac registration reject */ +#define CALL_COMPLETE 21/* send a CALL_PROC for incoming call */ +#define AOC_IND 26/* Advice of Charge */ + +#define IDI_N_MDATA (0x01) +#define IDI_N_CONNECT (0x02) +#define IDI_N_CONNECT_ACK (0x03) +#define IDI_N_DISC (0x04) +#define IDI_N_DISC_ACK (0x05) +#define IDI_N_RESET (0x06) +#define IDI_N_RESET_ACK (0x07) +#define IDI_N_DATA (0x08) +#define IDI_N_EDATA (0x09) +#define IDI_N_UDATA (0x0a) +#define IDI_N_BDATA (0x0b) +#define IDI_N_DATA_ACK (0x0c) +#define IDI_N_EDATA_ACK (0x0d) + +#define N_Q_BIT 0x10 /* Q-bit for req/ind */ +#define N_M_BIT 0x20 /* M-bit for req/ind */ +#define N_D_BIT 0x40 /* D-bit for req/ind */ + + +#define SHIFT 0x90 /* codeset shift */ +#define MORE 0xa0 /* more data */ +#define CL 0xb0 /* congestion level */ + + /* codeset 0 */ + +#define BC 0x04 /* Bearer Capability */ +#define CAU 0x08 /* cause */ +#define CAD 0x0c /* Connected address */ +#define CAI 0x10 /* call identity */ +#define CHI 0x18 /* channel identification */ +#define LLI 0x19 /* logical link id */ +#define CHA 0x1a /* charge advice */ +#define FTY 0x1c +#define PI 0x1e /* Progress Indicator */ +#define NI 0x27 /* Notification Indicator */ +#define DT 0x29 /* ETSI date/time */ +#define KEY 0x2c /* keypad information element */ +#define DSP 0x28 /* display */ +#define OAD 0x6c /* origination address */ +#define OSA 0x6d /* origination sub-address */ +#define CPN 0x70 /* called party number */ +#define DSA 0x71 /* destination sub-address */ +#define RDN 0x74 /* redirecting number */ +#define LLC 0x7c /* low layer compatibility */ +#define HLC 0x7d /* high layer compatibility */ +#define UUI 0x7e /* user user information */ +#define ESC 0x7f /* escape extension */ + +#define DLC 0x20 /* data link layer configuration */ +#define NLC 0x21 /* network layer configuration */ + + /* codeset 6 */ + +#define SIN 0x01 /* service indicator */ +#define CIF 0x02 /* charging information */ +#define DATE 0x03 /* date */ +#define CPS 0x07 /* called party status */ + +/*------------------------------------------------------------------*/ +/* return code coding */ +/*------------------------------------------------------------------*/ + +#define UNKNOWN_COMMAND 0x01 /* unknown command */ +#define WRONG_COMMAND 0x02 /* wrong command */ +#define WRONG_ID 0x03 /* unknown task/entity id */ +#define WRONG_CH 0x04 /* wrong task/entity id */ +#define UNKNOWN_IE 0x05 /* unknown information el. */ +#define WRONG_IE 0x06 /* wrong information el. */ +#define OUT_OF_RESOURCES 0x07 /* card out of res. */ +#define N_FLOW_CONTROL 0x10 /* Flow-Control, retry */ +#define ASSIGN_RC 0xe0 /* ASSIGN acknowledgement */ +#define ASSIGN_OK 0xef /* ASSIGN OK */ +#define OK_FC 0xfc /* Flow-Control RC */ +#define READY_INT 0xfd /* Ready interrupt */ +#define TIMER_INT 0xfe /* timer interrupt */ +#define OK 0xff /* command accepted */ + +/*------------------------------------------------------------------*/ + +typedef struct { + char cpn[32]; + char oad[32]; + char dsa[32]; + char osa[32]; + __u8 plan; + __u8 screen; + __u8 sin[4]; + __u8 chi[4]; + __u8 e_chi[4]; + __u8 bc[12]; + __u8 e_bc[12]; + __u8 llc[18]; + __u8 hlc[5]; + __u8 cau[4]; + __u8 e_cau[2]; + __u8 e_mt; + __u8 dt[6]; + char display[83]; + char keypad[35]; + char rdn[32]; +} idi_ind_message; + +typedef struct { + __u16 next __attribute__ ((packed)); + __u8 Req __attribute__ ((packed)); + __u8 ReqId __attribute__ ((packed)); + __u8 ReqCh __attribute__ ((packed)); + __u8 Reserved1 __attribute__ ((packed)); + __u16 Reference __attribute__ ((packed)); + __u8 Reserved[8] __attribute__ ((packed)); + eicon_PBUFFER XBuffer; +} eicon_REQ; + +typedef struct { + __u16 next __attribute__ ((packed)); + __u8 Rc __attribute__ ((packed)); + __u8 RcId __attribute__ ((packed)); + __u8 RcCh __attribute__ ((packed)); + __u8 Reserved1 __attribute__ ((packed)); + __u16 Reference __attribute__ ((packed)); + __u8 Reserved2[8] __attribute__ ((packed)); +} eicon_RC; + +typedef struct { + __u16 next __attribute__ ((packed)); + __u8 Ind __attribute__ ((packed)); + __u8 IndId __attribute__ ((packed)); + __u8 IndCh __attribute__ ((packed)); + __u8 MInd __attribute__ ((packed)); + __u16 MLength __attribute__ ((packed)); + __u16 Reference __attribute__ ((packed)); + __u8 RNR __attribute__ ((packed)); + __u8 Reserved __attribute__ ((packed)); + __u32 Ack __attribute__ ((packed)); + eicon_PBUFFER RBuffer; +} eicon_IND; + +typedef struct { + __u16 NextReq __attribute__ ((packed)); /* pointer to next Req Buffer */ + __u16 NextRc __attribute__ ((packed)); /* pointer to next Rc Buffer */ + __u16 NextInd __attribute__ ((packed)); /* pointer to next Ind Buffer */ + __u8 ReqInput __attribute__ ((packed)); /* number of Req Buffers sent */ + __u8 ReqOutput __attribute__ ((packed)); /* number of Req Buffers returned */ + __u8 ReqReserved __attribute__ ((packed));/*number of Req Buffers reserved */ + __u8 Int __attribute__ ((packed)); /* ISDN-P interrupt */ + __u8 XLock __attribute__ ((packed)); /* Lock field for arbitration */ + __u8 RcOutput __attribute__ ((packed)); /* number of Rc buffers received */ + __u8 IndOutput __attribute__ ((packed)); /* number of Ind buffers received */ + __u8 IMask __attribute__ ((packed)); /* Interrupt Mask Flag */ + __u8 Reserved1[2] __attribute__ ((packed)); /* reserved field, do not use */ + __u8 ReadyInt __attribute__ ((packed)); /* request field for ready int */ + __u8 Reserved2[12] __attribute__ ((packed)); /* reserved field, do not use */ + __u8 InterfaceType __attribute__ ((packed)); /* interface type 1=16K */ + __u16 Signature __attribute__ ((packed)); /* ISDN-P initialized ind */ + __u8 B[1]; /* buffer space for Req,Ind and Rc */ +} eicon_pr_ram; + +typedef struct { + __u8 *Data; + unsigned int Size; + unsigned int Len; + __u8 *Next; +} eicon_OBJBUFFER; + +extern int idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer); +extern int idi_hangup(eicon_card *card, eicon_chan *chan); +extern int idi_connect_res(eicon_card *card, eicon_chan *chan); +extern int eicon_idi_listen_req(eicon_card *card, eicon_chan *chan); +extern int idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone, + char *eazmsn, int si1, int si2); + +extern void idi_handle_ack(eicon_card *card, struct sk_buff *skb); +extern void idi_handle_ind(eicon_card *card, struct sk_buff *skb); +extern int eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb); +extern int idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que); +extern void idi_audio_cmd(eicon_card *ccard, eicon_chan *chan, int cmd, u_char *value); + +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon_io.c linux.pre11.3/drivers/isdn/eicon/eicon_io.c --- linux.vanilla/drivers/isdn/eicon/eicon_io.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/eicon/eicon_io.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,755 @@ +/* $Id: eicon_io.c,v 1.1 1999/03/29 11:19:45 armin Exp $ + * + * ISDN low-level module for Eicon.Diehl active ISDN-Cards. + * Code for communicating with hardware. + * + * Copyright 1999 by Armin Schindler (mac@melware.de) + * Copyright 1999 Cytronics & Melware (info@melware.de) + * + * Thanks to Eicon Technology Diehl GmbH & Co. oHG for + * documents, informations and hardware. + * + * This program is free software; you can redistribute 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. + * + * 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. + * + * $Log: eicon_io.c,v $ + * Revision 1.1 1999/03/29 11:19:45 armin + * I/O stuff now in seperate file (eicon_io.c) + * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. + * + * + */ + + +#include "eicon.h" + +void +eicon_io_rcv_dispatch(eicon_card *ccard) { + struct sk_buff *skb, *skb2, *skb_new; + eicon_IND *ind, *ind2, *ind_new; + eicon_chan *chan; + + if (!ccard) { + if (DebugVar & 1) + printk(KERN_WARNING "eicon_io_rcv_dispatch: NULL card!\n"); + return; + } + + while((skb = skb_dequeue(&ccard->rcvq))) { + ind = (eicon_IND *)skb->data; + + if ((chan = ccard->IdTable[ind->IndId]) == NULL) { + if (DebugVar & 1) { + switch(ind->Ind) { + case IDI_N_DISC_ACK: + /* doesn't matter if this happens */ + break; + default: + printk(KERN_ERR "idi: Indication for unknown channel Ind=%d Id=%d\n", ind->Ind, ind->IndId); + printk(KERN_DEBUG "idi_hdl: Ch??: Ind=%d Id=%d Ch=%d MInd=%d MLen=%d Len=%d\n", + ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length); + } + } + dev_kfree_skb(skb); + continue; + } + + if (chan->e.complete) { /* check for rec-buffer chaining */ + if (ind->MLength == ind->RBuffer.length) { + chan->e.complete = 1; + idi_handle_ind(ccard, skb); + continue; + } + else { + chan->e.complete = 0; + ind->Ind = ind->MInd; + skb_queue_tail(&chan->e.R, skb); + continue; + } + } + else { + if (!(skb2 = skb_dequeue(&chan->e.R))) { + chan->e.complete = 1; + if (DebugVar & 1) + printk(KERN_ERR "eicon: buffer incomplete, but 0 in queue\n"); + dev_kfree_skb(skb); + dev_kfree_skb(skb2); + continue; + } + ind2 = (eicon_IND *)skb2->data; + skb_new = alloc_skb(((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length), + GFP_ATOMIC); + ind_new = (eicon_IND *)skb_put(skb_new, + ((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length)); + ind_new->Ind = ind2->Ind; + ind_new->IndId = ind2->IndId; + ind_new->IndCh = ind2->IndCh; + ind_new->MInd = ind2->MInd; + ind_new->MLength = ind2->MLength; + ind_new->RBuffer.length = ind2->RBuffer.length + ind->RBuffer.length; + memcpy(&ind_new->RBuffer.P, &ind2->RBuffer.P, ind2->RBuffer.length); + memcpy((&ind_new->RBuffer.P)+ind2->RBuffer.length, &ind->RBuffer.P, ind->RBuffer.length); + dev_kfree_skb(skb); + dev_kfree_skb(skb2); + if (ind->MLength == ind->RBuffer.length) { + chan->e.complete = 2; + idi_handle_ind(ccard, skb_new); + continue; + } + else { + chan->e.complete = 0; + skb_queue_tail(&chan->e.R, skb_new); + continue; + } + } + } +} + +void +eicon_io_ack_dispatch(eicon_card *ccard) { + struct sk_buff *skb; + + if (!ccard) { + if (DebugVar & 1) + printk(KERN_WARNING "eicon_io_ack_dispatch: NULL card!\n"); + return; + } + while((skb = skb_dequeue(&ccard->rackq))) { + idi_handle_ack(ccard, skb); + } +} + + +/* + * IO-Functions for different card-types + */ + +u8 ram_inb(eicon_card *card, void *adr) { + eicon_pci_card *pcard; + eicon_isa_card *icard; + u32 addr = (u32) adr; + + pcard = &card->hwif.pci; + icard = &card->hwif.isa; + + switch(card->type) { + case EICON_CTYPE_MAESTRA: + outw((u16)addr, (u16)pcard->PCIreg + M_ADDR); + return(inb((u16)pcard->PCIreg + M_DATA)); + case EICON_CTYPE_MAESTRAP: + case EICON_CTYPE_S2M: + case EICON_CTYPE_S: + case EICON_CTYPE_SX: + case EICON_CTYPE_SCOM: + case EICON_CTYPE_QUADRO: + return(readb(addr)); + } + return(0); +} + +u16 ram_inw(eicon_card *card, void *adr) { + eicon_pci_card *pcard; + eicon_isa_card *icard; + u32 addr = (u32) adr; + + pcard = &card->hwif.pci; + icard = &card->hwif.isa; + + switch(card->type) { + case EICON_CTYPE_MAESTRA: + outw((u16)addr, (u16)pcard->PCIreg + M_ADDR); + return(inw((u16)pcard->PCIreg + M_DATA)); + case EICON_CTYPE_MAESTRAP: + case EICON_CTYPE_S2M: + case EICON_CTYPE_S: + case EICON_CTYPE_SX: + case EICON_CTYPE_SCOM: + case EICON_CTYPE_QUADRO: + return(readw(addr)); + } + return(0); +} + +void ram_outb(eicon_card *card, void *adr, u8 data) { + eicon_pci_card *pcard; + eicon_isa_card *icard; + u32 addr = (u32) adr; + + pcard = &card->hwif.pci; + icard = &card->hwif.isa; + + switch(card->type) { + case EICON_CTYPE_MAESTRA: + outw((u16)addr, (u16)pcard->PCIreg + M_ADDR); + outb((u8)data, (u16)pcard->PCIreg + M_DATA); + break; + case EICON_CTYPE_MAESTRAP: + case EICON_CTYPE_S2M: + case EICON_CTYPE_S: + case EICON_CTYPE_SX: + case EICON_CTYPE_SCOM: + case EICON_CTYPE_QUADRO: + writeb(data, addr); + break; + } +} + +void ram_outw(eicon_card *card, void *adr , u16 data) { + eicon_pci_card *pcard; + eicon_isa_card *icard; + u32 addr = (u32) adr; + + pcard = &card->hwif.pci; + icard = &card->hwif.isa; + + switch(card->type) { + case EICON_CTYPE_MAESTRA: + outw((u16)addr, (u16)pcard->PCIreg + M_ADDR); + outw((u16)data, (u16)pcard->PCIreg + M_DATA); + break; + case EICON_CTYPE_MAESTRAP: + case EICON_CTYPE_S2M: + case EICON_CTYPE_S: + case EICON_CTYPE_SX: + case EICON_CTYPE_SCOM: + case EICON_CTYPE_QUADRO: + writew(data, addr); + break; + } +} + +void ram_copyfromcard(eicon_card *card, void *adrto, void *adr, int len) { + int i; + switch(card->type) { + case EICON_CTYPE_MAESTRA: + for(i = 0; i < len; i++) { + writeb(ram_inb(card, adr + i), adrto + i); + } + break; + case EICON_CTYPE_MAESTRAP: + memcpy(adrto, adr, len); + break; + case EICON_CTYPE_S2M: + case EICON_CTYPE_S: + case EICON_CTYPE_SX: + case EICON_CTYPE_SCOM: + case EICON_CTYPE_QUADRO: + memcpy_fromio(adrto, adr, len); + break; + } +} + +void ram_copytocard(eicon_card *card, void *adrto, void *adr, int len) { + int i; + switch(card->type) { + case EICON_CTYPE_MAESTRA: + for(i = 0; i < len; i++) { + ram_outb(card, adrto + i, readb(adr + i)); + } + break; + case EICON_CTYPE_MAESTRAP: + memcpy(adrto, adr, len); + break; + case EICON_CTYPE_S2M: + case EICON_CTYPE_S: + case EICON_CTYPE_SX: + case EICON_CTYPE_SCOM: + case EICON_CTYPE_QUADRO: + memcpy_toio(adrto, adr, len); + break; + } +} + +/* + * Transmit-Function + */ +void +eicon_io_transmit(eicon_card *ccard) { + eicon_pci_card *pci_card; + eicon_isa_card *isa_card; + struct sk_buff *skb; + struct sk_buff *skb2; + unsigned long flags; + char *ram, *reg, *cfg; + eicon_pr_ram *prram = 0; + eicon_isa_com *com = 0; + eicon_REQ *ReqOut = 0; + eicon_REQ *reqbuf = 0; + eicon_chan *chan; + eicon_chan_ptr *chan2; + int ReqCount; + int scom = 0; + int tmp = 0; + int quloop = 1; + + pci_card = &ccard->hwif.pci; + isa_card = &ccard->hwif.isa; + + if (!ccard) { + if (DebugVar & 1) + printk(KERN_WARNING "eicon_transmit: NULL card!\n"); + return; + } + + switch(ccard->type) { + case EICON_CTYPE_S: + case EICON_CTYPE_SX: + case EICON_CTYPE_SCOM: + case EICON_CTYPE_QUADRO: + scom = 1; + com = (eicon_isa_com *)isa_card->shmem; + break; + case EICON_CTYPE_S2M: + scom = 0; + prram = (eicon_pr_ram *)isa_card->shmem; + break; + case EICON_CTYPE_MAESTRAP: + scom = 0; + ram = (char *)pci_card->PCIram; + reg = (char *)pci_card->PCIreg; + cfg = (char *)pci_card->PCIcfg; + prram = (eicon_pr_ram *)ram; + break; + case EICON_CTYPE_MAESTRA: + scom = 0; + ram = (char *)pci_card->PCIram; + reg = (char *)pci_card->PCIreg; + cfg = (char *)pci_card->PCIcfg; + prram = 0; + break; + default: + printk(KERN_WARNING "eicon_transmit: unsupported card-type!\n"); + return; + } + + ReqCount = 0; + if (!(skb2 = skb_dequeue(&ccard->sndq))) + quloop = 0; + while(quloop) { + save_flags(flags); + cli(); + if (scom) { + if (ram_inb(ccard, &com->Req)) { + if (!ccard->ReadyInt) { + tmp = ram_inb(ccard, &com->ReadyInt) + 1; + ram_outb(ccard, &com->ReadyInt, tmp); + ccard->ReadyInt++; + } + restore_flags(flags); + skb_queue_head(&ccard->sndq, skb2); + if (DebugVar & 32) + printk(KERN_INFO "eicon: transmit: Card not ready\n"); + return; + } + } else { + if (!(ram_inb(ccard, &prram->ReqOutput) - ram_inb(ccard, &prram->ReqInput))) { + restore_flags(flags); + skb_queue_head(&ccard->sndq, skb2); + if (DebugVar & 32) + printk(KERN_INFO "eicon: transmit: Card not ready\n"); + return; + } + } + restore_flags(flags); + chan2 = (eicon_chan_ptr *)skb2->data; + chan = chan2->ptr; + if (!chan->e.busy) { + if((skb = skb_dequeue(&chan->e.X))) { + save_flags(flags); + cli(); + reqbuf = (eicon_REQ *)skb->data; + if (scom) { + ram_outw(ccard, &com->XBuffer.length, reqbuf->XBuffer.length); + ram_copytocard(ccard, &com->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length); + ram_outb(ccard, &com->ReqCh, reqbuf->ReqCh); + + } else { + /* get address of next available request buffer */ + ReqOut = (eicon_REQ *)&prram->B[ram_inw(ccard, &prram->NextReq)]; + ram_outw(ccard, &ReqOut->XBuffer.length, reqbuf->XBuffer.length); + ram_copytocard(ccard, &ReqOut->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length); + ram_outb(ccard, &ReqOut->ReqCh, reqbuf->ReqCh); + ram_outb(ccard, &ReqOut->Req, reqbuf->Req); + } + + if (reqbuf->ReqId &0x1f) { /* if this is no ASSIGN */ + + if (!reqbuf->Reference) { /* Signal Layer */ + if (scom) + ram_outb(ccard, &com->ReqId, chan->e.D3Id); + else + ram_outb(ccard, &ReqOut->ReqId, chan->e.D3Id); + + chan->e.ReqCh = 0; + } + else { /* Net Layer */ + if (scom) + ram_outb(ccard, &com->ReqId, chan->e.B2Id); + else + ram_outb(ccard, &ReqOut->ReqId, chan->e.B2Id); + + chan->e.ReqCh = 1; + if (((reqbuf->Req & 0x0f) == 0x08) || + ((reqbuf->Req & 0x0f) == 0x01)) { /* Send Data */ + chan->waitq = reqbuf->XBuffer.length; + chan->waitpq += reqbuf->XBuffer.length; + } + } + + } else { /* It is an ASSIGN */ + + if (scom) + ram_outb(ccard, &com->ReqId, reqbuf->ReqId); + else + ram_outb(ccard, &ReqOut->ReqId, reqbuf->ReqId); + + if (!reqbuf->Reference) + chan->e.ReqCh = 0; + else + chan->e.ReqCh = 1; + } + if (scom) + chan->e.ref = ccard->ref_out++; + else + chan->e.ref = ram_inw(ccard, &ReqOut->Reference); + + chan->e.Req = reqbuf->Req; + ReqCount++; + if (scom) + ram_outb(ccard, &com->Req, reqbuf->Req); + else + ram_outw(ccard, &prram->NextReq, ram_inw(ccard, &ReqOut->next)); + + chan->e.busy = 1; + restore_flags(flags); + if (DebugVar & 32) + printk(KERN_DEBUG "eicon: Req=%x Id=%x Ch=%x Len=%x Ref=%d\n", + reqbuf->Req, + ram_inb(ccard, &ReqOut->ReqId), + reqbuf->ReqCh, reqbuf->XBuffer.length, + chan->e.ref); + dev_kfree_skb(skb); + } + dev_kfree_skb(skb2); + } + else { + skb_queue_tail(&ccard->sackq, skb2); + if (DebugVar & 32) + printk(KERN_INFO "eicon: transmit: busy chan %d\n", chan->No); + } + + if (scom) + quloop = 0; + else + if (!(skb2 = skb_dequeue(&ccard->sndq))) + quloop = 0; + + } + if (!scom) + ram_outb(ccard, &prram->ReqInput, (__u8)(ram_inb(ccard, &prram->ReqInput) + ReqCount)); + + while((skb = skb_dequeue(&ccard->sackq))) { + skb_queue_tail(&ccard->sndq, skb); + } +} + + +/* + * IRQ handler + */ +void +eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { + eicon_card *ccard = (eicon_card *)dev_id; + eicon_pci_card *pci_card; + eicon_isa_card *isa_card; + char *ram = 0; + char *reg = 0; + char *cfg = 0; + eicon_pr_ram *prram = 0; + eicon_isa_com *com = 0; + eicon_RC *RcIn; + eicon_IND *IndIn; + struct sk_buff *skb; + int Count = 0; + int Rc = 0; + int Ind = 0; + unsigned char *irqprobe = 0; + int scom = 0; + int tmp = 0; + + + if (!ccard) { + printk(KERN_WARNING "eicon_irq: spurious interrupt %d\n", irq); + return; + } + + if (ccard->type == EICON_CTYPE_QUADRO) { + tmp = 4; + while(tmp) { + com = (eicon_isa_com *)ccard->hwif.isa.shmem; + if ((readb(ccard->hwif.isa.intack))) { /* quadro found */ + break; + } + ccard = ccard->qnext; + tmp--; + } + } + + pci_card = &ccard->hwif.pci; + isa_card = &ccard->hwif.isa; + + switch(ccard->type) { + case EICON_CTYPE_S: + case EICON_CTYPE_SX: + case EICON_CTYPE_SCOM: + case EICON_CTYPE_QUADRO: + scom = 1; + com = (eicon_isa_com *)isa_card->shmem; + irqprobe = &isa_card->irqprobe; + break; + case EICON_CTYPE_S2M: + scom = 0; + prram = (eicon_pr_ram *)isa_card->shmem; + irqprobe = &isa_card->irqprobe; + break; + case EICON_CTYPE_MAESTRAP: + scom = 0; + ram = (char *)pci_card->PCIram; + reg = (char *)pci_card->PCIreg; + cfg = (char *)pci_card->PCIcfg; + irqprobe = &pci_card->irqprobe; + prram = (eicon_pr_ram *)ram; + break; + case EICON_CTYPE_MAESTRA: + scom = 0; + ram = (char *)pci_card->PCIram; + reg = (char *)pci_card->PCIreg; + cfg = (char *)pci_card->PCIcfg; + irqprobe = &pci_card->irqprobe; + prram = 0; + break; + default: + printk(KERN_WARNING "eicon_irq: unsupported card-type!\n"); + return; + } + + if (*irqprobe) { + switch(ccard->type) { + case EICON_CTYPE_S: + case EICON_CTYPE_SX: + case EICON_CTYPE_SCOM: + case EICON_CTYPE_QUADRO: + if (readb(isa_card->intack)) { + writeb(0, &com->Rc); + writeb(0, isa_card->intack); + } + (*irqprobe)++; + break; + case EICON_CTYPE_S2M: + if (readb(isa_card->intack)) { + writeb(0, &prram->RcOutput); + writeb(0, isa_card->intack); + } + (*irqprobe)++; + break; + case EICON_CTYPE_MAESTRAP: + if (readb(&ram[0x3fe])) { + writeb(0, &prram->RcOutput); + writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]); + writew(0, &cfg[MP_IRQ_RESET + 2]); + writeb(0, &ram[0x3fe]); + } + *irqprobe = 0; + break; + case EICON_CTYPE_MAESTRA: + outb(0x08, pci_card->PCIreg + M_RESET); + *irqprobe = 0; + break; + } + return; + } + + switch(ccard->type) { + case EICON_CTYPE_S: + case EICON_CTYPE_SX: + case EICON_CTYPE_SCOM: + case EICON_CTYPE_QUADRO: + case EICON_CTYPE_S2M: + if (!(readb(isa_card->intack))) { /* card did not interrupt */ + if (DebugVar & 1) + printk(KERN_DEBUG "eicon: IRQ: card tells no interrupt!\n"); + return; + } + break; + case EICON_CTYPE_MAESTRAP: + if (!(readb(&ram[0x3fe]))) { /* card did not interrupt */ + if (DebugVar & 1) + printk(KERN_DEBUG "eicon: IRQ: card tells no interrupt!\n"); + return; + } + break; + case EICON_CTYPE_MAESTRA: + outw(0x3fe, pci_card->PCIreg + M_ADDR); + if (!(inb(pci_card->PCIreg + M_DATA))) { /* card did not interrupt */ + if (DebugVar & 1) + printk(KERN_DEBUG "eicon: IRQ: card tells no interrupt!\n"); + return; + } + break; + } + + if (scom) { + + /* if a return code is available ... */ + if ((tmp = ram_inb(ccard, &com->Rc))) { + eicon_RC *ack; + if (tmp == READY_INT) { + if (DebugVar & 64) + printk(KERN_INFO "eicon: IRQ Rc=READY_INT\n"); + if (ccard->ReadyInt) { + ccard->ReadyInt--; + ram_outb(ccard, &com->Rc, 0); + } + } else { + skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC); + ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC)); + ack->Rc = tmp; + ack->RcId = ram_inb(ccard, &com->RcId); + ack->RcCh = ram_inb(ccard, &com->RcCh); + ack->Reference = ccard->ref_in++; + if (DebugVar & 64) + printk(KERN_INFO "eicon: IRQ Rc=%d Id=%d Ch=%d Ref=%d\n", + tmp,ack->RcId,ack->RcCh,ack->Reference); + skb_queue_tail(&ccard->rackq, skb); + eicon_schedule_ack(ccard); + ram_outb(ccard, &com->Req, 0); + ram_outb(ccard, &com->Rc, 0); + } + + } else { + + /* if an indication is available ... */ + if ((tmp = ram_inb(ccard, &com->Ind))) { + eicon_IND *ind; + int len = ram_inw(ccard, &com->RBuffer.length); + skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC); + ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1)); + ind->Ind = tmp; + ind->IndId = ram_inb(ccard, &com->IndId); + ind->IndCh = ram_inb(ccard, &com->IndCh); + ind->MInd = ram_inb(ccard, &com->MInd); + ind->MLength = ram_inw(ccard, &com->MLength); + ind->RBuffer.length = len; + if (DebugVar & 64) + printk(KERN_INFO "eicon: IRQ Ind=%d Id=%d Ch=%d MInd=%d MLen=%d Len=%d\n", + tmp,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len); + ram_copyfromcard(ccard, &ind->RBuffer.P, &com->RBuffer.P, len); + skb_queue_tail(&ccard->rcvq, skb); + eicon_schedule_rx(ccard); + ram_outb(ccard, &com->Ind, 0); + } + } + + } else { + + /* if return codes are available ... */ + if((Count = ram_inb(ccard, &prram->RcOutput))) { + eicon_RC *ack; + /* get the buffer address of the first return code */ + RcIn = (eicon_RC *)&prram->B[ram_inw(ccard, &prram->NextRc)]; + /* for all return codes do ... */ + while(Count--) { + + if((Rc=ram_inb(ccard, &RcIn->Rc))) { + skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC); + ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC)); + ack->Rc = Rc; + ack->RcId = ram_inb(ccard, &RcIn->RcId); + ack->RcCh = ram_inb(ccard, &RcIn->RcCh); + ack->Reference = ram_inw(ccard, &RcIn->Reference); + if (DebugVar & 64) + printk(KERN_INFO "eicon: IRQ Rc=%d Id=%d Ch=%d Ref=%d\n", + Rc,ack->RcId,ack->RcCh,ack->Reference); + ram_outb(ccard, &RcIn->Rc, 0); + skb_queue_tail(&ccard->rackq, skb); + eicon_schedule_ack(ccard); + } + /* get buffer address of next return code */ + RcIn = (eicon_RC *)&prram->B[ram_inw(ccard, &RcIn->next)]; + } + /* clear all return codes (no chaining!) */ + ram_outb(ccard, &prram->RcOutput, 0); + } + + /* if indications are available ... */ + if((Count = ram_inb(ccard, &prram->IndOutput))) { + eicon_IND *ind; + /* get the buffer address of the first indication */ + IndIn = (eicon_IND *)&prram->B[ram_inw(ccard, &prram->NextInd)]; + /* for all indications do ... */ + while(Count--) { + Ind = ram_inb(ccard, &IndIn->Ind); + if(Ind) { + int len = ram_inw(ccard, &IndIn->RBuffer.length); + skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC); + ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1)); + ind->Ind = Ind; + ind->IndId = ram_inb(ccard, &IndIn->IndId); + ind->IndCh = ram_inb(ccard, &IndIn->IndCh); + ind->MInd = ram_inb(ccard, &IndIn->MInd); + ind->MLength = ram_inw(ccard, &IndIn->MLength); + ind->RBuffer.length = len; + if (DebugVar & 64) + printk(KERN_INFO "eicon: IRQ Ind=%d Id=%d Ch=%d MInd=%d MLen=%d Len=%d\n", + Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len); + ram_copyfromcard(ccard, &ind->RBuffer.P, &IndIn->RBuffer.P, len); + skb_queue_tail(&ccard->rcvq, skb); + eicon_schedule_rx(ccard); + ram_outb(ccard, &IndIn->Ind, 0); + } + /* get buffer address of next indication */ + IndIn = (eicon_IND *)&prram->B[ram_inw(ccard, &IndIn->next)]; + } + ram_outb(ccard, &prram->IndOutput, 0); + } + + } + + /* clear interrupt */ + switch(ccard->type) { + case EICON_CTYPE_QUADRO: + writeb(0, isa_card->intack); + writeb(0, &com[0x401]); + break; + case EICON_CTYPE_S: + case EICON_CTYPE_SX: + case EICON_CTYPE_SCOM: + case EICON_CTYPE_S2M: + writeb(0, isa_card->intack); + break; + case EICON_CTYPE_MAESTRAP: + writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]); + writew(0, &cfg[MP_IRQ_RESET + 2]); + writeb(0, &ram[0x3fe]); + break; + case EICON_CTYPE_MAESTRA: + outb(0x08, pci_card->PCIreg + M_RESET); + outw(0x3fe, pci_card->PCIreg + M_ADDR); + outb(0, pci_card->PCIreg + M_DATA); + break; + } + + return; +} + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon_isa.c linux.pre11.3/drivers/isdn/eicon/eicon_isa.c --- linux.vanilla/drivers/isdn/eicon/eicon_isa.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/eicon/eicon_isa.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,432 @@ +/* $Id: eicon_isa.c,v 1.5 1999/04/01 12:48:33 armin Exp $ + * + * ISDN low-level module for Eicon.Diehl active ISDN-Cards. + * Hardware-specific code for old ISA cards. + * + * Copyright 1998 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1998,99 by Armin Schindler (mac@melware.de) + * Copyright 1999 Cytronics & Melware (info@melware.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, 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. + * + * $Log: eicon_isa.c,v $ + * Revision 1.5 1999/04/01 12:48:33 armin + * Changed some log outputs. + * + * Revision 1.4 1999/03/29 11:19:46 armin + * I/O stuff now in seperate file (eicon_io.c) + * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. + * + * Revision 1.3 1999/03/02 12:37:45 armin + * Added some important checks. + * Analog Modem with DSP. + * Channels will be added to Link-Level after loading firmware. + * + * Revision 1.2 1999/01/24 20:14:19 armin + * Changed and added debug stuff. + * Better data sending. (still problems with tty's flip buffer) + * + * Revision 1.1 1999/01/01 18:09:43 armin + * First checkin of new eicon driver. + * DIVA-Server BRI/PCI and PRI/PCI are supported. + * Old diehl code is obsolete. + * + * + */ + +#include "eicon.h" +#include "eicon_isa.h" + +#define check_shmem check_region +#define release_shmem release_region +#define request_shmem request_region + +char *eicon_isa_revision = "$Revision: 1.5 $"; + +/* Mask for detecting invalid IRQ parameter */ +static int eicon_isa_valid_irq[] = { + 0x1c1c, /* 2, 3, 4, 10, 11, 12 (S)*/ + 0x1c1c, /* 2, 3, 4, 10, 11, 12 (SX) */ + 0x1cbc, /* 2, 3, 4, 5, 7, 10, 11, 12 (SCOM) */ + 0x1cbc, /* 2, 3, 4, 5, 6, 10, 11, 12 (Quadro) */ + 0x1cbc /* 2, 3, 4, 5, 7, 10, 11, 12 (S2M) */ +}; + +static void +eicon_isa_release_shmem(eicon_isa_card *card) { + if (card->mvalid) + release_shmem((unsigned long)card->shmem, card->ramsize); + card->mvalid = 0; +} + +static void +eicon_isa_release_irq(eicon_isa_card *card) { + if (!card->master) + return; + if (card->ivalid) + free_irq(card->irq, card); + card->ivalid = 0; +} + +void +eicon_isa_release(eicon_isa_card *card) { + eicon_isa_release_irq(card); + eicon_isa_release_shmem(card); +} + +void +eicon_isa_printpar(eicon_isa_card *card) { + switch (card->type) { + case EICON_CTYPE_S: + case EICON_CTYPE_SX: + case EICON_CTYPE_SCOM: + case EICON_CTYPE_QUADRO: + case EICON_CTYPE_S2M: + printk(KERN_INFO "Eicon %s at 0x%lx, irq %d\n", + eicon_ctype_name[card->type], + (unsigned long)card->shmem, + card->irq); + } +} + +int +eicon_isa_find_card(int Mem, int Irq, char * Id) +{ + int primary = 1; + + if (!strlen(Id)) + return -1; + + /* Check for valid membase address */ + if ((Mem < 0x0c0000) || + (Mem > 0x0fc000) || + (Mem & 0xfff)) { + printk(KERN_WARNING "eicon_isa: illegal membase 0x%x for %s\n", + Mem, Id); + return -1; + } + if (check_shmem(Mem, RAMSIZE)) { + printk(KERN_WARNING "eicon_isa_boot: memory at 0x%x already in use.\n", Mem); + return -1; + } + + writew(0x55aa, Mem + 0x402); + if (readw(Mem + 0x402) != 0x55aa) primary = 0; + writew(0, Mem + 0x402); + if (readw(Mem + 0x402) != 0) primary = 0; + + printk(KERN_INFO "Eicon: Driver-ID: %s\n", Id); + if (primary) { + printk(KERN_INFO "Eicon: assuming pri card at 0x%x\n", Mem); + writeb(0, Mem + 0x3ffe); + return EICON_CTYPE_ISAPRI; + } else { + printk(KERN_INFO "Eicon: assuming bri card at 0x%x\n", Mem); + writeb(0, Mem + 0x400); + return EICON_CTYPE_ISABRI; + } + return -1; +} + +int +eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) { + int tmp; + int timeout; + eicon_isa_codebuf cbuf; + unsigned char *code; + eicon_isa_boot *boot; + + if (copy_from_user(&cbuf, cb, sizeof(eicon_isa_codebuf))) + return -EFAULT; + + /* Allocate code-buffer and copy code from userspace */ + if (cbuf.bootstrap_len > 1024) { + printk(KERN_WARNING "eicon_isa_boot: Invalid startup-code size %ld\n", + cbuf.bootstrap_len); + return -EINVAL; + } + if (!(code = kmalloc(cbuf.bootstrap_len, GFP_KERNEL))) { + printk(KERN_WARNING "eicon_isa_boot: Couldn't allocate code buffer\n"); + return -ENOMEM; + } + if (copy_from_user(code, &cb->code, cbuf.bootstrap_len)) { + kfree(code); + return -EFAULT; + } + + switch(card->type) { + case EICON_CTYPE_S: + case EICON_CTYPE_SX: + case EICON_CTYPE_SCOM: + case EICON_CTYPE_QUADRO: + case EICON_CTYPE_ISABRI: + card->ramsize = RAMSIZE; + card->intack = (__u8 *)card->shmem + INTACK; + card->startcpu = (__u8 *)card->shmem + STARTCPU; + card->stopcpu = (__u8 *)card->shmem + STOPCPU; + break; + case EICON_CTYPE_S2M: + case EICON_CTYPE_ISAPRI: + card->ramsize = RAMSIZE_P; + card->intack = (__u8 *)card->shmem + INTACK_P; + card->startcpu = (__u8 *)card->shmem + STARTCPU_P; + card->stopcpu = (__u8 *)card->shmem + STOPCPU_P; + break; + default: + printk(KERN_WARNING "eicon_isa_boot: Invalid card type %d\n", card->type); + return -EINVAL; + } + + /* Register shmem */ + if (check_shmem((unsigned long)card->shmem, card->ramsize)) { + printk(KERN_WARNING "eicon_isa_boot: memory at 0x%lx already in use.\n", + (unsigned long)card->shmem); + kfree(code); + return -EBUSY; + } + request_shmem((unsigned long)card->shmem, card->ramsize, "Eicon ISA ISDN"); + card->mvalid = 1; + + /* clear any pending irq's */ + readb(card->intack); + /* set reset-line active */ + writeb(0, card->stopcpu); + /* clear irq-requests */ + writeb(0, card->intack); + readb(card->intack); + + /* Copy code into card */ + memcpy_toio(&card->shmem->c, code, cbuf.bootstrap_len); + + /* Check for properly loaded code */ + if (!check_signature((unsigned long)&card->shmem->c, code, 1020)) { + printk(KERN_WARNING "eicon_isa_boot: Could not load startup-code\n"); + eicon_isa_release_shmem(card); + kfree(code); + return -EIO; + } + /* if 16k-ramsize, duplicate the reset-jump-code */ + if (card->ramsize == RAMSIZE_P) + memcpy_toio((__u8 *)card->shmem + 0x3ff0, &code[0x3f0], 12); + + kfree(code); + boot = &card->shmem->boot; + + /* Delay 0.2 sec. */ + SLEEP(20); + + /* Start CPU */ + writeb(cbuf.boot_opt, &boot->ctrl); + writeb(0, card->startcpu); + + /* Delay 0.2 sec. */ + SLEEP(20); + + timeout = jiffies + (HZ * 22); + while (timeout > jiffies) { + if (readb(&boot->ctrl) == 0) + break; + SLEEP(10); + } + if (readb(&boot->ctrl) != 0) { + printk(KERN_WARNING "eicon_isa_boot: CPU test failed\n"); + eicon_isa_release_shmem(card); + return -EIO; + } + + /* Check for memory-test errors */ + if (readw(&boot->ebit)) { + printk(KERN_WARNING "eicon_isa_boot: memory test failed (bit 0x%04x at 0x%08x)\n", + readw(&boot->ebit), readl(&boot->eloc)); + eicon_isa_release_shmem(card); + return -EIO; + } + + /* Check card type and memory size */ + tmp = readb(&boot->card); + if ((tmp < 0) || (tmp > 4)) { + printk(KERN_WARNING "eicon_isa_boot: Type detect failed\n"); + eicon_isa_release_shmem(card); + return -EIO; + } + card->type = tmp; + ((eicon_card *)card->card)->type = tmp; + + tmp = readb(&boot->msize); + if (tmp != 8 && tmp != 16 && tmp != 24 && + tmp != 32 && tmp != 48 && tmp != 60) { + printk(KERN_WARNING "eicon_isa_boot: invalid memsize\n"); + eicon_isa_release_shmem(card); + return -EIO; + } + printk(KERN_INFO "%s: startup-code loaded\n", eicon_ctype_name[card->type]); + if ((card->type == EICON_CTYPE_QUADRO) && (card->master)) { + tmp = eicon_addcard(card->type, (unsigned long)card->shmem, card->irq, + ((eicon_card *)card->card)->regname); + printk(KERN_INFO "Eicon: %d adapters added\n", tmp); + } + return 0; +} + +int +eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) { + eicon_isa_boot *boot; + int tmp; + int timeout; + int j; + eicon_isa_codebuf cbuf; + unsigned char *code; + unsigned char *p; + + if (copy_from_user(&cbuf, cb, sizeof(eicon_isa_codebuf))) + return -EFAULT; + + if (!(code = kmalloc(cbuf.firmware_len, GFP_KERNEL))) { + printk(KERN_WARNING "eicon_isa_boot: Couldn't allocate code buffer\n"); + return -ENOMEM; + } + + if (copy_from_user(code, &cb->code, cbuf.firmware_len)) { + kfree(code); + return -EFAULT; + } + + boot = &card->shmem->boot; + + if ((!card->ivalid) && card->master) { + card->irqprobe = 1; + /* Check for valid IRQ */ + if ((card->irq < 0) || (card->irq > 15) || + (!((1 << card->irq) & eicon_isa_valid_irq[card->type & 0x0f]))) { + printk(KERN_WARNING "eicon_isa_boot: illegal irq: %d\n", card->irq); + eicon_isa_release_shmem(card); + kfree(code); + return -EINVAL; + } + /* Register irq */ + if (!request_irq(card->irq, &eicon_irq, 0, "Eicon ISA ISDN", card)) + card->ivalid = 1; + else { + printk(KERN_WARNING "eicon_isa_boot: irq %d already in use.\n", + card->irq); + eicon_isa_release_shmem(card); + kfree(code); + return -EBUSY; + } + } + + tmp = readb(&boot->msize); + if (tmp != 8 && tmp != 16 && tmp != 24 && + tmp != 32 && tmp != 48 && tmp != 60) { + printk(KERN_WARNING "eicon_isa_boot: invalid memsize\n"); + eicon_isa_release_shmem(card); + return -EIO; + } + + eicon_isa_printpar(card); + + /* Download firmware */ + printk(KERN_INFO "%s %dkB, loading firmware ...\n", + eicon_ctype_name[card->type], + tmp * 16); + tmp = cbuf.firmware_len >> 8; + p = code; + while (tmp--) { + memcpy_toio(&boot->b, p, 256); + writeb(1, &boot->ctrl); + timeout = jiffies + 10; + while (timeout > jiffies) { + if (readb(&boot->ctrl) == 0) + break; + SLEEP(2); + } + if (readb(&boot->ctrl)) { + printk(KERN_WARNING "eicon_isa_boot: download timeout at 0x%x\n", p-code); + eicon_isa_release(card); + kfree(code); + return -EIO; + } + p += 256; + } + kfree(code); + + /* Initialize firmware parameters */ + memcpy_toio(&card->shmem->c[8], &cbuf.tei, 14); + memcpy_toio(&card->shmem->c[32], &cbuf.oad, 96); + memcpy_toio(&card->shmem->c[128], &cbuf.oad, 96); + + /* Start firmware, wait for signature */ + writeb(2, &boot->ctrl); + timeout = jiffies + (5*HZ); + while (timeout > jiffies) { + if (readw(&boot->signature) == 0x4447) + break; + SLEEP(2); + } + if (readw(&boot->signature) != 0x4447) { + printk(KERN_WARNING "eicon_isa_boot: firmware selftest failed %04x\n", + readw(&boot->signature)); + eicon_isa_release(card); + return -EIO; + } + + card->channels = readb(&card->shmem->c[0x3f6]); + + /* clear irq-requests, reset irq-count */ + readb(card->intack); + writeb(0, card->intack); + + if (card->master) { + card->irqprobe = 1; + /* Trigger an interrupt and check if it is delivered */ + tmp = readb(&card->shmem->com.ReadyInt); + tmp ++; + writeb(tmp, &card->shmem->com.ReadyInt); + timeout = jiffies + 20; + while (timeout > jiffies) { + if (card->irqprobe > 1) + break; + SLEEP(2); + } + if (card->irqprobe == 1) { + printk(KERN_WARNING "eicon_isa_boot: IRQ test failed\n"); + eicon_isa_release(card); + return -EIO; + } + } + writeb(card->irq, &card->shmem->com.Int); + + /* initializing some variables */ + ((eicon_card *)card->card)->ReadyInt = 0; + ((eicon_card *)card->card)->ref_in = 1; + ((eicon_card *)card->card)->ref_out = 1; + for(j=0; j<256; j++) ((eicon_card *)card->card)->IdTable[j] = NULL; + for(j=0; j< (card->channels + 1); j++) { + ((eicon_card *)card->card)->bch[j].e.busy = 0; + ((eicon_card *)card->card)->bch[j].e.D3Id = 0; + ((eicon_card *)card->card)->bch[j].e.B2Id = 0; + ((eicon_card *)card->card)->bch[j].e.ref = 0; + ((eicon_card *)card->card)->bch[j].e.Req = 0; + ((eicon_card *)card->card)->bch[j].e.complete = 1; + ((eicon_card *)card->card)->bch[j].fsm_state = EICON_STATE_NULL; + } + + printk(KERN_INFO "Eicon: Supported channels: %d\n", card->channels); + printk(KERN_INFO "%s successfully started\n", eicon_ctype_name[card->type]); + + /* Enable normal IRQ processing */ + card->irqprobe = 0; + return 0; +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon_isa.h linux.pre11.3/drivers/isdn/eicon/eicon_isa.h --- linux.vanilla/drivers/isdn/eicon/eicon_isa.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/eicon/eicon_isa.h Mon Jul 19 23:59:33 1999 @@ -0,0 +1,144 @@ +/* $Id: eicon_isa.h,v 1.3 1999/03/29 11:19:47 armin Exp $ + * + * ISDN low-level module for Eicon.Diehl active ISDN-Cards. + * + * Copyright 1998 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1998,99 by Armin Schindler (mac@melware.de) + * Copyright 1999 Cytronics & Melware (info@melware.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, 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. + * + * $Log: eicon_isa.h,v $ + * Revision 1.3 1999/03/29 11:19:47 armin + * I/O stuff now in seperate file (eicon_io.c) + * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. + * + * Revision 1.2 1999/03/02 12:37:46 armin + * Added some important checks. + * Analog Modem with DSP. + * Channels will be added to Link-Level after loading firmware. + * + * Revision 1.1 1999/01/01 18:09:44 armin + * First checkin of new eicon driver. + * DIVA-Server BRI/PCI and PRI/PCI are supported. + * Old diehl code is obsolete. + * + * + */ + +#ifndef eicon_isa_h +#define eicon_isa_h + +#ifdef __KERNEL__ + +/* Factory defaults for ISA-Cards */ +#define EICON_ISA_MEMBASE 0xd0000 +#define EICON_ISA_IRQ 3 +/* shmem offset for Quadro parts */ +#define EICON_ISA_QOFFSET 0x0800 + +typedef struct { + __u16 length __attribute__ ((packed)); /* length of data/parameter field */ + __u8 P[270]; /* data/parameter field */ +} eicon_scom_PBUFFER; + +/* General communication buffer */ +typedef struct { + __u8 Req; /* request register */ + __u8 ReqId; /* request task/entity identification */ + __u8 Rc; /* return code register */ + __u8 RcId; /* return code task/entity identification */ + __u8 Ind; /* Indication register */ + __u8 IndId; /* Indication task/entity identification */ + __u8 IMask; /* Interrupt Mask Flag */ + __u8 RNR; /* Receiver Not Ready (set by PC) */ + __u8 XLock; /* XBuffer locked Flag */ + __u8 Int; /* ISDN interrupt */ + __u8 ReqCh; /* Channel field for layer-3 Requests */ + __u8 RcCh; /* Channel field for layer-3 Returncodes */ + __u8 IndCh; /* Channel field for layer-3 Indications */ + __u8 MInd; /* more data indication field */ + __u16 MLength; /* more data total packet length */ + __u8 ReadyInt; /* request field for ready interrupt */ + __u8 Reserved[12]; /* reserved space */ + __u8 IfType; /* 1 = 16k-Interface */ + __u16 Signature __attribute__ ((packed)); /* ISDN adapter Signature */ + eicon_scom_PBUFFER XBuffer; /* Transmit Buffer */ + eicon_scom_PBUFFER RBuffer; /* Receive Buffer */ +} eicon_isa_com; + +/* struct for downloading firmware */ +typedef struct { + __u8 ctrl; + __u8 card; + __u8 msize; + __u8 fill0; + __u16 ebit __attribute__ ((packed)); + __u32 eloc __attribute__ ((packed)); + __u8 reserved[20]; + __u16 signature __attribute__ ((packed)); + __u8 fill[224]; + __u8 b[256]; +} eicon_isa_boot; + +/* Shared memory */ +typedef union { + unsigned char c[0x400]; + eicon_isa_com com; + eicon_isa_boot boot; +} eicon_isa_shmem; + +/* + * card's description + */ +typedef struct { + int ramsize; + int irq; /* IRQ */ + void* card; + eicon_isa_shmem* shmem; /* Shared-memory area */ + unsigned char* intack; /* Int-Acknowledge */ + unsigned char* stopcpu; /* Writing here stops CPU */ + unsigned char* startcpu; /* Writing here starts CPU */ + unsigned char type; /* card type */ + int channels; /* No. of channels */ + unsigned char irqprobe; /* Flag: IRQ-probing */ + unsigned char mvalid; /* Flag: Memory is valid */ + unsigned char ivalid; /* Flag: IRQ is valid */ + unsigned char master; /* Flag: Card ist Quadro 1/4 */ + void* generic; /* Ptr to generic card struct */ +} eicon_isa_card; + +/* Offsets for special locations on standard cards */ +#define INTACK 0x03fe +#define STOPCPU 0x0400 +#define STARTCPU 0x0401 +#define RAMSIZE 0x0400 +/* Offsets for special location on PRI card */ +#define INTACK_P 0x3ffc +#define STOPCPU_P 0x3ffe +#define STARTCPU_P 0x3fff +#define RAMSIZE_P 0x4000 + + +extern int eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb); +extern int eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb); +extern void eicon_isa_release(eicon_isa_card *card); +extern void eicon_isa_printpar(eicon_isa_card *card); +extern void eicon_isa_transmit(eicon_isa_card *card); +extern int eicon_isa_find_card(int Mem, int Irq, char * Id); + +#endif /* __KERNEL__ */ + +#endif /* eicon_isa_h */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon_mod.c linux.pre11.3/drivers/isdn/eicon/eicon_mod.c --- linux.vanilla/drivers/isdn/eicon/eicon_mod.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/eicon/eicon_mod.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,1460 @@ +/* $Id: eicon_mod.c,v 1.7 1999/07/11 17:16:27 armin Exp $ + * + * ISDN lowlevel-module for Eicon.Diehl active cards. + * + * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1998,99 by Armin Schindler (mac@melware.de) + * Copyright 1999 Cytronics & Melware (info@melware.de) + * + * Thanks to Eicon Technology Diehl GmbH & Co. oHG for + * documents, informations and hardware. + * + * Deutsche Telekom AG for S2M support. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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. + * + * $Log: eicon_mod.c,v $ + * Revision 1.7 1999/07/11 17:16:27 armin + * Bugfixes in queue handling. + * Added DSP-DTMF decoder functions. + * Reorganized ack_handler. + * + * Revision 1.6 1999/06/09 19:31:26 armin + * Wrong PLX size for request_region() corrected. + * Added first MCA code from Erik Weber. + * + * Revision 1.5 1999/04/01 12:48:35 armin + * Changed some log outputs. + * + * Revision 1.4 1999/03/29 11:19:47 armin + * I/O stuff now in seperate file (eicon_io.c) + * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. + * + * Revision 1.3 1999/03/02 12:37:47 armin + * Added some important checks. + * Analog Modem with DSP. + * Channels will be added to Link-Level after loading firmware. + * + * Revision 1.2 1999/01/24 20:14:21 armin + * Changed and added debug stuff. + * Better data sending. (still problems with tty's flip buffer) + * + * Revision 1.1 1999/01/01 18:09:44 armin + * First checkin of new eicon driver. + * DIVA-Server BRI/PCI and PRI/PCI are supported. + * Old diehl code is obsolete. + * + * + */ + +#include +#include +#include +#ifdef CONFIG_MCA +#include +#endif + +#include "eicon.h" + +#define INCLUDE_INLINE_FUNCS + +static eicon_card *cards = (eicon_card *) NULL; /* glob. var , contains + start of card-list */ + +static char *eicon_revision = "$Revision: 1.7 $"; + +extern char *eicon_pci_revision; +extern char *eicon_isa_revision; +extern char *eicon_idi_revision; + +#ifdef MODULE +#define MOD_USE_COUNT (GET_USE_COUNT (&__this_module)) +#endif + +#define EICON_CTRL_VERSION 1 + +ulong DebugVar; + +/* Parameters to be set by insmod */ +static int membase = -1; +static int irq = -1; +static char *id = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + +MODULE_DESCRIPTION( "Driver for Eicon.Diehl active ISDN cards"); +MODULE_AUTHOR( "Armin Schindler"); +MODULE_SUPPORTED_DEVICE( "ISDN subsystem"); +MODULE_PARM_DESC(membase, "Base address of first ISA card"); +MODULE_PARM_DESC(irq, "IRQ of first card"); +MODULE_PARM_DESC(id, "ID-String of first card"); +MODULE_PARM(membase, "i"); +MODULE_PARM(irq, "i"); +MODULE_PARM(id, "s"); + +char *eicon_ctype_name[] = { + "ISDN-S", + "ISDN-SX", + "ISDN-SCOM", + "ISDN-QUADRO", + "ISDN-S2M", + "DIVA Server BRI/PCI", + "DIVA Server 4BRI/PCI", + "DIVA Server 4BRI/PCI", + "DIVA Server PRI/PCI" +}; + +static int +getrel(char *p) +{ + int v = 0; + char *tmp = 0; + + if ((tmp = strchr(p, '.'))) + p = tmp + 1; + while (p[0] >= '0' && p[0] <= '9') { + v = ((v < 0) ? 0 : (v * 10)) + (int) (p[0] - '0'); + p++; + } + return v; + + +} + +static char * +eicon_getrev(const char *revision) +{ + char *rev; + char *p; + if ((p = strchr(revision, ':'))) { + rev = p + 2; + p = strchr(rev, '$'); + *--p = 0; + } else rev = "?.??"; + return rev; + +} + +static eicon_chan * +find_channel(eicon_card *card, int channel) +{ + if ((channel >= 0) && (channel < card->nchannels)) + return &(card->bch[channel]); + if (DebugVar & 1) + printk(KERN_WARNING "eicon: Invalid channel %d\n", channel); + return NULL; +} + +/* + * Free MSN list + */ +static void +eicon_clear_msn(eicon_card *card) +{ + struct msn_entry *p = card->msn_list; + struct msn_entry *q; + unsigned long flags; + + save_flags(flags); + cli(); + card->msn_list = NULL; + restore_flags(flags); + while (p) { + q = p->next; + kfree(p); + p = q; + } +} + +/* + * Find an MSN entry in the list. + * If ia5 != 0, return IA5-encoded EAZ, else + * return a bitmask with corresponding bit set. + */ +static __u16 +eicon_find_msn(eicon_card *card, char *msn, int ia5) +{ + struct msn_entry *p = card->msn_list; + __u8 eaz = '0'; + + while (p) { + if (!strcmp(p->msn, msn)) { + eaz = p->eaz; + break; + } + p = p->next; + } + if (!ia5) + return (1 << (eaz - '0')); + else + return eaz; +} + +/* + * Find an EAZ entry in the list. + * return a string with corresponding msn. + */ +char * +eicon_find_eaz(eicon_card *card, char eaz) +{ + struct msn_entry *p = card->msn_list; + + while (p) { + if (p->eaz == eaz) + return(p->msn); + p = p->next; + } + return("\0"); +} + +#if 0 +/* + * Add or delete an MSN to the MSN list + * + * First character of msneaz is EAZ, rest is MSN. + * If length of eazmsn is 1, delete that entry. + */ +static int +eicon_set_msn(eicon_card *card, char *eazmsn) +{ + struct msn_entry *p = card->msn_list; + struct msn_entry *q = NULL; + unsigned long flags; + int i; + + if (!strlen(eazmsn)) + return 0; + if (strlen(eazmsn) > 16) + return -EINVAL; + for (i = 0; i < strlen(eazmsn); i++) + if (!isdigit(eazmsn[i])) + return -EINVAL; + if (strlen(eazmsn) == 1) { + /* Delete a single MSN */ + while (p) { + if (p->eaz == eazmsn[0]) { + save_flags(flags); + cli(); + if (q) + q->next = p->next; + else + card->msn_list = p->next; + restore_flags(flags); + kfree(p); + if (DebugVar & 8) + printk(KERN_DEBUG + "Mapping for EAZ %c deleted\n", + eazmsn[0]); + return 0; + } + q = p; + p = p->next; + } + return 0; + } + /* Add a single MSN */ + while (p) { + /* Found in list, replace MSN */ + if (p->eaz == eazmsn[0]) { + save_flags(flags); + cli(); + strcpy(p->msn, &eazmsn[1]); + restore_flags(flags); + if (DebugVar & 8) + printk(KERN_DEBUG + "Mapping for EAZ %c changed to %s\n", + eazmsn[0], + &eazmsn[1]); + return 0; + } + p = p->next; + } + /* Not found in list, add new entry */ + p = kmalloc(sizeof(msn_entry), GFP_KERNEL); + if (!p) + return -ENOMEM; + p->eaz = eazmsn[0]; + strcpy(p->msn, &eazmsn[1]); + p->next = card->msn_list; + save_flags(flags); + cli(); + card->msn_list = p; + restore_flags(flags); + if (DebugVar & 8) + printk(KERN_DEBUG + "Mapping %c -> %s added\n", + eazmsn[0], + &eazmsn[1]); + return 0; +} +#endif + +static void +eicon_rcv_dispatch(struct eicon_card *card) +{ + switch (card->bus) { + case EICON_BUS_ISA: + case EICON_BUS_MCA: + case EICON_BUS_PCI: + eicon_io_rcv_dispatch(card); + break; + default: + if (DebugVar & 1) + printk(KERN_WARNING + "eicon_ack_dispatch: Illegal bustype %d\n", card->bus); + } +} + +static void +eicon_ack_dispatch(struct eicon_card *card) +{ + switch (card->bus) { + case EICON_BUS_ISA: + case EICON_BUS_MCA: + case EICON_BUS_PCI: + eicon_io_ack_dispatch(card); + break; + default: + if (DebugVar & 1) + printk(KERN_WARNING + "eicon_ack_dispatch: Illegal bustype %d\n", card->bus); + } +} + +static void +eicon_transmit(struct eicon_card *card) +{ + switch (card->bus) { + case EICON_BUS_ISA: + case EICON_BUS_MCA: + case EICON_BUS_PCI: + eicon_io_transmit(card); + break; + default: + if (DebugVar & 1) + printk(KERN_WARNING + "eicon_transmit: Illegal bustype %d\n", card->bus); + } +} + +static int +eicon_command(eicon_card * card, isdn_ctrl * c) +{ + ulong a; + eicon_chan *chan; + eicon_cdef cdef; + isdn_ctrl cmd; + char tmp[17]; + int ret = 0; + unsigned long flags; + + switch (c->command) { + case ISDN_CMD_IOCTL: + memcpy(&a, c->parm.num, sizeof(ulong)); + switch (c->arg) { + case EICON_IOCTL_GETVER: + return(EICON_CTRL_VERSION); + case EICON_IOCTL_GETTYPE: + return(card->type); + case EICON_IOCTL_GETMMIO: + switch (card->bus) { + case EICON_BUS_ISA: + case EICON_BUS_MCA: + return (int)card->hwif.isa.shmem; +#if CONFIG_PCI + case EICON_BUS_PCI: + return card->hwif.pci.PCIram; +#endif + default: + if (DebugVar & 1) + printk(KERN_WARNING + "eicon: Illegal BUS type %d\n", + card->bus); + ret = -ENODEV; + } + case EICON_IOCTL_SETMMIO: + if (card->flags & EICON_FLAGS_LOADED) + return -EBUSY; + switch (card->bus) { + case EICON_BUS_ISA: + case EICON_BUS_MCA: + if (eicon_isa_find_card(a, + card->hwif.isa.irq, + card->regname) < 0) + return -EFAULT; + card->hwif.isa.shmem = (eicon_isa_shmem *)a; + return 0; + default: + if (DebugVar & 1) + printk(KERN_WARNING + "eicon: Illegal BUS type %d\n", + card->bus); + ret = -ENODEV; + } + case EICON_IOCTL_GETIRQ: + switch (card->bus) { + case EICON_BUS_ISA: + case EICON_BUS_MCA: + return card->hwif.isa.irq; +#if CONFIG_PCI + case EICON_BUS_PCI: + return card->hwif.pci.irq; +#endif + default: + if (DebugVar & 1) + printk(KERN_WARNING + "eicon: Illegal BUS type %d\n", + card->bus); + ret = -ENODEV; + } + case EICON_IOCTL_SETIRQ: + if (card->flags & EICON_FLAGS_LOADED) + return -EBUSY; + if ((a < 2) || (a > 15)) + return -EFAULT; + switch (card->bus) { + case EICON_BUS_ISA: + case EICON_BUS_MCA: + card->hwif.isa.irq = a; + return 0; + default: + if (DebugVar & 1) + printk(KERN_WARNING + "eicon: Illegal BUS type %d\n", + card->bus); + ret = -ENODEV; + } + case EICON_IOCTL_LOADBOOT: + if (card->flags & EICON_FLAGS_RUNNING) + return -EBUSY; + switch (card->bus) { + case EICON_BUS_ISA: + case EICON_BUS_MCA: + ret = eicon_isa_bootload( + &(card->hwif.isa), + &(((eicon_codebuf *)a)->isa)); + break; + default: + if (DebugVar & 1) + printk(KERN_WARNING + "eicon: Illegal BUS type %d\n", + card->bus); + ret = -ENODEV; + } + return ret; + case EICON_IOCTL_LOADISA: + if (card->flags & EICON_FLAGS_RUNNING) + return -EBUSY; + switch (card->bus) { + case EICON_BUS_ISA: + case EICON_BUS_MCA: + ret = eicon_isa_load( + &(card->hwif.isa), + &(((eicon_codebuf *)a)->isa)); + if (!ret) { + card->flags |= EICON_FLAGS_LOADED; + card->flags |= EICON_FLAGS_RUNNING; + if (card->hwif.isa.channels > 1) { + cmd.command = ISDN_STAT_ADDCH; + cmd.driver = card->myid; + cmd.arg = card->hwif.isa.channels - 1; + card->interface.statcallb(&cmd); + } + cmd.command = ISDN_STAT_RUN; + cmd.driver = card->myid; + cmd.arg = 0; + card->interface.statcallb(&cmd); + } + break; + default: + if (DebugVar & 1) + printk(KERN_WARNING + "eicon: Illegal BUS type %d\n", + card->bus); + ret = -ENODEV; + } + return ret; + + case EICON_IOCTL_MANIF: + if (!card->flags & EICON_FLAGS_RUNNING) + return -ENODEV; + if (!card->Feature & PROTCAP_MANIF) + return -ENODEV; + ret = eicon_idi_manage( + card, + (eicon_manifbuf *)a); + return ret; +#if CONFIG_PCI + case EICON_IOCTL_LOADPCI: + if (card->flags & EICON_FLAGS_RUNNING) + return -EBUSY; + if (card->bus == EICON_BUS_PCI) { + switch(card->type) { + case EICON_CTYPE_MAESTRA: + ret = eicon_pci_load_bri( + &(card->hwif.pci), + &(((eicon_codebuf *)a)->pci)); + break; + + case EICON_CTYPE_MAESTRAP: + ret = eicon_pci_load_pri( + &(card->hwif.pci), + &(((eicon_codebuf *)a)->pci)); + break; + } + if (!ret) { + card->flags |= EICON_FLAGS_LOADED; + card->flags |= EICON_FLAGS_RUNNING; + if (card->hwif.pci.channels > 1) { + cmd.command = ISDN_STAT_ADDCH; + cmd.driver = card->myid; + cmd.arg = card->hwif.pci.channels - 1; + card->interface.statcallb(&cmd); + } + cmd.command = ISDN_STAT_RUN; + cmd.driver = card->myid; + cmd.arg = 0; + card->interface.statcallb(&cmd); + } + return ret; + } else return -ENODEV; +#endif +#if 0 + case EICON_IOCTL_SETMSN: + if ((ret = copy_from_user(tmp, (char *)a, sizeof(tmp)))) + return -EFAULT; + if ((ret = eicon_set_msn(card, tmp))) + return ret; +#if 0 + if (card->flags & EICON_FLAGS_RUNNING) + return(eicon_capi_manufacturer_req_msn(card)); +#endif + return 0; +#endif + case EICON_IOCTL_ADDCARD: + if ((ret = copy_from_user(&cdef, (char *)a, sizeof(cdef)))) + return -EFAULT; + if (!(eicon_addcard(0, cdef.membase, cdef.irq, cdef.id))) + return -EIO; + return 0; + case EICON_IOCTL_DEBUGVAR: + DebugVar = a; + printk(KERN_DEBUG"Eicon: Debug Value set to %ld\n", DebugVar); + return 0; +#ifdef MODULE + case EICON_IOCTL_FREEIT: + while (MOD_USE_COUNT > 0) MOD_DEC_USE_COUNT; + MOD_INC_USE_COUNT; + return 0; +#endif + default: + return -EINVAL; + } + break; + case ISDN_CMD_DIAL: + if (!card->flags & EICON_FLAGS_RUNNING) + return -ENODEV; + if (!(chan = find_channel(card, c->arg & 0x1f))) + break; + save_flags(flags); + cli(); + if ((chan->fsm_state != EICON_STATE_NULL) && (chan->fsm_state != EICON_STATE_LISTEN)) { + restore_flags(flags); + if (DebugVar & 1) + printk(KERN_WARNING "Dial on channel %d with state %d\n", + chan->No, chan->fsm_state); + return -EBUSY; + } + if (card->ptype == ISDN_PTYPE_EURO) + tmp[0] = eicon_find_msn(card, c->parm.setup.eazmsn, 1); + else + tmp[0] = c->parm.setup.eazmsn[0]; + chan->fsm_state = EICON_STATE_OCALL; + chan->callref = 0xffff; + restore_flags(flags); + + ret = idi_connect_req(card, chan, c->parm.setup.phone, + c->parm.setup.eazmsn, + c->parm.setup.si1, + c->parm.setup.si2); + if (ret) { + cmd.driver = card->myid; + cmd.command = ISDN_STAT_DHUP; + cmd.arg &= 0x1f; + card->interface.statcallb(&cmd); + } + return ret; + case ISDN_CMD_ACCEPTD: + if (!card->flags & EICON_FLAGS_RUNNING) + return -ENODEV; + if (!(chan = find_channel(card, c->arg & 0x1f))) + break; + if (chan->fsm_state == EICON_STATE_ICALL) { + idi_connect_res(card, chan); + } + return 0; + case ISDN_CMD_ACCEPTB: + if (!card->flags & EICON_FLAGS_RUNNING) + return -ENODEV; + return 0; + case ISDN_CMD_HANGUP: + if (!card->flags & EICON_FLAGS_RUNNING) + return -ENODEV; + if (!(chan = find_channel(card, c->arg & 0x1f))) + break; + idi_hangup(card, chan); + return 0; + case ISDN_CMD_SETEAZ: + if (!card->flags & EICON_FLAGS_RUNNING) + return -ENODEV; + if (!(chan = find_channel(card, c->arg & 0x1f))) + break; + if (strlen(c->parm.num)) { + if (card->ptype == ISDN_PTYPE_EURO) { + chan->eazmask = eicon_find_msn(card, c->parm.num, 0); + } + if (card->ptype == ISDN_PTYPE_1TR6) { + int i; + chan->eazmask = 0; + for (i = 0; i < strlen(c->parm.num); i++) + if (isdigit(c->parm.num[i])) + chan->eazmask |= (1 << (c->parm.num[i] - '0')); + } + } else + chan->eazmask = 0x3ff; + eicon_idi_listen_req(card, chan); + return 0; + case ISDN_CMD_CLREAZ: + if (!card->flags & EICON_FLAGS_RUNNING) + return -ENODEV; + if (!(chan = find_channel(card, c->arg & 0x1f))) + break; + chan->eazmask = 0; + eicon_idi_listen_req(card, chan); + return 0; + case ISDN_CMD_SETL2: + if (!card->flags & EICON_FLAGS_RUNNING) + return -ENODEV; + if (!(chan = find_channel(card, c->arg & 0x1f))) + break; + chan->l2prot = (c->arg >> 8); + return 0; + case ISDN_CMD_GETL2: + if (!card->flags & EICON_FLAGS_RUNNING) + return -ENODEV; + if (!(chan = find_channel(card, c->arg & 0x1f))) + break; + return chan->l2prot; + case ISDN_CMD_SETL3: + if (!card->flags & EICON_FLAGS_RUNNING) + return -ENODEV; + if (!(chan = find_channel(card, c->arg & 0x1f))) + break; + chan->l3prot = (c->arg >> 8); + return 0; + case ISDN_CMD_GETL3: + if (!card->flags & EICON_FLAGS_RUNNING) + return -ENODEV; + if (!(chan = find_channel(card, c->arg & 0x1f))) + break; + return chan->l3prot; + case ISDN_CMD_GETEAZ: + if (!card->flags & EICON_FLAGS_RUNNING) + return -ENODEV; + if (DebugVar & 1) + printk(KERN_DEBUG "eicon CMD_GETEAZ not implemented\n"); + return 0; + case ISDN_CMD_SETSIL: + if (!card->flags & EICON_FLAGS_RUNNING) + return -ENODEV; + if (DebugVar & 1) + printk(KERN_DEBUG "eicon CMD_SETSIL not implemented\n"); + return 0; + case ISDN_CMD_GETSIL: + if (!card->flags & EICON_FLAGS_RUNNING) + return -ENODEV; + if (DebugVar & 1) + printk(KERN_DEBUG "eicon CMD_GETSIL not implemented\n"); + return 0; + case ISDN_CMD_LOCK: + MOD_INC_USE_COUNT; + return 0; + case ISDN_CMD_UNLOCK: + MOD_DEC_USE_COUNT; + return 0; + case ISDN_CMD_AUDIO: + if (!card->flags & EICON_FLAGS_RUNNING) + return -ENODEV; + if (!(chan = find_channel(card, c->arg & 0x1f))) + break; + idi_audio_cmd(card, chan, c->arg >> 8, c->parm.num); + return 0; + } + + return -EINVAL; +} + +/* + * Find card with given driverId + */ +static inline eicon_card * +eicon_findcard(int driverid) +{ + eicon_card *p = cards; + + while (p) { + if (p->myid == driverid) + return p; + p = p->next; + } + return (eicon_card *) 0; +} + +/* + * Wrapper functions for interface to linklevel + */ +static int +if_command(isdn_ctrl * c) +{ + eicon_card *card = eicon_findcard(c->driver); + + if (card) + return (eicon_command(card, c)); + printk(KERN_ERR + "eicon: if_command %d called with invalid driverId %d!\n", + c->command, c->driver); + return -ENODEV; +} + +static int +if_writecmd(const u_char * buf, int len, int user, int id, int channel) +{ + eicon_card *card = eicon_findcard(id); + + if (card) { + if (!card->flags & EICON_FLAGS_RUNNING) + return -ENODEV; + return (len); + } + printk(KERN_ERR + "eicon: if_writecmd called with invalid driverId!\n"); + return -ENODEV; +} + +static int +if_readstatus(u_char * buf, int len, int user, int id, int channel) +{ +#if 0 + /* Not yet used */ + eicon_card *card = eicon_findcard(id); + + if (card) { + if (!card->flags & EICON_FLAGS_RUNNING) + return -ENODEV; + return (eicon_readstatus(buf, len, user, card)); + } + printk(KERN_ERR + "eicon: if_readstatus called with invalid driverId!\n"); +#endif + return -ENODEV; +} + +static int +if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) +{ + eicon_card *card = eicon_findcard(id); + eicon_chan *chan; + int ret = 0; + int len; + + len = skb->len; + + if (card) { + if (!card->flags & EICON_FLAGS_RUNNING) { + dev_kfree_skb(skb); + return -ENODEV; + } + if (!(chan = find_channel(card, channel))) { + dev_kfree_skb(skb); + return -ENODEV; + } + if (chan->fsm_state == EICON_STATE_ACTIVE) { + ret = idi_send_data(card, chan, ack, skb, 1); + return (ret); + } else { + dev_kfree_skb(skb); + return -ENODEV; + } + } + printk(KERN_ERR + "eicon: if_sendbuf called with invalid driverId!\n"); + dev_kfree_skb(skb); + return -ENODEV; +} + + +/* + * Allocate a new card-struct, initialize it + * link it into cards-list. + */ +static void +eicon_alloccard(int Type, int membase, int irq, char *id) +{ + int i; + int j; + int qloop; + char qid[5]; + eicon_card *card; +#if CONFIG_PCI + eicon_pci_card *pcic; +#endif + + qloop = (Type == EICON_CTYPE_QUADRO)?2:0; + for (i = 0; i <= qloop; i++) { + if (!(card = (eicon_card *) kmalloc(sizeof(eicon_card), GFP_KERNEL))) { + printk(KERN_WARNING + "eicon: (%s) Could not allocate card-struct.\n", id); + return; + } + memset((char *) card, 0, sizeof(eicon_card)); + skb_queue_head_init(&card->sndq); + skb_queue_head_init(&card->rcvq); + skb_queue_head_init(&card->rackq); + skb_queue_head_init(&card->sackq); + card->snd_tq.routine = (void *) (void *) eicon_transmit; + card->snd_tq.data = card; + card->rcv_tq.routine = (void *) (void *) eicon_rcv_dispatch; + card->rcv_tq.data = card; + card->ack_tq.routine = (void *) (void *) eicon_ack_dispatch; + card->ack_tq.data = card; + card->interface.maxbufsize = 4000; + card->interface.command = if_command; + card->interface.writebuf_skb = if_sendbuf; + card->interface.writecmd = if_writecmd; + card->interface.readstat = if_readstatus; + card->interface.features = + ISDN_FEATURE_L2_X75I | + ISDN_FEATURE_L2_HDLC | + ISDN_FEATURE_L2_TRANS | + ISDN_FEATURE_L3_TRANS | + ISDN_FEATURE_P_UNKNOWN; + card->interface.hl_hdrlen = 20; + card->ptype = ISDN_PTYPE_UNKNOWN; + strncpy(card->interface.id, id, sizeof(card->interface.id) - 1); + card->myid = -1; + card->type = Type; + switch (Type) { +#if CONFIG_MCA /* only needed for MCA */ + case EICON_CTYPE_S: + case EICON_CTYPE_SX: + case EICON_CTYPE_SCOM: + if (membase == -1) + membase = EICON_ISA_MEMBASE; + if (irq == -1) + irq = EICON_ISA_IRQ; + card->bus = EICON_BUS_MCA; + card->hwif.isa.card = (void *)card; + card->hwif.isa.shmem = (eicon_isa_shmem *)membase; + card->hwif.isa.master = 1; + + card->hwif.isa.irq = irq; + card->hwif.isa.type = Type; + card->nchannels = 2; + card->interface.channels = 1; + break; +#endif /* CONFIG_MCA */ + case EICON_CTYPE_QUADRO: + if (membase == -1) + membase = EICON_ISA_MEMBASE; + if (irq == -1) + irq = EICON_ISA_IRQ; + card->bus = EICON_BUS_ISA; + card->hwif.isa.card = (void *)card; + card->hwif.isa.shmem = (eicon_isa_shmem *)(membase + (i+1) * EICON_ISA_QOFFSET); + card->hwif.isa.master = 0; + strcpy(card->interface.id, id); + if (id[strlen(id) - 1] == 'a') { + card->interface.id[strlen(id) - 1] = 'a' + i + 1; + } else { + sprintf(qid, "_%c",'2' + i); + strcat(card->interface.id, qid); + } + printk(KERN_INFO "Eicon: Quadro: Driver-Id %s added.\n", + card->interface.id); + if (i == 0) { + eicon_card *p = cards; + while(p) { + if ((p->hwif.isa.master) && (p->hwif.isa.irq == irq)) { + p->qnext = card; + break; + } + p = p->next; + } + if (!p) { + printk(KERN_WARNING "eicon_alloccard: Quadro Master not found.\n"); + kfree(card); + return; + } + } else { + cards->qnext = card; + } + card->hwif.isa.irq = irq; + card->hwif.isa.type = Type; + card->nchannels = 2; + card->interface.channels = 1; + break; +#if CONFIG_PCI + case EICON_CTYPE_MAESTRA: + (eicon_pci_card *)pcic = (eicon_pci_card *)membase; + card->bus = EICON_BUS_PCI; + card->interface.features |= + ISDN_FEATURE_L2_V11096 | + ISDN_FEATURE_L2_V11019 | + ISDN_FEATURE_L2_V11038 | + ISDN_FEATURE_L2_MODEM | + ISDN_FEATURE_L2_FAX | + ISDN_FEATURE_L3_TRANSDSP | + ISDN_FEATURE_L3_FAX; + card->hwif.pci.card = (void *)card; + card->hwif.pci.PCIreg = pcic->PCIreg; + card->hwif.pci.PCIcfg = pcic->PCIcfg; + card->hwif.pci.master = 1; + card->hwif.pci.mvalid = pcic->mvalid; + card->hwif.pci.ivalid = 0; + card->hwif.pci.irq = irq; + card->hwif.pci.type = Type; + card->flags = 0; + card->nchannels = 2; + card->interface.channels = 1; + break; + + case EICON_CTYPE_MAESTRAP: + (eicon_pci_card *)pcic = (eicon_pci_card *)membase; + card->bus = EICON_BUS_PCI; + card->interface.features |= + ISDN_FEATURE_L2_V11096 | + ISDN_FEATURE_L2_V11019 | + ISDN_FEATURE_L2_V11038 | + ISDN_FEATURE_L2_MODEM | + ISDN_FEATURE_L2_FAX | + ISDN_FEATURE_L3_TRANSDSP | + ISDN_FEATURE_L3_FAX; + card->hwif.pci.card = (void *)card; + card->hwif.pci.shmem = (eicon_pci_shmem *)pcic->shmem; + card->hwif.pci.PCIreg = pcic->PCIreg; + card->hwif.pci.PCIram = pcic->PCIram; + card->hwif.pci.PCIcfg = pcic->PCIcfg; + card->hwif.pci.master = 1; + card->hwif.pci.mvalid = pcic->mvalid; + card->hwif.pci.ivalid = 0; + card->hwif.pci.irq = irq; + card->hwif.pci.type = Type; + card->flags = 0; + card->nchannels = 30; + card->interface.channels = 1; + break; +#endif + case EICON_CTYPE_ISABRI: + if (membase == -1) + membase = EICON_ISA_MEMBASE; + if (irq == -1) + irq = EICON_ISA_IRQ; + card->bus = EICON_BUS_ISA; + card->hwif.isa.card = (void *)card; + card->hwif.isa.shmem = (eicon_isa_shmem *)membase; + card->hwif.isa.master = 1; + card->hwif.isa.irq = irq; + card->hwif.isa.type = Type; + card->nchannels = 2; + card->interface.channels = 1; + break; + case EICON_CTYPE_ISAPRI: + if (membase == -1) + membase = EICON_ISA_MEMBASE; + if (irq == -1) + irq = EICON_ISA_IRQ; + card->bus = EICON_BUS_ISA; + card->hwif.isa.card = (void *)card; + card->hwif.isa.shmem = (eicon_isa_shmem *)membase; + card->hwif.isa.master = 1; + card->hwif.isa.irq = irq; + card->hwif.isa.type = Type; + card->nchannels = 30; + card->interface.channels = 1; + break; + default: + printk(KERN_WARNING "eicon_alloccard: Invalid type %d\n", Type); + kfree(card); + return; + } + if (!(card->bch = (eicon_chan *) kmalloc(sizeof(eicon_chan) * (card->nchannels + 1) + , GFP_KERNEL))) { + printk(KERN_WARNING + "eicon: (%s) Could not allocate bch-struct.\n", id); + kfree(card); + return; + } + for (j=0; j< (card->nchannels + 1); j++) { + memset((char *)&card->bch[j], 0, sizeof(eicon_chan)); + card->bch[j].plci = 0x8000; + card->bch[j].ncci = 0x8000; + card->bch[j].l2prot = ISDN_PROTO_L2_X75I; + card->bch[j].l3prot = ISDN_PROTO_L3_TRANS; + card->bch[j].e.D3Id = 0; + card->bch[j].e.B2Id = 0; + card->bch[j].e.Req = 0; + card->bch[j].No = j; + skb_queue_head_init(&card->bch[j].e.X); + skb_queue_head_init(&card->bch[j].e.R); + } + card->next = cards; + cards = card; + } +} + +/* + * register card at linklevel + */ +static int +eicon_registercard(eicon_card * card) +{ + switch (card->bus) { + case EICON_BUS_ISA: + /* TODO something to print */ + break; +#ifdef CONFIG_MCA + case EICON_BUS_MCA: + eicon_isa_printpar(&card->hwif.isa); + break; +#endif + case EICON_BUS_PCI: +#if CONFIG_PCI + eicon_pci_printpar(&card->hwif.pci); + break; +#endif + default: + if (DebugVar & 1) + printk(KERN_WARNING + "eicon_registercard: Illegal BUS type %d\n", + card->bus); + return -1; + } + if (!register_isdn(&card->interface)) { + printk(KERN_WARNING + "eicon_registercard: Unable to register %s\n", + card->interface.id); + return -1; + } + card->myid = card->interface.channels; + sprintf(card->regname, "%s", card->interface.id); + return 0; +} + +#ifdef MODULE +static void +unregister_card(eicon_card * card) +{ + isdn_ctrl cmd; + + cmd.command = ISDN_STAT_UNLOAD; + cmd.driver = card->myid; + card->interface.statcallb(&cmd); + switch (card->bus) { + case EICON_BUS_ISA: +#ifdef CONFIG_MCA + case EICON_BUS_MCA: +#endif + eicon_isa_release(&card->hwif.isa); + break; + case EICON_BUS_PCI: +#if CONFIG_PCI + eicon_pci_release(&card->hwif.pci); + break; +#endif + default: + if (DebugVar & 1) + printk(KERN_WARNING + "eicon: Invalid BUS type %d\n", + card->bus); + break; + } +} +#endif /* MODULE */ + +static void +eicon_freecard(eicon_card *card) { + eicon_clear_msn(card); + kfree(card->bch); + kfree(card); +} + +int +eicon_addcard(int Type, int membase, int irq, char *id) +{ + eicon_card *p; + eicon_card *q = NULL; + int registered; + int added = 0; + int failed = 0; + + if (!Type) /* ISA */ + if ((Type = eicon_isa_find_card(membase, irq, id)) < 0) + return 0; + eicon_alloccard(Type, membase, irq, id); + p = cards; + while (p) { + registered = 0; + if (!p->interface.statcallb) { + /* Not yet registered. + * Try to register and activate it. + */ + added++; + switch (p->bus) { + case EICON_BUS_ISA: + case EICON_BUS_MCA: + if (eicon_registercard(p)) + break; + registered = 1; + break; + case EICON_BUS_PCI: +#if CONFIG_PCI + if (eicon_registercard(p)) + break; + registered = 1; + break; +#endif + default: + if (DebugVar & 1) + printk(KERN_WARNING + "eicon: addcard: Invalid BUS type %d\n", + p->bus); + } + } else + /* Card already registered */ + registered = 1; + if (registered) { + /* Init OK, next card ... */ + q = p; + p = p->next; + } else { + /* registering failed, remove card from list, free memory */ + printk(KERN_WARNING + "eicon: Initialization of %s failed\n", + p->interface.id); + if (q) { + q->next = p->next; + eicon_freecard(p); + p = q->next; + } else { + cards = p->next; + eicon_freecard(p); + p = cards; + } + failed++; + } + } + return (added - failed); +} + +#define DRIVERNAME "Eicon active ISDN driver" +#define DRIVERRELEASE "1" + +#ifdef MODULE +#define eicon_init init_module +#endif + +__initfunc(int +eicon_init(void)) +{ + int card_count = 0; + int release = 0; + char tmprev[50]; + + DebugVar = 1; + + printk(KERN_INFO "%s Rev: ", DRIVERNAME); + strcpy(tmprev, eicon_revision); + printk("%s/", eicon_getrev(tmprev)); + release += getrel(tmprev); + strcpy(tmprev, eicon_pci_revision); + printk("%s/", eicon_getrev(tmprev)); + release += getrel(tmprev); + strcpy(tmprev, eicon_isa_revision); + printk("%s/", eicon_getrev(tmprev)); + release += getrel(tmprev); + strcpy(tmprev, eicon_idi_revision); + printk("%s\n", eicon_getrev(tmprev)); + release += getrel(tmprev); + sprintf(tmprev,"%d", release); + printk(KERN_INFO "%s Release: %s.%s\n", DRIVERNAME, + DRIVERRELEASE, tmprev); + +#ifdef CONFIG_MCA + /* Check if we have MCA-bus */ + if (!MCA_bus) + { + printk(KERN_INFO + "eicon: No MCA bus, ISDN-interfaces not probed.\n"); + } else { + if (DebugVar & 8) + printk(KERN_DEBUG + "eicon_mca_find_card, irq=%d.\n", + irq); + if (!eicon_mca_find_card(0, membase, irq, id)) + card_count++; + }; +#else + card_count = eicon_addcard(0, membase, irq, id); +#endif /* CONFIG_MCA */ + +#if CONFIG_PCI + card_count += eicon_pci_find_card(id); +#endif + if (!cards) { +#ifdef MODULE + printk(KERN_INFO "Eicon: No cards defined, driver not loaded !\n"); +#endif + return -ENODEV; + + } else + printk(KERN_INFO "Eicon: %d card%s added\n", card_count, + (card_count>1)?"s":""); + /* No symbols to export, hide all symbols */ + EXPORT_NO_SYMBOLS; + return 0; +} + +#ifdef MODULE +void +cleanup_module(void) +{ + eicon_card *card = cards; + eicon_card *last; + while (card) { +#ifdef CONFIG_MCA + if (MCA_bus) + { + mca_mark_as_unused (card->mca_slot); + mca_set_adapter_procfn(card->mca_slot, NULL, NULL); + }; +#endif + unregister_card(card); + card = card->next; + } + card = cards; + while (card) { + last = card; + card = card->next; + eicon_freecard(last); + } + printk(KERN_INFO "%s unloaded\n", DRIVERNAME); +} + +#else /* no module */ +__initfunc(void +eicon_setup(char *str, int *ints)) +{ + int i, argc; + + argc = ints[0]; + i = 1; + if (argc) { + membase = irq = -1; + if (argc) { + membase = ints[i]; + i++; + argc--; + } + if (argc) { + irq = ints[i]; + i++; + argc--; + } + if (strlen(str)) { + strcpy(id, str); + } else { + strcpy(id, "eicon"); + } + /* eicon_addcard(0, membase, irq, id); */ + printk(KERN_INFO "eicon: membase=0x%x irq=%d id=%s\n", membase, irq, id); + } +} +#endif /* MODULE */ + + +#ifdef CONFIG_MCA + +struct eicon_mca_adapters_struct { + char * name; + int adf_id; +}; +/* possible MCA-brands of eicon cards */ +struct eicon_mca_adapters_struct eicon_mca_adapters[] = { + { "ISDN-P/2 Adapter", 0x6abb }, + { "ISDN-[S|SX|SCOM]/2 Adapter", 0x6a93 }, + { "DIVA /MCA", 0x6336 }, + { NULL, 0 }, +}; + +int eicon_mca_find_card(int type, /* type-idx of eicon-card */ + int membase, + int irq, + char * id) /* name of eicon-isdn-dev */ +{ + int j, curr_slot = 0; + + if (DebugVar & 8) + printk(KERN_DEBUG + "eicon_mca_find_card type: %d, membase: %#x, irq %d \n", + type, membase, irq); + /* find a no-driver-assigned eicon card */ + for (j=0; eicon_mca_adapters[j].adf_id != 0; j++) + { + for ( curr_slot=0; curr_slot<=MCA_MAX_SLOT_NR; curr_slot++) + { + curr_slot = mca_find_unused_adapter( + eicon_mca_adapters[j].adf_id, curr_slot); + if (curr_slot != MCA_NOTFOUND) + { + /* check if pre-set parameters match + these of the card, check cards memory */ + if (!(int) eicon_mca_probe(curr_slot, + j, + membase, + irq, + id)) + { + return 0; + /* means: adapter parms did match */ + }; + }; + break; + /* MCA_NOTFOUND-branch: no matching adapter of + THIS flavor found, next flavor */ + + }; + }; + /* all adapter flavors checked without match, finito with: */ + return ENODEV; +}; + + +/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * stolen from 3c523.c/elmc_getinfo, ewe, 10.5.1999 + */ +int eicon_info(char * buf, int slot, void *d) +{ + int len = 0; + struct eicon_card *dev; + + dev = (struct eicon_card *) d; + + if (dev == NULL) + return len; + len += sprintf(buf+len, "eicon ISDN adapter, type %d.\n",dev->type); + len += sprintf(buf+len, "IRQ: %d\n", dev->hwif.isa.irq); + len += sprintf(buf+len, "MEMBASE: %#lx\n", (unsigned long)dev->hwif.isa.shmem); + + return len; +}; + +int eicon_mca_probe(int slot, /* slot-nr where the card was detected */ + int a_idx, /* idx-nr of probed card in eicon_mca_adapters */ + int membase, + int irq, + char * id) /* name of eicon-isdn-dev */ +{ + unsigned char adf_pos0; + int cards_irq, cards_membase, cards_io; + int type = EICON_CTYPE_S; + int irq_array[]={0,3,4,2}; + int irq_array1[]={3,4,0,0,2,10,11,12}; + + adf_pos0 = mca_read_stored_pos(slot,2); + if (DebugVar & 8) + printk(KERN_DEBUG + "eicon_mca_probe irq=%d, membase=%d\n", + irq, + membase); + switch (a_idx) { + case 0: /* P/2-Adapter (== PRI/S2M ? ) */ + cards_membase= 0xC0000+((adf_pos0>>4)*0x4000); + if (membase == -1) { + membase = cards_membase; + } else { + if (membase != cards_membase) + return ENODEV; + }; + cards_irq=irq_array[((adf_pos0 & 0xC)>>2)]; + if (irq == -1) { + irq = cards_irq; + } else { + if (irq != irq) + return ENODEV; + }; + cards_io= 0xC00 + ((adf_pos0>>4)*0x10); + type = EICON_CTYPE_ISAPRI; + break; + + case 1: /* [S|SX|SCOM]/2 */ + cards_membase= 0xC0000+((adf_pos0>>4)*0x2000); + if (membase == -1) { + membase = cards_membase; + } else { + if (membase != cards_membase) + return ENODEV; + }; + cards_irq=irq_array[((adf_pos0 & 0xC)>>2)]; + if (irq == -1) { + irq = cards_irq; + } else { + if (irq != cards_irq) + return ENODEV; + }; + + cards_io= 0xC00 + ((adf_pos0>>4)*0x10); + type = EICON_CTYPE_SCOM; + break; + + case 2: /* DIVA/MCA */ + cards_io = 0x200+ ((adf_pos0>>4)* 0x20); + cards_irq = irq_array1[(adf_pos0 & 0x7)]; + if (irq == -1) { + irq = cards_irq; + } else { + if (irq != irq) + return ENODEV; + }; + type = 0; + break; + default: + return ENODEV; + }; + /* Uebereinstimmung vorgegebener membase & irq */ + if ( 1 == eicon_addcard(type, membase, irq, id)) { + mca_set_adapter_name(slot, eicon_mca_adapters[a_idx].name); + mca_set_adapter_procfn(slot, (MCA_ProcFn) eicon_info, cards); + + mca_mark_as_used(slot); + cards->mca_slot = slot; + /* card->io noch setzen oder ?? */ + if (DebugVar & 8) + printk("eicon_addcard: erfolgreich fuer slot: %d.\n", + cards->mca_slot+1); + return 0 ; /* eicon_addcard hat eine Karte zugefuegt */ + } else { + return ENODEV; + }; +}; +#endif /* CONFIG_MCA */ + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon_pci.c linux.pre11.3/drivers/isdn/eicon/eicon_pci.c --- linux.vanilla/drivers/isdn/eicon/eicon_pci.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/eicon/eicon_pci.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,956 @@ +/* $Id: eicon_pci.c,v 1.7 1999/06/09 19:31:29 armin Exp $ + * + * ISDN low-level module for Eicon.Diehl active ISDN-Cards. + * Hardware-specific code for PCI cards. + * + * Copyright 1998,99 by Armin Schindler (mac@melware.de) + * Copyright 1999 Cytronics & Melware (info@melware.de) + * + * Thanks to Eicon Technology Diehl GmbH & Co. oHG for + * documents, informations and hardware. + * + * Deutsche Telekom AG for S2M support. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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. + * + * $Log: eicon_pci.c,v $ + * Revision 1.7 1999/06/09 19:31:29 armin + * Wrong PLX size for request_region() corrected. + * Added first MCA code from Erik Weber. + * + * Revision 1.6 1999/04/01 12:48:37 armin + * Changed some log outputs. + * + * Revision 1.5 1999/03/29 11:19:49 armin + * I/O stuff now in seperate file (eicon_io.c) + * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. + * + * Revision 1.4 1999/03/02 12:37:48 armin + * Added some important checks. + * Analog Modem with DSP. + * Channels will be added to Link-Level after loading firmware. + * + * Revision 1.3 1999/01/24 20:14:24 armin + * Changed and added debug stuff. + * Better data sending. (still problems with tty's flip buffer) + * + * Revision 1.2 1999/01/10 18:46:06 armin + * Bug with wrong values in HLC fixed. + * Bytes to send are counted and limited now. + * + * Revision 1.1 1999/01/01 18:09:45 armin + * First checkin of new eicon driver. + * DIVA-Server BRI/PCI and PRI/PCI are supported. + * Old diehl code is obsolete. + * + * + */ + +#include + +#include "eicon.h" +#include "eicon_pci.h" + + +char *eicon_pci_revision = "$Revision: 1.7 $"; + +#if CONFIG_PCI /* intire stuff is only for PCI */ + +#undef EICON_PCI_DEBUG + +int eicon_pci_find_card(char *ID) +{ + if (pci_present()) { + struct pci_dev *pdev = NULL; + int pci_nextindex=0, pci_cards=0, pci_akt=0; + int pci_type = PCI_MAESTRA; + int NoMorePCICards = FALSE; + char *ram, *reg, *cfg; + unsigned int pram=0, preg=0, pcfg=0; + char did[12]; + eicon_pci_card *aparms; + + if (!(aparms = (eicon_pci_card *) kmalloc(sizeof(eicon_pci_card), GFP_KERNEL))) { + printk(KERN_WARNING + "eicon_pci: Could not allocate card-struct.\n"); + return 0; + } + + for (pci_cards = 0; pci_cards < 0x0f; pci_cards++) + { + do { + if ((pdev = pci_find_device(PCI_VENDOR_EICON, + pci_type, + pdev))) + { + pci_nextindex++; + break; + } + else { + pci_nextindex = 0; + switch (pci_type) /* switch to next card type */ + { + case PCI_MAESTRA: + pci_type = PCI_MAESTRAQ; break; + case PCI_MAESTRAQ: + pci_type = PCI_MAESTRAQ_U; break; + case PCI_MAESTRAQ_U: + pci_type = PCI_MAESTRAP; break; + default: + case PCI_MAESTRAP: + NoMorePCICards = TRUE; + } + } + } + while (!NoMorePCICards); + if (NoMorePCICards) + { + if (pci_cards < 1) { + printk(KERN_INFO "Eicon: No supported PCI cards found.\n"); + kfree(aparms); + return 0; + } + else + { + printk(KERN_INFO "Eicon: %d PCI card%s registered.\n", + pci_cards, (pci_cards > 1) ? "s":""); + kfree(aparms); + return (pci_cards); + } + } + + pci_akt = 0; + switch(pci_type) + { + case PCI_MAESTRA: + printk(KERN_INFO "Eicon: DIVA Server BRI/PCI detected !\n"); + aparms->type = EICON_CTYPE_MAESTRA; + + aparms->irq = pdev->irq; + preg = pdev->base_address[2] & 0xfffffffc; + pcfg = pdev->base_address[1] & 0xffffff80; + +#ifdef EICON_PCI_DEBUG + printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq); + printk(KERN_DEBUG "eicon_pci: reg=0x%x\n", preg); + printk(KERN_DEBUG "eicon_pci: cfg=0x%x\n", pcfg); +#endif + pci_akt = 1; + break; + + case PCI_MAESTRAQ: + case PCI_MAESTRAQ_U: + printk(KERN_ERR "Eicon: DIVA Server 4BRI/PCI detected but not supported !\n"); + pci_cards--; + pci_akt = 0; + break; + + case PCI_MAESTRAP: + printk(KERN_INFO "Eicon: DIVA Server PRI/PCI detected !\n"); + aparms->type = EICON_CTYPE_MAESTRAP; /*includes 9M,30M*/ + aparms->irq = pdev->irq; + pram = pdev->base_address[0] & 0xfffff000; + preg = pdev->base_address[2] & 0xfffff000; + pcfg = pdev->base_address[4] & 0xfffff000; + +#ifdef EICON_PCI_DEBUG + printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq); + printk(KERN_DEBUG "eicon_pci: ram=0x%x\n", + (pram)); + printk(KERN_DEBUG "eicon_pci: reg=0x%x\n", + (preg)); + printk(KERN_DEBUG "eicon_pci: cfg=0x%x\n", + (pcfg)); +#endif + pci_akt = 1; + break; + default: + printk(KERN_ERR "eicon_pci: Unknown PCI card detected !\n"); + pci_cards--; + pci_akt = 0; + break; + } + + if (pci_akt) { + /* remapping memory */ + switch(pci_type) + { + case PCI_MAESTRA: + aparms->PCIreg = (unsigned int) preg; + aparms->PCIcfg = (unsigned int) pcfg; + if (check_region((aparms->PCIreg), 0x20)) { + printk(KERN_WARNING "eicon_pci: reg port already in use !\n"); + aparms->PCIreg = 0; + break; + } else { + request_region(aparms->PCIreg, 0x20, "eicon reg"); + } + if (check_region((aparms->PCIcfg), 0x80)) { + printk(KERN_WARNING "eicon_pci: cfg port already in use !\n"); + aparms->PCIcfg = 0; + release_region(aparms->PCIreg, 0x20); + break; + } else { + request_region(aparms->PCIcfg, 0x80, "eicon cfg"); + } + break; + case PCI_MAESTRAQ: + case PCI_MAESTRAQ_U: + case PCI_MAESTRAP: + aparms->shmem = (eicon_pci_shmem *) ioremap(pram, 0x10000); + ram = (u8 *) ((u32)aparms->shmem + MP_SHARED_RAM_OFFSET); + reg = ioremap(preg, 0x4000); + cfg = ioremap(pcfg, 0x1000); + aparms->PCIram = (unsigned int) ram; + aparms->PCIreg = (unsigned int) reg; + aparms->PCIcfg = (unsigned int) cfg; + break; + } + if ((!aparms->PCIreg) || (!aparms->PCIcfg)) { + printk(KERN_ERR "eicon_pci: Card could not be added !\n"); + pci_cards--; + } else { + aparms->mvalid = 1; + + sprintf(did, "%s%d", (strlen(ID) < 1) ? "eicon":ID, pci_cards); + + printk(KERN_INFO "%s: DriverID: '%s'\n",eicon_ctype_name[aparms->type] , did); + + if (!(eicon_addcard(aparms->type, (int) aparms, aparms->irq, did))) { + printk(KERN_ERR "eicon_pci: Card could not be added !\n"); + pci_cards--; + } + } + } + + } + } else + printk(KERN_ERR "eicon_pci: Kernel compiled with PCI but no PCI-bios found !\n"); + return 0; +} + +/* + * Checks protocol file id for "F#xxxx" string fragment to + * extract the features, supported by this protocol version. + * binary representation of the feature string value is returned + * in *value. The function returns 0 if feature string was not + * found or has a wrong format, else 1. + */ +static int GetProtFeatureValue(char *sw_id, int *value) +{ + __u8 i, offset; + + while (*sw_id) + { + if ((sw_id[0] == 'F') && (sw_id[1] == '#')) + { + sw_id = &sw_id[2]; + for (i=0, *value=0; i<4; i++, sw_id++) + { + if ((*sw_id >= '0') && (*sw_id <= '9')) + { + offset = '0'; + } + else if ((*sw_id >= 'A') && (*sw_id <= 'F')) + { + offset = 'A' + 10; + } + else if ((*sw_id >= 'a') && (*sw_id <= 'f')) + { + offset = 'a' + 10; + } + else + { + return 0; + } + *value |= (*sw_id - offset) << (4*(3-i)); + } + return 1; + } + else + { + sw_id++; + } + } + return 0; +} + + +void +eicon_pci_printpar(eicon_pci_card *card) { + switch (card->type) { + case EICON_CTYPE_MAESTRA: + printk(KERN_INFO "%s at 0x%x / 0x%x, irq %d\n", + eicon_ctype_name[card->type], + (unsigned int)card->PCIreg, + (unsigned int)card->PCIcfg, + card->irq); + break; + case EICON_CTYPE_MAESTRAQ: + case EICON_CTYPE_MAESTRAQ_U: + case EICON_CTYPE_MAESTRAP: + printk(KERN_INFO "%s at 0x%x, irq %d\n", + eicon_ctype_name[card->type], + (unsigned int)card->shmem, + card->irq); +#ifdef EICON_PCI_DEBUG + printk(KERN_INFO "eicon_pci: remapped ram= 0x%x\n",(unsigned int)card->PCIram); + printk(KERN_INFO "eicon_pci: remapped reg= 0x%x\n",(unsigned int)card->PCIreg); + printk(KERN_INFO "eicon_pci: remapped cfg= 0x%x\n",(unsigned int)card->PCIcfg); +#endif + break; + } +} + + +static void +eicon_pci_release_shmem(eicon_pci_card *card) { + if (!card->master) + return; + if (card->mvalid) { + switch (card->type) { + case EICON_CTYPE_MAESTRA: + /* reset board */ + outb(0, card->PCIcfg + 0x4c); /* disable interrupts from PLX */ + outb(0, card->PCIreg + M_RESET); + SLEEP(20); + outb(0, card->PCIreg + M_ADDRH); + outw(0, card->PCIreg + M_ADDR); + outw(0, card->PCIreg + M_DATA); + + release_region(card->PCIreg, 0x20); + release_region(card->PCIcfg, 0x80); + break; + case EICON_CTYPE_MAESTRAQ: + case EICON_CTYPE_MAESTRAQ_U: + case EICON_CTYPE_MAESTRAP: + /* reset board */ + writeb(_MP_RISC_RESET | _MP_LED1 | _MP_LED2, card->PCIreg + MP_RESET); + SLEEP(20); + writeb(0, card->PCIreg + MP_RESET); + SLEEP(20); + + iounmap((void *)card->shmem); + iounmap((void *)card->PCIreg); + iounmap((void *)card->PCIcfg); + break; + } + } + card->mvalid = 0; +} + +static void +eicon_pci_release_irq(eicon_pci_card *card) { + if (!card->master) + return; + if (card->ivalid) + free_irq(card->irq, card); + card->ivalid = 0; +} + +void +eicon_pci_release(eicon_pci_card *card) { + eicon_pci_release_irq(card); + eicon_pci_release_shmem(card); +} + +/* + * Upload buffer content to adapters shared memory + * on verify error, 1 is returned and a message is printed on screen + * else 0 is returned + * Can serve IO-Type and Memory type adapters + */ +int eicon_upload(t_dsp_download_space *p_para, + __u16 length, /* byte count */ + __u8 *buffer, + int verify) +{ + __u32 i, dwdata = 0, val = 0, timeout; + __u16 data; + eicon_pci_boot *boot = 0; + + switch (p_para->type) /* actions depend on type of union */ + { + case DL_PARA_IO_TYPE: + for (i=0; idat.io.r3addr + i) >> 16), p_para->dat.io.ioADDRH); + outw ((u16) (p_para->dat.io.r3addr + i), p_para->dat.io.ioADDR); + /* outw (((u16 *)code)[i >> 1], p_para->dat.io.ioDATA); */ + outw (*(u16 *)&buffer[i], p_para->dat.io.ioDATA); + } + if (verify) /* check written block */ + { + for (i=0; idat.io.r3addr + i) >> 16), p_para->dat.io.ioADDRH); + outw ((u16) (p_para->dat.io.r3addr + i), p_para->dat.io.ioADDR); + data = inw(p_para->dat.io.ioDATA); + if (data != *(u16 *)&buffer[i]) + { + p_para->dat.io.r3addr += i; + p_para->dat.io.BadData = data; + p_para->dat.io.GoodData = *(u16 *)&buffer[i]; + return 1; + } + } + } + break; + + case DL_PARA_MEM_TYPE: + boot = p_para->dat.mem.boot; + writel(p_para->dat.mem.r3addr, &boot->addr); + for (i=0; i> 2], &boot->data[i]); + } + if (verify) /* check written block */ + { + for (i=0; idata[i]); + if (((u32 *)buffer)[i >> 2] != dwdata) + { + p_para->dat.mem.r3addr += i; + p_para->dat.mem.BadData = dwdata; + p_para->dat.mem.GoodData = ((u32 *)buffer)[i >> 2]; + return 1; + } + } + } + writel(((length + 3) / 4), &boot->len); /* len in dwords */ + writel(2, &boot->cmd); + + timeout = jiffies + 20; + while (timeout > jiffies) { + val = readl(&boot->cmd); + if (!val) break; + SLEEP(2); + } + if (val) + { + p_para->dat.mem.timeout = 1; + return 1; + } + break; + } + return 0; +} + + +/* show header information of code file */ +static +int eicon_pci_print_hdr(unsigned char *code, int offset) +{ + unsigned char hdr[80]; + int i, fvalue = 0; + + i = 0; + while ((i < (sizeof(hdr) -1)) + && (code[offset + i] != '\0') + && (code[offset + i] != '\r') + && (code[offset + i] != '\n')) + { + hdr[i] = code[offset + i]; + i++; + } + hdr[i] = '\0'; + printk(KERN_DEBUG "Eicon: loading %s\n", hdr); + if (GetProtFeatureValue(hdr, &fvalue)) return(fvalue); + else return(0); +} + + +/* + * Configure a card, download code into BRI card, + * check if we get interrupts and return 0 on succes. + * Return -ERRNO on failure. + */ +int +eicon_pci_load_bri(eicon_pci_card *card, eicon_pci_codebuf *cb) { + int i,j; + int timeout; + unsigned int offset, offp=0, size, length; + int signature = 0; + int FeatureValue = 0; + eicon_pci_codebuf cbuf; + t_dsp_download_space dl_para; + t_dsp_download_desc dsp_download_table; + unsigned char *code; + unsigned int reg; + unsigned int cfg; + + if (copy_from_user(&cbuf, cb, sizeof(eicon_pci_codebuf))) + return -EFAULT; + + reg = card->PCIreg; + cfg = card->PCIcfg; + + /* reset board */ + outb(0, reg + M_RESET); + SLEEP(10); + outb(0, reg + M_ADDRH); + outw(0, reg + M_ADDR); + outw(0, reg + M_DATA); + +#ifdef EICON_PCI_DEBUG + printk(KERN_DEBUG "eicon_pci: reset card\n"); +#endif + + /* clear shared memory */ + outb(0xff, reg + M_ADDRH); + outw(0, reg + M_ADDR); + for(i = 0; i < 0xffff; i++) outw(0, reg + M_DATA); + SLEEP(10); + +#ifdef EICON_PCI_DEBUG + printk(KERN_DEBUG "eicon_pci: clear shared memory\n"); +#endif + + /* download protocol and dsp file */ + +#ifdef EICON_PCI_DEBUG + printk(KERN_DEBUG "eicon_pci: downloading firmware...\n"); +#endif + + /* Allocate code-buffer */ + if (!(code = kmalloc(400, GFP_KERNEL))) { + printk(KERN_WARNING "eicon_pci_boot: Couldn't allocate code buffer\n"); + return -ENOMEM; + } + + /* prepare protocol upload */ + dl_para.type = DL_PARA_IO_TYPE; + dl_para.dat.io.ioADDR = reg + M_ADDR; + dl_para.dat.io.ioADDRH = reg + M_ADDRH; + dl_para.dat.io.ioDATA = reg + M_DATA; + + for (j = 0; j <= cbuf.dsp_code_num; j++) + { + if (j == 0) size = cbuf.protocol_len; + else size = cbuf.dsp_code_len[j]; + + offset = 0; + + if (j == 0) dl_para.dat.io.r3addr = 0; + if (j == 1) dl_para.dat.io.r3addr = M_DSP_CODE_BASE + + ((sizeof(__u32) + (sizeof(dsp_download_table) * 35) + 3) &0xfffffffc); + if (j == 2) dl_para.dat.io.r3addr = M_DSP_CODE_BASE; + if (j == 3) dl_para.dat.io.r3addr = M_DSP_CODE_BASE + sizeof(__u32); + + do /* download block of up to 400 bytes */ + { + length = ((size - offset) >= 400) ? 400 : (size - offset); + + if (copy_from_user(code, (&cb->code) + offp + offset, length)) { + kfree(code); + return -EFAULT; + } + + if ((offset == 0) && (j < 2)) { + FeatureValue = eicon_pci_print_hdr(code, j ? 0x00 : 0x80); +#ifdef EICON_PCI_DEBUG + if (FeatureValue) printk(KERN_DEBUG "eicon_pci: Feature Value : 0x%04x.\n", FeatureValue); +#endif + if ((j==0) && (!(FeatureValue & PROTCAP_TELINDUS))) { + printk(KERN_ERR "eicon_pci: Protocol Code cannot handle Telindus\n"); + kfree(code); + return -EFAULT; + } + ((eicon_card *)card->card)->Feature = FeatureValue; + } + + if (eicon_upload(&dl_para, length, code, 1)) + { + printk(KERN_ERR "eicon_pci: code block check failed at 0x%x !\n",dl_para.dat.io.r3addr); + kfree(code); + return -EIO; + } + /* move onto next block */ + offset += length; + dl_para.dat.io.r3addr += length; + } while (offset < size); + +#ifdef EICON_PCI_DEBUG + printk(KERN_DEBUG "Eicon: %d bytes loaded.\n", offset); +#endif + offp += size; + } + kfree(code); + + /* clear signature */ + outb(0xff, reg + M_ADDRH); + outw(0x1e, reg + M_ADDR); + outw(0, reg + M_DATA); + +#ifdef EICON_PCI_DEBUG + printk(KERN_DEBUG "eicon_pci: copy configuration data into shared memory...\n"); +#endif + /* copy configuration data into shared memory */ + outw(8, reg + M_ADDR); outb(cbuf.tei, reg + M_DATA); + outw(9, reg + M_ADDR); outb(cbuf.nt2, reg + M_DATA); + outw(10,reg + M_ADDR); outb(0, reg + M_DATA); + outw(11,reg + M_ADDR); outb(cbuf.WatchDog, reg + M_DATA); + outw(12,reg + M_ADDR); outb(cbuf.Permanent, reg + M_DATA); + outw(13,reg + M_ADDR); outb(0, reg + M_DATA); /* XInterface */ + outw(14,reg + M_ADDR); outb(cbuf.StableL2, reg + M_DATA); + outw(15,reg + M_ADDR); outb(cbuf.NoOrderCheck, reg + M_DATA); + outw(16,reg + M_ADDR); outb(0, reg + M_DATA); /* HandsetType */ + outw(17,reg + M_ADDR); outb(0, reg + M_DATA); /* SigFlags */ + outw(18,reg + M_ADDR); outb(cbuf.LowChannel, reg + M_DATA); + outw(19,reg + M_ADDR); outb(cbuf.ProtVersion, reg + M_DATA); + outw(20,reg + M_ADDR); outb(cbuf.Crc4, reg + M_DATA); + outw(21,reg + M_ADDR); outb((cbuf.Loopback) ? 2:0, reg + M_DATA); + + for (i=0;i<32;i++) + { + outw( 32+i, reg + M_ADDR); outb(cbuf.l[0].oad[i], reg + M_DATA); + outw( 64+i, reg + M_ADDR); outb(cbuf.l[0].osa[i], reg + M_DATA); + outw( 96+i, reg + M_ADDR); outb(cbuf.l[0].spid[i], reg + M_DATA); + outw(128+i, reg + M_ADDR); outb(cbuf.l[1].oad[i], reg + M_DATA); + outw(160+i, reg + M_ADDR); outb(cbuf.l[1].osa[i], reg + M_DATA); + outw(192+i, reg + M_ADDR); outb(cbuf.l[1].spid[i], reg + M_DATA); + } + +#ifdef EICON_PCI_DEBUG + printk(KERN_ERR "eicon_pci: starting CPU...\n"); +#endif + /* let the CPU run */ + outw(0x08, reg + M_RESET); + + timeout = jiffies + (5*HZ); + while (timeout > jiffies) { + outw(0x1e, reg + M_ADDR); + signature = inw(reg + M_DATA); + if (signature == DIVAS_SIGNATURE) break; + SLEEP(2); + } + if (signature != DIVAS_SIGNATURE) + { +#ifdef EICON_PCI_DEBUG + printk(KERN_ERR "eicon_pci: signature 0x%x expected 0x%x\n",signature,DIVAS_SIGNATURE); +#endif + printk(KERN_ERR "eicon_pci: Timeout, protocol code not running !\n"); + return -EIO; + } +#ifdef EICON_PCI_DEBUG + printk(KERN_DEBUG "eicon_pci: Protocol code running, signature OK\n"); +#endif + + /* get serial number and number of channels supported by card */ + outb(0xff, reg + M_ADDRH); + outw(0x3f6, reg + M_ADDR); + card->channels = inw(reg + M_DATA); + card->serial = (u32)inw(cfg + 0x22) << 16 | (u32)inw(cfg + 0x26); + printk(KERN_INFO "Eicon: Supported channels : %d\n", card->channels); + printk(KERN_INFO "Eicon: Card serial no. = %lu\n", card->serial); + + /* test interrupt */ + card->irqprobe = 1; + + if (!card->ivalid) { + if (request_irq(card->irq, &eicon_irq, 0, "Eicon PCI ISDN", card->card)) + { + printk(KERN_ERR "eicon_pci: Couldn't request irq %d\n", card->irq); + return -EIO; + } + } + card->ivalid = 1; + +#ifdef EICON_PCI_DEBUG + printk(KERN_DEBUG "eicon_pci: testing interrupt\n"); +#endif + /* Trigger an interrupt and check if it is delivered */ + outb(0x41, cfg + 0x4c); /* enable PLX for interrupts */ + outb(0x89, reg + M_RESET); /* place int request */ + + timeout = jiffies + 20; + while (timeout > jiffies) { + if (card->irqprobe != 1) break; + SLEEP(5); + } + if (card->irqprobe == 1) { + free_irq(card->irq, card); + card->ivalid = 0; + printk(KERN_ERR "eicon_pci: Getting no interrupts !\n"); + return -EIO; + } + + /* initializing some variables */ + ((eicon_card *)card->card)->ReadyInt = 0; + for(j=0; j<256; j++) ((eicon_card *)card->card)->IdTable[j] = NULL; + for(j=0; j< (card->channels + 1); j++) { + ((eicon_card *)card->card)->bch[j].e.busy = 0; + ((eicon_card *)card->card)->bch[j].e.D3Id = 0; + ((eicon_card *)card->card)->bch[j].e.B2Id = 0; + ((eicon_card *)card->card)->bch[j].e.ref = 0; + ((eicon_card *)card->card)->bch[j].e.Req = 0; + ((eicon_card *)card->card)->bch[j].e.complete = 1; + ((eicon_card *)card->card)->bch[j].fsm_state = EICON_STATE_NULL; + } + + printk(KERN_INFO "Eicon: Card successfully started\n"); + + return 0; +} + + +/* + * Configure a card, download code into PRI card, + * check if we get interrupts and return 0 on succes. + * Return -ERRNO on failure. + */ +int +eicon_pci_load_pri(eicon_pci_card *card, eicon_pci_codebuf *cb) { + eicon_pci_boot *boot; + eicon_pr_ram *prram; + int i,j; + int timeout; + int FeatureValue = 0; + unsigned int offset, offp=0, size, length; + unsigned long int signature = 0; + t_dsp_download_space dl_para; + t_dsp_download_desc dsp_download_table; + eicon_pci_codebuf cbuf; + unsigned char *code; + unsigned char req_int; + char *ram, *reg, *cfg; + + if (copy_from_user(&cbuf, cb, sizeof(eicon_pci_codebuf))) + return -EFAULT; + + boot = &card->shmem->boot; + ram = (char *)card->PCIram; + reg = (char *)card->PCIreg; + cfg = (char *)card->PCIcfg; + prram = (eicon_pr_ram *)ram; + + /* reset board */ + writeb(_MP_RISC_RESET | _MP_LED1 | _MP_LED2, card->PCIreg + MP_RESET); + SLEEP(20); + writeb(0, card->PCIreg + MP_RESET); + SLEEP(20); + + /* set command count to 0 */ + writel(0, &boot->reserved); + + /* check if CPU increments the life word */ + i = readw(&boot->live); + SLEEP(20); + if (i == readw(&boot->live)) { + printk(KERN_ERR "eicon_pci: card is reset, but CPU not running !\n"); + return -EIO; + } +#ifdef EICON_PCI_DEBUG + printk(KERN_DEBUG "eicon_pci: reset card OK (CPU running)\n"); +#endif + + /* download firmware : DSP and Protocol */ +#ifdef EICON_PCI_DEBUG + printk(KERN_DEBUG "eicon_pci: downloading firmware...\n"); +#endif + + /* Allocate code-buffer */ + if (!(code = kmalloc(400, GFP_KERNEL))) { + printk(KERN_WARNING "eicon_pci_boot: Couldn't allocate code buffer\n"); + return -ENOMEM; + } + + /* prepare protocol upload */ + dl_para.type = DL_PARA_MEM_TYPE; + dl_para.dat.mem.boot = boot; + + for (j = 0; j <= cbuf.dsp_code_num; j++) + { + if (j==0) size = cbuf.protocol_len; + else size = cbuf.dsp_code_len[j]; + + if (j==1) writel(MP_DSP_ADDR, &boot->addr); /* DSP code entry point */ + + if (j == 0) dl_para.dat.io.r3addr = MP_PROTOCOL_ADDR; + if (j == 1) dl_para.dat.io.r3addr = MP_DSP_CODE_BASE + + ((sizeof(__u32) + (sizeof(dsp_download_table) * 35) + 3) &0xfffffffc); + if (j == 2) dl_para.dat.io.r3addr = MP_DSP_CODE_BASE; + if (j == 3) dl_para.dat.io.r3addr = MP_DSP_CODE_BASE + sizeof(__u32); + + offset = 0; + do /* download block of up to 400 bytes */ + { + length = ((size - offset) >= 400) ? 400 : (size - offset); + + if (copy_from_user(code, (&cb->code) + offp + offset, length)) { + kfree(code); + return -EFAULT; + } + + if ((offset == 0) && (j < 2)) { + FeatureValue = eicon_pci_print_hdr(code, j ? 0x00 : 0x80); +#ifdef EICON_PCI_DEBUG + if (FeatureValue) printk(KERN_DEBUG "eicon_pci: Feature Value : 0x%x.\n", FeatureValue); +#endif + if ((j==0) && (!(FeatureValue & PROTCAP_TELINDUS))) { + printk(KERN_ERR "eicon_pci: Protocol Code cannot handle Telindus\n"); + kfree(code); + return -EFAULT; + } + ((eicon_card *)card->card)->Feature = FeatureValue; + } + + if (eicon_upload(&dl_para, length, code, 1)) + { + if (dl_para.dat.mem.timeout == 0) + printk(KERN_ERR "eicon_pci: code block check failed at 0x%x !\n",dl_para.dat.io.r3addr); + else + printk(KERN_ERR "eicon_pci: timeout, no ACK to load !\n"); + kfree(code); + return -EIO; + } + + /* move onto next block */ + offset += length; + dl_para.dat.mem.r3addr += length; + } while (offset < size); +#ifdef EICON_PCI_DEBUG + printk(KERN_DEBUG "eicon_pci: %d bytes loaded.\n", offset); +#endif + offp += size; + } + kfree(code); + + /* initialize the adapter data structure */ +#ifdef EICON_PCI_DEBUG + printk(KERN_DEBUG "eicon_pci: copy configuration data into shared memory...\n"); +#endif + /* clear out config space */ + for (i = 0; i < 256; i++) writeb(0, &ram[i]); + + /* copy configuration down to the card */ + writeb(cbuf.tei, &ram[8]); + writeb(cbuf.nt2, &ram[9]); + writeb(0, &ram[10]); + writeb(cbuf.WatchDog, &ram[11]); + writeb(cbuf.Permanent, &ram[12]); + writeb(cbuf.XInterface, &ram[13]); + writeb(cbuf.StableL2, &ram[14]); + writeb(cbuf.NoOrderCheck, &ram[15]); + writeb(cbuf.HandsetType, &ram[16]); + writeb(0, &ram[17]); + writeb(cbuf.LowChannel, &ram[18]); + writeb(cbuf.ProtVersion, &ram[19]); + writeb(cbuf.Crc4, &ram[20]); + for (i = 0; i < 32; i++) + { + writeb(cbuf.l[0].oad[i], &ram[32 + i]); + writeb(cbuf.l[0].osa[i], &ram[64 + i]); + writeb(cbuf.l[0].spid[i], &ram[96 + i]); + writeb(cbuf.l[1].oad[i], &ram[128 + i]); + writeb(cbuf.l[1].osa[i], &ram[160 + i]); + writeb(cbuf.l[1].spid[i], &ram[192 + i]); + } +#ifdef EICON_PCI_DEBUG + printk(KERN_DEBUG "eicon_pci: configured card OK\n"); +#endif + + /* start adapter */ +#ifdef EICON_PCI_DEBUG + printk(KERN_DEBUG "eicon_pci: tell card to start...\n"); +#endif + writel(MP_PROTOCOL_ADDR, &boot->addr); /* RISC code entry point */ + writel(3, &boot->cmd); /* DIVAS_START_CMD */ + + /* wait till card ACKs */ + timeout = jiffies + (5*HZ); + while (timeout > jiffies) { + signature = readl(&boot->signature); + if ((signature >> 16) == DIVAS_SIGNATURE) break; + SLEEP(2); + } + if ((signature >> 16) != DIVAS_SIGNATURE) + { +#ifdef EICON_PCI_DEBUG + printk(KERN_ERR "eicon_pci: signature 0x%lx expected 0x%x\n",(signature >> 16),DIVAS_SIGNATURE); +#endif + printk(KERN_ERR "eicon_pci: timeout, protocol code not running !\n"); + return -EIO; + } +#ifdef EICON_PCI_DEBUG + printk(KERN_DEBUG "eicon_pci: Protocol code running, signature OK\n"); +#endif + + /* get serial number and number of channels supported by card */ + card->channels = readb(&ram[0x3f6]); + card->serial = readl(&ram[0x3f0]); + printk(KERN_INFO "Eicon: Supported channels : %d\n", card->channels); + printk(KERN_INFO "Eicon: Card serial no. = %lu\n", card->serial); + + /* test interrupt */ + readb(&ram[0x3fe]); + writeb(0, &ram[0x3fe]); /* reset any pending interrupt */ + readb(&ram[0x3fe]); + + writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]); + writew(0, &cfg[MP_IRQ_RESET + 2]); + + card->irqprobe = 1; + + if (!card->ivalid) { + if (request_irq(card->irq, &eicon_irq, 0, "Eicon PCI ISDN", card->card)) + { + printk(KERN_ERR "eicon_pci: Couldn't request irq %d\n", card->irq); + return -EIO; + } + } + card->ivalid = 1; + + req_int = readb(&prram->ReadyInt); +#ifdef EICON_PCI_DEBUG + printk(KERN_DEBUG "eicon_pci: testing interrupt\n"); +#endif + req_int++; + /* Trigger an interrupt and check if it is delivered */ + writeb(req_int, &prram->ReadyInt); + + timeout = jiffies + 20; + while (timeout > jiffies) { + if (card->irqprobe != 1) break; + SLEEP(2); + } + if (card->irqprobe == 1) { + free_irq(card->irq, card); + card->ivalid = 0; + printk(KERN_ERR "eicon_pci: Getting no interrupts !\n"); + return -EIO; + } + + /* initializing some variables */ + ((eicon_card *)card->card)->ReadyInt = 0; + for(j=0; j<256; j++) ((eicon_card *)card->card)->IdTable[j] = NULL; + for(j=0; j< (card->channels + 1); j++) { + ((eicon_card *)card->card)->bch[j].e.busy = 0; + ((eicon_card *)card->card)->bch[j].e.D3Id = 0; + ((eicon_card *)card->card)->bch[j].e.B2Id = 0; + ((eicon_card *)card->card)->bch[j].e.ref = 0; + ((eicon_card *)card->card)->bch[j].e.Req = 0; + ((eicon_card *)card->card)->bch[j].e.complete = 1; + ((eicon_card *)card->card)->bch[j].fsm_state = EICON_STATE_NULL; + } + + printk(KERN_INFO "Eicon: Card successfully started\n"); + + return 0; +} + +#endif /* CONFIG_PCI */ + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon_pci.h linux.pre11.3/drivers/isdn/eicon/eicon_pci.h --- linux.vanilla/drivers/isdn/eicon/eicon_pci.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/eicon/eicon_pci.h Mon Jul 19 23:59:33 1999 @@ -0,0 +1,188 @@ +/* $Id: eicon_pci.h,v 1.3 1999/03/29 11:19:51 armin Exp $ + * + * ISDN low-level module for Eicon.Diehl active ISDN-Cards (PCI part). + * + * Copyright 1998,99 by Armin Schindler (mac@melware.de) + * Copyright 1999 Cytronics & Melware (info@melware.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, 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. + * + * $Log: eicon_pci.h,v $ + * Revision 1.3 1999/03/29 11:19:51 armin + * I/O stuff now in seperate file (eicon_io.c) + * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. + * + * Revision 1.2 1999/03/02 12:37:50 armin + * Added some important checks. + * Analog Modem with DSP. + * Channels will be added to Link-Level after loading firmware. + * + * Revision 1.1 1999/01/01 18:09:46 armin + * First checkin of new eicon driver. + * DIVA-Server BRI/PCI and PRI/PCI are supported. + * Old diehl code is obsolete. + * + * + */ + +#ifndef eicon_pci_h +#define eicon_pci_h + +#ifdef __KERNEL__ + + +#define PCI_VENDOR_EICON 0x1133 +#define PCI_DIVA_PRO20 0xe001 /* Not supported */ +#define PCI_DIVA20 0xe002 /* Not supported */ +#define PCI_DIVA_PRO20_U 0xe003 /* Not supported */ +#define PCI_DIVA20_U 0xe004 /* Not supported */ +#define PCI_MAESTRA 0xe010 +#define PCI_MAESTRAQ 0xe012 +#define PCI_MAESTRAQ_U 0xe013 +#define PCI_MAESTRAP 0xe014 + +#define DIVA_PRO20 1 +#define DIVA20 2 +#define DIVA_PRO20_U 3 +#define DIVA20_U 4 +#define MAESTRA 5 +#define MAESTRAQ 6 +#define MAESTRAQ_U 7 +#define MAESTRAP 8 + +#define TRUE 1 +#define FALSE 0 + +#define DIVAS_SIGNATURE 0x4447 + + +/* MAESTRA BRI PCI */ + +#define M_RESET 0x10 /* offset of reset register */ +#define M_DATA 0x00 /* offset of data register */ +#define M_ADDR 0x04 /* offset of address register */ +#define M_ADDRH 0x0c /* offset of high address register */ + +#define M_DSP_CODE_LEN 0xbf7d0000 +#define M_DSP_CODE 0xbf7d0004 /* max 128K DSP-Code */ +#define M_DSP_CODE_BASE 0xbf7a0000 +#define M_MAX_DSP_CODE_SIZE 0x00050000 /* max 320K DSP-Code (Telindus) */ + + + +/* MAESTRA PRI PCI */ + +#define MP_SHARED_RAM_OFFSET 0x1000 /* offset of shared RAM base in the DRAM memory bar */ + +#define MP_IRQ_RESET 0xc18 /* offset of interrupt status register in the CONFIG memory bar */ +#define MP_IRQ_RESET_VAL 0xfe /* value to clear an interrupt */ + +#define MP_PROTOCOL_ADDR 0xa0011000 /* load address of protocol code */ +#define MP_DSP_ADDR 0xa03c0000 /* load address of DSP code */ +#define MP_MAX_PROTOCOL_CODE_SIZE 0x000a0000 /* max 640K Protocol-Code */ +#define MP_DSP_CODE_BASE 0xa03a0000 +#define MP_MAX_DSP_CODE_SIZE 0x00060000 /* max 384K DSP-Code */ + +#define MP_RESET 0x20 /* offset of RESET register in the DEVICES memory bar */ + +/* RESET register bits */ +#define _MP_S2M_RESET 0x10 /* active lo */ +#define _MP_LED2 0x08 /* 1 = on */ +#define _MP_LED1 0x04 /* 1 = on */ +#define _MP_DSP_RESET 0x02 /* active lo */ +#define _MP_RISC_RESET 0x81 /* active hi, bit 7 for compatibility with old boards */ + +/* boot interface structure */ +typedef struct { + __u32 cmd __attribute__ ((packed)); + __u32 addr __attribute__ ((packed)); + __u32 len __attribute__ ((packed)); + __u32 err __attribute__ ((packed)); + __u32 live __attribute__ ((packed)); + __u32 reserved[(0x1020>>2)-6] __attribute__ ((packed)); + __u32 signature __attribute__ ((packed)); + __u8 data[1]; /* real interface description */ +} eicon_pci_boot; + + +#define DL_PARA_IO_TYPE 0 +#define DL_PARA_MEM_TYPE 1 + +typedef struct tag_dsp_download_space +{ + __u16 type; /* see definitions above to differ union elements */ + union + { + struct + { + __u32 r3addr; + __u16 ioADDR; + __u16 ioADDRH; + __u16 ioDATA; + __u16 BadData; /* in case of verify error */ + __u16 GoodData; + } io; /* for io based adapters */ + struct + { + __u32 r3addr; + eicon_pci_boot *boot; + __u32 BadData; /* in case of verify error */ + __u32 GoodData; + __u16 timeout; + } mem; /* for memory based adapters */ + } dat; +} t_dsp_download_space; + + +/* Shared memory */ +typedef union { + eicon_pci_boot boot; +} eicon_pci_shmem; + +/* + * card's description + */ +typedef struct { + int ramsize; + int irq; /* IRQ */ + unsigned int PCIram; + unsigned int PCIreg; + unsigned int PCIcfg; + long int serial; /* Serial No. */ + int channels; /* No. of supported channels */ + void* card; + eicon_pci_shmem* shmem; /* Shared-memory area */ + unsigned char* intack; /* Int-Acknowledge */ + unsigned char* stopcpu; /* Writing here stops CPU */ + unsigned char* startcpu; /* Writing here starts CPU */ + unsigned char type; /* card type */ + unsigned char irqprobe; /* Flag: IRQ-probing */ + unsigned char mvalid; /* Flag: Memory is valid */ + unsigned char ivalid; /* Flag: IRQ is valid */ + unsigned char master; /* Flag: Card is Quadro 1/4 */ + void* generic; /* Ptr to generic card struct */ +} eicon_pci_card; + + + +extern int eicon_pci_load_pri(eicon_pci_card *card, eicon_pci_codebuf *cb); +extern int eicon_pci_load_bri(eicon_pci_card *card, eicon_pci_codebuf *cb); +extern void eicon_pci_release(eicon_pci_card *card); +extern void eicon_pci_printpar(eicon_pci_card *card); +extern int eicon_pci_find_card(char *ID); + +#endif /* __KERNEL__ */ + +#endif /* eicon_pci_h */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/Makefile linux.pre11.3/drivers/isdn/hisax/Makefile --- linux.vanilla/drivers/isdn/hisax/Makefile Wed Mar 24 10:55:17 1999 +++ linux.pre11.3/drivers/isdn/hisax/Makefile Mon Jul 19 23:59:33 1999 @@ -8,7 +8,7 @@ O_TARGET := O_OBJS := isdnl1.o tei.o isdnl2.o isdnl3.o \ - lmgr.o q931.o callc.o fsm.o + lmgr.o q931.o callc.o fsm.o cert.o # EXTRA_CFLAGS += -S @@ -25,12 +25,11 @@ endif ISAC_OBJ := -ARCOFI_OBJ := HSCX_OBJ := +ISAR_OBJ := HFC_OBJ := HFC_2BDS0 := -RAWHDLC_OBJ := - +JADE_OBJ := ifeq ($(CONFIG_HISAX_16_0),y) O_OBJS += teles0.o ISAC_OBJ := isac.o @@ -43,17 +42,40 @@ HSCX_OBJ := hscx.o endif +ifeq ($(CONFIG_HISAX_TELESPCI),y) + O_OBJS += telespci.o + ISAC_OBJ := isac.o + HSCX_OBJ := hscx.o +endif + +ifeq ($(CONFIG_HISAX_S0BOX),y) + O_OBJS += s0box.o + ISAC_OBJ := isac.o + HSCX_OBJ := hscx.o +endif + ifeq ($(CONFIG_HISAX_AVM_A1),y) O_OBJS += avm_a1.o ISAC_OBJ := isac.o HSCX_OBJ := hscx.o endif +ifeq ($(CONFIG_HISAX_AVM_A1_PCMCIA),y) + O_OBJS += avm_a1p.o + ISAC_OBJ := isac.o + HSCX_OBJ := hscx.o +endif + +ifeq ($(CONFIG_HISAX_FRITZPCI),y) + O_OBJS += avm_pci.o + ISAC_OBJ := isac.o +endif + + ifeq ($(CONFIG_HISAX_ELSA),y) O_OBJS += elsa.o ISAC_OBJ := isac.o HSCX_OBJ := hscx.o - ARCOFI_OBJ := arcofi.o endif ifeq ($(CONFIG_HISAX_IX1MICROR2),y) @@ -84,6 +106,7 @@ O_OBJS += sedlbauer.o ISAC_OBJ := isac.o HSCX_OBJ := hscx.o + ISAR_OBJ := isar.o endif ifeq ($(CONFIG_HISAX_SPORTSTER),y) @@ -103,15 +126,13 @@ ISAC_OBJ := isac.o endif -ifeq ($(CONFIG_HISAX_TELES3C),y) - O_OBJS += teles3c.o +ifeq ($(CONFIG_HISAX_HFCS),y) + O_OBJS += hfcscard.o HFC_2BDS0 := hfc_2bds0.o endif -ifeq ($(CONFIG_HISAX_AMD7930),y) - RAWHDLC_OBJ := foreign.o rawhdlc.o -endif -ifeq ($(CONFIG_HISAX_DBRI),y) - RAWHDLC_OBJ := foreign.o rawhdlc.o + +ifeq ($(CONFIG_HISAX_HFC_PCI),y) + HFC_2BDS0 += hfc_pci.o endif ifeq ($(CONFIG_HISAX_NICCY),y) @@ -120,7 +141,45 @@ HSCX_OBJ := hscx.o endif -O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(HFC_OBJ) $(ARCOFI_OBJ) $(HFC_2BDS0) $(RAWHDLC_OBJ) +ifeq ($(CONFIG_HISAX_ISURF),y) + O_OBJS += isurf.o + ISAC_OBJ := isac.o + ISAR_OBJ := isar.o +endif + +ifeq ($(CONFIG_HISAX_HSTSAPHIR),y) + O_OBJS += saphir.o + ISAC_OBJ := isac.o + HSCX_OBJ := hscx.o +endif + +ifeq ($(CONFIG_HISAX_BKM_A4T),y) + O_OBJS += bkm_a4t.o + ISAC_OBJ := isac.o + JADE_OBJ := jade.o +endif +ifeq ($(CONFIG_HISAX_SCT_QUADRO),y) + O_OBJS += bkm_a8.o + ISAC_OBJ := isac.o + HSCX_OBJ := hscx.o +endif + +ifeq ($(CONFIG_HISAX_GAZEL),y) + O_OBJS += gazel.o + ISAC_OBJ := isac.o + HSCX_OBJ := hscx.o +endif + +# ifeq ($(CONFIG_HISAX_TESTEMU),y) +# O_OBJS += testemu.o +# endif + +ifeq ($(ISAC_OBJ), isac.o) + ISAC_OBJ += arcofi.o +endif + +O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(ISAR_OBJ) $(JADE_OBJ) +O_OBJS += $(HFC_OBJ) $(HFC_2BDS0) OX_OBJS += config.o O_TARGET := @@ -134,4 +193,14 @@ endif endif + include $(TOPDIR)/Rules.make + +MD5FILES += isac.c isdnl1.c isdnl2.c isdnl3.c \ + tei.c callc.c cert.c l3dss1.c l3_1tr6.c elsa.c + +CERT = $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?) + +cert.o: $(MD5FILES) md5sums.asc + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -D CERTIFICATION=$(CERT) -c -o cert.o cert.c + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/amd7930.c linux.pre11.3/drivers/isdn/hisax/amd7930.c --- linux.vanilla/drivers/isdn/hisax/amd7930.c Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/hisax/amd7930.c Mon Jul 19 23:59:33 1999 @@ -1,4 +1,4 @@ -/* $Id: amd7930.c,v 1.2 1998/02/12 23:07:10 keil Exp $ +/* $Id: amd7930.c,v 1.3 1999/07/12 21:04:52 keil Exp $ * * HiSax ISDN driver - chip specific routines for AMD 7930 * @@ -7,6 +7,10 @@ * * * $Log: amd7930.c,v $ + * Revision 1.3 1999/07/12 21:04:52 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * * Revision 1.2 1998/02/12 23:07:10 keil * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * @@ -105,7 +109,7 @@ #include "rawhdlc.h" #include -static const char *amd7930_revision = "$Revision: 1.2 $"; +static const char *amd7930_revision = "$Revision: 1.3 $"; #define RCV_BUFSIZE 1024 /* Size of raw receive buffer in bytes */ #define RCV_BUFBLKS 4 /* Number of blocks to divide buffer into @@ -733,8 +737,6 @@ return(0); case CARD_RELEASE: release_amd7930(cs); - return(0); - case CARD_SETIRQ: return(0); case CARD_INIT: cs->l1cmd = amd7930_l1cmd; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/arcofi.c linux.pre11.3/drivers/isdn/hisax/arcofi.c --- linux.vanilla/drivers/isdn/hisax/arcofi.c Sun Nov 8 15:10:14 1998 +++ linux.pre11.3/drivers/isdn/hisax/arcofi.c Mon Jul 19 23:59:33 1999 @@ -1,12 +1,31 @@ -/* $Id: arcofi.c,v 1.1 1997/10/29 18:51:20 keil Exp $ +/* $Id: arcofi.c,v 1.7 1999/07/01 08:11:17 keil Exp $ - * arcofi.h Ansteuerung ARCOFI 2165 + * arcofi.c Ansteuerung ARCOFI 2165 * * Author Karsten Keil (keil@temic-ech.spacenet.de) * * * * $Log: arcofi.c,v $ + * Revision 1.7 1999/07/01 08:11:17 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 1.6 1998/09/30 22:21:56 keil + * cosmetics + * + * Revision 1.5 1998/09/27 12:52:57 keil + * cosmetics + * + * Revision 1.4 1998/08/20 13:50:24 keil + * More support for hybrid modem (not working yet) + * + * Revision 1.3 1998/05/25 12:57:38 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * + * Revision 1.2 1998/04/15 16:47:16 keil + * new interface + * * Revision 1.1 1997/10/29 18:51:20 keil * New files * @@ -16,35 +35,120 @@ #include "hisax.h" #include "isdnl1.h" #include "isac.h" +#include "arcofi.h" -int -send_arcofi(struct IsdnCardState *cs, const u_char *msg) { +#define ARCOFI_TIMER_VALUE 20 + +static void +add_arcofi_timer(struct IsdnCardState *cs) { + if (test_and_set_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) { + del_timer(&cs->dc.isac.arcofitimer); + } + init_timer(&cs->dc.isac.arcofitimer); + cs->dc.isac.arcofitimer.expires = jiffies + ((ARCOFI_TIMER_VALUE * HZ)/1000); + add_timer(&cs->dc.isac.arcofitimer); +} + +static void +send_arcofi(struct IsdnCardState *cs) { u_char val; - char tmp[32]; - long flags; - int cnt=2; - cs->mon_txp = 0; - cs->mon_txc = msg[0]; - memcpy(cs->mon_tx, &msg[1], cs->mon_txc); - cs->mocr &= 0x0f; - cs->mocr |= 0xa0; - test_and_clear_bit(HW_MON1_TX_END, &cs->HW_Flags); - cs->writeisac(cs, ISAC_MOCR, cs->mocr); + add_arcofi_timer(cs); + cs->dc.isac.mon_txp = 0; + cs->dc.isac.mon_txc = cs->dc.isac.arcofi_list->len; + memcpy(cs->dc.isac.mon_tx, cs->dc.isac.arcofi_list->msg, cs->dc.isac.mon_txc); + switch(cs->dc.isac.arcofi_bc) { + case 0: break; + case 1: cs->dc.isac.mon_tx[1] |= 0x40; + break; + default: break; + } + cs->dc.isac.mocr &= 0x0f; + cs->dc.isac.mocr |= 0xa0; + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); val = cs->readisac(cs, ISAC_MOSR); - cs->writeisac(cs, ISAC_MOX1, cs->mon_tx[cs->mon_txp++]); - cs->mocr |= 0x10; - cs->writeisac(cs, ISAC_MOCR, cs->mocr); - save_flags(flags); - sti(); - while (cnt && !test_bit(HW_MON1_TX_END, &cs->HW_Flags)) { - cnt--; - current->state = TASK_INTERRUPTIBLE; - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + cs->writeisac(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]); + cs->dc.isac.mocr |= 0x10; + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); +} + +int +arcofi_fsm(struct IsdnCardState *cs, int event, void *data) { + if (cs->debug & L1_DEB_MONITOR) { + debugl1(cs, "arcofi state %d event %d", cs->dc.isac.arcofi_state, event); } - restore_flags(flags); - sprintf(tmp, "arcofi tout %d", cnt); - debugl1(cs, tmp); - return(cnt); + if (event == ARCOFI_TIMEOUT) { + cs->dc.isac.arcofi_state = ARCOFI_NOP; + test_and_set_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags); + wake_up_interruptible(&cs->dc.isac.arcofi_wait); + return(1); + } + switch (cs->dc.isac.arcofi_state) { + case ARCOFI_NOP: + if (event == ARCOFI_START) { + cs->dc.isac.arcofi_list = data; + cs->dc.isac.arcofi_state = ARCOFI_TRANSMIT; + send_arcofi(cs); + } + break; + case ARCOFI_TRANSMIT: + if (event == ARCOFI_TX_END) { + if (cs->dc.isac.arcofi_list->receive) { + add_arcofi_timer(cs); + cs->dc.isac.arcofi_state = ARCOFI_RECEIVE; + } else { + if (cs->dc.isac.arcofi_list->next) { + cs->dc.isac.arcofi_list = + cs->dc.isac.arcofi_list->next; + send_arcofi(cs); + } else { + if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) { + del_timer(&cs->dc.isac.arcofitimer); + } + cs->dc.isac.arcofi_state = ARCOFI_NOP; + wake_up_interruptible(&cs->dc.isac.arcofi_wait); + } + } + } + break; + case ARCOFI_RECEIVE: + if (event == ARCOFI_RX_END) { + if (cs->dc.isac.arcofi_list->next) { + cs->dc.isac.arcofi_list = + cs->dc.isac.arcofi_list->next; + cs->dc.isac.arcofi_state = ARCOFI_TRANSMIT; + send_arcofi(cs); + } else { + if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) { + del_timer(&cs->dc.isac.arcofitimer); + } + cs->dc.isac.arcofi_state = ARCOFI_NOP; + wake_up_interruptible(&cs->dc.isac.arcofi_wait); + } + } + break; + default: + debugl1(cs, "Arcofi unknown state %x", cs->dc.isac.arcofi_state); + return(2); + } + return(0); } +static void +arcofi_timer(struct IsdnCardState *cs) { + arcofi_fsm(cs, ARCOFI_TIMEOUT, NULL); +} + +void +clear_arcofi(struct IsdnCardState *cs) { + if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) { + del_timer(&cs->dc.isac.arcofitimer); + } +} + +void +init_arcofi(struct IsdnCardState *cs) { + cs->dc.isac.arcofitimer.function = (void *) arcofi_timer; + cs->dc.isac.arcofitimer.data = (long) cs; + init_timer(&cs->dc.isac.arcofitimer); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/arcofi.h linux.pre11.3/drivers/isdn/hisax/arcofi.h --- linux.vanilla/drivers/isdn/hisax/arcofi.h Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/hisax/arcofi.h Mon Jul 19 23:59:33 1999 @@ -1,4 +1,4 @@ -/* $Id: arcofi.h,v 1.1 1997/10/29 18:51:20 keil Exp $ +/* $Id: arcofi.h,v 1.4 1999/07/01 08:11:18 keil Exp $ * arcofi.h Ansteuerung ARCOFI 2165 * @@ -7,6 +7,16 @@ * * * $Log: arcofi.h,v $ + * Revision 1.4 1999/07/01 08:11:18 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 1.3 1998/05/25 12:57:39 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * + * Revision 1.2 1998/04/15 16:47:17 keil + * new interface + * * Revision 1.1 1997/10/29 18:51:20 keil * New files * @@ -14,4 +24,16 @@ #define ARCOFI_USE 1 -extern int send_arcofi(struct IsdnCardState *cs, const u_char *msg); +/* states */ +#define ARCOFI_NOP 0 +#define ARCOFI_TRANSMIT 1 +#define ARCOFI_RECEIVE 2 +/* events */ +#define ARCOFI_START 1 +#define ARCOFI_TX_END 2 +#define ARCOFI_RX_END 3 +#define ARCOFI_TIMEOUT 4 + +extern int arcofi_fsm(struct IsdnCardState *cs, int event, void *data); +extern void init_arcofi(struct IsdnCardState *cs); +extern void clear_arcofi(struct IsdnCardState *cs); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/asuscom.c linux.pre11.3/drivers/isdn/hisax/asuscom.c --- linux.vanilla/drivers/isdn/hisax/asuscom.c Sun Nov 8 15:10:14 1998 +++ linux.pre11.3/drivers/isdn/hisax/asuscom.c Mon Jul 19 23:59:33 1999 @@ -1,13 +1,29 @@ -/* $Id: asuscom.c,v 1.2 1998/02/02 13:27:06 keil Exp $ +/* $Id: asuscom.c,v 1.7 1999/07/12 21:04:53 keil Exp $ * asuscom.c low level stuff for ASUSCOM NETWORK INC. ISDNLink cards * - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) * * Thanks to ASUSCOM NETWORK INC. Taiwan and Dynalink NL for informations * * * $Log: asuscom.c,v $ + * Revision 1.7 1999/07/12 21:04:53 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 1.6 1999/07/01 08:11:18 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 1.5 1998/11/15 23:54:19 keil + * changes from 2.0 + * + * Revision 1.4 1998/06/18 23:18:20 keil + * Support for new IPAC card + * + * Revision 1.3 1998/04/15 16:46:53 keil + * new init code + * * Revision 1.2 1998/02/02 13:27:06 keil * New * @@ -17,12 +33,13 @@ #define __NO_VERSION__ #include "hisax.h" #include "isac.h" +#include "ipac.h" #include "hscx.h" #include "isdnl1.h" extern const char *CardType[]; -const char *Asuscom_revision = "$Revision: 1.2 $"; +const char *Asuscom_revision = "$Revision: 1.7 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -33,6 +50,12 @@ #define ASUS_CTRL_U7 3 #define ASUS_CTRL_POTS 5 +#define ASUS_IPAC_ALE 0 +#define ASUS_IPAC_DATA 1 + +#define ASUS_ISACHSCX 1 +#define ASUS_IPAC 2 + /* CARD_ADR (Write) */ #define ASUS_RESET 0x80 /* Bit 7 Reset-Leitung */ @@ -107,6 +130,30 @@ } static u_char +ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset) +{ + return (readreg(cs->hw.asus.adr, cs->hw.asus.isac, offset|0x80)); +} + +static void +WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) +{ + writereg(cs->hw.asus.adr, cs->hw.asus.isac, offset|0x80, value); +} + +static void +ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) +{ + readfifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size); +} + +static void +WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) +{ + writefifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size); +} + +static u_char ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { return (readreg(cs->hw.asus.adr, @@ -141,7 +188,7 @@ asuscom_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u_char val, stat = 0; + u_char val; if (!cs) { printk(KERN_WARNING "ISDNLink: Spurious interrupt!\n"); @@ -149,16 +196,12 @@ } val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40); Start_HSCX: - if (val) { + if (val) hscx_int_main(cs, val); - stat |= 1; - } val = readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA); Start_ISAC: - if (val) { + if (val) isac_interrupt(cs, val); - stat |= 2; - } val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40); if (val) { if (cs->debug & L1_DEB_HSCX) @@ -171,16 +214,58 @@ debugl1(cs, "ISAC IntStat after IntRoutine"); goto Start_ISAC; } - if (stat & 1) { - writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0xFF); - writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0xFF); - writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0x0); - writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0x0); - } - if (stat & 2) { - writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0xFF); - writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0x0); + writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0x0); + writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0x0); + writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0x0); +} + +static void +asuscom_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char ista, val, icnt = 5; + + if (!cs) { + printk(KERN_WARNING "ISDNLink: Spurious interrupt!\n"); + return; + } + ista = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA); +Start_IPAC: + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); + if (ista & 0x0f) { + val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) + hscx_int_main(cs, val); + } + if (ista & 0x20) { + val = 0xfe & readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA | 0x80); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA); + if ((ista & 0x3f) && icnt) { + icnt--; + goto Start_IPAC; } + if (!icnt) + printk(KERN_WARNING "ASUS IRQ LOOP\n"); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xFF); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xC0); } void @@ -197,14 +282,27 @@ { long flags; - byteout(cs->hw.asus.adr, ASUS_RESET); /* Reset On */ + 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(); current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - byteout(cs->hw.asus.adr, 0); /* Reset Off */ + schedule_timeout((10*HZ)/1000); + 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 */ current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); + schedule_timeout((10*HZ)/1000); + 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); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_AOE, 0x0); + 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); } @@ -218,14 +316,9 @@ case CARD_RELEASE: release_io_asuscom(cs); return(0); - case CARD_SETIRQ: - return(request_irq(cs->irq, &asuscom_interrupt, - I4L_IRQ_FLAG, "HiSax", cs)); case CARD_INIT: - clear_pending_isac_ints(cs); - clear_pending_hscx_ints(cs); - initisac(cs); - inithscx(cs); + cs->debug |= L1_DEB_IPAC; + inithscxisac(cs, 3); return(0); case CARD_TEST: return(0); @@ -238,6 +331,7 @@ { int bytecnt; struct IsdnCardState *cs = card->cs; + u_char val; char tmp[64]; strcpy(tmp, Asuscom_revision); @@ -248,12 +342,6 @@ bytecnt = 8; cs->hw.asus.cfg_reg = card->para[1]; cs->irq = card->para[0]; - cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR; - cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC; - cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX; - cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7; - cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS; - if (check_region((cs->hw.asus.cfg_reg), bytecnt)) { printk(KERN_WARNING "HiSax: %s config port %x-%x already in use\n", @@ -264,27 +352,47 @@ } else { request_region(cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn"); } - - printk(KERN_INFO - "ISDNLink: defined at 0x%x IRQ %d\n", - cs->hw.asus.cfg_reg, - cs->irq); - printk(KERN_INFO "ISDNLink: resetting card\n"); - reset_asuscom(cs); - cs->readisac = &ReadISAC; - cs->writeisac = &WriteISAC; - cs->readisacfifo = &ReadISACfifo; - cs->writeisacfifo = &WriteISACfifo; + printk(KERN_INFO "ISDNLink: defined at 0x%x IRQ %d\n", + cs->hw.asus.cfg_reg, cs->irq); cs->BC_Read_Reg = &ReadHSCX; cs->BC_Write_Reg = &WriteHSCX; cs->BC_Send_Data = &hscx_fill_fifo; cs->cardmsg = &Asus_card_msg; - ISACVersion(cs, "ISDNLink:"); - if (HscxVersion(cs, "ISDNLink:")) { - printk(KERN_WARNING - "ISDNLink: wrong HSCX versions check IO address\n"); - release_io_asuscom(cs); - return (0); + val = readreg(cs->hw.asus.cfg_reg + ASUS_IPAC_ALE, + cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID); + if (val == 1) { + cs->subtyp = ASUS_IPAC; + cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE; + cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA; + cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + cs->readisac = &ReadISAC_IPAC; + cs->writeisac = &WriteISAC_IPAC; + cs->readisacfifo = &ReadISACfifo_IPAC; + cs->writeisacfifo = &WriteISACfifo_IPAC; + cs->irq_func = &asuscom_interrupt_ipac; + printk(KERN_INFO "Asus: IPAC version %x\n", val); + } else { + cs->subtyp = ASUS_ISACHSCX; + cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR; + cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC; + cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX; + cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7; + cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS; + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->irq_func = &asuscom_interrupt; + ISACVersion(cs, "ISDNLink:"); + if (HscxVersion(cs, "ISDNLink:")) { + printk(KERN_WARNING + "ISDNLink: wrong HSCX versions check IO address\n"); + release_io_asuscom(cs); + return (0); + } } + printk(KERN_INFO "ISDNLink: resetting card\n"); + reset_asuscom(cs); return (1); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/avm_a1.c linux.pre11.3/drivers/isdn/hisax/avm_a1.c --- linux.vanilla/drivers/isdn/hisax/avm_a1.c Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/hisax/avm_a1.c Mon Jul 19 23:59:33 1999 @@ -1,11 +1,24 @@ -/* $Id: avm_a1.c,v 2.7 1998/02/02 13:29:37 keil Exp $ +/* $Id: avm_a1.c,v 2.11 1999/07/12 21:04:54 keil Exp $ * avm_a1.c low level stuff for AVM A1 (Fritz) isdn cards * - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) * * * $Log: avm_a1.c,v $ + * Revision 2.11 1999/07/12 21:04:54 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 2.10 1998/11/15 23:54:21 keil + * changes from 2.0 + * + * Revision 2.9 1998/08/13 23:36:12 keil + * HiSax 3.1 - don't work stable with current LinkLevel + * + * Revision 2.8 1998/04/15 16:44:27 keil + * new init code + * * Revision 2.7 1998/02/02 13:29:37 keil * fast io * @@ -57,7 +70,7 @@ #include "isdnl1.h" extern const char *CardType[]; -const char *avm_revision = "$Revision: 2.7 $"; +static const char *avm_revision = "$Revision: 2.11 $"; #define AVM_A1_STAT_ISAC 0x01 #define AVM_A1_STAT_HSCX 0x02 @@ -144,8 +157,7 @@ avm_a1_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u_char val, sval, stat = 0; - char tmp[32]; + u_char val, sval; if (!cs) { printk(KERN_WARNING "AVM A1: Spurious interrupt!\n"); @@ -155,35 +167,25 @@ if (!(sval & AVM_A1_STAT_TIMER)) { byteout(cs->hw.avm.cfg_reg, 0x1E); sval = bytein(cs->hw.avm.cfg_reg); - } else if (cs->debug & L1_DEB_INTSTAT) { - sprintf(tmp, "avm IntStatus %x", sval); - debugl1(cs, tmp); - } + } else if (cs->debug & L1_DEB_INTSTAT) + debugl1(cs, "avm IntStatus %x", sval); if (!(sval & AVM_A1_STAT_HSCX)) { val = readreg(cs->hw.avm.hscx[1], HSCX_ISTA); - if (val) { + if (val) hscx_int_main(cs, val); - stat |= 1; - } } if (!(sval & AVM_A1_STAT_ISAC)) { val = readreg(cs->hw.avm.isac, ISAC_ISTA); - if (val) { + if (val) isac_interrupt(cs, val); - stat |= 2; - } } } - if (stat & 1) { - writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0xFF); - writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0xFF); - writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0x0); - writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0x0); - } - if (stat & 2) { - writereg(cs->hw.avm.isac, ISAC_MASK, 0xFF); - writereg(cs->hw.avm.isac, ISAC_MASK, 0x0); - } + writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0xFF); + writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0xFF); + writereg(cs->hw.avm.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.avm.isac, ISAC_MASK, 0x0); + writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0x0); + writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0x0); } inline static void @@ -213,14 +215,11 @@ case CARD_RELEASE: release_ioregs(cs, 0x3f); return(0); - case CARD_SETIRQ: - return(request_irq(cs->irq, &avm_a1_interrupt, - I4L_IRQ_FLAG, "HiSax", cs)); case CARD_INIT: - clear_pending_isac_ints(cs); - clear_pending_hscx_ints(cs); - initisac(cs); - inithscx(cs); + inithscxisac(cs, 1); + byteout(cs->hw.avm.cfg_reg, 0x16); + byteout(cs->hw.avm.cfg_reg, 0x1E); + inithscxisac(cs, 2); return(0); case CARD_TEST: return(0); @@ -348,7 +347,6 @@ val = bytein(cs->hw.avm.cfg_reg + 2); printk(KERN_INFO "AVM A1: Byte at %x is %x\n", cs->hw.avm.cfg_reg + 2, val); - byteout(cs->hw.avm.cfg_reg, 0x1E); val = bytein(cs->hw.avm.cfg_reg); printk(KERN_INFO "AVM A1: Byte at %x is %x\n", cs->hw.avm.cfg_reg, val); @@ -373,6 +371,7 @@ cs->BC_Write_Reg = &WriteHSCX; cs->BC_Send_Data = &hscx_fill_fifo; cs->cardmsg = &AVM_card_msg; + cs->irq_func = &avm_a1_interrupt; ISACVersion(cs, "AVM A1:"); if (HscxVersion(cs, "AVM A1:")) { printk(KERN_WARNING diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/avm_a1p.c linux.pre11.3/drivers/isdn/hisax/avm_a1p.c --- linux.vanilla/drivers/isdn/hisax/avm_a1p.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/avm_a1p.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,321 @@ +/* $Id: avm_a1p.c,v 2.4 1999/07/12 21:04:55 keil Exp $ + * + * avm_a1p.c low level stuff for the following AVM cards: + * A1 PCMCIA + * FRITZ!Card PCMCIA + * FRITZ!Card PCMCIA 2.0 + * + * Author Carsten Paeth (calle@calle.in-berlin.de) + * + * $Log: avm_a1p.c,v $ + * Revision 2.4 1999/07/12 21:04:55 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 2.3 1998/11/15 23:54:22 keil + * changes from 2.0 + * + * Revision 2.2 1998/08/13 23:36:13 keil + * HiSax 3.1 - don't work stable with current LinkLevel + * + * Revision 2.1 1998/07/15 15:01:23 calle + * Support for AVM passive PCMCIA cards: + * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0 + * + * Revision 1.1.2.1 1998/07/15 14:43:26 calle + * Support for AVM passive PCMCIA cards: + * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0 + * + * + */ +#define __NO_VERSION__ +#include "hisax.h" +#include "isac.h" +#include "hscx.h" +#include "isdnl1.h" + +/* register offsets */ +#define ADDRREG_OFFSET 0x02 +#define DATAREG_OFFSET 0x03 +#define ASL0_OFFSET 0x04 +#define ASL1_OFFSET 0x05 +#define MODREG_OFFSET 0x06 +#define VERREG_OFFSET 0x07 + +/* address offsets */ +#define ISAC_FIFO_OFFSET 0x00 +#define ISAC_REG_OFFSET 0x20 +#define HSCX_CH_DIFF 0x40 +#define HSCX_FIFO_OFFSET 0x80 +#define HSCX_REG_OFFSET 0xa0 + +/* read bits ASL0 */ +#define ASL0_R_TIMER 0x10 /* active low */ +#define ASL0_R_ISAC 0x20 /* active low */ +#define ASL0_R_HSCX 0x40 /* active low */ +#define ASL0_R_TESTBIT 0x80 +#define ASL0_R_IRQPENDING (ASL0_R_ISAC|ASL0_R_HSCX|ASL0_R_TIMER) + +/* write bits ASL0 */ +#define ASL0_W_RESET 0x01 +#define ASL0_W_TDISABLE 0x02 +#define ASL0_W_TRESET 0x04 +#define ASL0_W_IRQENABLE 0x08 +#define ASL0_W_TESTBIT 0x80 + +/* write bits ASL1 */ +#define ASL1_W_LED0 0x10 +#define ASL1_W_LED1 0x20 +#define ASL1_W_ENABLE_S0 0xC0 + +#define byteout(addr,val) outb(val,addr) +#define bytein(addr) inb(addr) + +static const char *avm_revision = "$Revision: 2.4 $"; + +static inline u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) +{ + long flags; + u_char ret; + + offset -= 0x20; + save_flags(flags); + cli(); + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset); + ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET); + restore_flags(flags); + return ret; +} + +static inline void +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) +{ + long flags; + + offset -= 0x20; + + save_flags(flags); + cli(); + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset); + byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value); + restore_flags(flags); +} + +static inline void +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + long flags; + + save_flags(flags); + cli(); + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET); + insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size); + restore_flags(flags); +} + +static inline void +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + long flags; + + save_flags(flags); + cli(); + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET); + outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size); + restore_flags(flags); +} + +static inline u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) +{ + u_char ret; + long flags; + + offset -= 0x20; + + save_flags(flags); + cli(); + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, + HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset); + ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET); + restore_flags(flags); + return ret; +} + +static inline void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) +{ + long flags; + + offset -= 0x20; + + save_flags(flags); + cli(); + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, + HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset); + byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value); + restore_flags(flags); +} + +static inline void +ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size) +{ + long flags; + + save_flags(flags); + cli(); + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, + HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF); + insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size); + restore_flags(flags); +} + +static inline void +WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size) +{ + long flags; + + save_flags(flags); + cli(); + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, + HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF); + outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size); + restore_flags(flags); +} + +/* + * fast interrupt HSCX stuff goes here + */ + +#define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg) +#define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data) +#define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt) + +#include "hscx_irq.c" + +static void +avm_a1p_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val, sval; + + if (!cs) { + printk(KERN_WARNING "AVM A1 PCMCIA: Spurious interrupt!\n"); + return; + } + while ((sval = (~bytein(cs->hw.avm.cfg_reg+ASL0_OFFSET) & ASL0_R_IRQPENDING))) { + if (cs->debug & L1_DEB_INTSTAT) + debugl1(cs, "avm IntStatus %x", sval); + if (sval & ASL0_R_HSCX) { + val = ReadHSCX(cs, 1, HSCX_ISTA); + if (val) + hscx_int_main(cs, val); + } + if (sval & ASL0_R_ISAC) { + val = ReadISAC(cs, ISAC_ISTA); + if (val) + isac_interrupt(cs, val); + } + } + WriteHSCX(cs, 0, HSCX_MASK, 0xff); + WriteHSCX(cs, 1, HSCX_MASK, 0xff); + WriteISAC(cs, ISAC_MASK, 0xff); + WriteISAC(cs, ISAC_MASK, 0x00); + WriteHSCX(cs, 0, HSCX_MASK, 0x00); + WriteHSCX(cs, 1, HSCX_MASK, 0x00); +} + +static int +AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + switch (mt) { + case CARD_RESET: + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00); + HZDELAY(HZ / 5 + 1); + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET); + HZDELAY(HZ / 5 + 1); + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00); + return 0; + + case CARD_RELEASE: + /* free_irq is done in HiSax_closecard(). */ + /* free_irq(cs->irq, cs); */ + return 0; + + case CARD_INIT: + clear_pending_isac_ints(cs); + clear_pending_hscx_ints(cs); + inithscxisac(cs, 1); + inithscxisac(cs, 2); + return 0; + + case CARD_TEST: + /* we really don't need it for the PCMCIA Version */ + return 0; + + default: + /* all card drivers ignore others, so we do the same */ + return 0; + } + return 0; +} + +__initfunc(int +setup_avm_a1_pcmcia(struct IsdnCard *card)) +{ + u_char model, vers; + struct IsdnCardState *cs = card->cs; + long flags; + char tmp[64]; + + + strcpy(tmp, avm_revision); + printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n", + HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_A1_PCMCIA) + return (0); + + cs->hw.avm.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + + + save_flags(flags); + outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0); + sti(); + + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00); + HZDELAY(HZ / 5 + 1); + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET); + HZDELAY(HZ / 5 + 1); + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00); + + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET, ASL0_W_TDISABLE|ASL0_W_TRESET); + + restore_flags(flags); + + model = bytein(cs->hw.avm.cfg_reg+MODREG_OFFSET); + vers = bytein(cs->hw.avm.cfg_reg+VERREG_OFFSET); + + printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n", + cs->hw.avm.cfg_reg, cs->irq, model, vers); + + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &AVM_card_msg; + cs->irq_func = &avm_a1p_interrupt; + + ISACVersion(cs, "AVM A1 PCMCIA:"); + if (HscxVersion(cs, "AVM A1 PCMCIA:")) { + printk(KERN_WARNING + "AVM A1 PCMCIA: wrong HSCX versions check IO address\n"); + return (0); + } + return (1); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/avm_pci.c linux.pre11.3/drivers/isdn/hisax/avm_pci.c --- linux.vanilla/drivers/isdn/hisax/avm_pci.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/avm_pci.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,898 @@ +/* $Id: avm_pci.c,v 1.9 1999/07/12 21:04:57 keil Exp $ + + * avm_pci.c low level stuff for AVM Fritz!PCI and ISA PnP isdn cards + * Thanks to AVM, Berlin for informations + * + * Author Karsten Keil (keil@isdn4linux.de) + * + * + * $Log: avm_pci.c,v $ + * Revision 1.9 1999/07/12 21:04:57 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 1.8 1999/07/01 08:11:19 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 1.7 1999/02/22 18:26:30 keil + * Argh ! ISAC address was only set with PCI + * + * Revision 1.6 1998/11/27 19:59:28 keil + * set subtype for Fritz!PCI + * + * Revision 1.5 1998/11/27 12:56:45 keil + * forgot to update setup function name + * + * Revision 1.4 1998/11/15 23:53:19 keil + * Fritz!PnP; changes from 2.0 + * + * Revision 1.3 1998/09/27 23:53:39 keil + * Fix error handling + * + * Revision 1.2 1998/09/27 12:54:55 keil + * bcs assign was lost in setstack, very bad results + * + * Revision 1.1 1998/08/20 13:47:30 keil + * first version + * + * + * + */ +#define __NO_VERSION__ +#include +#include "hisax.h" +#include "isac.h" +#include "isdnl1.h" +#include +#ifndef COMPAT_HAS_NEW_PCI +#include +#endif +#include + +extern const char *CardType[]; +static const char *avm_pci_rev = "$Revision: 1.9 $"; + +#define AVM_FRITZ_PCI 1 +#define AVM_FRITZ_PNP 2 + +#define PCI_VENDOR_AVM 0x1244 +#define PCI_FRITZPCI_ID 0xa00 + +#define HDLC_FIFO 0x0 +#define HDLC_STATUS 0x4 + +#define AVM_HDLC_1 0x00 +#define AVM_HDLC_2 0x01 +#define AVM_ISAC_FIFO 0x02 +#define AVM_ISAC_REG_LOW 0x04 +#define AVM_ISAC_REG_HIGH 0x06 + +#define AVM_STATUS0_IRQ_ISAC 0x01 +#define AVM_STATUS0_IRQ_HDLC 0x02 +#define AVM_STATUS0_IRQ_TIMER 0x04 +#define AVM_STATUS0_IRQ_MASK 0x07 + +#define AVM_STATUS0_RESET 0x01 +#define AVM_STATUS0_DIS_TIMER 0x02 +#define AVM_STATUS0_RES_TIMER 0x04 +#define AVM_STATUS0_ENA_IRQ 0x08 +#define AVM_STATUS0_TESTBIT 0x10 + +#define AVM_STATUS1_INT_SEL 0x0f +#define AVM_STATUS1_ENA_IOM 0x80 + +#define HDLC_MODE_ITF_FLG 0x01 +#define HDLC_MODE_TRANS 0x02 +#define HDLC_MODE_CCR_7 0x04 +#define HDLC_MODE_CCR_16 0x08 +#define HDLC_MODE_TESTLOOP 0x80 + +#define HDLC_INT_XPR 0x80 +#define HDLC_INT_XDU 0x40 +#define HDLC_INT_RPR 0x20 +#define HDLC_INT_MASK 0xE0 + +#define HDLC_STAT_RME 0x01 +#define HDLC_STAT_RDO 0x10 +#define HDLC_STAT_CRCVFRRAB 0x0E +#define HDLC_STAT_CRCVFR 0x06 +#define HDLC_STAT_RML_MASK 0x3f00 + +#define HDLC_CMD_XRS 0x80 +#define HDLC_CMD_XME 0x01 +#define HDLC_CMD_RRS 0x20 +#define HDLC_CMD_XML_MASK 0x3f00 + + +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) +{ + register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW; + register u_char val; + register long flags; + + save_flags(flags); + cli(); + outb(idx, cs->hw.avm.cfg_reg + 4); + val = inb(cs->hw.avm.isac + (offset & 0xf)); + restore_flags(flags); + return (val); +} + +static void +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) +{ + register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW; + register long flags; + + save_flags(flags); + cli(); + outb(idx, cs->hw.avm.cfg_reg + 4); + outb(value, cs->hw.avm.isac + (offset & 0xf)); + restore_flags(flags); +} + +static void +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + outb(AVM_ISAC_FIFO, cs->hw.avm.cfg_reg + 4); + insb(cs->hw.avm.isac, data, size); +} + +static void +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + outb(AVM_ISAC_FIFO, cs->hw.avm.cfg_reg + 4); + outsb(cs->hw.avm.isac, data, size); +} + +static inline u_int +ReadHDLCPCI(struct IsdnCardState *cs, int chan, u_char offset) +{ + register u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; + register u_int val; + register long flags; + + save_flags(flags); + cli(); + outl(idx, cs->hw.avm.cfg_reg + 4); + val = inl(cs->hw.avm.isac + offset); + restore_flags(flags); + return (val); +} + +static inline void +WriteHDLCPCI(struct IsdnCardState *cs, int chan, u_char offset, u_int value) +{ + register u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; + register long flags; + + save_flags(flags); + cli(); + outl(idx, cs->hw.avm.cfg_reg + 4); + outl(value, cs->hw.avm.isac + offset); + restore_flags(flags); +} + +static inline u_char +ReadHDLCPnP(struct IsdnCardState *cs, int chan, u_char offset) +{ + register u_char idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; + register u_char val; + register long flags; + + save_flags(flags); + cli(); + outb(idx, cs->hw.avm.cfg_reg + 4); + val = inb(cs->hw.avm.isac + offset); + restore_flags(flags); + return (val); +} + +static inline void +WriteHDLCPnP(struct IsdnCardState *cs, int chan, u_char offset, u_char value) +{ + register u_char idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; + register long flags; + + save_flags(flags); + cli(); + outb(idx, cs->hw.avm.cfg_reg + 4); + outb(value, cs->hw.avm.isac + offset); + restore_flags(flags); +} + +static u_char +ReadHDLC_s(struct IsdnCardState *cs, int chan, u_char offset) +{ + return(0xff & ReadHDLCPCI(cs, chan, offset)); +} + +static void +WriteHDLC_s(struct IsdnCardState *cs, int chan, u_char offset, u_char value) +{ + WriteHDLCPCI(cs, chan, offset, value); +} + +static inline +struct BCState *Sel_BCS(struct IsdnCardState *cs, int channel) +{ + if (cs->bcs[0].mode && (cs->bcs[0].channel == channel)) + return(&cs->bcs[0]); + else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel)) + return(&cs->bcs[1]); + else + return(NULL); +} + +void inline +hdlc_sched_event(struct BCState *bcs, int event) +{ + bcs->event |= 1 << event; + queue_task(&bcs->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +void +write_ctrl(struct BCState *bcs, int which) { + + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs, "hdlc %c wr%x ctrl %x", + 'A' + bcs->channel, which, bcs->hw.hdlc.ctrl.ctrl); + if (bcs->cs->subtyp == AVM_FRITZ_PCI) { + WriteHDLCPCI(bcs->cs, bcs->channel, HDLC_STATUS, bcs->hw.hdlc.ctrl.ctrl); + } else { + if (which & 4) + WriteHDLCPnP(bcs->cs, bcs->channel, HDLC_STATUS + 2, + bcs->hw.hdlc.ctrl.sr.mode); + if (which & 2) + WriteHDLCPnP(bcs->cs, bcs->channel, HDLC_STATUS + 1, + bcs->hw.hdlc.ctrl.sr.xml); + if (which & 1) + WriteHDLCPnP(bcs->cs, bcs->channel, HDLC_STATUS, + bcs->hw.hdlc.ctrl.sr.cmd); + } +} + +void +modehdlc(struct BCState *bcs, int mode, int bc) +{ + struct IsdnCardState *cs = bcs->cs; + int hdlc = bcs->channel; + + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hdlc %c mode %d ichan %d", + 'A' + hdlc, mode, bc); + bcs->mode = mode; + bcs->channel = bc; + bcs->hw.hdlc.ctrl.ctrl = 0; + switch (mode) { + case (L1_MODE_NULL): + bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS; + bcs->hw.hdlc.ctrl.sr.mode = HDLC_MODE_TRANS; + write_ctrl(bcs, 5); + break; + case (L1_MODE_TRANS): + bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS; + bcs->hw.hdlc.ctrl.sr.mode = HDLC_MODE_TRANS; + write_ctrl(bcs, 5); + bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS; + write_ctrl(bcs, 1); + bcs->hw.hdlc.ctrl.sr.cmd = 0; + hdlc_sched_event(bcs, B_XMTBUFREADY); + break; + case (L1_MODE_HDLC): + bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS; + bcs->hw.hdlc.ctrl.sr.mode = HDLC_MODE_ITF_FLG; + write_ctrl(bcs, 5); + bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS; + write_ctrl(bcs, 1); + bcs->hw.hdlc.ctrl.sr.cmd = 0; + hdlc_sched_event(bcs, B_XMTBUFREADY); + break; + } +} + +static inline void +hdlc_empty_fifo(struct BCState *bcs, int count) +{ + register u_int *ptr; + u_char *p; + u_char idx = bcs->channel ? AVM_HDLC_2 : AVM_HDLC_1; + int cnt=0; + struct IsdnCardState *cs = bcs->cs; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hdlc_empty_fifo %d", count); + if (bcs->hw.hdlc.rcvidx + count > HSCX_BUFMAX) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "hdlc_empty_fifo: incoming packet too large"); + return; + } + ptr = (u_int *) p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx; + bcs->hw.hdlc.rcvidx += count; + if (cs->subtyp == AVM_FRITZ_PCI) { + outl(idx, cs->hw.avm.cfg_reg + 4); + while (cnt < count) { + *ptr++ = inl(cs->hw.avm.isac); + cnt += 4; + } + } else { + outb(idx, cs->hw.avm.cfg_reg + 4); + while (cnt < count) { + *p++ = inb(cs->hw.avm.isac); + cnt++; + } + } + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + if (cs->subtyp == AVM_FRITZ_PNP) + p = (u_char *) ptr; + t += sprintf(t, "hdlc_empty_fifo %c cnt %d", + bcs->channel ? 'B' : 'A', count); + QuickHex(t, p, count); + debugl1(cs, bcs->blog); + } +} + +static inline void +hdlc_fill_fifo(struct BCState *bcs) +{ + struct IsdnCardState *cs = bcs->cs; + int count, cnt =0; + int fifo_size = 32; + u_char *p; + u_int *ptr; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hdlc_fill_fifo"); + if (!bcs->tx_skb) + return; + if (bcs->tx_skb->len <= 0) + return; + + bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XME; + if (bcs->tx_skb->len > fifo_size) { + count = fifo_size; + } else { + count = bcs->tx_skb->len; + if (bcs->mode != L1_MODE_TRANS) + bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XME; + } + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hdlc_fill_fifo %d/%ld", count, bcs->tx_skb->len); + ptr = (u_int *) p = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.hdlc.count += count; + bcs->hw.hdlc.ctrl.sr.xml = ((count == fifo_size) ? 0 : count); + write_ctrl(bcs, 3); /* sets the correct index too */ + if (cs->subtyp == AVM_FRITZ_PCI) { + while (cnthw.avm.isac); + cnt += 4; + } + } else { + while (cnthw.avm.isac); + cnt++; + } + } + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + if (cs->subtyp == AVM_FRITZ_PNP) + p = (u_char *) ptr; + t += sprintf(t, "hdlc_fill_fifo %c cnt %d", + bcs->channel ? 'B' : 'A', count); + QuickHex(t, p, count); + debugl1(cs, bcs->blog); + } +} + +static void +fill_hdlc(struct BCState *bcs) +{ + long flags; + save_flags(flags); + cli(); + hdlc_fill_fifo(bcs); + restore_flags(flags); +} + +static inline void +HDLC_irq(struct BCState *bcs, u_int stat) { + int len; + struct sk_buff *skb; + + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat); + if (stat & HDLC_INT_RPR) { + if (stat & HDLC_STAT_RDO) { + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs, "RDO"); + else + debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat); + bcs->hw.hdlc.ctrl.sr.xml = 0; + bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_RRS; + write_ctrl(bcs, 1); + bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_RRS; + write_ctrl(bcs, 1); + bcs->hw.hdlc.rcvidx = 0; + } else { + if (!(len = (stat & HDLC_STAT_RML_MASK)>>8)) + len = 32; + hdlc_empty_fifo(bcs, len); + if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) { + if (((stat & HDLC_STAT_CRCVFRRAB)==HDLC_STAT_CRCVFR) || + (bcs->mode == L1_MODE_TRANS)) { + if (!(skb = dev_alloc_skb(bcs->hw.hdlc.rcvidx))) + printk(KERN_WARNING "HDLC: receive out of memory\n"); + else { + memcpy(skb_put(skb, bcs->hw.hdlc.rcvidx), + bcs->hw.hdlc.rcvbuf, bcs->hw.hdlc.rcvidx); + skb_queue_tail(&bcs->rqueue, skb); + } + bcs->hw.hdlc.rcvidx = 0; + hdlc_sched_event(bcs, B_RCVBUFREADY); + } else { + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs, "invalid frame"); + else + debugl1(bcs->cs, "ch%d invalid frame %#x", bcs->channel, stat); + bcs->hw.hdlc.rcvidx = 0; + } + } + } + } + if (stat & HDLC_INT_XDU) { + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.hdlc.count); + bcs->tx_cnt += bcs->hw.hdlc.count; + bcs->hw.hdlc.count = 0; +// hdlc_sched_event(bcs, B_XMTBUFREADY); + if (bcs->cs->debug & L1_DEB_WARN) + debugl1(bcs->cs, "ch%d XDU", bcs->channel); + } else if (bcs->cs->debug & L1_DEB_WARN) + debugl1(bcs->cs, "ch%d XDU without skb", bcs->channel); + bcs->hw.hdlc.ctrl.sr.xml = 0; + bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS; + write_ctrl(bcs, 1); + bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS; + write_ctrl(bcs, 1); + hdlc_fill_fifo(bcs); + } else if (stat & HDLC_INT_XPR) { + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + hdlc_fill_fifo(bcs); + return; + } else { + if (bcs->st->lli.l1writewakeup && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) + bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hdlc.count); + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + bcs->hw.hdlc.count = 0; + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.hdlc.count = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + hdlc_fill_fifo(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + hdlc_sched_event(bcs, B_XMTBUFREADY); + } + } +} + +inline void +HDLC_irq_main(struct IsdnCardState *cs) +{ + u_int stat; + long flags; + struct BCState *bcs; + + save_flags(flags); + cli(); + if (cs->subtyp == AVM_FRITZ_PCI) { + stat = ReadHDLCPCI(cs, 0, HDLC_STATUS); + } else { + stat = ReadHDLCPnP(cs, 0, HDLC_STATUS); + if (stat & HDLC_INT_RPR) + stat |= (ReadHDLCPnP(cs, 0, HDLC_STATUS+1))<<8; + } + if (stat & HDLC_INT_MASK) { + if (!(bcs = Sel_BCS(cs, 0))) { + if (cs->debug) + debugl1(cs, "hdlc spurious channel 0 IRQ"); + } else + HDLC_irq(bcs, stat); + } + if (cs->subtyp == AVM_FRITZ_PCI) { + stat = ReadHDLCPCI(cs, 1, HDLC_STATUS); + } else { + stat = ReadHDLCPnP(cs, 1, HDLC_STATUS); + if (stat & HDLC_INT_RPR) + stat |= (ReadHDLCPnP(cs, 1, HDLC_STATUS+1))<<8; + } + if (stat & HDLC_INT_MASK) { + if (!(bcs = Sel_BCS(cs, 1))) { + if (cs->debug) + debugl1(cs, "hdlc spurious channel 1 IRQ"); + } else + HDLC_irq(bcs, stat); + } + restore_flags(flags); +} + +void +hdlc_l2l1(struct PStack *st, int pr, void *arg) +{ + struct sk_buff *skb = arg; + long flags; + + switch (pr) { + case (PH_DATA | REQUEST): + save_flags(flags); + cli(); + if (st->l1.bcs->tx_skb) { + skb_queue_tail(&st->l1.bcs->squeue, skb); + restore_flags(flags); + } else { + st->l1.bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + st->l1.bcs->hw.hdlc.count = 0; + restore_flags(flags); + st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); + } + break; + case (PH_PULL | INDICATION): + if (st->l1.bcs->tx_skb) { + printk(KERN_WARNING "hdlc_l2l1: this shouldn't happen\n"); + break; + } + test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + st->l1.bcs->tx_skb = skb; + st->l1.bcs->hw.hdlc.count = 0; + st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); + break; + case (PH_PULL | REQUEST): + if (!st->l1.bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + break; + case (PH_ACTIVATE | REQUEST): + test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + modehdlc(st->l1.bcs, st->l1.mode, st->l1.bc); + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | REQUEST): + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | CONFIRM): + test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + modehdlc(st->l1.bcs, 0, st->l1.bc); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); + break; + } +} + +void +close_hdlcstate(struct BCState *bcs) +{ + modehdlc(bcs, 0, 0); + if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { + if (bcs->hw.hdlc.rcvbuf) { + kfree(bcs->hw.hdlc.rcvbuf); + bcs->hw.hdlc.rcvbuf = NULL; + } + if (bcs->blog) { + kfree(bcs->blog); + bcs->blog = NULL; + } + discard_queue(&bcs->rqueue); + discard_queue(&bcs->squeue); + if (bcs->tx_skb) { + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + } + } +} + +int +open_hdlcstate(struct IsdnCardState *cs, struct BCState *bcs) +{ + if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { + if (!(bcs->hw.hdlc.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for hdlc.rcvbuf\n"); + return (1); + } + if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for bcs->blog\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + kfree(bcs->hw.hdlc.rcvbuf); + bcs->hw.hdlc.rcvbuf = NULL; + return (2); + } + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + } + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->event = 0; + bcs->hw.hdlc.rcvidx = 0; + bcs->tx_cnt = 0; + return (0); +} + +int +setstack_hdlc(struct PStack *st, struct BCState *bcs) +{ + bcs->channel = st->l1.bc; + if (open_hdlcstate(st->l1.hardware, bcs)) + return (-1); + st->l1.bcs = bcs; + st->l2.l2l1 = hdlc_l2l1; + setstack_manager(st); + bcs->st = st; + setstack_l1_B(st); + return (0); +} + +HISAX_INITFUNC(void +clear_pending_hdlc_ints(struct IsdnCardState *cs)) +{ + u_int val; + + if (cs->subtyp == AVM_FRITZ_PCI) { + val = ReadHDLCPCI(cs, 0, HDLC_STATUS); + debugl1(cs, "HDLC 1 STA %x", val); + val = ReadHDLCPCI(cs, 1, HDLC_STATUS); + debugl1(cs, "HDLC 2 STA %x", val); + } else { + val = ReadHDLCPnP(cs, 0, HDLC_STATUS); + debugl1(cs, "HDLC 1 STA %x", val); + val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 1); + debugl1(cs, "HDLC 1 RML %x", val); + val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 2); + debugl1(cs, "HDLC 1 MODE %x", val); + val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 3); + debugl1(cs, "HDLC 1 VIN %x", val); + val = ReadHDLCPnP(cs, 1, HDLC_STATUS); + debugl1(cs, "HDLC 2 STA %x", val); + val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 1); + debugl1(cs, "HDLC 2 RML %x", val); + val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 2); + debugl1(cs, "HDLC 2 MODE %x", val); + val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 3); + debugl1(cs, "HDLC 2 VIN %x", val); + } +} + +HISAX_INITFUNC(void +inithdlc(struct IsdnCardState *cs)) +{ + cs->bcs[0].BC_SetStack = setstack_hdlc; + cs->bcs[1].BC_SetStack = setstack_hdlc; + cs->bcs[0].BC_Close = close_hdlcstate; + cs->bcs[1].BC_Close = close_hdlcstate; + modehdlc(cs->bcs, 0, 0); + modehdlc(cs->bcs + 1, 0, 0); +} + +static void +avm_pcipnp_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val; + u_char sval; + + if (!cs) { + printk(KERN_WARNING "AVM PCI: Spurious interrupt!\n"); + return; + } + sval = inb(cs->hw.avm.cfg_reg + 2); + if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK) + /* possible a shared IRQ reqest */ + return; + if (!(sval & AVM_STATUS0_IRQ_ISAC)) { + val = ReadISAC(cs, ISAC_ISTA); + isac_interrupt(cs, val); + } + if (!(sval & AVM_STATUS0_IRQ_HDLC)) { + HDLC_irq_main(cs); + } + WriteISAC(cs, ISAC_MASK, 0xFF); + WriteISAC(cs, ISAC_MASK, 0x0); +} + +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); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + 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); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + printk(KERN_INFO "AVM PCI/PnP: S1 %x\n", inb(cs->hw.avm.cfg_reg + 3)); +} + +static int +AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + switch (mt) { + case CARD_RESET: + reset_avmpcipnp(cs); + return(0); + case CARD_RELEASE: + outb(0, cs->hw.avm.cfg_reg + 2); + release_region(cs->hw.avm.cfg_reg, 32); + return(0); + case CARD_INIT: + clear_pending_isac_ints(cs); + initisac(cs); + clear_pending_hdlc_ints(cs); + inithdlc(cs); + outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER, + cs->hw.avm.cfg_reg + 2); + WriteISAC(cs, ISAC_MASK, 0); + outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | + AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2); + /* RESET Receiver and Transmitter */ + WriteISAC(cs, ISAC_CMDR, 0x41); + return(0); + case CARD_TEST: + return(0); + } + return(0); +} + +#ifdef COMPAT_HAS_NEW_PCI +static struct pci_dev *dev_avm __initdata = NULL; +#else +static int pci_index __initdata = 0; +#endif + +__initfunc(int +setup_avm_pcipnp(struct IsdnCard *card)) +{ + u_int val, ver; + struct IsdnCardState *cs = card->cs; + char tmp[64]; + + strcpy(tmp, avm_pci_rev); + printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_FRITZPCI) + return (0); + if (card->para[1]) { + cs->hw.avm.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + cs->subtyp = AVM_FRITZ_PNP; + } else { +#if CONFIG_PCI +#ifdef COMPAT_HAS_NEW_PCI + if (!pci_present()) { + printk(KERN_ERR "FritzPCI: no PCI bus present\n"); + return(0); + } + if ((dev_avm = pci_find_device(PCI_VENDOR_AVM, + PCI_FRITZPCI_ID, dev_avm))) { + cs->irq = dev_avm->irq; + if (!cs->irq) { + printk(KERN_WARNING "FritzPCI: No IRQ for PCI card found\n"); + return(0); + } + cs->hw.avm.cfg_reg = dev_avm->base_address[1] & + PCI_BASE_ADDRESS_IO_MASK; + if (!cs->hw.avm.cfg_reg) { + printk(KERN_WARNING "FritzPCI: No IO-Adr for PCI card found\n"); + return(0); + } + cs->subtyp = AVM_FRITZ_PCI; + } else { + printk(KERN_WARNING "FritzPCI: No PCI card found\n"); + return(0); + } +#else + for (; pci_index < 255; pci_index++) { + unsigned char pci_bus, pci_device_fn; + unsigned int ioaddr; + unsigned char irq; + + if (pcibios_find_device (PCI_VENDOR_AVM, + PCI_FRITZPCI_ID, pci_index, + &pci_bus, &pci_device_fn) != 0) { + continue; + } + pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_INTERRUPT_LINE, &irq); + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_1, &ioaddr); + cs->irq = irq; + cs->hw.avm.cfg_reg = ioaddr & PCI_BASE_ADDRESS_IO_MASK; + if (!cs->hw.avm.cfg_reg) { + printk(KERN_WARNING "FritzPCI: No IO-Adr for PCI card found\n"); + return(0); + } + cs->subtyp = AVM_FRITZ_PCI; + break; + } + if (pci_index == 255) { + printk(KERN_WARNING "FritzPCI: No PCI card found\n"); + return(0); + } + pci_index++; +#endif /* COMPAT_HAS_NEW_PCI */ + cs->irq_flags |= SA_SHIRQ; +#else + printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n"); + return (0); +#endif /* CONFIG_PCI */ + } + cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; + if (check_region((cs->hw.avm.cfg_reg), 32)) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.avm.cfg_reg, + cs->hw.avm.cfg_reg + 31); + return (0); + } else { + request_region(cs->hw.avm.cfg_reg, 32, + (cs->subtyp == AVM_FRITZ_PCI) ? "avm PCI" : "avm PnP"); + } + switch (cs->subtyp) { + case AVM_FRITZ_PCI: + val = inl(cs->hw.avm.cfg_reg); + printk(KERN_INFO "AVM PCI: stat %#x\n", val); + printk(KERN_INFO "AVM PCI: Class %X Rev %d\n", + val & 0xff, (val>>8) & 0xff); + cs->BC_Read_Reg = &ReadHDLC_s; + cs->BC_Write_Reg = &WriteHDLC_s; + break; + case AVM_FRITZ_PNP: + val = inb(cs->hw.avm.cfg_reg); + ver = inb(cs->hw.avm.cfg_reg + 1); + printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver); + reset_avmpcipnp(cs); + cs->BC_Read_Reg = &ReadHDLCPnP; + cs->BC_Write_Reg = &WriteHDLCPnP; + break; + default: + printk(KERN_WARNING "AVM unknown subtype %d\n", cs->subtyp); + return(0); + } + printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n", + (cs->subtyp == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" : "AVM Fritz!PnP", + cs->irq, cs->hw.avm.cfg_reg); + + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Send_Data = &fill_hdlc; + cs->cardmsg = &AVM_card_msg; + cs->irq_func = &avm_pcipnp_interrupt; + ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:"); + return (1); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/bkm_a4t.c linux.pre11.3/drivers/isdn/hisax/bkm_a4t.c --- linux.vanilla/drivers/isdn/hisax/bkm_a4t.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/bkm_a4t.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,397 @@ +/* $Id: bkm_a4t.c,v 1.4 1999/07/14 11:43:14 keil Exp $ + * bkm_a4t.c low level stuff for T-Berkom A4T + * derived from the original file sedlbauer.c + * derived from the original file niccy.c + * derived from the original file netjet.c + * + * Author Roland Klabunde (R.Klabunde@Berkom.de) + * + * $Log: bkm_a4t.c,v $ + * Revision 1.4 1999/07/14 11:43:14 keil + * correct PCI_SUBSYSTEM_VENDOR_ID + * + * Revision 1.3 1999/07/12 21:04:58 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 1.2 1999/07/01 08:07:53 keil + * Initial version + * + * + */ + +#define __NO_VERSION__ + +#include "hisax.h" +#include "isac.h" +#include "hscx.h" +#include "jade.h" +#include "isdnl1.h" +#include "bkm_ax.h" +#include +#ifndef COMPAT_HAS_NEW_PCI +#include +#endif + +extern const char *CardType[]; + +const char *bkm_a4t_revision = "$Revision: 1.4 $"; + + +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) +{ + register u_int ret; + long flags; + unsigned int *po = (unsigned int *) adr; /* Postoffice */ + save_flags(flags); + cli(); + *po = (GCS_2 | PO_WRITE | off); + __WAITI20__(po); + *po = (ale | PO_READ); + __WAITI20__(po); + ret = *po; + restore_flags(flags); + return ((unsigned char) ret); +} + + +static inline void +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) +{ + /* fifo read without cli because it's allready done */ + int i; + for (i = 0; i < size; i++) + *data++ = readreg(ale, adr, off); +} + + +static inline void +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) +{ + long flags; + unsigned int *po = (unsigned int *) adr; /* Postoffice */ + save_flags(flags); + cli(); + *po = (GCS_2 | PO_WRITE | off); + __WAITI20__(po); + *po = (ale | PO_WRITE | data); + __WAITI20__(po); + restore_flags(flags); +} + + +static inline void +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) +{ + /* fifo write without cli because it's allready done */ + int i; + + for (i = 0; i < size; i++) + writereg(ale, adr, off, *data++); +} + + +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) +{ + return (readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset)); +} + +static void +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) +{ + writereg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset, value); +} + +static void +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + readfifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size); +} + +static void +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + writefifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size); +} + +static u_char +ReadJADE(struct IsdnCardState *cs, int jade, u_char offset) +{ + return (readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80)))); +} + +static void +WriteJADE(struct IsdnCardState *cs, int jade, u_char offset, u_char value) +{ + writereg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80)), value); +} + +/* + * fast interrupt JADE stuff goes here + */ + +#define READJADE(cs, nr, reg) readreg(cs->hw.ax.jade_ale,\ + cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80))) +#define WRITEJADE(cs, nr, reg, data) writereg(cs->hw.ax.jade_ale,\ + cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), data) + +#define READJADEFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ax.jade_ale,\ + cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt) +#define WRITEJADEFIFO(cs, nr, ptr, cnt) writefifo( cs->hw.ax.jade_ale,\ + cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt) + +#include "jade_irq.c" + +static void +bkm_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val = 0; + I20_REGISTER_FILE *pI20_Regs; + + if (!cs) { + printk(KERN_WARNING "HiSax: Telekom A4T: Spurious interrupt!\n"); + return; + } + pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); + + /* ISDN interrupt pending? */ + if (pI20_Regs->i20IntStatus & intISDN) { + /* Reset the ISDN interrupt */ + pI20_Regs->i20IntStatus = intISDN; + /* Disable ISDN interrupt */ + pI20_Regs->i20IntCtrl &= ~intISDN; + /* Channel A first */ + val = readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, jade_HDLC_ISR + 0x80); + if (val) { + jade_int_main(cs, val, 0); + } + /* Channel B */ + val = readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, jade_HDLC_ISR + 0xC0); + if (val) { + jade_int_main(cs, val, 1); + } + /* D-Channel */ + val = readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, ISAC_ISTA); + if (val) { + isac_interrupt(cs, val); + } + /* Reenable ISDN interrupt */ + pI20_Regs->i20IntCtrl |= intISDN; + } +} + +void +release_io_bkm(struct IsdnCardState *cs) +{ + if (cs->hw.ax.base) { + iounmap((void *) cs->hw.ax.base); + cs->hw.ax.base = 0; + } +} + +static void +enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable) +{ + if (cs->typ == ISDN_CTYPE_BKM_A4T) { + I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); + if (bEnable) + pI20_Regs->i20IntCtrl |= (intISDN | intPCI); + else + /* CAUTION: This disables the video capture driver too */ + pI20_Regs->i20IntCtrl &= ~(intISDN | intPCI); + } +} + +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 */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10 * HZ) / 1000); + /* Remove the soft reset */ + pI20_Regs->i20SysControl = sysRESET | 0xFF; + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10 * HZ) / 1000); + /* Set our configuration */ + pI20_Regs->i20SysControl = sysRESET | sysCFG; + /* Issue ISDN reset */ + pI20_Regs->i20GuestControl = guestWAIT_CFG | + g_A4T_JADE_RES | + g_A4T_ISAR_RES | + g_A4T_ISAC_RES | + g_A4T_JADE_BOOTR | + g_A4T_ISAR_BOOTR; + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10 * HZ) / 1000); + + /* Remove RESET state from ISDN */ + pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES | + g_A4T_JADE_RES | + g_A4T_ISAR_RES); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10 * HZ) / 1000); + restore_flags(flags); + } +} + +static int +BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + switch (mt) { + case CARD_RESET: + /* Disable ints */ + enable_bkm_int(cs, 0); + reset_bkm(cs); + return (0); + case CARD_RELEASE: + /* Sanity */ + enable_bkm_int(cs, 0); + reset_bkm(cs); + release_io_bkm(cs); + return (0); + case CARD_INIT: + clear_pending_isac_ints(cs); + clear_pending_jade_ints(cs); + initisac(cs); + initjade(cs); + /* Enable ints */ + enable_bkm_int(cs, 1); + return (0); + case CARD_TEST: + return (0); + } + return (0); +} + +#ifdef COMPAT_HAS_NEW_PCI +static struct pci_dev *dev_a4t __initdata = NULL; +#else +static int pci_index __initdata = 0; +#endif + +__initfunc(int + setup_bkm_a4t(struct IsdnCard *card)) +{ + struct IsdnCardState *cs = card->cs; + char tmp[64]; + u_int pci_memaddr = 0, found = 0; + I20_REGISTER_FILE *pI20_Regs; +#if CONFIG_PCI +#ifndef COMPAT_HAS_NEW_PCI + u_char pci_bus, pci_device_fn, pci_irq = 0; +#endif +#endif + + strcpy(tmp, bkm_a4t_revision); + printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ == ISDN_CTYPE_BKM_A4T) { + cs->subtyp = BKM_A4T; + } else + return (0); + +#if CONFIG_PCI +#ifdef COMPAT_HAS_NEW_PCI + if (!pci_present()) { + printk(KERN_ERR "bkm_a4t: no PCI bus present\n"); + return (0); + } + if ((dev_a4t = pci_find_device(I20_VENDOR_ID, I20_DEVICE_ID, dev_a4t))) { + u_int sub_sys_id = 0; + + pci_read_config_dword(dev_a4t, PCI_SUBSYSTEM_VENDOR_ID, + &sub_sys_id); + if (sub_sys_id == ((A4T_SUBSYS_ID << 16) | A4T_SUBVEN_ID)) { + found = 1; + pci_memaddr = dev_a4t->base_address[0]; + cs->irq = dev_a4t->irq; + } + } +#else + for (; pci_index < 0xff; pci_index++) { + if (pcibios_find_device(I20_VENDOR_ID, + I20_DEVICE_ID, + pci_index, + &pci_bus, + &pci_device_fn) == PCIBIOS_SUCCESSFUL) { + u_int sub_sys_id = 0; + + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_SUBSYSTEM_VENDOR_ID, &sub_sys_id); + if (sub_sys_id == ((A4T_SUBSYS_ID << 16) | A4T_SUBVEN_ID)) { + found = 1; + pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_INTERRUPT_LINE, &pci_irq); + cs->irq = pci_irq; + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_0, &pci_memaddr); + break; + } + } + } +#endif /* COMPAT_HAS_NEW_PCI */ + if (!found) { + printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]); + return (0); + } +#ifndef COMPAT_HAS_NEW_PCI + pci_index++; +#endif + if (!cs->irq) { /* IRQ range check ?? */ + printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]); + return (0); + } + if (!pci_memaddr) { + printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]); + return (0); + } + pci_memaddr &= PCI_BASE_ADDRESS_MEM_MASK; + cs->hw.ax.base = (u_int) ioremap(pci_memaddr, 4096); + /* Check suspecious address */ + pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); + if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) { + printk(KERN_WARNING "HiSax: %s address %x-%x suspecious\n", + CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096); + iounmap((void *) cs->hw.ax.base); + cs->hw.ax.base = 0; + return (0); + } + cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET; + cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET; + cs->hw.ax.isac_ale = GCS_1; + cs->hw.ax.jade_ale = GCS_3; +#else + printk(KERN_WARNING "HiSax: %s: NO_PCI_BIOS\n", CardType[card->typ]); + printk(KERN_WARNING "HiSax: %s: unable to configure\n", CardType[card->typ]); + return (0); +#endif /* CONFIG_PCI */ + printk(KERN_INFO "HiSax: %s: Card configured at 0x%X IRQ %d\n", + CardType[card->typ], cs->hw.ax.base, cs->irq); + + reset_bkm(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadJADE; + cs->BC_Write_Reg = &WriteJADE; + cs->BC_Send_Data = &jade_fill_fifo; + cs->cardmsg = &BKM_card_msg; + cs->irq_func = &bkm_interrupt; + cs->irq_flags |= SA_SHIRQ; + ISACVersion(cs, "Telekom A4T:"); + /* Jade version */ + JadeVersion(cs, "Telekom A4T:"); + return (1); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/bkm_a8.c linux.pre11.3/drivers/isdn/hisax/bkm_a8.c --- linux.vanilla/drivers/isdn/hisax/bkm_a8.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/bkm_a8.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,523 @@ +/* $Id: bkm_a8.c,v 1.4 1999/07/14 11:43:15 keil Exp $ + * bkm_a8.c low level stuff for Scitel Quadro (4*S0, passive) + * derived from the original file sedlbauer.c + * derived from the original file niccy.c + * derived from the original file netjet.c + * + * Author Roland Klabunde (R.Klabunde@Berkom.de) + * + * $Log: bkm_a8.c,v $ + * Revision 1.4 1999/07/14 11:43:15 keil + * correct PCI_SUBSYSTEM_VENDOR_ID + * + * Revision 1.3 1999/07/12 21:04:59 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 1.2 1999/07/01 08:07:54 keil + * Initial version + * + * + */ +#define __NO_VERSION__ + +#include "hisax.h" +#include "isac.h" +#include "ipac.h" +#include "hscx.h" +#include "isdnl1.h" +#include "bkm_ax.h" +#include +#ifndef COMPAT_HAS_NEW_PCI +#include +#endif + +#define ATTEMPT_PCI_REMAPPING /* Required for PLX rev 1 */ + +extern const char *CardType[]; + +const char sct_quadro_revision[] = "$Revision: 1.4 $"; + +/* To survive the startup phase */ +typedef struct { + u_int active; /* true/false */ + u_int base; /* ipac base address */ +} IPAC_STATE; + +static IPAC_STATE ipac_state[4 + 1] __initdata = +{ + {0, 0}, /* dummy */ + {0, 0}, /* SCT_1 */ + {0, 0}, /* SCT_2 */ + {0, 0}, /* SCT_3 */ + {0, 0} /* SCT_4 */ +}; + +static const char *sct_quadro_subtypes[] = +{ + "", + "#1", + "#2", + "#3", + "#4" +}; + + +#define wordout(addr,val) outw(val,addr) +#define wordin(addr) inw(addr) + +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) +{ + register u_char ret; + long flags; + save_flags(flags); + cli(); + wordout(ale, off); + ret = wordin(adr) & 0xFF; + restore_flags(flags); + return (ret); +} + +static inline void +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) +{ + /* fifo read without cli because it's allready done */ + int i; + wordout(ale, off); + for (i = 0; i < size; i++) + data[i] = wordin(adr) & 0xFF; +} + + +static inline void +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) +{ + long flags; + save_flags(flags); + cli(); + wordout(ale, off); + wordout(adr, data); + restore_flags(flags); +} + +static inline void +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) +{ + /* fifo write without cli because it's allready done */ + int i; + wordout(ale, off); + for (i = 0; i < size; i++) + wordout(adr, data[i]); +} + +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) +{ + return (readreg(cs->hw.ax.base, cs->hw.ax.data_adr, offset | 0x80)); +} + +static void +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) +{ + writereg(cs->hw.ax.base, cs->hw.ax.data_adr, offset | 0x80, value); +} + +static void +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + readfifo(cs->hw.ax.base, cs->hw.ax.data_adr, 0x80, data, size); +} + +static void +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + writefifo(cs->hw.ax.base, cs->hw.ax.data_adr, 0x80, data, size); +} + + +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) +{ + return (readreg(cs->hw.ax.base, cs->hw.ax.data_adr, offset + (hscx ? 0x40 : 0))); +} + +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) +{ + writereg(cs->hw.ax.base, cs->hw.ax.data_adr, offset + (hscx ? 0x40 : 0), value); +} + +/* Check whether the specified ipac is already active or not */ +static int +is_ipac_active(u_int ipac_nr) +{ + return (ipac_state[ipac_nr].active); +} + +/* Set the specific ipac to active */ +static void +set_ipac_active(u_int ipac_nr, u_int active) +{ + /* set activation state */ + ipac_state[ipac_nr].active = active; +} + +/* + * fast interrupt HSCX stuff goes here + */ + +#define READHSCX(cs, nr, reg) readreg(cs->hw.ax.base, \ + cs->hw.ax.data_adr, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.ax.base, \ + cs->hw.ax.data_adr, reg + (nr ? 0x40 : 0), data) +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ax.base, \ + cs->hw.ax.data_adr, (nr ? 0x40 : 0), ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.ax.base, \ + cs->hw.ax.data_adr, (nr ? 0x40 : 0), ptr, cnt) + +#include "hscx_irq.c" + +static void +bkm_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char ista, val, icnt = 5; + int i; + if (!cs) { + printk(KERN_WARNING "HiSax: Scitel Quadro: Spurious interrupt!\n"); + return; + } + ista = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ISTA); + + Start_IPAC: + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); + if (ista & 0x0f) { + val = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, HSCX_ISTA + 0x40); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) { + hscx_int_main(cs, val); + } + } + if (ista & 0x20) { + val = 0xfe & readreg(cs->hw.ax.base, cs->hw.ax.data_adr, ISAC_ISTA | 0x80); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ISTA); + if ((ista & 0x3f) && icnt) { + icnt--; + goto Start_IPAC; + } + if (!icnt) + printk(KERN_WARNING "HiSax: %s (%s) IRQ LOOP\n", + CardType[cs->typ], + sct_quadro_subtypes[cs->subtyp]); + writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xFF); + writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xC0); + + /* Read out all interrupt sources from currently not active ipacs */ + /* "Handle" all interrupts from currently not active ipac by reading the regs */ + for (i = SCT_1; i <= SCT_4; i++) + if (!is_ipac_active(i)) { + u_int base = ipac_state[i].base; + if (readreg(base, base + 4, 0xC1)) { + readreg(base, base + 4, 0xA0); + readreg(base, base + 4, 0xA4); + readreg(base, base + 4, 0x20); + readreg(base, base + 4, 0x24); + readreg(base, base + 4, 0x60); + readreg(base, base + 4, 0x64); + readreg(base, base + 4, 0xC1); + readreg(base, base + 4, ISAC_CIR0 + 0x80); + } + } +} + + +void +release_io_sct_quadro(struct IsdnCardState *cs) +{ + /* ?? */ +} + +static void +enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable) +{ + if (cs->typ == ISDN_CTYPE_SCT_QUADRO) { + if (bEnable) + wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) | 0x41)); + else + /* Issue general di only if no ipac is active */ + if (!is_ipac_active(SCT_1) && + !is_ipac_active(SCT_2) && + !is_ipac_active(SCT_3) && + !is_ipac_active(SCT_4)) + wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) & ~0x41)); + } +} + +static void +reset_bkm(struct IsdnCardState *cs) +{ + long flags; + + if (cs->typ == ISDN_CTYPE_SCT_QUADRO) { + if (!is_ipac_active(SCT_1) && + !is_ipac_active(SCT_2) && + !is_ipac_active(SCT_3) && + !is_ipac_active(SCT_4)) { + /* Issue total reset only if no ipac is active */ + wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) & ~4)); + + save_flags(flags); + sti(); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10 * HZ) / 1000); + + /* Remove the soft reset */ + wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) | 4)); + + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10 * HZ) / 1000); + restore_flags(flags); + } + } +} + +static int +BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + switch (mt) { + case CARD_RESET: + /* Disable ints */ + set_ipac_active(cs->subtyp, 0); + enable_bkm_int(cs, 0); + reset_bkm(cs); + return (0); + case CARD_RELEASE: + /* Sanity */ + set_ipac_active(cs->subtyp, 0); + enable_bkm_int(cs, 0); + reset_bkm(cs); + release_io_sct_quadro(cs); + return (0); + case CARD_INIT: + cs->debug |= L1_DEB_IPAC; + set_ipac_active(cs->subtyp, 1); + inithscxisac(cs, 3); + /* Enable ints */ + enable_bkm_int(cs, 1); + return (0); + case CARD_TEST: + return (0); + } + return (0); +} + +#ifdef COMPAT_HAS_NEW_PCI +static struct pci_dev *dev_a8 __initdata = NULL; +#else +static int pci_index __initdata = 0; +#endif + +__initfunc(int + setup_sct_quadro(struct IsdnCard *card)) +{ + struct IsdnCardState *cs = card->cs; + char tmp[64]; +#if CONFIG_PCI + u_char pci_bus = 0, pci_device_fn = 0, pci_irq = 0, pci_rev_id; + u_int found = 0; + u_int pci_ioaddr1, pci_ioaddr2, pci_ioaddr3, pci_ioaddr4, pci_ioaddr5; +#endif + + strcpy(tmp, sct_quadro_revision); + printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ == ISDN_CTYPE_SCT_QUADRO) { + cs->subtyp = SCT_1; /* Preset */ + } else + return (0); + + /* Identify subtype by para[0] */ + if (card->para[0] >= SCT_1 && card->para[0] <= SCT_4) + cs->subtyp = card->para[0]; + else + printk(KERN_WARNING "HiSax: %s: Invalid subcontroller in configuration, default to 1\n", + CardType[card->typ]); +#if CONFIG_PCI +#ifdef COMPAT_HAS_NEW_PCI + if (!pci_present()) { + printk(KERN_ERR "bkm_a4t: no PCI bus present\n"); + return (0); + } + if ((dev_a8 = pci_find_device(PLX_VENDOR_ID, PLX_DEVICE_ID, dev_a8))) { + u_int sub_sys_id = 0; + + pci_read_config_dword(dev_a8, PCI_SUBSYSTEM_VENDOR_ID, + &sub_sys_id); + if (sub_sys_id == ((SCT_SUBSYS_ID << 16) | SCT_SUBVEN_ID)) { + found = 1; + pci_ioaddr1 = dev_a8->base_address[1]; + pci_irq = dev_a8->irq; + pci_bus = dev_a8->bus->number; + pci_device_fn = dev_a8->devfn; + } + } +#else + for (; pci_index < 0xff; pci_index++) { + if (pcibios_find_device( + PLX_VENDOR_ID, + PLX_DEVICE_ID, + pci_index, + &pci_bus, + &pci_device_fn) == PCIBIOS_SUCCESSFUL) { + + u_int sub_sys_id = 0; + + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_SUBSYSTEM_VENDOR_ID, &sub_sys_id); + if (sub_sys_id == ((SCT_SUBSYS_ID << 16) | SCT_SUBVEN_ID)) { + found = 1; + pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_INTERRUPT_LINE, &pci_irq); + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_1, &pci_ioaddr1); + cs->irq = pci_irq; + break; + } + } + } +#endif /* COMPAT_HAS_NEW_PCI */ + if (!found) { + printk(KERN_WARNING "HiSax: %s (%s): Card not found\n", + CardType[card->typ], + sct_quadro_subtypes[cs->subtyp]); + return (0); + } +#ifndef COMPAT_HAS_NEW_PCI + pci_index++; /* need for more as one card */ +#endif + if (!pci_irq) { /* IRQ range check ?? */ + printk(KERN_WARNING "HiSax: %s (%s): No IRQ\n", + CardType[card->typ], + sct_quadro_subtypes[cs->subtyp]); + return (0); + } +#ifdef ATTEMPT_PCI_REMAPPING +/* HACK: PLX revision 1 bug: PLX address bit 7 must not be set */ + pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_REVISION_ID, &pci_rev_id); + if ((pci_ioaddr1 & 0x80) && (pci_rev_id == 1)) { + printk(KERN_WARNING "HiSax: %s (%s): PLX rev 1, remapping required!\n", + CardType[card->typ], + sct_quadro_subtypes[cs->subtyp]); + /* Restart PCI negotiation */ + pcibios_write_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_1, (u_int) - 1); + /* Move up by 0x80 byte */ + pci_ioaddr1 += 0x80; + pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK; + pcibios_write_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_1, pci_ioaddr1); +#ifdef COMPAT_HAS_NEW_PCI + dev_a8->base_address[1] = pci_ioaddr1; +#endif /* COMPAT_HAS_NEW_PCI */ + } +/* End HACK */ +#endif + pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &pci_ioaddr1); + pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &pci_ioaddr2); + pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_3, &pci_ioaddr3); + pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_4, &pci_ioaddr4); + pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_5, &pci_ioaddr5); + if (!pci_ioaddr1 || !pci_ioaddr2 || !pci_ioaddr3 || !pci_ioaddr4 || !pci_ioaddr5) { + printk(KERN_WARNING "HiSax: %s (%s): No IO base address(es)\n", + CardType[card->typ], + sct_quadro_subtypes[cs->subtyp]); + return (0); + } + pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK; + pci_ioaddr2 &= PCI_BASE_ADDRESS_IO_MASK; + pci_ioaddr3 &= PCI_BASE_ADDRESS_IO_MASK; + pci_ioaddr4 &= PCI_BASE_ADDRESS_IO_MASK; + pci_ioaddr5 &= PCI_BASE_ADDRESS_IO_MASK; + /* Take over */ + cs->irq = pci_irq; + cs->irq_flags |= SA_SHIRQ; + /* pci_ioaddr1 is unique to all subdevices */ + /* pci_ioaddr2 is for the fourth subdevice only */ + /* pci_ioaddr3 is for the third subdevice only */ + /* pci_ioaddr4 is for the second subdevice only */ + /* pci_ioaddr5 is for the first subdevice only */ + cs->hw.ax.plx_adr = pci_ioaddr1; + /* Enter all ipac_base addresses */ + ipac_state[SCT_1].base = pci_ioaddr5 + 0x00; + ipac_state[SCT_2].base = pci_ioaddr4 + 0x08; + ipac_state[SCT_3].base = pci_ioaddr3 + 0x10; + ipac_state[SCT_4].base = pci_ioaddr2 + 0x20; + /* For isac and hscx control path */ + cs->hw.ax.base = ipac_state[cs->subtyp].base; + /* For isac and hscx data path */ + cs->hw.ax.data_adr = cs->hw.ax.base + 4; +#else + printk(KERN_WARNING "HiSax: %s (%s): NO_PCI_BIOS\n", + CardType[card->typ], + sct_quadro_subtypes[cs->subtyp]); + printk(KERN_WARNING "HiSax: %s (%s): Unable to configure\n", + CardType[card->typ], + sct_quadro_subtypes[cs->subtyp]); + return (0); +#endif /* CONFIG_PCI */ + printk(KERN_INFO "HiSax: %s (%s) configured at 0x%.4X, 0x%.4X, 0x%.4X and IRQ %d\n", + CardType[card->typ], + sct_quadro_subtypes[cs->subtyp], + cs->hw.ax.plx_adr, + cs->hw.ax.base, + cs->hw.ax.data_adr, + cs->irq); + + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + + /* Disable all currently not active ipacs */ + if (!is_ipac_active(SCT_1)) + set_ipac_active(SCT_1, 0); + if (!is_ipac_active(SCT_2)) + set_ipac_active(SCT_2, 0); + if (!is_ipac_active(SCT_3)) + set_ipac_active(SCT_3, 0); + if (!is_ipac_active(SCT_4)) + set_ipac_active(SCT_4, 0); + + /* Perfom general reset (if possible) */ + reset_bkm(cs); + + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &BKM_card_msg; + cs->irq_func = &bkm_interrupt_ipac; + + printk(KERN_INFO "HiSax: %s (%s): IPAC Version %d\n", + CardType[card->typ], + sct_quadro_subtypes[cs->subtyp], + readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ID)); + return (1); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/bkm_ax.h linux.pre11.3/drivers/isdn/hisax/bkm_ax.h --- linux.vanilla/drivers/isdn/hisax/bkm_ax.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/bkm_ax.h Mon Jul 19 23:59:33 1999 @@ -0,0 +1,133 @@ +/* $Id: bkm_ax.h,v 1.2 1999/07/01 08:07:55 keil Exp $ + * bkm_ax.h low level decls for T-Berkom cards A4T and Scitel Quadro (4*S0, passive) + * + * Author Roland Klabunde (R.Klabunde@Berkom.de) + * + * $Log: bkm_ax.h,v $ + * Revision 1.2 1999/07/01 08:07:55 keil + * Initial version + * + * + * + */ + +#ifndef __BKM_AX_H__ +#define __BKM_AX_H__ + +/* Supported boards (subtypes) */ +#define SCT_1 1 +#define SCT_2 2 +#define SCT_3 3 +#define SCT_4 4 +#define BKM_A4T 5 + + +/* A4T */ +#define I20_DEVICE_ID 0x6120 /* I20 PCI device ID */ +#define I20_VENDOR_ID 0x11DE /* I20 PCI vendor ID */ +#define A4T_SUBVEN_ID 0x0871 +#define A4T_SUBSYS_ID 0xFFA4 +/* Scitel Quadro */ +#define PLX_DEVICE_ID 0x9050 /* Scitel Quadro PLX */ +#define PLX_VENDOR_ID 0x10B5 +#define SCT_SUBVEN_ID 0x0871 +#define SCT_SUBSYS_ID 0xFFA8 + + +#define PLX_ADDR_PLX 0x14 /* Addr PLX configuration */ +#define PLX_ADDR_ISAC 0x18 /* Addr ISAC */ +#define PLX_ADDR_HSCX 0x1C /* Addr HSCX */ +#define PLX_ADDR_ALE 0x20 /* Addr ALE */ +#define PLX_ADDR_ALEPLUS 0x24 /* Next Addr behind ALE */ + +#define PLX_SUBVEN 0x2C /* Offset SubVendor */ +#define PLX_SUBSYS 0x2E /* Offset SubSystem */ + + +/* Application specific registers I20 (Siemens SZB6120H) */ +typedef struct { + /* Video front end horizontal configuration register */ + volatile u_int i20VFEHorzCfg; /* Offset 00 */ + /* Video front end vertical configuration register */ + volatile u_int i20VFEVertCfg; /* Offset 04 */ + /* Video front end scaler and pixel format register */ + volatile u_int i20VFEScaler; /* Offset 08 */ + /* Video display top register */ + volatile u_int i20VDispTop; /* Offset 0C */ + /* Video display bottom register */ + volatile u_int i20VDispBottom; /* Offset 10 */ + /* Video stride, status and frame grab register */ + volatile u_int i20VidFrameGrab;/* Offset 14 */ + /* Video display configuration register */ + volatile u_int i20VDispCfg; /* Offset 18 */ + /* Video masking map top */ + volatile u_int i20VMaskTop; /* Offset 1C */ + /* Video masking map bottom */ + volatile u_int i20VMaskBottom; /* Offset 20 */ + /* Overlay control register */ + volatile u_int i20OvlyControl; /* Offset 24 */ + /* System, PCI and general purpose pins control register */ + volatile u_int i20SysControl; /* Offset 28 */ +#define sysRESET 0x01000000 /* bit 24:Softreset (Low) */ + /* GPIO 4...0: Output fixed for our cfg! */ +#define sysCFG 0x000000E0 /* GPIO 7,6,5: Input */ + /* General purpose pins and guest bus control register */ + volatile u_int i20GuestControl;/* Offset 2C */ +#define guestWAIT_CFG 0x00005555 /* 4 PCI waits for all */ +#define guestISDN_INT_E 0x01000000 /* ISDN Int en (low) */ +#define guestVID_INT_E 0x02000000 /* Video interrupt en (low) */ +#define guestADI1_INT_R 0x04000000 /* ADI #1 int req (low) */ +#define guestADI2_INT_R 0x08000000 /* ADI #2 int req (low) */ +#define guestISDN_RES 0x10000000 /* ISDN reset bit (high) */ +#define guestADI1_INT_S 0x20000000 /* ADI #1 int pending (low) */ +#define guestADI2_INT_S 0x40000000 /* ADI #2 int pending (low) */ +#define guestISDN_INT_S 0x80000000 /* ISAC int pending (low) */ + +#define g_A4T_JADE_RES 0x01000000 /* JADE Reset (High) */ +#define g_A4T_ISAR_RES 0x02000000 /* ISAR Reset (High) */ +#define g_A4T_ISAC_RES 0x04000000 /* ISAC Reset (High) */ +#define g_A4T_JADE_BOOTR 0x08000000 /* JADE enable boot SRAM (Low) NOT USED */ +#define g_A4T_ISAR_BOOTR 0x10000000 /* ISAR enable boot SRAM (Low) NOT USED */ +#define g_A4T_JADE_INT_S 0x20000000 /* JADE interrupt pnd (Low) */ +#define g_A4T_ISAR_INT_S 0x40000000 /* ISAR interrupt pnd (Low) */ +#define g_A4T_ISAC_INT_S 0x80000000 /* ISAC interrupt pnd (Low) */ + + volatile u_int i20CodeSource; /* Offset 30 */ + volatile u_int i20CodeXferCtrl;/* Offset 34 */ + volatile u_int i20CodeMemPtr; /* Offset 38 */ + + volatile u_int i20IntStatus; /* Offset 3C */ + volatile u_int i20IntCtrl; /* Offset 40 */ +#define intISDN 0x40000000 /* GIRQ1En (ISAC/ADI) (High) */ +#define intVID 0x20000000 /* GIRQ0En (VSYNC) (High) */ +#define intCOD 0x10000000 /* CodRepIrqEn (High) */ +#define intPCI 0x01000000 /* PCI IntA enable (High) */ + + volatile u_int i20I2CCtrl; /* Offset 44 */ +} I20_REGISTER_FILE, *PI20_REGISTER_FILE; + +/* + * Postoffice structure for A4T + * + */ +#define PO_OFFSET 0x00000200 /* Postoffice offset from base */ + +#define GCS_0 0x00000000 /* Guest bus chip selects */ +#define GCS_1 0x00100000 +#define GCS_2 0x00200000 +#define GCS_3 0x00300000 + +#define PO_READ 0x00000000 /* R/W from/to guest bus */ +#define PO_WRITE 0x00800000 + +#define PO_PEND 0x02000000 + +#define POSTOFFICE(postoffice) *(volatile unsigned int*)(postoffice) + +/* Wait unlimited (don't worry) */ +#define __WAITI20__(postoffice) \ +do { \ + while ((POSTOFFICE(postoffice) & PO_PEND)) ; \ +} while (0) + +#endif /* __BKM_AX_H__ */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/callc.c linux.pre11.3/drivers/isdn/hisax/callc.c --- linux.vanilla/drivers/isdn/hisax/callc.c Mon Dec 28 23:09:42 1998 +++ linux.pre11.3/drivers/isdn/hisax/callc.c Mon Jul 19 23:59:33 1999 @@ -1,12 +1,74 @@ -/* $Id: callc.c,v 2.13 1998/02/12 23:07:16 keil Exp $ +/* $Id: callc.c,v 2.29 1999/07/13 21:05:41 werner Exp $ - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden * + * This file is (c) under GNU PUBLIC LICENSE + * For changes and modifications please read + * ../../../Documentation/isdn/HiSax.cert + * * Thanks to Jan den Ouden * Fritz Elfert * * $Log: callc.c,v $ + * Revision 2.29 1999/07/13 21:05:41 werner + * Modified set_channel_limit to use new callback ISDN_STAT_DISCH. + * + * Revision 2.28 1999/07/09 08:30:02 keil + * cosmetics + * + * Revision 2.27 1999/07/05 23:51:38 werner + * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl + * hisaxctrl id 10 + * + * Revision 2.26 1999/07/01 08:11:21 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 2.25 1999/01/02 11:17:20 keil + * Changes for 2.2 + * + * Revision 2.24 1998/11/15 23:54:24 keil + * changes from 2.0 + * + * Revision 2.23 1998/09/30 22:21:57 keil + * cosmetics + * + * Revision 2.22 1998/08/20 13:50:29 keil + * More support for hybrid modem (not working yet) + * + * Revision 2.21 1998/08/13 23:36:15 keil + * HiSax 3.1 - don't work stable with current LinkLevel + * + * Revision 2.20 1998/06/26 15:13:05 fritz + * Added handling of STAT_ICALL with incomplete CPN. + * Added AT&L for ttyI emulator. + * Added more locking stuff in tty_write. + * + * Revision 2.19 1998/05/25 14:08:06 keil + * HiSax 3.0 + * fixed X.75 and leased line to work again + * Point2Point and fixed TEI are runtime options now: + * hisaxctrl 7 1 set PTP + * hisaxctrl 8 + * set fixed TEI to TEIVALUE (0-63) + * + * Revision 2.18 1998/05/25 12:57:40 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * + * Revision 2.17 1998/04/15 16:46:06 keil + * RESUME support + * + * Revision 2.16 1998/04/10 10:35:17 paul + * fixed (silly?) warnings from egcs on Alpha. + * + * Revision 2.15 1998/03/19 13:18:37 keil + * Start of a CAPI like interface for supplementary Service + * first service: SUSPEND + * + * Revision 2.14 1998/03/07 22:56:54 tsbogend + * made HiSax working on Linux/Alpha + * * Revision 2.13 1998/02/12 23:07:16 keil * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * @@ -60,12 +122,18 @@ #define __NO_VERSION__ #include "hisax.h" +#include "../avmb1/capicmd.h" /* this should be moved in a common place */ #ifdef MODULE +#ifdef COMPAT_HAS_NEW_SYMTAB #define MOD_USE_COUNT ( GET_USE_COUNT (&__this_module)) -#endif /* MODULE */ +#else +extern long mod_use_count_; +#define MOD_USE_COUNT mod_use_count_ +#endif /* COMPAT_HAS_NEW_SYMTAB */ +#endif /* MODULE */ -const char *lli_revision = "$Revision: 2.13 $"; +const char *lli_revision = "$Revision: 2.29 $"; extern struct IsdnCard cards[]; extern int nrcards; @@ -77,20 +145,18 @@ static struct Fsm callcfsm = {NULL, 0, 0, NULL, NULL}; -static struct Fsm lcfsm = -{NULL, 0, 0, NULL, NULL}; static int chancount = 0; -/* experimental REJECT after ALERTING for CALLBACK to beat the 4s delay */ -#define ALERT_REJECT 1 +/* experimental REJECT after ALERTING for CALLBACK to beat the 4s delay */ +#define ALERT_REJECT 0 /* Value to delay the sending of the first B-channel paket after CONNECT * here is no value given by ITU, but experience shows that 300 ms will * work on many networks, if you or your other side is behind local exchanges * a greater value may be recommented. If the delay is to short the first paket * will be lost and autodetect on many comercial routers goes wrong ! - * You can adjust this value on runtime with + * You can adjust this value on runtime with * hisaxctrl 2 * value is in milliseconds */ @@ -98,27 +164,7 @@ /* Flags for remembering action done in lli */ -#define FLG_START_D 0 -#define FLG_ESTAB_D 1 -#define FLG_CALL_SEND 2 -#define FLG_CALL_REC 3 -#define FLG_CALL_ALERT 4 -#define FLG_START_B 5 -#define FLG_CONNECT_B 6 -#define FLG_LL_DCONN 7 -#define FLG_LL_BCONN 8 -#define FLG_DISC_SEND 9 -#define FLG_DISC_REC 10 -#define FLG_REL_REC 11 -#define FLG_DO_ALERT 12 -#define FLG_DO_HANGUP 13 -#define FLG_DO_CONNECT 14 -#define FLG_DO_ESTAB 15 - -/* - * Because of callback it's a good idea to delay the shutdown of the d-channel - */ -#define DREL_TIMER_VALUE 10000 +#define FLG_START_B 0 /* * Find card with given driverId @@ -136,55 +182,66 @@ return (struct IsdnCardState *) 0; } -static void -link_debug(struct Channel *chanp, char *s, int direction) +int +discard_queue(struct sk_buff_head *q) { - char tmp[100], tm[32]; + struct sk_buff *skb; + int ret=0; - jiftime(tm, jiffies); - sprintf(tmp, "%s Channel %d %s %s\n", tm, chanp->chan, - direction ? "LL->HL" : "HL->LL", s); - HiSax_putstatus(chanp->cs, tmp); + while ((skb = skb_dequeue(q))) { + idev_kfree_skb(skb, FREE_READ); + ret++; + } + return(ret); } +static void +link_debug(struct Channel *chanp, int direction, char *fmt, ...) +{ + va_list args; + char tmp[16]; + + va_start(args, fmt); + sprintf(tmp, "Ch%d %s ", chanp->chan, + direction ? "LL->HL" : "HL->LL"); + VHiSax_putstatus(chanp->cs, tmp, fmt, args); + va_end(args); +} enum { - ST_NULL, /* 0 inactive */ - ST_OUT_WAIT_D, /* 1 outgoing, awaiting d-channel establishment */ - ST_IN_WAIT_D, /* 2 incoming, awaiting d-channel establishment */ - ST_OUT_DIAL, /* 3 outgoing, SETUP send; awaiting confirm */ - ST_IN_WAIT_LL, /* 4 incoming call received; wait for LL confirm */ - ST_IN_ALERT_SEND, /* 5 incoming call received; ALERT send */ - ST_IN_WAIT_CONN_ACK, /* 6 incoming CONNECT send; awaiting CONN_ACK */ - ST_WAIT_BCONN, /* 7 CONNECT/CONN_ACK received, awaiting b-channel prot. estbl. */ - ST_ACTIVE, /* 8 active, b channel prot. established */ - ST_WAIT_BRELEASE, /* 9 call clear. (initiator), awaiting b channel prot. rel. */ - ST_WAIT_BREL_DISC, /* 10 call clear. (receiver), DISCONNECT req. received */ - ST_WAIT_DCOMMAND, /* 11 call clear. (receiver), awaiting DCHANNEL message */ - ST_WAIT_DRELEASE, /* 12 DISCONNECT sent, awaiting RELEASE */ - ST_WAIT_D_REL_CNF, /* 13 RELEASE sent, awaiting RELEASE confirm */ - ST_WAIT_DSHUTDOWN, /* 14 awaiting d-channel shutdown */ + ST_NULL, /* 0 inactive */ + ST_OUT_DIAL, /* 1 outgoing, SETUP send; awaiting confirm */ + ST_IN_WAIT_LL, /* 2 incoming call received; wait for LL confirm */ + ST_IN_ALERT_SENT, /* 3 incoming call received; ALERT send */ + ST_IN_WAIT_CONN_ACK, /* 4 incoming CONNECT send; awaiting CONN_ACK */ + ST_WAIT_BCONN, /* 5 CONNECT/CONN_ACK received, awaiting b-channel prot. estbl. */ + ST_ACTIVE, /* 6 active, b channel prot. established */ + ST_WAIT_BRELEASE, /* 7 call clear. (initiator), awaiting b channel prot. rel. */ + ST_WAIT_BREL_DISC, /* 8 call clear. (receiver), DISCONNECT req. received */ + ST_WAIT_DCOMMAND, /* 9 call clear. (receiver), awaiting DCHANNEL message */ + ST_WAIT_DRELEASE, /* 10 DISCONNECT sent, awaiting RELEASE */ + ST_WAIT_D_REL_CNF, /* 11 RELEASE sent, awaiting RELEASE confirm */ + ST_IN_PROCEED_SEND, /* 12 incoming call, proceeding send */ }; + -#define STATE_COUNT (ST_WAIT_DSHUTDOWN +1) +#define STATE_COUNT (ST_IN_PROCEED_SEND + 1) -static char *strState[] = -{ - "ST_NULL", - "ST_OUT_WAIT_D", - "ST_IN_WAIT_D", - "ST_OUT_DIAL", - "ST_IN_WAIT_LL", - "ST_IN_ALERT_SEND", - "ST_IN_WAIT_CONN_ACK", - "ST_WAIT_BCONN", - "ST_ACTIVE", + static char *strState[] = + { + "ST_NULL", + "ST_OUT_DIAL", + "ST_IN_WAIT_LL", + "ST_IN_ALERT_SENT", + "ST_IN_WAIT_CONN_ACK", + "ST_WAIT_BCONN", + "ST_ACTIVE", "ST_WAIT_BRELEASE", "ST_WAIT_BREL_DISC", "ST_WAIT_DCOMMAND", "ST_WAIT_DRELEASE", "ST_WAIT_D_REL_CNF", - "ST_WAIT_DSHUTDOWN", + "ST_IN_PROCEED_SEND", }; enum { @@ -192,29 +249,28 @@ EV_SETUP_CNF, /* 1 */ EV_ACCEPTB, /* 2 */ EV_DISCONNECT_IND, /* 3 */ - EV_RELEASE_CNF, /* 4 */ - EV_DLEST, /* 5 */ - EV_DLRL, /* 6 */ + EV_RELEASE, /* 4 */ + EV_LEASED, /* 5 */ + EV_LEASED_REL, /* 6 */ EV_SETUP_IND, /* 7 */ - EV_RELEASE_IND, /* 8 */ - EV_ACCEPTD, /* 9 */ - EV_SETUP_CMPL_IND, /* 10 */ - EV_BC_EST, /* 11 */ - EV_WRITEBUF, /* 12 */ - EV_ESTABLISH, /* 13 */ - EV_HANGUP, /* 14 */ - EV_BC_REL, /* 15 */ - EV_CINF, /* 16 */ - EV_SUSPEND, /* 17 */ - EV_RESUME, /* 18 */ - EV_SHUTDOWN_D, /* 19 */ - EV_NOSETUP_RSP, /* 20 */ - EV_SETUP_ERR, /* 21 */ - EV_CONNECT_ERR, /* 22 */ - EV_RELEASE_ERR, /* 23 */ + EV_ACCEPTD, /* 8 */ + EV_SETUP_CMPL_IND, /* 9 */ + EV_BC_EST, /* 10 */ + EV_WRITEBUF, /* 11 */ + EV_HANGUP, /* 12 */ + EV_BC_REL, /* 13 */ + EV_CINF, /* 14 */ + EV_SUSPEND, /* 15 */ + EV_RESUME, /* 16 */ + EV_NOSETUP_RSP, /* 17 */ + EV_SETUP_ERR, /* 18 */ + EV_CONNECT_ERR, /* 19 */ + EV_PROCEED, /* 20 */ + EV_ALERT, /* 21 */ + EV_REDIR, /* 22 */ }; -#define EVENT_COUNT (EV_RELEASE_ERR +1) +#define EVENT_COUNT (EV_REDIR + 1) static char *strEvent[] = { @@ -222,83 +278,45 @@ "EV_SETUP_CNF", "EV_ACCEPTB", "EV_DISCONNECT_IND", - "EV_RELEASE_CNF", - "EV_DLEST", - "EV_DLRL", + "EV_RELEASE", + "EV_LEASED", + "EV_LEASED_REL", "EV_SETUP_IND", - "EV_RELEASE_IND", "EV_ACCEPTD", "EV_SETUP_CMPL_IND", "EV_BC_EST", "EV_WRITEBUF", - "EV_ESTABLISH", "EV_HANGUP", "EV_BC_REL", "EV_CINF", "EV_SUSPEND", "EV_RESUME", - "EV_SHUTDOWN_D", "EV_NOSETUP_RSP", "EV_SETUP_ERR", "EV_CONNECT_ERR", - "EV_RELEASE_ERR", -}; - -enum { - ST_LC_NULL, - ST_LC_ACTIVATE_WAIT, - ST_LC_DELAY, - ST_LC_ESTABLISH_WAIT, - ST_LC_CONNECTED, - ST_LC_FLUSH_WAIT, - ST_LC_RELEASE_WAIT, -}; - -#define LC_STATE_COUNT (ST_LC_RELEASE_WAIT+1) - -static char *strLcState[] = -{ - "ST_LC_NULL", - "ST_LC_ACTIVATE_WAIT", - "ST_LC_DELAY", - "ST_LC_ESTABLISH_WAIT", - "ST_LC_CONNECTED", - "ST_LC_FLUSH_WAIT", - "ST_LC_RELEASE_WAIT", -}; - -enum { - EV_LC_ESTABLISH, - EV_LC_PH_ACTIVATE, - EV_LC_PH_DEACTIVATE, - EV_LC_DL_ESTABLISH, - EV_LC_TIMER, - EV_LC_DL_RELEASE, - EV_LC_RELEASE, + "EV_PROCEED", + "EV_ALERT", + "EV_REDIR", }; -#define LC_EVENT_COUNT (EV_LC_RELEASE+1) -static char *strLcEvent[] = +static inline void +HL_LL(struct Channel *chanp, int command) { - "EV_LC_ESTABLISH", - "EV_LC_PH_ACTIVATE", - "EV_LC_PH_DEACTIVATE", - "EV_LC_DL_ESTABLISH", - "EV_LC_TIMER", - "EV_LC_DL_RELEASE", - "EV_LC_RELEASE", -}; - -#define LC_D 0 -#define LC_B 1 + isdn_ctrl ic; + + ic.driver = chanp->cs->myid; + ic.command = command; + ic.arg = chanp->chan; + chanp->cs->iif.statcallb(&ic); +} static inline void lli_deliver_cause(struct Channel *chanp) { - isdn_ctrl ic; - - if (chanp->proc->para.cause < 0) + isdn_ctrl ic; + + if (chanp->proc->para.cause == NO_CAUSE) return; ic.driver = chanp->cs->myid; ic.command = ISDN_STAT_CAUSE; @@ -312,166 +330,121 @@ chanp->cs->iif.statcallb(&ic); } -static void -lli_d_established(struct FsmInst *fi, int event, void *arg) +static inline void +lli_close(struct FsmInst *fi) { - struct Channel *chanp = fi->userdata; - - test_and_set_bit(FLG_ESTAB_D, &chanp->Flags); - if (chanp->leased) { - isdn_ctrl ic; - int ret; - char txt[32]; + struct Channel *chanp = fi->userdata; - chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) chanp->chan); - FsmChangeState(fi, ST_IN_WAIT_LL); - test_and_set_bit(FLG_CALL_REC, &chanp->Flags); - if (chanp->debug & 1) - link_debug(chanp, "STAT_ICALL_LEASED", 0); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_ICALL; - ic.arg = chanp->chan; - ic.parm.setup.si1 = 7; - ic.parm.setup.si2 = 0; - ic.parm.setup.plan = 0; - ic.parm.setup.screen = 0; - sprintf(ic.parm.setup.eazmsn,"%d", chanp->chan + 1); - sprintf(ic.parm.setup.phone,"LEASED%d", chanp->cs->myid); - ret = chanp->cs->iif.statcallb(&ic); - if (chanp->debug & 1) { - sprintf(txt, "statcallb ret=%d", ret); - link_debug(chanp, txt, 1); - } - if (!ret) { - chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan); - FsmChangeState(fi, ST_NULL); - } - } else if (fi->state == ST_WAIT_DSHUTDOWN) - FsmChangeState(fi, ST_NULL); + FsmChangeState(fi, ST_NULL); + chanp->Flags = 0; + chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); +} + + static void +lli_leased_in(struct FsmInst *fi, int event, void *arg) +{ + struct Channel *chanp = fi->userdata; + + isdn_ctrl ic; + int ret; + + chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); + FsmChangeState(fi, ST_IN_WAIT_LL); + if (chanp->debug & 1) + link_debug(chanp, 0, "STAT_ICALL_LEASED"); + ic.driver = chanp->cs->myid; + ic.command = ((chanp->chan < 2) ? ISDN_STAT_ICALL : ISDN_STAT_ICALLW); + ic.arg = chanp->chan; + ic.parm.setup.si1 = 7; + ic.parm.setup.si2 = 0; + ic.parm.setup.plan = 0; + ic.parm.setup.screen = 0; + sprintf(ic.parm.setup.eazmsn,"%d", chanp->chan + 1); + sprintf(ic.parm.setup.phone,"LEASED%d", chanp->cs->myid); + ret = chanp->cs->iif.statcallb(&ic); + if (chanp->debug & 1) + link_debug(chanp, 1, "statcallb ret=%d", ret); + + if (!ret) { + chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); + FsmChangeState(fi, ST_NULL); + } } -static void -lli_d_released(struct FsmInst *fi, int event, void *arg) -{ - struct Channel *chanp = fi->userdata; - - test_and_clear_bit(FLG_START_D, &chanp->Flags); -} /* * Dial out */ static void +lli_init_bchan_out(struct FsmInst *fi, int event, void *arg) +{ + struct Channel *chanp = fi->userdata; + + FsmChangeState(fi, ST_WAIT_BCONN); + if (chanp->debug & 1) + link_debug(chanp, 0, "STAT_DCONN"); + HL_LL(chanp, ISDN_STAT_DCONN); + init_b_st(chanp, 0); + chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL); +} + +static void lli_prep_dialout(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; - FsmChangeState(fi, ST_OUT_WAIT_D); FsmDelTimer(&chanp->drel_timer, 60); FsmDelTimer(&chanp->dial_timer, 73); chanp->l2_active_protocol = chanp->l2_protocol; chanp->incoming = 0; - chanp->lc_b->l2_start = !0; - switch (chanp->l2_active_protocol) { - case (ISDN_PROTO_L2_X75I): - chanp->lc_b->l2_establish = !0; - break; - case (ISDN_PROTO_L2_HDLC): - case (ISDN_PROTO_L2_TRANS): - chanp->lc_b->l2_establish = 0; - break; - default: - printk(KERN_WARNING "lli_prep_dialout unknown protocol\n"); - break; - } - if (test_bit(FLG_ESTAB_D, &chanp->Flags)) { - FsmEvent(fi, EV_DLEST, NULL); - } else { - chanp->Flags = 0; - test_and_set_bit(FLG_START_D, &chanp->Flags); - if (chanp->leased) { - chanp->lc_d->l2_establish = 0; - } - FsmEvent(&chanp->lc_d->lcfi, EV_LC_ESTABLISH, NULL); - } -} -static void -lli_do_dialout(struct FsmInst *fi, int event, void *arg) -{ - struct Channel *chanp = fi->userdata; - - FsmChangeState(fi, ST_OUT_DIAL); - chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) chanp->chan); - if (chanp->leased) { - FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL); - } else { - test_and_set_bit(FLG_ESTAB_D, &chanp->Flags); - chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP_REQ, chanp); - test_and_set_bit(FLG_CALL_SEND, &chanp->Flags); - } + chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); + if (chanp->leased) { + lli_init_bchan_out(fi, event, arg); + } else { + FsmChangeState(fi, ST_OUT_DIAL); + chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | REQUEST, chanp); + } } static void -lli_init_bchan_out(struct FsmInst *fi, int event, void *arg) +lli_resume(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; - isdn_ctrl ic; - FsmChangeState(fi, ST_WAIT_BCONN); - test_and_set_bit(FLG_LL_DCONN, &chanp->Flags); - if (chanp->debug & 1) - link_debug(chanp, "STAT_DCONN", 0); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DCONN; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - init_b_st(chanp, 0); - test_and_set_bit(FLG_START_B, &chanp->Flags); - FsmEvent(&chanp->lc_b->lcfi, EV_LC_ESTABLISH, NULL); + FsmDelTimer(&chanp->drel_timer, 60); + FsmDelTimer(&chanp->dial_timer, 73); + chanp->l2_active_protocol = chanp->l2_protocol; + chanp->incoming = 0; + + chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); + if (chanp->leased) { + lli_init_bchan_out(fi, event, arg); + } else { + FsmChangeState(fi, ST_OUT_DIAL); + chanp->d_st->lli.l4l3(chanp->d_st, CC_RESUME | REQUEST, chanp); + } } static void lli_go_active(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; - isdn_ctrl ic; FsmChangeState(fi, ST_ACTIVE); chanp->data_open = !0; - test_and_set_bit(FLG_CONNECT_B, &chanp->Flags); if (chanp->debug & 1) - link_debug(chanp, "STAT_BCONN", 0); - test_and_set_bit(FLG_LL_BCONN, &chanp->Flags); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_BCONN; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - chanp->cs->cardmsg(chanp->cs, MDL_INFO_CONN, (void *) chanp->chan); + link_debug(chanp, 0, "STAT_BCONN"); + HL_LL(chanp, ISDN_STAT_BCONN); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_CONN, (void *) (long)chanp->chan); } -/* incomming call */ -static void -lli_start_dchan(struct FsmInst *fi, int event, void *arg) -{ - struct Channel *chanp = fi->userdata; +/* + * RESUME + */ - FsmChangeState(fi, ST_IN_WAIT_D); - FsmDelTimer(&chanp->drel_timer, 61); - if (event == EV_ACCEPTD) - test_and_set_bit(FLG_DO_CONNECT, &chanp->Flags); - else if (event == EV_HANGUP) { - test_and_set_bit(FLG_DO_HANGUP, &chanp->Flags); -#ifdef ALERT_REJECT - test_and_set_bit(FLG_DO_ALERT, &chanp->Flags); -#endif - } - if (test_bit(FLG_ESTAB_D, &chanp->Flags)) { - FsmEvent(fi, EV_DLEST, NULL); - } else if (!test_and_set_bit(FLG_START_D, &chanp->Flags)) - FsmEvent(&chanp->lc_d->lcfi, EV_LC_ESTABLISH, NULL); -} +/* incomming call */ static void lli_deliver_call(struct FsmInst *fi, int event, void *arg) @@ -479,9 +452,8 @@ struct Channel *chanp = fi->userdata; isdn_ctrl ic; int ret; - char txt[32]; - chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) chanp->chan); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); /* * Report incoming calls only once to linklevel, use CallFlags * which is set to 3 with each broadcast message in isdnl1.c @@ -489,11 +461,11 @@ */ if (1) { /* for only one TEI */ FsmChangeState(fi, ST_IN_WAIT_LL); - test_and_set_bit(FLG_CALL_REC, &chanp->Flags); if (chanp->debug & 1) - link_debug(chanp, "STAT_ICALL", 0); + link_debug(chanp, 0, (chanp->chan < 2) ? "STAT_ICALL" : "STAT_ICALLW"); ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_ICALL; + ic.command = ((chanp->chan < 2) ? ISDN_STAT_ICALL : ISDN_STAT_ICALLW); + ic.arg = chanp->chan; /* * No need to return "unknown" for calls without OAD, @@ -501,962 +473,496 @@ */ ic.parm.setup = chanp->proc->para.setup; ret = chanp->cs->iif.statcallb(&ic); - if (chanp->debug & 1) { - sprintf(txt, "statcallb ret=%d", ret); - link_debug(chanp, txt, 1); - } + if (chanp->debug & 1) + link_debug(chanp, 1, "statcallb ret=%d", ret); + switch (ret) { - case 1: /* OK, anybody likes this call */ + case 1: /* OK, someone likes this call */ FsmDelTimer(&chanp->drel_timer, 61); - if (test_bit(FLG_ESTAB_D, &chanp->Flags)) { - FsmChangeState(fi, ST_IN_ALERT_SEND); - test_and_set_bit(FLG_CALL_ALERT, &chanp->Flags); - chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING_REQ, chanp->proc); - } else { - test_and_set_bit(FLG_DO_ALERT, &chanp->Flags); - FsmChangeState(fi, ST_IN_WAIT_D); - test_and_set_bit(FLG_START_D, &chanp->Flags); - FsmEvent(&chanp->lc_d->lcfi, EV_LC_ESTABLISH, NULL); - } + FsmChangeState(fi, ST_IN_ALERT_SENT); + chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); + break; + case 4: /* direct redirect */ + case 3: /* Proceeding desired */ + FsmDelTimer(&chanp->drel_timer, 61); + FsmChangeState(fi, ST_IN_PROCEED_SEND); + chanp->d_st->lli.l4l3(chanp->d_st, CC_PROCEED_SEND | REQUEST, chanp->proc); + if (ret == 4) + { chanp->setup = ic.parm.setup; + chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc); + } break; case 2: /* Rejecting Call */ - test_and_clear_bit(FLG_CALL_REC, &chanp->Flags); break; case 0: /* OK, nobody likes this call */ default: /* statcallb problems */ - chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE, chanp->proc); - chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan); + chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); FsmChangeState(fi, ST_NULL); -#ifndef LAYER2_WATCHING - if (test_bit(FLG_ESTAB_D, &chanp->Flags)) - FsmRestartTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 61); -#endif break; } } else { - chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE, chanp->proc); - chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan); - FsmChangeState(fi, ST_NULL); -#ifndef LAYER2_WATCHING - if (test_bit(FLG_ESTAB_D, &chanp->Flags)) - FsmRestartTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 62); -#endif + chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); } } static void -lli_establish_d(struct FsmInst *fi, int event, void *arg) +lli_send_dconnect(struct FsmInst *fi, int event, void *arg) { - /* This establish the D-channel for pending L3 messages - * without blocking th channel - */ struct Channel *chanp = fi->userdata; - test_and_set_bit(FLG_DO_ESTAB, &chanp->Flags); - FsmChangeState(fi, ST_IN_WAIT_D); - test_and_set_bit(FLG_START_D, &chanp->Flags); - FsmEvent(&chanp->lc_d->lcfi, EV_LC_ESTABLISH, NULL); + FsmChangeState(fi, ST_IN_WAIT_CONN_ACK); + chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc); } static void -lli_do_action(struct FsmInst *fi, int event, void *arg) +lli_send_alert(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; - test_and_set_bit(FLG_ESTAB_D, &chanp->Flags); - if (chanp->leased) { - FsmChangeState(fi, ST_IN_WAIT_CONN_ACK); - test_and_clear_bit(FLG_DO_ALERT, &chanp->Flags); - test_and_clear_bit(FLG_DO_CONNECT, &chanp->Flags); - FsmEvent(&chanp->fi, EV_SETUP_CMPL_IND, NULL); - } else if (test_and_clear_bit(FLG_DO_CONNECT, &chanp->Flags) && - !test_bit(FLG_DO_HANGUP, &chanp->Flags)) { - FsmChangeState(fi, ST_IN_WAIT_CONN_ACK); - test_and_clear_bit(FLG_DO_ALERT, &chanp->Flags); - chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP_RSP, chanp->proc); - } else if (test_and_clear_bit(FLG_DO_ALERT, &chanp->Flags)) { - if (test_bit(FLG_DO_HANGUP, &chanp->Flags)) - FsmRestartTimer(&chanp->drel_timer, 40, EV_HANGUP, NULL, 63); - FsmChangeState(fi, ST_IN_ALERT_SEND); - test_and_set_bit(FLG_CALL_ALERT, &chanp->Flags); - chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING_REQ, chanp->proc); - } else if (test_and_clear_bit(FLG_DO_HANGUP, &chanp->Flags)) { - FsmChangeState(fi, ST_WAIT_DRELEASE); - chanp->proc->para.cause = 0x15; /* Call Rejected */ - chanp->d_st->lli.l4l3(chanp->d_st, CC_REJECT_REQ, chanp->proc); - test_and_set_bit(FLG_DISC_SEND, &chanp->Flags); - } else if (test_and_clear_bit(FLG_DO_ESTAB, &chanp->Flags)) { - FsmChangeState(fi, ST_NULL); - chanp->Flags = 0; - test_and_set_bit(FLG_ESTAB_D, &chanp->Flags); - chanp->d_st->lli.l4l3(chanp->d_st, CC_ESTABLISH, chanp->proc); - chanp->proc = NULL; -#ifndef LAYER2_WATCHING - FsmAddTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 60); -#endif - } + FsmChangeState(fi, ST_IN_ALERT_SENT); + chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); } static void -lli_send_dconnect(struct FsmInst *fi, int event, void *arg) +lli_send_redir(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; - FsmChangeState(fi, ST_IN_WAIT_CONN_ACK); - chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP_RSP, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc); } static void lli_init_bchan_in(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; - isdn_ctrl ic; FsmChangeState(fi, ST_WAIT_BCONN); - test_and_set_bit(FLG_LL_DCONN, &chanp->Flags); if (chanp->debug & 1) - link_debug(chanp, "STAT_DCONN", 0); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DCONN; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); + link_debug(chanp, 0, "STAT_DCONN"); + HL_LL(chanp, ISDN_STAT_DCONN); chanp->l2_active_protocol = chanp->l2_protocol; chanp->incoming = !0; - chanp->lc_b->l2_start = 0; - switch (chanp->l2_active_protocol) { - case (ISDN_PROTO_L2_X75I): - chanp->lc_b->l2_establish = !0; - break; - case (ISDN_PROTO_L2_HDLC): - case (ISDN_PROTO_L2_TRANS): - chanp->lc_b->l2_establish = 0; - break; - default: - printk(KERN_WARNING "bchannel unknown protocol\n"); - break; - } init_b_st(chanp, !0); - test_and_set_bit(FLG_START_B, &chanp->Flags); - FsmEvent(&chanp->lc_b->lcfi, EV_LC_ESTABLISH, NULL); -} - -/* Call clearing */ - -static void -lli_cancel_call(struct FsmInst *fi, int event, void *arg) -{ - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; - - FsmChangeState(fi, ST_WAIT_DRELEASE); - if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, "STAT_BHUP", 0); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_BHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - if (test_and_clear_bit(FLG_START_B, &chanp->Flags)) - release_b_st(chanp); - chanp->proc->para.cause = 0x10; /* Normal Call Clearing */ - chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT_REQ, chanp->proc); - test_and_set_bit(FLG_DISC_SEND, &chanp->Flags); + chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL); } static void -lli_shutdown_d(struct FsmInst *fi, int event, void *arg) +lli_setup_rsp(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; - - FsmDelTimer(&chanp->drel_timer, 62); -#ifdef LAYER2_WATCHING - FsmChangeState(fi, ST_NULL); -#else - if (!test_bit(FLG_TWO_DCHAN, &chanp->cs->HW_Flags)) { - if (chanp->chan) { - if (chanp->cs->channel[0].fi.state != ST_NULL) - return; - } else { - if (chanp->cs->channel[1].fi.state != ST_NULL) - return; - } - } - FsmChangeState(fi, ST_WAIT_DSHUTDOWN); - test_and_clear_bit(FLG_ESTAB_D, &chanp->Flags); - FsmEvent(&chanp->lc_d->lcfi, EV_LC_RELEASE, NULL); + struct Channel *chanp = fi->userdata; + + if (chanp->leased) { + lli_init_bchan_in(fi, event, arg); + } else { + FsmChangeState(fi, ST_IN_WAIT_CONN_ACK); +#ifdef WANT_ALERT + chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); #endif + chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc); + } } -static void -lli_timeout_d(struct FsmInst *fi, int event, void *arg) -{ - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; - - if (test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, "STAT_DHUP", 0); - lli_deliver_cause(chanp); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - FsmChangeState(fi, ST_NULL); - chanp->Flags = 0; - test_and_set_bit(FLG_ESTAB_D, &chanp->Flags); -#ifndef LAYER2_WATCHING - FsmAddTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 60); -#endif - chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan); -} +/* Call suspend */ static void -lli_go_null(struct FsmInst *fi, int event, void *arg) +lli_suspend(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; - FsmChangeState(fi, ST_NULL); - chanp->Flags = 0; - FsmDelTimer(&chanp->drel_timer, 63); - chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan); + chanp->d_st->lli.l4l3(chanp->d_st, CC_SUSPEND | REQUEST, chanp->proc); } -static void -lli_disconn_bchan(struct FsmInst *fi, int event, void *arg) -{ - struct Channel *chanp = fi->userdata; - - chanp->data_open = 0; - FsmChangeState(fi, ST_WAIT_BRELEASE); - test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags); - FsmEvent(&chanp->lc_b->lcfi, EV_LC_RELEASE, NULL); -} +/* Call clearing */ static void -lli_send_d_disc(struct FsmInst *fi, int event, void *arg) +lli_disconnect_req(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; - isdn_ctrl ic; - if (test_bit(FLG_DISC_REC, &chanp->Flags) || - test_bit(FLG_REL_REC, &chanp->Flags)) - return; FsmChangeState(fi, ST_WAIT_DRELEASE); - if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, "STAT_BHUP", 0); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_BHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - if (test_and_clear_bit(FLG_START_B, &chanp->Flags)) - release_b_st(chanp); - if (chanp->leased) { - ic.command = ISDN_STAT_CAUSE; - ic.arg = chanp->chan; - sprintf(ic.parm.num, "L0010"); - chanp->cs->iif.statcallb(&ic); - if (chanp->debug & 1) - link_debug(chanp, "STAT_DHUP", 0); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - FsmChangeState(fi, ST_WAIT_DSHUTDOWN); - test_and_clear_bit(FLG_ESTAB_D, &chanp->Flags); - FsmEvent(&chanp->lc_d->lcfi, EV_LC_RELEASE, NULL); - } else { - if (test_and_clear_bit(FLG_DO_HANGUP, &chanp->Flags)) - chanp->proc->para.cause = 0x15; /* Call Reject */ - else - chanp->proc->para.cause = 0x10; /* Normal Call Clearing */ - chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT_REQ, chanp->proc); - test_and_set_bit(FLG_DISC_SEND, &chanp->Flags); - } + chanp->proc->para.cause = 0x10; /* Normal Call Clearing */ + chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST, chanp->proc); } static void -lli_released_bchan(struct FsmInst *fi, int event, void *arg) +lli_disconnect_reject(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; + struct Channel *chanp = fi->userdata; - FsmChangeState(fi, ST_WAIT_DCOMMAND); - chanp->data_open = 0; - if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, "STAT_BHUP", 0); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_BHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - release_b_st(chanp); - test_and_clear_bit(FLG_START_B, &chanp->Flags); + FsmChangeState(fi, ST_WAIT_DRELEASE); + chanp->proc->para.cause = 0x15; /* Call Rejected */ + chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST, chanp->proc); } - static void -lli_release_bchan(struct FsmInst *fi, int event, void *arg) +lli_dhup_close(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; + struct Channel *chanp = fi->userdata; - chanp->data_open = 0; - test_and_set_bit(FLG_DISC_REC, &chanp->Flags); - FsmChangeState(fi, ST_WAIT_BREL_DISC); - test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags); - FsmEvent(&chanp->lc_b->lcfi, EV_LC_RELEASE, NULL); + if (chanp->debug & 1) + link_debug(chanp, 0, "STAT_DHUP"); + lli_deliver_cause(chanp); + HL_LL(chanp, ISDN_STAT_DHUP); + + lli_close(fi); } static void -lli_received_d_rel(struct FsmInst *fi, int event, void *arg) +lli_reject_req(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; + struct Channel *chanp = fi->userdata; - chanp->data_open = 0; - FsmChangeState(fi, ST_NULL); - test_and_set_bit(FLG_REL_REC, &chanp->Flags); - if (test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags)) { - chanp->lc_b->l2_establish = 0; /* direct reset in lc_b->lcfi */ - FsmEvent(&chanp->lc_b->lcfi, EV_LC_RELEASE, NULL); - } - if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, "STAT_BHUP", 0); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_BHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - if (test_and_clear_bit(FLG_START_B, &chanp->Flags)) - release_b_st(chanp); - if (test_bit(FLG_LL_DCONN, &chanp->Flags) || - test_bit(FLG_CALL_SEND, &chanp->Flags) || - test_bit(FLG_CALL_ALERT, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, "STAT_DHUP", 0); - lli_deliver_cause(chanp); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - test_and_clear_bit(FLG_DISC_SEND, &chanp->Flags); - test_and_clear_bit(FLG_CALL_REC, &chanp->Flags); - test_and_clear_bit(FLG_CALL_ALERT, &chanp->Flags); - test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags); - test_and_clear_bit(FLG_CALL_SEND, &chanp->Flags); - lli_timeout_d(fi, event, arg); +#ifndef ALERT_REJECT + chanp->proc->para.cause = 0x15; /* Call Rejected */ + chanp->d_st->lli.l4l3(chanp->d_st, CC_REJECT | REQUEST, chanp->proc); + lli_dhup_close(fi, event, arg); +#else + FsmRestartTimer(&chanp->drel_timer, 40, EV_HANGUP, NULL, 63); + FsmChangeState(fi, ST_IN_ALERT_SENT); + chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); +#endif } static void -lli_received_d_relcnf(struct FsmInst *fi, int event, void *arg) +lli_disconn_bchan(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; - isdn_ctrl ic; chanp->data_open = 0; - FsmChangeState(fi, ST_NULL); - if (test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags)) { - chanp->lc_b->l2_establish = 0; /* direct reset in lc_b->lcfi */ - FsmEvent(&chanp->lc_b->lcfi, EV_LC_RELEASE, NULL); - } - if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, "STAT_BHUP", 0); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_BHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - if (test_and_clear_bit(FLG_START_B, &chanp->Flags)) - release_b_st(chanp); - if (test_bit(FLG_LL_DCONN, &chanp->Flags) || - test_bit(FLG_CALL_SEND, &chanp->Flags) || - test_bit(FLG_CALL_ALERT, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, "STAT_DHUP", 0); - lli_deliver_cause(chanp); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - test_and_clear_bit(FLG_DISC_SEND, &chanp->Flags); - test_and_clear_bit(FLG_CALL_REC, &chanp->Flags); - test_and_clear_bit(FLG_CALL_ALERT, &chanp->Flags); - test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags); - test_and_clear_bit(FLG_CALL_SEND, &chanp->Flags); - lli_timeout_d(fi, event, arg); + FsmChangeState(fi, ST_WAIT_BRELEASE); + chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); } static void -lli_received_d_disc(struct FsmInst *fi, int event, void *arg) +lli_start_disc(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; isdn_ctrl ic; - chanp->data_open = 0; - FsmChangeState(fi, ST_WAIT_D_REL_CNF); - test_and_set_bit(FLG_DISC_REC, &chanp->Flags); - if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, "STAT_BHUP", 0); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_BHUP; + if (chanp->leased) { + ic.command = ISDN_STAT_CAUSE; ic.arg = chanp->chan; + sprintf(ic.parm.num, "L0010"); chanp->cs->iif.statcallb(&ic); - } - if (test_and_clear_bit(FLG_START_B, &chanp->Flags)) - release_b_st(chanp); - if (test_bit(FLG_LL_DCONN, &chanp->Flags) || - test_bit(FLG_CALL_SEND, &chanp->Flags) || - test_bit(FLG_CALL_ALERT, &chanp->Flags)) { if (chanp->debug & 1) - link_debug(chanp, "STAT_DHUP", 0); - lli_deliver_cause(chanp); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); + link_debug(chanp, 0, "STAT_DHUP"); + HL_LL(chanp, ISDN_STAT_DHUP); + lli_close(fi); + } else { + lli_disconnect_req(fi, event, arg); } - test_and_clear_bit(FLG_CALL_ALERT, &chanp->Flags); - test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags); - test_and_clear_bit(FLG_CALL_SEND, &chanp->Flags); - chanp->d_st->lli.l4l3(chanp->d_st, CC_RELEASE_REQ, chanp->proc); } -/* processing charge info */ static void -lli_charge_info(struct FsmInst *fi, int event, void *arg) +lli_rel_b_disc(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; - - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_CINF; - ic.arg = chanp->chan; - sprintf(ic.parm.num, "%d", chanp->proc->para.chargeinfo); - chanp->cs->iif.statcallb(&ic); -} - -/* error procedures */ - -static void -lli_no_dchan(struct FsmInst *fi, int event, void *arg) -{ - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; - - if (chanp->debug & 1) - link_debug(chanp, "STAT_NODCH", 0); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_NODCH; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - chanp->Flags = 0; - FsmChangeState(fi, ST_NULL); - FsmEvent(&chanp->lc_d->lcfi, EV_LC_RELEASE, NULL); -} - -static void -lli_no_dchan_ready(struct FsmInst *fi, int event, void *arg) -{ - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; - - if (chanp->debug & 1) - link_debug(chanp, "STAT_DHUP", 0); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); -} - -static void -lli_no_dchan_in(struct FsmInst *fi, int event, void *arg) -{ - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; - - if (chanp->debug & 1) - link_debug(chanp, "STAT_DHUP", 0); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - chanp->d_st->lli.l4l3(chanp->d_st, CC_DLRL, chanp->proc); - chanp->Flags = 0; - FsmChangeState(fi, ST_NULL); - FsmEvent(&chanp->lc_d->lcfi, EV_LC_RELEASE, NULL); -} - -static void -lli_no_setup_rsp(struct FsmInst *fi, int event, void *arg) -{ - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; - - FsmChangeState(fi, ST_NULL); - test_and_clear_bit(FLG_CALL_SEND, &chanp->Flags); - if (chanp->debug & 1) - link_debug(chanp, "STAT_DHUP", 0); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - lli_shutdown_d(fi, event, arg); + struct Channel *chanp = fi->userdata; + + release_b_st(chanp); + lli_start_disc(fi, event, arg); } static void -lli_setup_err(struct FsmInst *fi, int event, void *arg) +lli_bhup_disc(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; - - FsmChangeState(fi, ST_WAIT_DRELEASE); - if (test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, "STAT_DHUP", 0); - lli_deliver_cause(chanp); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - test_and_set_bit(FLG_DISC_SEND, &chanp->Flags); /* DISCONN was sent from L3 */ + struct Channel *chanp = fi->userdata; + + if (chanp->debug & 1) + link_debug(chanp, 0, "STAT_BHUP"); + HL_LL(chanp, ISDN_STAT_BHUP); + + lli_rel_b_disc(fi, event, arg); } static void -lli_connect_err(struct FsmInst *fi, int event, void *arg) +lli_bhup_rel_b(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = fi->userdata; - isdn_ctrl ic; + struct Channel *chanp = fi->userdata; - FsmChangeState(fi, ST_WAIT_DRELEASE); - if (test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, "STAT_DHUP", 0); - lli_deliver_cause(chanp); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - test_and_set_bit(FLG_DISC_SEND, &chanp->Flags); /* DISCONN was sent from L3 */ + FsmChangeState(fi, ST_WAIT_DCOMMAND); + chanp->data_open = 0; + if (chanp->debug & 1) + link_debug(chanp, 0, "STAT_BHUP"); + HL_LL(chanp, ISDN_STAT_BHUP); + release_b_st(chanp); } static void -lli_got_dlrl(struct FsmInst *fi, int event, void *arg) +lli_release_bchan(struct FsmInst *fi, int event, void *arg) { struct Channel *chanp = fi->userdata; - isdn_ctrl ic; chanp->data_open = 0; - FsmChangeState(fi, ST_NULL); - if (test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags)) { - chanp->lc_b->l2_establish = 0; /* direct reset in lc_b->lcfi */ - FsmEvent(&chanp->lc_b->lcfi, EV_LC_RELEASE, NULL); - } - if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, "STAT_BHUP", 0); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_BHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - if (test_and_clear_bit(FLG_START_B, &chanp->Flags)) - release_b_st(chanp); - if (chanp->leased) { - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_CAUSE; - ic.arg = chanp->chan; - sprintf(ic.parm.num, "L%02X%02X", 0, 0x2f); - chanp->cs->iif.statcallb(&ic); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - chanp->Flags = 0; - } else { - if (test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags)) { - if (chanp->debug & 1) - link_debug(chanp, "STAT_DHUP", 0); - if (chanp->cs->protocol == ISDN_PTYPE_EURO) { - chanp->proc->para.cause = 0x2f; - chanp->proc->para.loc = 0; - } else { - chanp->proc->para.cause = 0x70; - chanp->proc->para.loc = 0; - } - lli_deliver_cause(chanp); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_DHUP; - ic.arg = chanp->chan; - chanp->cs->iif.statcallb(&ic); - } - chanp->d_st->lli.l4l3(chanp->d_st, CC_DLRL, chanp->proc); - chanp->Flags = 0; - FsmEvent(&chanp->lc_d->lcfi, EV_LC_RELEASE, NULL); - } - chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan); -} - -/* *INDENT-OFF* */ -static struct FsmNode fnlist[] HISAX_INITDATA = -{ - {ST_NULL, EV_DIAL, lli_prep_dialout}, - {ST_NULL, EV_SETUP_IND, lli_deliver_call}, - {ST_NULL, EV_SHUTDOWN_D, lli_shutdown_d}, - {ST_NULL, EV_DLRL, lli_go_null}, - {ST_NULL, EV_DLEST, lli_d_established}, - {ST_NULL, EV_ESTABLISH, lli_establish_d}, - {ST_OUT_WAIT_D, EV_DLEST, lli_do_dialout}, - {ST_OUT_WAIT_D, EV_DLRL, lli_no_dchan}, - {ST_OUT_WAIT_D, EV_HANGUP, lli_no_dchan}, - {ST_IN_WAIT_D, EV_DLEST, lli_do_action}, - {ST_IN_WAIT_D, EV_DLRL, lli_no_dchan_in}, - {ST_IN_WAIT_D, EV_ACCEPTD, lli_start_dchan}, - {ST_IN_WAIT_D, EV_HANGUP, lli_start_dchan}, - {ST_OUT_DIAL, EV_SETUP_CNF, lli_init_bchan_out}, - {ST_OUT_DIAL, EV_HANGUP, lli_cancel_call}, - {ST_OUT_DIAL, EV_DISCONNECT_IND, lli_received_d_disc}, - {ST_OUT_DIAL, EV_RELEASE_IND, lli_received_d_rel}, - {ST_OUT_DIAL, EV_RELEASE_CNF, lli_received_d_relcnf}, - {ST_OUT_DIAL, EV_NOSETUP_RSP, lli_no_setup_rsp}, - {ST_OUT_DIAL, EV_SETUP_ERR, lli_setup_err}, - {ST_OUT_DIAL, EV_DLRL, lli_got_dlrl}, - {ST_IN_WAIT_LL, EV_DLEST, lli_d_established}, - {ST_IN_WAIT_LL, EV_DLRL, lli_d_released}, - {ST_IN_WAIT_LL, EV_ACCEPTD, lli_start_dchan}, - {ST_IN_WAIT_LL, EV_HANGUP, lli_start_dchan}, - {ST_IN_WAIT_LL, EV_DISCONNECT_IND, lli_received_d_disc}, - {ST_IN_WAIT_LL, EV_RELEASE_IND, lli_received_d_rel}, - {ST_IN_WAIT_LL, EV_RELEASE_CNF, lli_received_d_relcnf}, - {ST_IN_ALERT_SEND, EV_SETUP_CMPL_IND, lli_init_bchan_in}, - {ST_IN_ALERT_SEND, EV_ACCEPTD, lli_send_dconnect}, - {ST_IN_ALERT_SEND, EV_HANGUP, lli_send_d_disc}, - {ST_IN_ALERT_SEND, EV_DISCONNECT_IND, lli_received_d_disc}, - {ST_IN_ALERT_SEND, EV_RELEASE_IND, lli_received_d_rel}, - {ST_IN_ALERT_SEND, EV_RELEASE_CNF, lli_received_d_relcnf}, - {ST_IN_ALERT_SEND, EV_DLRL, lli_got_dlrl}, - {ST_IN_WAIT_CONN_ACK, EV_SETUP_CMPL_IND, lli_init_bchan_in}, - {ST_IN_WAIT_CONN_ACK, EV_HANGUP, lli_send_d_disc}, - {ST_IN_WAIT_CONN_ACK, EV_DISCONNECT_IND, lli_received_d_disc}, - {ST_IN_WAIT_CONN_ACK, EV_RELEASE_IND, lli_received_d_rel}, - {ST_IN_WAIT_CONN_ACK, EV_RELEASE_CNF, lli_received_d_relcnf}, - {ST_IN_WAIT_CONN_ACK, EV_CONNECT_ERR, lli_connect_err}, - {ST_IN_WAIT_CONN_ACK, EV_DLRL, lli_got_dlrl}, - {ST_WAIT_BCONN, EV_BC_EST, lli_go_active}, - {ST_WAIT_BCONN, EV_BC_REL, lli_send_d_disc}, - {ST_WAIT_BCONN, EV_HANGUP, lli_send_d_disc}, - {ST_WAIT_BCONN, EV_DISCONNECT_IND, lli_received_d_disc}, - {ST_WAIT_BCONN, EV_RELEASE_IND, lli_received_d_rel}, - {ST_WAIT_BCONN, EV_RELEASE_CNF, lli_received_d_relcnf}, - {ST_WAIT_BCONN, EV_DLRL, lli_got_dlrl}, - {ST_WAIT_BCONN, EV_CINF, lli_charge_info}, - {ST_ACTIVE, EV_CINF, lli_charge_info}, - {ST_ACTIVE, EV_BC_REL, lli_released_bchan}, - {ST_ACTIVE, EV_HANGUP, lli_disconn_bchan}, - {ST_ACTIVE, EV_DISCONNECT_IND, lli_release_bchan}, - {ST_ACTIVE, EV_RELEASE_CNF, lli_received_d_relcnf}, - {ST_ACTIVE, EV_RELEASE_IND, lli_received_d_rel}, - {ST_ACTIVE, EV_DLRL, lli_got_dlrl}, - {ST_WAIT_BRELEASE, EV_BC_REL, lli_send_d_disc}, - {ST_WAIT_BRELEASE, EV_DISCONNECT_IND, lli_received_d_disc}, - {ST_WAIT_BRELEASE, EV_RELEASE_CNF, lli_received_d_relcnf}, - {ST_WAIT_BRELEASE, EV_RELEASE_IND, lli_received_d_rel}, - {ST_WAIT_BRELEASE, EV_DLRL, lli_got_dlrl}, - {ST_WAIT_BREL_DISC, EV_BC_REL, lli_received_d_disc}, - {ST_WAIT_BREL_DISC, EV_RELEASE_CNF, lli_received_d_relcnf}, - {ST_WAIT_BREL_DISC, EV_RELEASE_IND, lli_received_d_rel}, - {ST_WAIT_BREL_DISC, EV_DLRL, lli_got_dlrl}, - {ST_WAIT_DCOMMAND, EV_HANGUP, lli_send_d_disc}, - {ST_WAIT_DCOMMAND, EV_DISCONNECT_IND, lli_received_d_disc}, - {ST_WAIT_DCOMMAND, EV_RELEASE_CNF, lli_received_d_relcnf}, - {ST_WAIT_DCOMMAND, EV_RELEASE_IND, lli_received_d_rel}, - {ST_WAIT_DCOMMAND, EV_DLRL, lli_got_dlrl}, - {ST_WAIT_DRELEASE, EV_RELEASE_IND, lli_timeout_d}, - {ST_WAIT_DRELEASE, EV_RELEASE_CNF, lli_timeout_d}, - {ST_WAIT_DRELEASE, EV_RELEASE_ERR, lli_timeout_d}, - {ST_WAIT_DRELEASE, EV_DIAL, lli_no_dchan_ready}, - {ST_WAIT_DRELEASE, EV_DLRL, lli_got_dlrl}, - {ST_WAIT_D_REL_CNF, EV_RELEASE_CNF, lli_timeout_d}, - {ST_WAIT_D_REL_CNF, EV_RELEASE_ERR, lli_timeout_d}, -/* ETS 300-104 16.1 */ - {ST_WAIT_D_REL_CNF, EV_RELEASE_IND, lli_timeout_d}, - {ST_WAIT_D_REL_CNF, EV_DIAL, lli_no_dchan_ready}, - {ST_WAIT_D_REL_CNF, EV_DLRL, lli_got_dlrl}, - {ST_WAIT_DSHUTDOWN, EV_DLRL, lli_go_null}, - {ST_WAIT_DSHUTDOWN, EV_DLEST, lli_d_established}, - {ST_WAIT_DSHUTDOWN, EV_DIAL, lli_prep_dialout}, - {ST_WAIT_DSHUTDOWN, EV_SETUP_IND, lli_deliver_call}, -}; -/* *INDENT-ON* */ - - -#define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode)) - -static void -lc_activate_l1(struct FsmInst *fi, int event, void *arg) -{ - struct LcFsm *lf = fi->userdata; - - FsmDelTimer(&lf->act_timer, 50); - FsmChangeState(fi, ST_LC_ACTIVATE_WAIT); - /* This timeout is to avoid a hang if no L1 activation is possible */ - FsmAddTimer(&lf->act_timer, 30000, EV_LC_TIMER, NULL, 50); - lf->st->ma.manl1(lf->st, PH_ACTIVATE_REQ, NULL); -} - -static void -lc_activated_from_l1(struct FsmInst *fi, int event, void *arg) -{ - struct LcFsm *lf = fi->userdata; - - if (lf->l2_establish) - FsmChangeState(fi, ST_LC_DELAY); - else { - FsmChangeState(fi, ST_LC_CONNECTED); - lf->lccall(lf, LC_ESTABLISH, NULL); - } + FsmChangeState(fi, ST_WAIT_BREL_DISC); + chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); } -static void -lc_l1_activated(struct FsmInst *fi, int event, void *arg) -{ - struct LcFsm *lf = fi->userdata; - - FsmDelTimer(&lf->act_timer, 50); - FsmChangeState(fi, ST_LC_DELAY); - /* This timer is needed for delay the first paket on a channel - to be shure that the other side is ready too */ - if (lf->delay) - FsmAddTimer(&lf->act_timer, lf->delay, EV_LC_TIMER, NULL, 51); - else - FsmEvent(fi, EV_LC_TIMER, NULL); -} static void -lc_start_l2(struct FsmInst *fi, int event, void *arg) +lli_rel_b_dhup(struct FsmInst *fi, int event, void *arg) { - struct LcFsm *lf = fi->userdata; + struct Channel *chanp = fi->userdata; -/* if (!lf->st->l1.act_state) - lf->st->l1.act_state = 2; -*/ if (lf->l2_establish) { - FsmChangeState(fi, ST_LC_ESTABLISH_WAIT); - if (lf->l2_start) - lf->st->ma.manl2(lf->st, DL_ESTABLISH, NULL); - } else { - FsmChangeState(fi, ST_LC_CONNECTED); - lf->lccall(lf, LC_ESTABLISH, NULL); - } + release_b_st(chanp); + lli_dhup_close(fi, event, arg); } static void -lc_connected(struct FsmInst *fi, int event, void *arg) +lli_bhup_dhup(struct FsmInst *fi, int event, void *arg) { - struct LcFsm *lf = fi->userdata; + struct Channel *chanp = fi->userdata; - FsmDelTimer(&lf->act_timer, 50); - FsmChangeState(fi, ST_LC_CONNECTED); - lf->lccall(lf, LC_ESTABLISH, NULL); + if (chanp->debug & 1) + link_debug(chanp, 0, "STAT_BHUP"); + HL_LL(chanp, ISDN_STAT_BHUP); + + lli_rel_b_dhup(fi, event, arg); } static void -lc_release_l2(struct FsmInst *fi, int event, void *arg) +lli_abort(struct FsmInst *fi, int event, void *arg) { - struct LcFsm *lf = fi->userdata; + struct Channel *chanp = fi->userdata; - if (lf->l2_establish) { - FsmChangeState(fi, ST_LC_RELEASE_WAIT); - lf->st->ma.manl2(lf->st, DL_RELEASE, NULL); - } else { - FsmChangeState(fi, ST_LC_NULL); - lf->st->ma.manl1(lf->st, PH_DEACTIVATE_REQ, NULL); - lf->lccall(lf, LC_RELEASE, NULL); - } + chanp->data_open = 0; + chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); + + lli_bhup_dhup(fi, event, arg); } - + static void -lc_l2_released(struct FsmInst *fi, int event, void *arg) +lli_release_req(struct FsmInst *fi, int event, void *arg) { - struct LcFsm *lf = fi->userdata; - - FsmChangeState(fi, ST_LC_RELEASE_WAIT); - FsmDelTimer(&lf->act_timer, 51); - /* This delay is needed for send out the UA frame before - * PH_DEACTIVATE the interface - */ - FsmAddTimer(&lf->act_timer, 20, EV_LC_TIMER, NULL, 54); + struct Channel *chanp = fi->userdata; + + FsmChangeState(fi, ST_WAIT_D_REL_CNF); + chanp->d_st->lli.l4l3(chanp->d_st, CC_RELEASE | REQUEST, chanp->proc); } static void -lc_release_l1(struct FsmInst *fi, int event, void *arg) +lli_rel_b_release_req(struct FsmInst *fi, int event, void *arg) { - struct LcFsm *lf = fi->userdata; - - FsmDelTimer(&lf->act_timer, 54); - FsmChangeState(fi, ST_LC_NULL); - lf->st->ma.manl1(lf->st, PH_DEACTIVATE_REQ, NULL); - lf->lccall(lf, LC_RELEASE, NULL); + struct Channel *chanp = fi->userdata; + + release_b_st(chanp); + lli_release_req(fi, event, arg); } static void -lc_l1_deactivated(struct FsmInst *fi, int event, void *arg) -{ - struct LcFsm *lf = fi->userdata; - - FsmDelTimer(&lf->act_timer, 54); - FsmChangeState(fi, ST_LC_NULL); - lf->lccall(lf, LC_RELEASE, NULL); -} -/* *INDENT-OFF* */ -static struct FsmNode LcFnList[] HISAX_INITDATA = -{ - {ST_LC_NULL, EV_LC_ESTABLISH, lc_activate_l1}, - {ST_LC_NULL, EV_LC_PH_ACTIVATE, lc_activated_from_l1}, - {ST_LC_NULL, EV_LC_DL_ESTABLISH, lc_connected}, - {ST_LC_ACTIVATE_WAIT, EV_LC_PH_ACTIVATE, lc_l1_activated}, - {ST_LC_ACTIVATE_WAIT, EV_LC_TIMER, lc_release_l1}, - {ST_LC_ACTIVATE_WAIT, EV_LC_PH_DEACTIVATE, lc_l1_deactivated}, - {ST_LC_DELAY, EV_LC_ESTABLISH, lc_start_l2}, - {ST_LC_DELAY, EV_LC_TIMER, lc_start_l2}, - {ST_LC_DELAY, EV_LC_DL_ESTABLISH, lc_connected}, - {ST_LC_DELAY, EV_LC_PH_DEACTIVATE, lc_l1_deactivated}, - {ST_LC_ESTABLISH_WAIT, EV_LC_DL_ESTABLISH, lc_connected}, - {ST_LC_ESTABLISH_WAIT, EV_LC_RELEASE, lc_release_l1}, - {ST_LC_ESTABLISH_WAIT, EV_LC_DL_RELEASE, lc_release_l1}, - {ST_LC_ESTABLISH_WAIT, EV_LC_PH_DEACTIVATE, lc_l1_deactivated}, - {ST_LC_CONNECTED, EV_LC_ESTABLISH, lc_connected}, - {ST_LC_CONNECTED, EV_LC_RELEASE, lc_release_l2}, - {ST_LC_CONNECTED, EV_LC_DL_RELEASE, lc_l2_released}, - {ST_LC_CONNECTED, EV_LC_PH_DEACTIVATE, lc_l1_deactivated}, - {ST_LC_FLUSH_WAIT, EV_LC_TIMER, lc_release_l2}, - {ST_LC_FLUSH_WAIT, EV_LC_PH_DEACTIVATE, lc_l1_deactivated}, - {ST_LC_RELEASE_WAIT, EV_LC_DL_RELEASE, lc_release_l1}, - {ST_LC_RELEASE_WAIT, EV_LC_TIMER, lc_release_l1}, - {ST_LC_FLUSH_WAIT, EV_LC_PH_DEACTIVATE, lc_l1_deactivated}, -}; -/* *INDENT-ON* */ - - -#define LC_FN_COUNT (sizeof(LcFnList)/sizeof(struct FsmNode)) - -HISAX_INITFUNC(void -CallcNew(void)) +lli_bhup_release_req(struct FsmInst *fi, int event, void *arg) { - callcfsm.state_count = STATE_COUNT; - callcfsm.event_count = EVENT_COUNT; - callcfsm.strEvent = strEvent; - callcfsm.strState = strState; - FsmNew(&callcfsm, fnlist, FNCOUNT); - - lcfsm.state_count = LC_STATE_COUNT; - lcfsm.event_count = LC_EVENT_COUNT; - lcfsm.strEvent = strLcEvent; - lcfsm.strState = strLcState; - FsmNew(&lcfsm, LcFnList, LC_FN_COUNT); + struct Channel *chanp = fi->userdata; + + if (chanp->debug & 1) + link_debug(chanp, 0, "STAT_BHUP"); + HL_LL(chanp, ISDN_STAT_BHUP); + + lli_rel_b_release_req(fi, event, arg); } -void -CallcFree(void) -{ - FsmFree(&lcfsm); - FsmFree(&callcfsm); -} +/* processing charge info */ static void -release_b_st(struct Channel *chanp) +lli_charge_info(struct FsmInst *fi, int event, void *arg) { - struct PStack *st = chanp->b_st; + struct Channel *chanp = fi->userdata; + isdn_ctrl ic; - chanp->bcs->BC_Close(chanp->bcs); - switch (chanp->l2_active_protocol) { - case (ISDN_PROTO_L2_X75I): - releasestack_isdnl2(st); - break; - case (ISDN_PROTO_L2_HDLC): - case (ISDN_PROTO_L2_TRANS): - releasestack_transl2(st); - break; - } - /* Reset B-Channel Statemachine */ - FsmDelTimer(&chanp->lc_b->act_timer, 79); - FsmChangeState(&chanp->lc_b->lcfi, ST_LC_NULL); + ic.driver = chanp->cs->myid; + ic.command = ISDN_STAT_CINF; + ic.arg = chanp->chan; + sprintf(ic.parm.num, "%d", chanp->proc->para.chargeinfo); + chanp->cs->iif.statcallb(&ic); } +/* error procedures */ + static void -dc_l1man(struct PStack *st, int pr, void *arg) +lli_dchan_not_ready(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp; + struct Channel *chanp = fi->userdata; - chanp = (struct Channel *) st->lli.userdata; - switch (pr) { - case (PH_ACTIVATE_CNF): - case (PH_ACTIVATE_IND): - FsmEvent(&chanp->lc_d->lcfi, EV_LC_PH_ACTIVATE, NULL); - break; - case (PH_DEACTIVATE_IND): - FsmEvent(&chanp->lc_d->lcfi, EV_LC_PH_DEACTIVATE, NULL); - break; - } + if (chanp->debug & 1) + link_debug(chanp, 0, "STAT_DHUP"); + HL_LL(chanp, ISDN_STAT_DHUP); } static void -dc_l2man(struct PStack *st, int pr, void *arg) +lli_no_setup_rsp(struct FsmInst *fi, int event, void *arg) { - struct Channel *chanp = (struct Channel *) st->lli.userdata; + struct Channel *chanp = fi->userdata; - switch (pr) { - case (DL_ESTABLISH): - FsmEvent(&chanp->lc_d->lcfi, EV_LC_DL_ESTABLISH, NULL); - break; - case (DL_RELEASE): - FsmEvent(&chanp->lc_d->lcfi, EV_LC_DL_RELEASE, NULL); - break; - } -} + if (chanp->debug & 1) + link_debug(chanp, 0, "STAT_DHUP"); + HL_LL(chanp, ISDN_STAT_DHUP); + lli_close(fi); +} + +static void +lli_error(struct FsmInst *fi, int event, void *arg) +{ + FsmChangeState(fi, ST_WAIT_DRELEASE); +} + +static void +lli_failure_l(struct FsmInst *fi, int event, void *arg) +{ + struct Channel *chanp = fi->userdata; + isdn_ctrl ic; + + FsmChangeState(fi, ST_NULL); + ic.driver = chanp->cs->myid; + ic.command = ISDN_STAT_CAUSE; + ic.arg = chanp->chan; + sprintf(ic.parm.num, "L%02X%02X", 0, 0x2f); + chanp->cs->iif.statcallb(&ic); + HL_LL(chanp, ISDN_STAT_DHUP); + chanp->Flags = 0; + chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); +} + +static void +lli_rel_b_fail(struct FsmInst *fi, int event, void *arg) +{ + struct Channel *chanp = fi->userdata; + + release_b_st(chanp); + lli_failure_l(fi, event, arg); +} + +static void +lli_bhup_fail(struct FsmInst *fi, int event, void *arg) +{ + struct Channel *chanp = fi->userdata; + + if (chanp->debug & 1) + link_debug(chanp, 0, "STAT_BHUP"); + HL_LL(chanp, ISDN_STAT_BHUP); + + lli_rel_b_fail(fi, event, arg); +} + +static void +lli_failure_a(struct FsmInst *fi, int event, void *arg) +{ + struct Channel *chanp = fi->userdata; + + chanp->data_open = 0; + chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); + + lli_bhup_fail(fi, event, arg); +} + + /* *INDENT-OFF* */ + static struct FsmNode fnlist[] HISAX_INITDATA = + { + {ST_NULL, EV_DIAL, lli_prep_dialout}, + {ST_NULL, EV_RESUME, lli_resume}, + {ST_NULL, EV_SETUP_IND, lli_deliver_call}, + {ST_NULL, EV_LEASED, lli_leased_in}, + {ST_OUT_DIAL, EV_SETUP_CNF, lli_init_bchan_out}, + {ST_OUT_DIAL, EV_HANGUP, lli_disconnect_req}, + {ST_OUT_DIAL, EV_DISCONNECT_IND, lli_release_req}, + {ST_OUT_DIAL, EV_RELEASE, lli_dhup_close}, + {ST_OUT_DIAL, EV_NOSETUP_RSP, lli_no_setup_rsp}, + {ST_OUT_DIAL, EV_SETUP_ERR, lli_error}, + {ST_IN_WAIT_LL, EV_LEASED_REL, lli_failure_l}, + {ST_IN_WAIT_LL, EV_ACCEPTD, lli_setup_rsp}, + {ST_IN_WAIT_LL, EV_HANGUP, lli_reject_req}, + {ST_IN_WAIT_LL, EV_DISCONNECT_IND, lli_release_req}, + {ST_IN_WAIT_LL, EV_RELEASE, lli_dhup_close}, + {ST_IN_ALERT_SENT, EV_SETUP_CMPL_IND, lli_init_bchan_in}, + {ST_IN_ALERT_SENT, EV_ACCEPTD, lli_send_dconnect}, + {ST_IN_ALERT_SENT, EV_HANGUP, lli_disconnect_reject}, + {ST_IN_ALERT_SENT, EV_DISCONNECT_IND, lli_release_req}, + {ST_IN_ALERT_SENT, EV_RELEASE, lli_dhup_close}, + {ST_IN_ALERT_SENT, EV_REDIR, lli_send_redir}, + {ST_IN_PROCEED_SEND, EV_REDIR, lli_send_redir}, + {ST_IN_PROCEED_SEND, EV_ALERT, lli_send_alert}, + {ST_IN_PROCEED_SEND, EV_ACCEPTD, lli_send_dconnect}, + {ST_IN_PROCEED_SEND, EV_HANGUP, lli_disconnect_reject}, + {ST_IN_PROCEED_SEND, EV_DISCONNECT_IND, lli_dhup_close}, + {ST_IN_ALERT_SENT, EV_RELEASE, lli_dhup_close}, + {ST_IN_WAIT_CONN_ACK, EV_SETUP_CMPL_IND, lli_init_bchan_in}, + {ST_IN_WAIT_CONN_ACK, EV_HANGUP, lli_disconnect_req}, + {ST_IN_WAIT_CONN_ACK, EV_DISCONNECT_IND, lli_release_req}, + {ST_IN_WAIT_CONN_ACK, EV_RELEASE, lli_dhup_close}, + {ST_IN_WAIT_CONN_ACK, EV_CONNECT_ERR, lli_error}, + {ST_WAIT_BCONN, EV_BC_EST, lli_go_active}, + {ST_WAIT_BCONN, EV_BC_REL, lli_rel_b_disc}, + {ST_WAIT_BCONN, EV_HANGUP, lli_rel_b_disc}, + {ST_WAIT_BCONN, EV_DISCONNECT_IND, lli_rel_b_release_req}, + {ST_WAIT_BCONN, EV_RELEASE, lli_rel_b_dhup}, + {ST_WAIT_BCONN, EV_LEASED_REL, lli_rel_b_fail}, + {ST_WAIT_BCONN, EV_CINF, lli_charge_info}, + {ST_ACTIVE, EV_CINF, lli_charge_info}, + {ST_ACTIVE, EV_BC_REL, lli_bhup_rel_b}, + {ST_ACTIVE, EV_SUSPEND, lli_suspend}, + {ST_ACTIVE, EV_HANGUP, lli_disconn_bchan}, + {ST_ACTIVE, EV_DISCONNECT_IND, lli_release_bchan}, + {ST_ACTIVE, EV_RELEASE, lli_abort}, + {ST_ACTIVE, EV_LEASED_REL, lli_failure_a}, + {ST_WAIT_BRELEASE, EV_BC_REL, lli_bhup_disc}, + {ST_WAIT_BRELEASE, EV_DISCONNECT_IND, lli_bhup_release_req}, + {ST_WAIT_BRELEASE, EV_RELEASE, lli_bhup_dhup}, + {ST_WAIT_BRELEASE, EV_LEASED_REL, lli_bhup_fail}, + {ST_WAIT_BREL_DISC, EV_BC_REL, lli_bhup_release_req}, + {ST_WAIT_BREL_DISC, EV_RELEASE, lli_bhup_dhup}, + {ST_WAIT_DCOMMAND, EV_HANGUP, lli_start_disc}, + {ST_WAIT_DCOMMAND, EV_DISCONNECT_IND, lli_release_req}, + {ST_WAIT_DCOMMAND, EV_RELEASE, lli_dhup_close}, + {ST_WAIT_DCOMMAND, EV_LEASED_REL, lli_failure_l}, + {ST_WAIT_DRELEASE, EV_RELEASE, lli_dhup_close}, + {ST_WAIT_DRELEASE, EV_DIAL, lli_dchan_not_ready}, + /* ETS 300-104 16.1 */ + {ST_WAIT_D_REL_CNF, EV_RELEASE, lli_dhup_close}, + {ST_WAIT_D_REL_CNF, EV_DIAL, lli_dchan_not_ready}, +}; + /* *INDENT-ON* */ -static void -bc_l1man(struct PStack *st, int pr, void *arg) + + #define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode)) + +HISAX_INITFUNC(void +CallcNew(void)) { - struct Channel *chanp = (struct Channel *) st->lli.userdata; + callcfsm.state_count = STATE_COUNT; + callcfsm.event_count = EVENT_COUNT; + callcfsm.strEvent = strEvent; + callcfsm.strState = strState; + FsmNew(&callcfsm, fnlist, FNCOUNT); +} - switch (pr) { - case (PH_ACTIVATE_IND): - case (PH_ACTIVATE_CNF): - FsmEvent(&chanp->lc_b->lcfi, EV_LC_PH_ACTIVATE, NULL); - break; - case (PH_DEACTIVATE_IND): - FsmEvent(&chanp->lc_b->lcfi, EV_LC_PH_DEACTIVATE, NULL); - break; - } +void +CallcFree(void) +{ + FsmFree(&callcfsm); } static void -bc_l2man(struct PStack *st, int pr, void *arg) +release_b_st(struct Channel *chanp) { - struct Channel *chanp = (struct Channel *) st->lli.userdata; + struct PStack *st = chanp->b_st; - switch (pr) { - case (DL_ESTABLISH): - FsmEvent(&chanp->lc_b->lcfi, EV_LC_DL_ESTABLISH, NULL); - break; - case (DL_RELEASE): - FsmEvent(&chanp->lc_b->lcfi, EV_LC_DL_RELEASE, NULL); - break; - } + if(test_and_clear_bit(FLG_START_B, &chanp->Flags)) { + chanp->bcs->BC_Close(chanp->bcs); + switch (chanp->l2_active_protocol) { + case (ISDN_PROTO_L2_X75I): + releasestack_isdnl2(st); + break; + case (ISDN_PROTO_L2_HDLC): + case (ISDN_PROTO_L2_TRANS): + case (ISDN_PROTO_L2_MODEM): + releasestack_transl2(st); + break; + } + } } struct Channel -*selectfreechannel(struct PStack *st) +*selectfreechannel(struct PStack *st, int bch) { struct IsdnCardState *cs = st->l1.hardware; struct Channel *chanp = st->lli.userdata; @@ -1466,87 +972,96 @@ i=1; else i=0; - while (i<2) { + + if (!bch) + { i = 2; /* virtual channel */ + chanp += 2; + } + + while (i < ((bch) ? cs->chanlimit : (2 + MAX_WAITING_CALLS))) { if (chanp->fi.state == ST_NULL) return (chanp); chanp++; i++; - } - return (NULL); -} - -int -is_activ(struct PStack *st) -{ - struct IsdnCardState *cs = st->l1.hardware; - struct Channel *chanp = st->lli.userdata; - int i; + } - if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags)) - i=1; - else - i=0; - while (i<2) { - if (test_bit(FLG_ESTAB_D, &chanp->Flags)) - return (1); + if (bch) /* number of channels is limited */ + { i = 2; /* virtual channel */ + chanp = st->lli.userdata; + chanp += i; + while (i < (2 + MAX_WAITING_CALLS)) { + if (chanp->fi.state == ST_NULL) + return (chanp); chanp++; i++; - } - return (0); + } + } + return (NULL); } +static void stat_redir_result(struct IsdnCardState *cs, int chan, ulong result) +{ isdn_ctrl ic; + + ic.driver = cs->myid; + ic.command = ISDN_STAT_REDIR; + ic.arg = chan; + (ulong)(ic.parm.num[0]) = result; + cs->iif.statcallb(&ic); +} /* stat_redir_result */ + static void -ll_handler(struct l3_process *pc, int pr, void *arg) +dchan_l3l4(struct PStack *st, int pr, void *arg) { + struct l3_process *pc = arg; + struct IsdnCardState *cs = st->l1.hardware; struct Channel *chanp; - char tmp[64], tm[32]; - if (pr == CC_SETUP_IND) { - if (!(chanp = selectfreechannel(pc->st))) { - pc->st->lli.l4l3(pc->st, CC_DLRL, pc); - return; - } else { - chanp->proc = pc; - pc->chan = chanp; + if(!pc) + return; + + if (pr == (CC_SETUP | INDICATION)) { + if (!(chanp = selectfreechannel(pc->st, pc->para.bchannel))) { + pc->para.cause = 0x11; /* User busy */ + pc->st->lli.l4l3(pc->st, CC_REJECT | REQUEST, pc); + } else { + chanp->proc = pc; + pc->chan = chanp; FsmEvent(&chanp->fi, EV_SETUP_IND, NULL); - return; } - } else if (pr == CC_ESTABLISH) { - if (is_activ(pc->st)) { - pc->st->lli.l4l3(pc->st, CC_ESTABLISH, pc); - return; - } else if (!(chanp = selectfreechannel(pc->st))) { - pc->st->lli.l4l3(pc->st, CC_DLRL, pc); - return; - } else { - chanp->proc = pc; - FsmEvent(&chanp->fi, EV_ESTABLISH, NULL); - return; - } - - + return; } - chanp = pc->chan; + if (!(chanp = pc->chan)) + return; + switch (pr) { - case (CC_DISCONNECT_IND): + case (CC_DISCONNECT | INDICATION): FsmEvent(&chanp->fi, EV_DISCONNECT_IND, NULL); break; - case (CC_RELEASE_CNF): - FsmEvent(&chanp->fi, EV_RELEASE_CNF, NULL); + case (CC_RELEASE | CONFIRM): + FsmEvent(&chanp->fi, EV_RELEASE, NULL); + break; + case (CC_SUSPEND | CONFIRM): + FsmEvent(&chanp->fi, EV_RELEASE, NULL); + break; + case (CC_RESUME | CONFIRM): + FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL); + break; + case (CC_RESUME_ERR): + FsmEvent(&chanp->fi, EV_RELEASE, NULL); break; - case (CC_RELEASE_IND): - FsmEvent(&chanp->fi, EV_RELEASE_IND, NULL); + case (CC_RELEASE | INDICATION): + FsmEvent(&chanp->fi, EV_RELEASE, NULL); break; - case (CC_SETUP_COMPLETE_IND): + case (CC_SETUP_COMPL | INDICATION): FsmEvent(&chanp->fi, EV_SETUP_CMPL_IND, NULL); break; - case (CC_SETUP_CNF): + case (CC_SETUP | CONFIRM): FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL); break; - case (CC_INFO_CHARGE): + case (CC_CHARGE | INDICATION): FsmEvent(&chanp->fi, EV_CINF, NULL); break; - case (CC_NOSETUP_RSP_ERR): + case (CC_NOSETUP_RSP): FsmEvent(&chanp->fi, EV_NOSETUP_RSP, NULL); break; case (CC_SETUP_ERR): @@ -1556,17 +1071,22 @@ FsmEvent(&chanp->fi, EV_CONNECT_ERR, NULL); break; case (CC_RELEASE_ERR): - FsmEvent(&chanp->fi, EV_RELEASE_ERR, NULL); - break; - case (CC_PROCEEDING_IND): - case (CC_ALERTING_IND): + FsmEvent(&chanp->fi, EV_RELEASE, NULL); break; + case (CC_PROCEED_SEND | INDICATION): + case (CC_PROCEEDING | INDICATION): + case (CC_ALERTING | INDICATION): + case (CC_PROGRESS | INDICATION): + case (CC_NOTIFY | INDICATION): + break; + case (CC_REDIR | INDICATION): + stat_redir_result(cs, chanp->chan, pc->redir_result); + break; default: if (chanp->debug & 0x800) { - jiftime(tm, jiffies); - sprintf(tmp, "%s Channel %d L3->L4 unknown primitiv %d\n", - tm, chanp->chan, pr); - HiSax_putstatus(chanp->cs, tmp); + HiSax_putstatus(chanp->cs, "Ch", + "%d L3->L4 unknown primitiv %#x", + chanp->chan, pr); } } } @@ -1576,7 +1096,7 @@ { struct PStack *st = chanp->d_st; struct IsdnCardState *cs = chanp->cs; - char tmp[128]; + char tmp[16]; HiSax_addlist(cs, st); setstack_HiSax(st, cs); @@ -1590,95 +1110,51 @@ st->l2.window = 1; st->l2.T200 = 1000; /* 1000 milliseconds */ st->l2.N200 = 3; /* try 3 times */ - if (st->protocol == ISDN_PTYPE_1TR6) - st->l2.T203 = 10000; /* 10000 milliseconds */ + st->l2.T203 = 10000; /* 10000 milliseconds */ + if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags)) + sprintf(tmp, "DCh%d Q.921 ", chanp->chan); else - st->l2.T203 = 10000; /* 5000 milliseconds */ - - sprintf(tmp, "Channel %d q.921", chanp->chan); + sprintf(tmp, "DCh Q.921 "); setstack_isdnl2(st, tmp); - setstack_isdnl3(st, chanp); + setstack_l3dc(st, chanp); st->lli.userdata = chanp; st->lli.l2writewakeup = NULL; - st->l3.l3l4 = ll_handler; - st->l1.l1man = dc_l1man; - st->l2.l2man = dc_l2man; + st->l3.l3l4 = dchan_l3l4; } static void -callc_debug(struct FsmInst *fi, char *s) +callc_debug(struct FsmInst *fi, char *fmt, ...) { - char str[80], tm[32]; + va_list args; struct Channel *chanp = fi->userdata; + char tmp[16]; - jiftime(tm, jiffies); - sprintf(str, "%s Channel %d callc %s\n", tm, chanp->chan, s); - HiSax_putstatus(chanp->cs, str); -} - -static void -lc_debug(struct FsmInst *fi, char *s) -{ - char str[256], tm[32]; - struct LcFsm *lf = fi->userdata; - - jiftime(tm, jiffies); - sprintf(str, "%s Channel %d dc %s\n", tm, lf->ch->chan, s); - HiSax_putstatus(lf->ch->cs, str); -} - -static void -dlc_debug(struct FsmInst *fi, char *s) -{ - char str[256], tm[32]; - struct LcFsm *lf = fi->userdata; - - jiftime(tm, jiffies); - sprintf(str, "%s Channel %d bc %s\n", tm, lf->ch->chan, s); - HiSax_putstatus(lf->ch->cs, str); + va_start(args, fmt); + sprintf(tmp, "Ch%d callc ", chanp->chan); + VHiSax_putstatus(chanp->cs, tmp, fmt, args); + va_end(args); } static void -lccall_d(struct LcFsm *lf, int pr, void *arg) -{ - struct IsdnCardState *cs = lf->st->l1.hardware; - struct Channel *chanp; - int i; - - if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags)) { - chanp = lf->ch; - i = 1; - } else { - chanp = cs->channel; - i = 0; - } - while (i < 2) { - switch (pr) { - case (LC_ESTABLISH): - FsmEvent(&chanp->fi, EV_DLEST, NULL); - break; - case (LC_RELEASE): - FsmEvent(&chanp->fi, EV_DLRL, NULL); - break; - } - chanp++; - i++; - } +dummy_pstack(struct PStack *st, int pr, void *arg) { + printk(KERN_WARNING"call to dummy_pstack pr=%04x arg %lx\n", pr, (long)arg); } static void -lccall_b(struct LcFsm *lf, int pr, void *arg) -{ - struct Channel *chanp = lf->ch; - - switch (pr) { - case (LC_ESTABLISH): - FsmEvent(&chanp->fi, EV_BC_EST, NULL); - break; - case (LC_RELEASE): - FsmEvent(&chanp->fi, EV_BC_REL, NULL); - break; - } +init_PStack(struct PStack **stp) { + *stp = kmalloc(sizeof(struct PStack), GFP_ATOMIC); + (*stp)->next = NULL; + (*stp)->l1.l1l2 = dummy_pstack; + (*stp)->l1.l1hw = dummy_pstack; + (*stp)->l1.l1tei = dummy_pstack; + (*stp)->l2.l2tei = dummy_pstack; + (*stp)->l2.l2l1 = dummy_pstack; + (*stp)->l2.l2l3 = dummy_pstack; + (*stp)->l3.l3l2 = dummy_pstack; + (*stp)->l3.l3ml3 = dummy_pstack; + (*stp)->l3.l3l4 = dummy_pstack; + (*stp)->lli.l4l3 = dummy_pstack; + (*stp)->ma.layer = dummy_pstack; } static void @@ -1693,9 +1169,8 @@ chanp->debug = 0; chanp->Flags = 0; chanp->leased = 0; - chanp->b_st = kmalloc(sizeof(struct PStack), GFP_ATOMIC); - chanp->b_st->next = NULL; - + init_PStack(&chanp->b_st); + chanp->b_st->l1.delay = DEFAULT_B_DELAY; chanp->fi.fsm = &callcfsm; chanp->fi.state = ST_NULL; chanp->fi.debug = 0; @@ -1704,56 +1179,35 @@ FsmInitTimer(&chanp->fi, &chanp->dial_timer); FsmInitTimer(&chanp->fi, &chanp->drel_timer); if (!chan || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) { - chanp->d_st = kmalloc(sizeof(struct PStack), GFP_ATOMIC); + init_PStack(&chanp->d_st); + if (chan) + csta->channel->d_st->next = chanp->d_st; chanp->d_st->next = NULL; init_d_st(chanp); - chanp->lc_d = kmalloc(sizeof(struct LcFsm), GFP_ATOMIC); - chanp->lc_d->lcfi.fsm = &lcfsm; - chanp->lc_d->lcfi.state = ST_LC_NULL; - chanp->lc_d->lcfi.debug = 0; - chanp->lc_d->lcfi.userdata = chanp->lc_d; - chanp->lc_d->lcfi.printdebug = lc_debug; - chanp->lc_d->type = LC_D; - chanp->lc_d->delay = 0; - chanp->lc_d->ch = chanp; - chanp->lc_d->st = chanp->d_st; - chanp->lc_d->l2_establish = !0; - chanp->lc_d->l2_start = !0; - chanp->lc_d->lccall = lccall_d; - FsmInitTimer(&chanp->lc_d->lcfi, &chanp->lc_d->act_timer); } else { chanp->d_st = csta->channel->d_st; - chanp->lc_d = csta->channel->lc_d; } - chanp->lc_b = kmalloc(sizeof(struct LcFsm), GFP_ATOMIC); - chanp->lc_b->lcfi.fsm = &lcfsm; - chanp->lc_b->lcfi.state = ST_LC_NULL; - chanp->lc_b->lcfi.debug = 0; - chanp->lc_b->lcfi.userdata = chanp->lc_b; - chanp->lc_b->lcfi.printdebug = dlc_debug; - chanp->lc_b->type = LC_B; - chanp->lc_b->delay = DEFAULT_B_DELAY; - chanp->lc_b->ch = chanp; - chanp->lc_b->st = chanp->b_st; - chanp->lc_b->l2_establish = !0; - chanp->lc_b->l2_start = !0; - chanp->lc_b->lccall = lccall_b; - FsmInitTimer(&chanp->lc_b->lcfi, &chanp->lc_b->act_timer); chanp->data_open = 0; } int CallcNewChan(struct IsdnCardState *csta) -{ +{ int i; + chancount += 2; init_chan(0, csta); init_chan(1, csta); printk(KERN_INFO "HiSax: 2 channels added\n"); -#ifdef LAYER2_WATCHING - printk(KERN_INFO "LAYER2 ESTABLISH\n"); - test_and_set_bit(FLG_START_D, &csta->channel->Flags); - FsmEvent(&csta->channel->lc_d->lcfi, EV_LC_ESTABLISH, NULL); -#endif + + for (i = 0; i < MAX_WAITING_CALLS; i++) + init_chan(i+2,csta); + printk(KERN_INFO "HiSax: MAX_WAITING_CALLS added\n"); + + if (test_bit(FLG_PTP, &csta->channel->d_st->l2.flag)) { + printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n"); + csta->channel->d_st->lli.l4l3(csta->channel->d_st, + DL_ESTABLISH | REQUEST, NULL); + } return (2); } @@ -1779,29 +1233,16 @@ for (i = 0; i < 2; i++) { FsmDelTimer(&csta->channel[i].drel_timer, 74); FsmDelTimer(&csta->channel[i].dial_timer, 75); - FsmDelTimer(&csta->channel[i].lc_d->act_timer, 77); - FsmDelTimer(&csta->channel[i].lc_b->act_timer, 76); - if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) - release_d_st(csta->channel + i); - if (csta->channel[i].b_st) { - if (test_and_clear_bit(FLG_START_B, &csta->channel[i].Flags)) - release_b_st(csta->channel + i); - kfree(csta->channel[i].b_st); - csta->channel[i].b_st = NULL; - } else + if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) + release_d_st(csta->channel + i); + if (csta->channel[i].b_st) { + release_b_st(csta->channel + i); + kfree(csta->channel[i].b_st); + csta->channel[i].b_st = NULL; + } else printk(KERN_WARNING "CallcFreeChan b_st ch%d allready freed\n", i); - if (csta->channel[i].lc_b) { - kfree(csta->channel[i].lc_b); - csta->channel[i].b_st = NULL; - } if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) { release_d_st(csta->channel + i); - FsmDelTimer(&csta->channel[i].lc_d->act_timer, 77); - if (csta->channel[i].lc_d) { - kfree(csta->channel[i].lc_d); - csta->channel[i].d_st = NULL; - } else - printk(KERN_WARNING "CallcFreeChan lc_d ch%d allready freed\n", i); } else csta->channel[i].d_st = NULL; } @@ -1814,15 +1255,23 @@ struct sk_buff *skb = arg; switch (pr) { - case (DL_DATA): + case (DL_DATA | INDICATION): if (chanp->data_open) chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb); else { - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); } break; + case (DL_ESTABLISH | INDICATION): + case (DL_ESTABLISH | CONFIRM): + FsmEvent(&chanp->fi, EV_BC_EST, NULL); + break; + case (DL_RELEASE | INDICATION): + case (DL_RELEASE | CONFIRM): + FsmEvent(&chanp->fi, EV_BC_REL, NULL); + break; default: - printk(KERN_WARNING "lldata_handler unknown primitive %d\n", + printk(KERN_WARNING "lldata_handler unknown primitive %#x\n", pr); break; } @@ -1835,22 +1284,24 @@ struct sk_buff *skb = arg; switch (pr) { - case (PH_DATA_IND): + case (PH_DATA | INDICATION): if (chanp->data_open) chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb); else { - if (chanp->lc_b->lcfi.state == ST_LC_DELAY) - FsmEvent(&chanp->lc_b->lcfi, EV_LC_DL_ESTABLISH, NULL); - if (chanp->data_open) { - link_debug(chanp, "channel now open", 0); - chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, - chanp->chan, skb); - } else - dev_kfree_skb(skb); + link_debug(chanp, 0, "channel not open"); + idev_kfree_skb(skb, FREE_READ); } break; + case (PH_ACTIVATE | INDICATION): + case (PH_ACTIVATE | CONFIRM): + FsmEvent(&chanp->fi, EV_BC_EST, NULL); + break; + case (PH_DEACTIVATE | INDICATION): + case (PH_DEACTIVATE | CONFIRM): + FsmEvent(&chanp->fi, EV_BC_REL, NULL); + break; default: - printk(KERN_WARNING "lltrans_handler unknown primitive %d\n", + printk(KERN_WARNING "lltrans_handler unknown primitive %#x\n", pr); break; } @@ -1874,10 +1325,25 @@ { struct PStack *st = chanp->b_st; struct IsdnCardState *cs = chanp->cs; - char tmp[128]; + char tmp[16]; st->l1.hardware = cs; - chanp->bcs->mode = 2; + if (chanp->leased) + st->l1.bc = chanp->chan & 1; + else + st->l1.bc = chanp->proc->para.bchannel - 1; + switch (chanp->l2_active_protocol) { + case (ISDN_PROTO_L2_X75I): + case (ISDN_PROTO_L2_HDLC): + st->l1.mode = L1_MODE_HDLC; + break; + case (ISDN_PROTO_L2_TRANS): + st->l1.mode = L1_MODE_TRANS; + break; + case (ISDN_PROTO_L2_MODEM): + st->l1.mode = L1_MODE_MODEM; + break; + } if (chanp->bcs->BC_SetStack(st, chanp->bcs)) return (-1); st->l2.flag = 0; @@ -1892,50 +1358,89 @@ st->l3.debug = 0; switch (chanp->l2_active_protocol) { case (ISDN_PROTO_L2_X75I): - sprintf(tmp, "Channel %d x.75", chanp->chan); + sprintf(tmp, "Ch%d X.75", chanp->chan); setstack_isdnl2(st, tmp); + setstack_l3bc(st, chanp); st->l2.l2l3 = lldata_handler; - st->l1.l1man = bc_l1man; - st->l2.l2man = bc_l2man; st->lli.userdata = chanp; st->lli.l1writewakeup = NULL; st->lli.l2writewakeup = ll_writewakeup; st->l2.l2m.debug = chanp->debug & 16; st->l2.debug = chanp->debug & 64; - st->ma.manl2(st, MDL_NOTEIPROC, NULL); - st->l1.mode = L1_MODE_HDLC; - if (chanp->leased) - st->l1.bc = chanp->chan & 1; - else - st->l1.bc = chanp->proc->para.bchannel - 1; break; case (ISDN_PROTO_L2_HDLC): - st->l1.l1l2 = lltrans_handler; - st->l1.l1man = bc_l1man; - st->lli.userdata = chanp; - st->lli.l1writewakeup = ll_writewakeup; - st->l1.mode = L1_MODE_HDLC; - if (chanp->leased) - st->l1.bc = chanp->chan & 1; - else - st->l1.bc = chanp->proc->para.bchannel - 1; - break; case (ISDN_PROTO_L2_TRANS): + case (ISDN_PROTO_L2_MODEM): st->l1.l1l2 = lltrans_handler; - st->l1.l1man = bc_l1man; st->lli.userdata = chanp; st->lli.l1writewakeup = ll_writewakeup; - st->l1.mode = L1_MODE_TRANS; - if (chanp->leased) - st->l1.bc = chanp->chan & 1; - else - st->l1.bc = chanp->proc->para.bchannel - 1; + setstack_transl2(st); + setstack_l3bc(st, chanp); break; } + test_and_set_bit(FLG_START_B, &chanp->Flags); + return (0); } static void +leased_l4l3(struct PStack *st, int pr, void *arg) +{ + struct Channel *chanp = (struct Channel *) st->lli.userdata; + struct sk_buff *skb = arg; + + switch (pr) { + case (DL_DATA | REQUEST): + link_debug(chanp, 0, "leased line d-channel DATA"); + idev_kfree_skb(skb, FREE_READ); + break; + case (DL_ESTABLISH | REQUEST): + st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL); + break; + case (DL_RELEASE | REQUEST): + break; + default: + printk(KERN_WARNING "transd_l4l3 unknown primitive %#x\n", + pr); + break; + } +} + +static void +leased_l1l2(struct PStack *st, int pr, void *arg) +{ + struct Channel *chanp = (struct Channel *) st->lli.userdata; + struct sk_buff *skb = arg; + int i,event = EV_LEASED_REL; + + switch (pr) { + case (PH_DATA | INDICATION): + link_debug(chanp, 0, "leased line d-channel DATA"); + idev_kfree_skb(skb, FREE_READ); + break; + case (PH_ACTIVATE | INDICATION): + case (PH_ACTIVATE | CONFIRM): + event = EV_LEASED; + case (PH_DEACTIVATE | INDICATION): + case (PH_DEACTIVATE | CONFIRM): + if (test_bit(FLG_TWO_DCHAN, &chanp->cs->HW_Flags)) + i = 1; + else + i = 0; + while (i < 2) { + FsmEvent(&chanp->fi, event, NULL); + chanp++; + i++; + } + break; + default: + printk(KERN_WARNING + "transd_l1l2 unknown primitive %#x\n", pr); + break; + } +} + +static void channel_report(struct Channel *chanp) { } @@ -1946,30 +1451,117 @@ int i; struct Channel *chanp = csta->channel; - for (i = 0; i < 2; i++) { + for (i = 0; i < (2 + MAX_WAITING_CALLS) ; i++) { chanp[i].debug = debugflags; chanp[i].fi.debug = debugflags & 2; chanp[i].d_st->l2.l2m.debug = debugflags & 8; chanp[i].b_st->l2.l2m.debug = debugflags & 0x10; chanp[i].d_st->l2.debug = debugflags & 0x20; chanp[i].b_st->l2.debug = debugflags & 0x40; - chanp[i].lc_d->lcfi.debug = debugflags & 0x80; - chanp[i].lc_b->lcfi.debug = debugflags & 0x100; + chanp[i].d_st->l3.l3m.debug = debugflags & 0x80; + chanp[i].b_st->l3.l3m.debug = debugflags & 0x100; chanp[i].b_st->ma.tei_m.debug = debugflags & 0x200; chanp[i].b_st->ma.debug = debugflags & 0x200; chanp[i].d_st->l1.l1m.debug = debugflags & 0x1000; + chanp[i].b_st->l1.l1m.debug = debugflags & 0x2000; + } + if (debugflags & 4) + csta->debug |= DEB_DLOG_HEX; + else + csta->debug &= ~DEB_DLOG_HEX; +} + +static char tmpbuf[256]; + +static void +capi_debug(struct Channel *chanp, capi_msg *cm) +{ + char *t = tmpbuf; + + t += sprintf(tmpbuf, "%d CAPIMSG", chanp->chan); + t += QuickHex(t, (u_char *)cm, (cm->Length>50)? 50: cm->Length); + t--; + *t= 0; + HiSax_putstatus(chanp->cs, "Ch", "%d CAPIMSG %s", chanp->chan, tmpbuf); +} + +void +lli_got_fac_req(struct Channel *chanp, capi_msg *cm) { + if ((cm->para[0] != 3) || (cm->para[1] != 0)) + return; + if (cm->para[2]<3) + return; + if (cm->para[4] != 0) + return; + switch(cm->para[3]) { + case 4: /* Suspend */ + if (cm->para[5]) { + strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1); + FsmEvent(&chanp->fi, EV_SUSPEND, cm); + } + break; + case 5: /* Resume */ + if (cm->para[5]) { + strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1); + if (chanp->fi.state == ST_NULL) { + FsmEvent(&chanp->fi, EV_RESUME, cm); + } else { + FsmDelTimer(&chanp->dial_timer, 72); + FsmAddTimer(&chanp->dial_timer, 80, EV_RESUME, cm, 73); + } + } + break; + } +} + +void +lli_got_manufacturer(struct Channel *chanp, struct IsdnCardState *cs, capi_msg *cm) { + if ((cs->typ == ISDN_CTYPE_ELSA) || (cs->typ == ISDN_CTYPE_ELSA_PNP) || + (cs->typ == ISDN_CTYPE_ELSA_PCI)) { + if (cs->hw.elsa.MFlag) { + cs->cardmsg(cs, CARD_AUX_IND, cm->para); + } } - csta->dlogflag = debugflags & 4; } + +/***************************************************************/ +/* Limit the available number of channels for the current card */ +/***************************************************************/ +static int +set_channel_limit(struct IsdnCardState *cs, int chanmax) +{ isdn_ctrl ic; + int i, ii; + + if ((chanmax < 0) || (chanmax > 2)) + return(-EINVAL); + cs->chanlimit = 0; + for (ii = 0; ii < 2; ii++) { + ic.driver = cs->myid; + ic.command = ISDN_STAT_DISCH; + ic.arg = ii; + if (ii >= chanmax) + ic.parm.num[0] = 0; /* disabled */ + else + ic.parm.num[0] = 1; /* enabled */ + i = cs->iif.statcallb(&ic); + if (i) return(-EINVAL); + if (ii < chanmax) + cs->chanlimit++; + } + return(0); +} /* set_channel_limit */ + + int HiSax_command(isdn_ctrl * ic) { struct IsdnCardState *csta = hisax_findcard(ic->driver); + struct PStack *st; struct Channel *chanp; - char tmp[128]; int i; - unsigned int num; + u_int num; + u_long adr; if (!csta) { printk(KERN_ERR @@ -1977,32 +1569,32 @@ ic->command, ic->driver); return -ENODEV; } + switch (ic->command) { case (ISDN_CMD_SETEAZ): chanp = csta->channel + ic->arg; - if (chanp->debug & 1) { - sprintf(tmp, "SETEAZ card %d %s", csta->cardnr + 1, - ic->parm.num); - link_debug(chanp, tmp, 1); - } break; + case (ISDN_CMD_SETL2): chanp = csta->channel + (ic->arg & 0xff); - if (chanp->debug & 1) { - sprintf(tmp, "SETL2 card %d %ld", csta->cardnr + 1, - ic->arg >> 8); - link_debug(chanp, tmp, 1); - } + if (chanp->debug & 1) + link_debug(chanp, 1, "SETL2 card %d %ld", + csta->cardnr + 1, ic->arg >> 8); chanp->l2_protocol = ic->arg >> 8; break; + case (ISDN_CMD_SETL3): + chanp = csta->channel + (ic->arg & 0xff); + if (chanp->debug & 1) + link_debug(chanp, 1, "SETL3 card %d %ld", + csta->cardnr + 1, ic->arg >> 8); + chanp->l3_protocol = ic->arg >> 8; + break; case (ISDN_CMD_DIAL): chanp = csta->channel + (ic->arg & 0xff); - if (chanp->debug & 1) { - sprintf(tmp, "DIAL %s -> %s (%d,%d)", + if (chanp->debug & 1) + link_debug(chanp, 1, "DIAL %s -> %s (%d,%d)", ic->parm.setup.eazmsn, ic->parm.setup.phone, - ic->parm.setup.si1, ic->parm.setup.si2); - link_debug(chanp, tmp, 1); - } + ic->parm.setup.si1, ic->parm.setup.si2); chanp->setup = ic->parm.setup; if (!strcmp(chanp->setup.eazmsn, "0")) chanp->setup.eazmsn[0] = '\0'; @@ -2018,57 +1610,54 @@ case (ISDN_CMD_ACCEPTB): chanp = csta->channel + ic->arg; if (chanp->debug & 1) - link_debug(chanp, "ACCEPTB", 1); + link_debug(chanp, 1, "ACCEPTB"); FsmEvent(&chanp->fi, EV_ACCEPTB, NULL); break; case (ISDN_CMD_ACCEPTD): chanp = csta->channel + ic->arg; if (chanp->debug & 1) - link_debug(chanp, "ACCEPTD", 1); + link_debug(chanp, 1, "ACCEPTD"); FsmEvent(&chanp->fi, EV_ACCEPTD, NULL); break; case (ISDN_CMD_HANGUP): chanp = csta->channel + ic->arg; if (chanp->debug & 1) - link_debug(chanp, "HANGUP", 1); + link_debug(chanp, 1, "HANGUP"); FsmEvent(&chanp->fi, EV_HANGUP, NULL); break; - case (ISDN_CMD_SUSPEND): + case (CAPI_PUT_MESSAGE): chanp = csta->channel + ic->arg; - if (chanp->debug & 1) { - sprintf(tmp, "SUSPEND %s", ic->parm.num); - link_debug(chanp, tmp, 1); - } - FsmEvent(&chanp->fi, EV_SUSPEND, ic); - break; - case (ISDN_CMD_RESUME): - chanp = csta->channel + ic->arg; - if (chanp->debug & 1) { - sprintf(tmp, "RESUME %s", ic->parm.num); - link_debug(chanp, tmp, 1); + if (chanp->debug & 1) + capi_debug(chanp, &ic->parm.cmsg); + if (ic->parm.cmsg.Length < 8) + break; + switch(ic->parm.cmsg.Command) { + case CAPI_FACILITY: + if (ic->parm.cmsg.Subcommand == CAPI_REQ) + lli_got_fac_req(chanp, &ic->parm.cmsg); + break; + case CAPI_MANUFACTURER: + if (ic->parm.cmsg.Subcommand == CAPI_REQ) + lli_got_manufacturer(chanp, csta, &ic->parm.cmsg); + break; + default: + break; } - FsmEvent(&chanp->fi, EV_RESUME, ic); break; case (ISDN_CMD_LOCK): HiSax_mod_inc_use_count(); #ifdef MODULE - if (csta->channel[0].debug & 0x400) { - jiftime(tmp, jiffies); - i = strlen(tmp); - sprintf(tmp + i, " LOCK modcnt %d\n", MOD_USE_COUNT); - HiSax_putstatus(csta, tmp); - } + if (csta->channel[0].debug & 0x400) + HiSax_putstatus(csta, " LOCK ", "modcnt %lx", + MOD_USE_COUNT); #endif /* MODULE */ break; case (ISDN_CMD_UNLOCK): HiSax_mod_dec_use_count(); #ifdef MODULE - if (csta->channel[0].debug & 0x400) { - jiftime(tmp, jiffies); - i = strlen(tmp); - sprintf(tmp + i, " UNLOCK modcnt %d\n", MOD_USE_COUNT); - HiSax_putstatus(csta, tmp); - } + if (csta->channel[0].debug & 0x400) + HiSax_putstatus(csta, " UNLOCK ", "modcnt %lx", + MOD_USE_COUNT); #endif /* MODULE */ break; case (ISDN_CMD_IOCTL): @@ -2081,19 +1670,19 @@ case (1): num = *(unsigned int *) ic->parm.num; distr_debug(csta, num); - sprintf(tmp, "debugging flags card %d set to %x\n", + printk(KERN_DEBUG "HiSax: debugging flags card %d set to %x\n", csta->cardnr + 1, num); - HiSax_putstatus(csta, tmp); - printk(KERN_DEBUG "HiSax: %s", tmp); + HiSax_putstatus(csta, "debugging flags ", + "card %d set to %x", csta->cardnr + 1, num); break; case (2): - num = *(unsigned int *) ic->parm.num; - csta->channel[0].lc_b->delay = num; - csta->channel[1].lc_b->delay = num; - sprintf(tmp, "delay card %d set to %d ms\n", + num = *(unsigned int *) ic->parm.num; + csta->channel[0].b_st->l1.delay = num; + csta->channel[1].b_st->l1.delay = num; + HiSax_putstatus(csta, "delay ", "card %d set to %d ms", + csta->cardnr + 1, num); + printk(KERN_DEBUG "HiSax: delay card %d set to %d ms\n", csta->cardnr + 1, num); - HiSax_putstatus(csta, tmp); - printk(KERN_DEBUG "HiSax: %s", tmp); break; case (3): for (i = 0; i < *(unsigned int *) ic->parm.num; i++) @@ -2106,54 +1695,141 @@ case (5): /* set card in leased mode */ num = *(unsigned int *) ic->parm.num; if ((num <1) || (num > 2)) { - sprintf(tmp, "Set LEASED wrong channel %d\n", + HiSax_putstatus(csta, "Set LEASED ", + "wrong channel %d", num); + printk(KERN_WARNING "HiSax: Set LEASED wrong channel %d\n", num); - HiSax_putstatus(csta, tmp); - printk(KERN_WARNING "HiSax: %s", tmp); } else { num--; - csta->channel[num].leased = 1; - csta->channel[num].lc_d->l2_establish = 0; - sprintf(tmp, "card %d channel %d set leased mode\n", + chanp = csta->channel +num; + chanp->leased = 1; + HiSax_putstatus(csta, "Card", + "%d channel %d set leased mode\n", csta->cardnr + 1, num + 1); - HiSax_putstatus(csta, tmp); - FsmEvent(&csta->channel[num].lc_d->lcfi, EV_LC_ESTABLISH, NULL); + chanp->d_st->l1.l1l2 = leased_l1l2; + chanp->d_st->lli.l4l3 = leased_l4l3; + chanp->d_st->lli.l4l3(chanp->d_st, + DL_ESTABLISH | REQUEST, NULL); } break; case (6): /* set B-channel test loop */ num = *(unsigned int *) ic->parm.num; if (csta->stlist) - csta->stlist->ma.manl1(csta->stlist, - PH_TESTLOOP_REQ, (void *) num); + csta->stlist->l2.l2l1(csta->stlist, + PH_TESTLOOP | REQUEST, (void *) (long)num); + break; + case (7): /* set card in PTP mode */ + num = *(unsigned int *) ic->parm.num; + if (test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) { + printk(KERN_ERR "HiSax PTP mode only with one TEI possible\n"); + } else if (num) { + test_and_set_bit(FLG_PTP, &csta->channel[0].d_st->l2.flag); + test_and_set_bit(FLG_FIXED_TEI, &csta->channel[0].d_st->l2.flag); + csta->channel[0].d_st->l2.tei = 0; + HiSax_putstatus(csta, "set card ", "in PTP mode"); + printk(KERN_DEBUG "HiSax: set card in PTP mode\n"); + printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n"); + csta->channel[0].d_st->lli.l4l3(csta->channel[0].d_st, + DL_ESTABLISH | REQUEST, NULL); + } else { + test_and_clear_bit(FLG_PTP, &csta->channel[0].d_st->l2.flag); + test_and_clear_bit(FLG_FIXED_TEI, &csta->channel[0].d_st->l2.flag); + HiSax_putstatus(csta, "set card ", "in PTMP mode"); + printk(KERN_DEBUG "HiSax: set card in PTMP mode\n"); + } + break; + case (8): /* set card in FIXED TEI mode */ + num = *(unsigned int *) ic->parm.num; + chanp = csta->channel + (num & 1); + num = num >>1; + test_and_set_bit(FLG_FIXED_TEI, &chanp->d_st->l2.flag); + chanp->d_st->l2.tei = num; + HiSax_putstatus(csta, "set card ", "in FIXED TEI (%d) mode", num); + printk(KERN_DEBUG "HiSax: set card in FIXED TEI (%d) mode\n", + num); + break; + case (9): /* load firmware */ + memcpy(&adr, ic->parm.num, sizeof(ulong)); + csta->cardmsg(csta, CARD_LOAD_FIRM, + (void *) adr); break; #ifdef MODULE case (55): - while ( MOD_USE_COUNT > 0) - MOD_DEC_USE_COUNT; + MOD_USE_COUNT = 0; HiSax_mod_inc_use_count(); break; #endif /* MODULE */ case (11): + num = csta->debug & DEB_DLOG_HEX; csta->debug = *(unsigned int *) ic->parm.num; - sprintf(tmp, "l1 debugging flags card %d set to %x\n", + csta->debug |= num; + HiSax_putstatus(cards[0].cs, "l1 debugging ", + "flags card %d set to %x", + csta->cardnr + 1, csta->debug); + printk(KERN_DEBUG "HiSax: l1 debugging flags card %d set to %x\n", csta->cardnr + 1, csta->debug); - HiSax_putstatus(cards[0].cs, tmp); - printk(KERN_DEBUG "HiSax: %s", tmp); break; case (13): csta->channel[0].d_st->l3.debug = *(unsigned int *) ic->parm.num; csta->channel[1].d_st->l3.debug = *(unsigned int *) ic->parm.num; - sprintf(tmp, "l3 debugging flags card %d set to %x\n", + HiSax_putstatus(cards[0].cs, "l3 debugging ", + "flags card %d set to %x\n", csta->cardnr + 1, + *(unsigned int *) ic->parm.num); + printk(KERN_DEBUG "HiSax: l3 debugging flags card %d set to %x\n", csta->cardnr + 1, *(unsigned int *) ic->parm.num); - HiSax_putstatus(cards[0].cs, tmp); - printk(KERN_DEBUG "HiSax: %s", tmp); break; + case (10): + i = *(unsigned int *) ic->parm.num; + if ((i < 0) || (i > 2)) + return(-EINVAL); /* invalid number */ + return(set_channel_limit(csta, i)); + break; + case (12): + i = *(unsigned int *) ic->parm.num; +#ifdef CONFIG_HISAX_HFC_PCI + if (csta->typ != ISDN_CTYPE_HFC_PCI) + return(-EINVAL); + return(hfcpci_set_echo(csta,i)); +#else + return(-EINVAL); +#endif + break; default: printk(KERN_DEBUG "HiSax: invalid ioclt %d\n", (int) ic->arg); return (-EINVAL); } break; + + case (ISDN_CMD_PROCEED): + chanp = csta->channel + ic->arg; + if (chanp->debug & 1) + link_debug(chanp, 1, "PROCEED"); + FsmEvent(&chanp->fi, EV_PROCEED, NULL); + break; + + case (ISDN_CMD_ALERT): + chanp = csta->channel + ic->arg; + if (chanp->debug & 1) + link_debug(chanp, 1, "ALERT"); + FsmEvent(&chanp->fi, EV_ALERT, NULL); + break; + + case (ISDN_CMD_REDIR): + chanp = csta->channel + ic->arg; + if (chanp->debug & 1) + link_debug(chanp, 1, "REDIR"); + chanp->setup = ic->parm.setup; + FsmEvent(&chanp->fi, EV_REDIR, NULL); + break; + + /* protocol specific io commands */ + case (ISDN_CMD_PROT_IO): + for (st = csta->stlist; st; st = st->next) + if (st->protocol == (ic->arg & 0xFF)) + return(st->lli.l4l3_proto(st, ic)); + return(-EINVAL); + break; default: break; } @@ -2170,7 +1846,6 @@ int len = skb->len; unsigned long flags; struct sk_buff *nskb; - char tmp[64]; if (!csta) { printk(KERN_ERR @@ -2180,13 +1855,13 @@ chanp = csta->channel + chan; st = chanp->b_st; if (!chanp->data_open) { - link_debug(chanp, "writebuf: channel not open", 1); + link_debug(chanp, 1, "writebuf: channel not open"); return -EIO; } if (len > MAX_DATA_SIZE) { - sprintf(tmp, "writebuf: packet too large (%d bytes)", len); - printk(KERN_WARNING "HiSax_%s !\n", tmp); - link_debug(chanp, tmp, 1); + link_debug(chanp, 1, "writebuf: packet too large (%d bytes)", len); + printk(KERN_WARNING "HiSax_writebuf: packet too large (%d bytes) !\n", + len); return -EINVAL; } if (len) { @@ -2194,25 +1869,24 @@ /* Must return 0 here, since this is not an error * but a temporary lack of resources. */ - if (chanp->debug & 0x800) { - sprintf(tmp, "writebuf: no buffers for %d bytes", len); - link_debug(chanp, tmp, 1); - } + if (chanp->debug & 0x800) + link_debug(chanp, 1, "writebuf: no buffers for %d bytes", len); return 0; - } + } else if (chanp->debug & 0x800) + link_debug(chanp, 1, "writebuf %d/%d/%d", len, chanp->bcs->tx_cnt,MAX_DATA_MEM); save_flags(flags); cli(); nskb = skb_clone(skb, GFP_ATOMIC); if (nskb) { if (!ack) nskb->pkt_type = PACKET_NOACK; - if (chanp->lc_b->l2_establish) - st->l3.l3l2(st, DL_DATA, nskb); + if (chanp->l2_active_protocol == ISDN_PROTO_L2_X75I) + st->l3.l3l2(st, DL_DATA | REQUEST, nskb); else { chanp->bcs->tx_cnt += len; - st->l2.l2l1(st, PH_DATA_REQ, nskb); + st->l2.l2l1(st, PH_DATA | REQUEST, nskb); } - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_WRITE); } else len = 0; restore_flags(flags); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/cert.c linux.pre11.3/drivers/isdn/hisax/cert.c --- linux.vanilla/drivers/isdn/hisax/cert.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/cert.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,55 @@ +/* $Id: cert.c,v 2.1 1998/11/15 23:51:15 keil Exp $ + + * Author Karsten Keil (keil@isdn4linux.de) + * + * This file is (c) under GNU PUBLIC LICENSE + * For changes and modifications please read + * ../../../Documentation/isdn/HiSax.cert + * + * $Log: cert.c,v $ + * Revision 2.1 1998/11/15 23:51:15 keil + * certification stuff + * + * Revision 1.2.2.1 1998/11/03 21:46:37 keil + * first version + * + * + */ + +#include + +int +certification_check(int output) { + +#ifdef CERTIFICATION +#if CERTIFICATION == 0 + if (output) { + printk(KERN_INFO "HiSax: Approval certification valid\n"); + printk(KERN_INFO "HiSax: Approved with ELSA Quickstep series cards\n"); + printk(KERN_INFO "HiSax: Approval registration numbers:\n"); + printk(KERN_INFO "HiSax: German D133361J CETECOM ICT Services GmbH\n"); + printk(KERN_INFO "HiSax: EU (D133362J) CETECOM ICT Services GmbH\n"); + } + return(0); +#endif +#if CERTIFICATION == 1 + if (output) { + printk(KERN_INFO "HiSax: Approval certification failed because of\n"); + printk(KERN_INFO "HiSax: unauthorized source code changes\n"); + } + return(1); +#endif +#if CERTIFICATION == 127 + if (output) { + printk(KERN_INFO "HiSax: Approval certification not possible\n"); + printk(KERN_INFO "HiSax: because \"md5sum\" is not available\n"); + } + return(2); +#endif +#else + if (output) { + printk(KERN_INFO "HiSax: Certification not verified\n"); + } + return(3); +#endif +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/config.c linux.pre11.3/drivers/isdn/hisax/config.c --- linux.vanilla/drivers/isdn/hisax/config.c Wed Mar 24 10:55:17 1999 +++ linux.pre11.3/drivers/isdn/hisax/config.c Mon Jul 19 23:59:33 1999 @@ -1,10 +1,67 @@ -/* $Id: config.c,v 2.12 1998/02/11 17:28:02 keil Exp $ +/* $Id: config.c,v 2.28 1999/07/14 12:38:36 werner Exp $ - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden * * * $Log: config.c,v $ + * Revision 2.28 1999/07/14 12:38:36 werner + * Added changes for echo channel handling + * + * Revision 2.27 1999/07/12 21:05:00 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 2.26 1999/07/08 21:27:17 keil + * version 3.2 + * + * Revision 2.25 1999/07/05 23:51:44 werner + * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl + * hisaxctrl id 10 + * + * Revision 2.24 1999/07/01 08:11:26 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 2.23 1999/02/17 10:53:02 cpetig + * Added Hisax_closecard to exported symbols. + * As indicated by Oliver Schoett . + * + * If anyone is annoyed by exporting symbols deep inside the code, please + * contact me. + * + * Revision 2.22 1999/02/04 21:41:53 keil + * Fix printk msg + * + * Revision 2.21 1999/02/04 10:48:52 keil + * Fix readstat bug + * + * Revision 2.20 1998/11/15 23:54:28 keil + * changes from 2.0 + * + * Revision 2.19 1998/08/13 23:36:18 keil + * HiSax 3.1 - don't work stable with current LinkLevel + * + * Revision 2.18 1998/07/30 21:01:37 niemann + * Fixed Sedlbauer Speed Fax PCMCIA missing isdnl3new + * + * Revision 2.17 1998/07/15 15:01:26 calle + * Support for AVM passive PCMCIA cards: + * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0 + * + * Revision 2.16 1998/05/25 14:10:03 keil + * HiSax 3.0 + * X.75 and leased are working again. + * + * Revision 2.15 1998/05/25 12:57:43 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * + * Revision 2.14 1998/04/15 16:38:25 keil + * Add S0Box and Teles PCI support + * + * Revision 2.13 1998/03/09 23:19:23 keil + * Changes for PCMCIA + * * Revision 2.12 1998/02/11 17:28:02 keil * Niccy PnP/PCI support * @@ -55,6 +112,12 @@ #include #include #include "hisax.h" +#include +#include +#include +#include +#define HISAX_STATUS_BUFSIZE 4096 +#define INCLUDE_INLINE_FUNCS /* * This structure array contains one entry per card. An entry looks @@ -78,42 +141,107 @@ * 13 Teleint p0=irq p1=iobase * 14 Teles 16.3c p0=irq p1=iobase * 15 Sedlbauer speed p0=irq p1=iobase + * 15 Sedlbauer PC/104 p0=irq p1=iobase + * 15 Sedlbauer speed pci no parameter * 16 USR Sportster internal p0=irq p1=iobase * 17 MIC card p0=irq p1=iobase * 18 ELSA Quickstep 1000PCI no parameter * 19 Compaq ISDN S0 ISA card p0=irq p1=IO0 (HSCX) p2=IO1 (ISAC) p3=IO2 * 20 Travers Technologies NETjet PCI card - * 21 reserved TELES PCI + * 21 TELES PCI no parameter * 22 Sedlbauer Speed Star p0=irq p1=iobase * 23 reserved * 24 Dr Neuhaus Niccy PnP/PCI card p0=irq p1=IO0 p2=IO1 (PnP only) - * - * + * 25 Teles S0Box p0=irq p1=iobase (from isapnp setup) + * 26 AVM A1 PCMCIA (Fritz) p0=irq p1=iobase + * 27 AVM PnP/PCI p0=irq p1=iobase (PCI no parameter) + * 28 Sedlbauer Speed Fax+ p0=irq p1=iobase (from isapnp setup) + * 29 Siemens I-Surf p0=irq p1=iobase p2=memory (from isapnp setup) + * 30 ACER P10 p0=irq p1=iobase (from isapnp setup) + * 31 HST Saphir p0=irq p1=iobase + * 32 Telekom A4T none + * 33 Scitel Quadro p0=subcontroller (4*S0, subctrl 1...4) + * 34 Gazel ISDN cards + * 35 HFC 2BDS0 PCI none * protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1 * * */ +const char *CardType[] = +{"No Card", "Teles 16.0", "Teles 8.0", "Teles 16.3", "Creatix/Teles PnP", + "AVM A1", "Elsa ML", "Elsa Quickstep", "Teles PCMCIA", "ITK ix1-micro Rev.2", + "Elsa PCMCIA", "Eicon.Diehl Diva", "ISDNLink", "TeleInt", "Teles 16.3c", + "Sedlbauer Speed Card", "USR Sportster", "ith mic Linux", "Elsa PCI", + "Compaq ISA", "NETjet", "Teles PCI", "Sedlbauer Speed Star (PCMCIA)", + "AMD 7930", "NICCY", "S0Box", "AVM A1 (PCMCIA)", "AVM Fritz PnP/PCI", + "Sedlbauer Speed Fax +", "Siemens I-Surf", "Acer P10", "HST Saphir", + "Telekom A4T", "Scitel Quadro", "Gazel", "HFC 2BDS0 PCI", +}; + +void HiSax_closecard(int cardnr); + #ifdef CONFIG_HISAX_ELSA #define DEFAULT_CARD ISDN_CTYPE_ELSA #define DEFAULT_CFG {0,0,0,0} -#ifdef MODULE int elsa_init_pcmcia(void*, int, int*, int); +#ifdef COMPAT_HAS_NEW_SYMTAB EXPORT_SYMBOL(elsa_init_pcmcia); -#endif -#endif +#else +static struct symbol_table hisax_syms_elsa = { +#include + X(elsa_init_pcmcia), +#include +}; +#endif /* COMPAT_HAS_NEW_SYMTAB */ +#endif /* CONFIG_HISAX_ELSA */ + #ifdef CONFIG_HISAX_AVM_A1 #undef DEFAULT_CARD #undef DEFAULT_CFG #define DEFAULT_CARD ISDN_CTYPE_A1 #define DEFAULT_CFG {10,0x340,0,0} #endif + +#ifdef CONFIG_HISAX_AVM_A1_PCMCIA +#undef DEFAULT_CARD +#undef DEFAULT_CFG +#define DEFAULT_CARD ISDN_CTYPE_A1_PCMCIA +#define DEFAULT_CFG {11,0x170,0,0} +int avm_a1_init_pcmcia(void*, int, int*, int); +#ifdef COMPAT_HAS_NEW_SYMTAB +EXPORT_SYMBOL(avm_a1_init_pcmcia); +#else +static struct symbol_table hisax_syms_avm_a1= { +#include + X(avm_a1_init_pcmcia), + X(HiSax_closecard), +#include +}; +#endif /* COMPAT_HAS_NEW_SYMTAB */ +#endif /* CONFIG_HISAX_AVM_A1_PCMCIA */ + +#ifdef CONFIG_HISAX_FRITZPCI +#undef DEFAULT_CARD +#undef DEFAULT_CFG +#define DEFAULT_CARD ISDN_CTYPE_FRITZPCI +#define DEFAULT_CFG {0,0,0,0} +#endif + #ifdef CONFIG_HISAX_16_3 #undef DEFAULT_CARD #undef DEFAULT_CFG #define DEFAULT_CARD ISDN_CTYPE_16_3 #define DEFAULT_CFG {15,0x180,0,0} #endif + +#ifdef CONFIG_HISAX_S0BOX +#undef DEFAULT_CARD +#undef DEFAULT_CFG +#define DEFAULT_CARD ISDN_CTYPE_S0BOX +#define DEFAULT_CFG {7,0x378,0,0} +#endif + #ifdef CONFIG_HISAX_16_0 #undef DEFAULT_CARD #undef DEFAULT_CFG @@ -121,6 +249,13 @@ #define DEFAULT_CFG {15,0xd0000,0xd80,0} #endif +#ifdef CONFIG_HISAX_TELESPCI +#undef DEFAULT_CARD +#undef DEFAULT_CFG +#define DEFAULT_CARD ISDN_CTYPE_TELESPCI +#define DEFAULT_CFG {0,0,0,0} +#endif + #ifdef CONFIG_HISAX_IX1MICROR2 #undef DEFAULT_CARD #undef DEFAULT_CFG @@ -155,8 +290,16 @@ #define DEFAULT_CARD ISDN_CTYPE_SEDLBAUER #define DEFAULT_CFG {11,0x270,0,0} int sedl_init_pcmcia(void*, int, int*, int); +#ifdef COMPAT_HAS_NEW_SYMTAB EXPORT_SYMBOL(sedl_init_pcmcia); -#endif +#else +static struct symbol_table hisax_syms_sedl= { +#include + X(sedl_init_pcmcia), +#include +}; +#endif /* COMPAT_HAS_NEW_SYMTAB */ +#endif /* CONFIG_HISAX_SEDLBAUER */ #ifdef CONFIG_HISAX_SPORTSTER #undef DEFAULT_CARD @@ -179,13 +322,21 @@ #define DEFAULT_CFG {0,0,0,0} #endif -#ifdef CONFIG_HISAX_TELES3C +#ifdef CONFIG_HISAX_HFCS #undef DEFAULT_CARD #undef DEFAULT_CFG #define DEFAULT_CARD ISDN_CTYPE_TELES3C #define DEFAULT_CFG {5,0x500,0,0} #endif +#ifdef CONFIG_HISAX_HFC_PCI +#undef DEFAULT_CARD +#undef DEFAULT_CFG +#define DEFAULT_CARD ISDN_CTYPE_HFC_PCI +#define DEFAULT_CFG {0,0,0,0} +#endif + + #ifdef CONFIG_HISAX_AMD7930 #undef DEFAULT_CARD #undef DEFAULT_CFG @@ -193,20 +344,48 @@ #define DEFAULT_CFG {12,0x3e0,0,0} #endif -#ifdef CONFIG_HISAX_DBRI +#ifdef CONFIG_HISAX_NICCY #undef DEFAULT_CARD #undef DEFAULT_CFG -#define DEFAULT_CARD ISDN_CTYPE_DBRI +#define DEFAULT_CARD ISDN_CTYPE_NICCY #define DEFAULT_CFG {0,0x0,0,0} #endif -#ifdef CONFIG_HISAX_NICCY +#ifdef CONFIG_HISAX_ISURF #undef DEFAULT_CARD #undef DEFAULT_CFG -#define DEFAULT_CARD ISDN_CTYPE_NICCY +#define DEFAULT_CARD ISDN_CTYPE_ISURF +#define DEFAULT_CFG {5,0x100,0xc8000,0} +#endif + +#ifdef CONFIG_HISAX_HSTSAPHIR +#undef DEFAULT_CARD +#undef DEFAULT_CFG +#define DEFAULT_CARD ISDN_CTYPE_HSTSAPHIR +#define DEFAULT_CFG {5,0x250,0,0} +#endif + +#ifdef CONFIG_HISAX_BKM_A4T +#undef DEFAULT_CARD +#undef DEFAULT_CFG +#define DEFAULT_CARD ISDN_CTYPE_BKM_A4T #define DEFAULT_CFG {0,0x0,0,0} #endif +#ifdef CONFIG_HISAX_SCT_QUADRO +#undef DEFAULT_CARD +#undef DEFAULT_CFG +#define DEFAULT_CARD ISDN_CTYPE_SCT_QUADRO +#define DEFAULT_CFG {1,0x0,0,0} +#endif + +#ifdef CONFIG_HISAX_GAZEL +#undef DEFAULT_CARD +#undef DEFAULT_CFG +#define DEFAULT_CARD ISDN_CTYPE_GAZEL +#define DEFAULT_CFG {15,0x180,0,0} +#endif + #ifdef CONFIG_HISAX_1TR6 #define DEFAULT_PROTO ISDN_PTYPE_1TR6 #define DEFAULT_PROTO_NAME "1TR6" @@ -232,10 +411,10 @@ #endif #define FIRST_CARD { \ - DEFAULT_CARD, \ - DEFAULT_PROTO, \ - DEFAULT_CFG, \ - NULL, \ + DEFAULT_CARD, \ + DEFAULT_PROTO, \ + DEFAULT_CFG, \ + NULL, \ } #define EMPTY_CARD {0, DEFAULT_PROTO, {0, 0, 0, 0}, NULL} @@ -250,29 +429,20 @@ EMPTY_CARD, EMPTY_CARD, EMPTY_CARD, - EMPTY_CARD, - EMPTY_CARD, - EMPTY_CARD, - EMPTY_CARD, - EMPTY_CARD, - EMPTY_CARD, - EMPTY_CARD, - EMPTY_CARD, }; -static char HiSaxID[96] HISAX_INITDATA = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \ -"\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 char HiSaxID[64] HISAX_INITDATA = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \ -"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; +"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; char *HiSax_id HISAX_INITDATA = HiSaxID; #ifdef MODULE /* Variables for insmod */ static int type[] HISAX_INITDATA = -{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 int protocol[] HISAX_INITDATA = -{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 int io[] HISAX_INITDATA = -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +{0, 0, 0, 0, 0, 0, 0, 0}; #undef IO0_IO1 #ifdef CONFIG_HISAX_16_3 #define IO0_IO1 @@ -283,29 +453,30 @@ #endif #ifdef IO0_IO1 static int io0[] HISAX_INITDATA = -{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 int io1[] HISAX_INITDATA = -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +{0, 0, 0, 0, 0, 0, 0, 0}; #endif static int irq[] HISAX_INITDATA = -{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 int mem[] HISAX_INITDATA = -{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 char *id HISAX_INITDATA = HiSaxID; +#ifdef COMPAT_HAS_NEW_SYMTAB MODULE_AUTHOR("Karsten Keil"); -MODULE_PARM(type, "1-3i"); -MODULE_PARM(protocol, "1-2i"); +MODULE_PARM(type, "1-8i"); +MODULE_PARM(protocol, "1-8i"); MODULE_PARM(io, "1-8i"); -MODULE_PARM(irq, "1-2i"); -MODULE_PARM(mem, "1-12i"); +MODULE_PARM(irq, "1-8i"); +MODULE_PARM(mem, "1-8i"); MODULE_PARM(id, "s"); #ifdef CONFIG_HISAX_16_3 /* For Creatix/Teles PnP */ MODULE_PARM(io0, "1-8i"); MODULE_PARM(io1, "1-8i"); -#endif - -#endif +#endif /* CONFIG_HISAX_16_3 */ +#endif /* COMPAT_HAS_NEW_SYMTAB */ +#endif /* MODULE */ int nrcards; @@ -333,23 +504,25 @@ HISAX_INITFUNC(void HiSaxVersion(void)) { - char tmp[64], rev[64]; - char *r = rev; + char tmp[64]; + printk(KERN_INFO "HiSax: Linux Driver for passive ISDN cards\n"); +#ifdef MODULE + printk(KERN_INFO "HiSax: Version 3.2a (module)\n"); +#else + printk(KERN_INFO "HiSax: Version 3.2a (kernel)\n"); +#endif strcpy(tmp, l1_revision); - r += sprintf(r, "%s/", HiSax_getrev(tmp)); + printk(KERN_INFO "HiSax: Layer1 Revision %s\n", HiSax_getrev(tmp)); strcpy(tmp, l2_revision); - r += sprintf(r, "%s/", HiSax_getrev(tmp)); + printk(KERN_INFO "HiSax: Layer2 Revision %s\n", HiSax_getrev(tmp)); + strcpy(tmp, tei_revision); + printk(KERN_INFO "HiSax: TeiMgr Revision %s\n", HiSax_getrev(tmp)); strcpy(tmp, l3_revision); - r += sprintf(r, "%s/", HiSax_getrev(tmp)); + printk(KERN_INFO "HiSax: Layer3 Revision %s\n", HiSax_getrev(tmp)); strcpy(tmp, lli_revision); - r += sprintf(r, "%s/", HiSax_getrev(tmp)); - strcpy(tmp, tei_revision); - r += sprintf(r, "%s", HiSax_getrev(tmp)); - - printk(KERN_INFO "HiSax: Driver for Siemens chip set ISDN cards\n"); - printk(KERN_INFO "HiSax: Version 2.8\n"); - printk(KERN_INFO "HiSax: Revisions %s\n", rev); + printk(KERN_INFO "HiSax: LinkLayer Revision %s\n", HiSax_getrev(tmp)); + certification_check(1); } void @@ -375,7 +548,7 @@ argc = ints[0]; i = 0; j = 1; - while (argc && (i < 16)) { + while (argc && (i < HISAX_MAX_CARDS)) { if (argc) { cards[i].typ = ints[j]; j++; @@ -413,32 +586,864 @@ } #endif +#if CARD_TELES0 +extern int setup_teles0(struct IsdnCard *card); +#endif + +#if CARD_TELES3 +extern int setup_teles3(struct IsdnCard *card); +#endif + +#if CARD_S0BOX +extern int setup_s0box(struct IsdnCard *card); +#endif + +#if CARD_TELESPCI +extern int setup_telespci(struct IsdnCard *card); +#endif + +#if CARD_AVM_A1 +extern int setup_avm_a1(struct IsdnCard *card); +#endif + +#if CARD_AVM_A1_PCMCIA +extern int setup_avm_a1_pcmcia(struct IsdnCard *card); +#endif + +#if CARD_FRITZPCI +extern int setup_avm_pcipnp(struct IsdnCard *card); +#endif + +#if CARD_ELSA +extern int setup_elsa(struct IsdnCard *card); +#endif + +#if CARD_IX1MICROR2 +extern int setup_ix1micro(struct IsdnCard *card); +#endif + +#if CARD_DIEHLDIVA +extern int setup_diva(struct IsdnCard *card); +#endif + +#if CARD_ASUSCOM +extern int setup_asuscom(struct IsdnCard *card); +#endif + +#if CARD_TELEINT +extern int setup_TeleInt(struct IsdnCard *card); +#endif + +#if CARD_SEDLBAUER +extern int setup_sedlbauer(struct IsdnCard *card); +#endif + +#if CARD_SPORTSTER +extern int setup_sportster(struct IsdnCard *card); +#endif + +#if CARD_MIC +extern int setup_mic(struct IsdnCard *card); +#endif + +#if CARD_NETJET +extern int setup_netjet(struct IsdnCard *card); +#endif + +#if CARD_HFCS +extern int setup_hfcs(struct IsdnCard *card); +#endif + +#if CARD_HFC_PCI +extern int setup_hfcpci(struct IsdnCard *card); +#endif + +#if CARD_AMD7930 +extern int setup_amd7930(struct IsdnCard *card); +#endif + +#if CARD_NICCY +extern int setup_niccy(struct IsdnCard *card); +#endif + +#if CARD_ISURF +extern int setup_isurf(struct IsdnCard *card); +#endif + +#if CARD_HSTSAPHIR +extern int setup_saphir(struct IsdnCard *card); +#endif + +#if CARD_TESTEMU +extern int setup_testemu(struct IsdnCard *card); +#endif + +#if CARD_BKM_A4T +extern int setup_bkm_a4t(struct IsdnCard *card); +#endif + +#if CARD_SCT_QUADRO +extern int setup_sct_quadro(struct IsdnCard *card); +#endif + +#if CARD_GAZEL +extern int setup_gazel(struct IsdnCard *card); +#endif + +/* + * Find card with given driverId + */ +static inline struct IsdnCardState +*hisax_findcard(int driverid) +{ + int i; + + for (i = 0; i < nrcards; i++) + if (cards[i].cs) + if (cards[i].cs->myid == driverid) + return (cards[i].cs); + return (NULL); +} + +/* + * Find card with given card number + */ +struct IsdnCardState +*hisax_get_card(int cardnr) +{ + if ((cardnr <= nrcards) && (cardnr>0)) + if (cards[cardnr-1].cs) + return (cards[cardnr-1].cs); + return (NULL); +} + +int +HiSax_readstatus(u_char * buf, int len, int user, int id, int channel) +{ + int count,cnt; + u_char *p = buf; + struct IsdnCardState *cs = hisax_findcard(id); + + if (cs) { + if (len > HISAX_STATUS_BUFSIZE) { + printk(KERN_WARNING "HiSax: status overflow readstat %d/%d\n", + len, HISAX_STATUS_BUFSIZE); + } + count = cs->status_end - cs->status_read +1; + if (count >= len) + count = len; + if (user) + copy_to_user(p, cs->status_read, count); + else + memcpy(p, cs->status_read, count); + cs->status_read += count; + if (cs->status_read > cs->status_end) + cs->status_read = cs->status_buf; + p += count; + count = len - count; + while (count) { + if (count > HISAX_STATUS_BUFSIZE) + cnt = HISAX_STATUS_BUFSIZE; + else + cnt = count; + if (user) + copy_to_user(p, cs->status_read, cnt); + else + memcpy(p, cs->status_read, cnt); + p += cnt; + cs->status_read += cnt % HISAX_STATUS_BUFSIZE; + count -= cnt; + } + return len; + } else { + printk(KERN_ERR + "HiSax: if_readstatus called with invalid driverId!\n"); + return -ENODEV; + } +} + +inline int +jiftime(char *s, long mark) +{ + s += 8; + + *s-- = '\0'; + *s-- = mark % 10 + '0'; + mark /= 10; + *s-- = mark % 10 + '0'; + mark /= 10; + *s-- = '.'; + *s-- = mark % 10 + '0'; + mark /= 10; + *s-- = mark % 6 + '0'; + mark /= 6; + *s-- = ':'; + *s-- = mark % 10 + '0'; + mark /= 10; + *s-- = mark % 10 + '0'; + return(8); +} + +static u_char tmpbuf[HISAX_STATUS_BUFSIZE]; + +void +VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args) +{ +/* if head == NULL the fmt contains the full info */ + + long flags; + int count, i; + u_char *p; + isdn_ctrl ic; + int len; + + save_flags(flags); + cli(); + p = tmpbuf; + if (head) { + p += jiftime(p, jiffies); + p += sprintf(p, " %s", head); + p += vsprintf(p, fmt, args); + *p++ = '\n'; + *p = 0; + len = p - tmpbuf; + p = tmpbuf; + } else { + p = fmt; + len = strlen(fmt); + } + if (!cs) { + printk(KERN_WARNING "HiSax: No CardStatus for message %s", p); + restore_flags(flags); + return; + } + if (len > HISAX_STATUS_BUFSIZE) { + printk(KERN_WARNING "HiSax: status overflow %d/%d\n", + len, HISAX_STATUS_BUFSIZE); + restore_flags(flags); + return; + } + count = len; + i = cs->status_end - cs->status_write +1; + if (i >= len) + i = len; + len -= i; + memcpy(cs->status_write, p, i); + cs->status_write += i; + if (cs->status_write > cs->status_end) + cs->status_write = cs->status_buf; + p += i; + if (len) { + memcpy(cs->status_write, p, len); + cs->status_write += len; + } +#ifdef KERNELSTACK_DEBUG + i = (ulong)&len - current->kernel_stack_page; + sprintf(tmpbuf, "kstack %s %lx use %ld\n", current->comm, + current->kernel_stack_page, i); + len = strlen(tmpbuf); + for (p = tmpbuf, i = len; i > 0; i--, p++) { + *cs->status_write++ = *p; + if (cs->status_write > cs->status_end) + cs->status_write = cs->status_buf; + count++; + } +#endif + restore_flags(flags); + if (count) { + ic.command = ISDN_STAT_STAVAIL; + ic.driver = cs->myid; + ic.arg = count; + cs->iif.statcallb(&ic); + } +} + +void +HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + VHiSax_putstatus(cs, head, fmt, args); + va_end(args); +} + +int +ll_run(struct IsdnCardState *cs) +{ + long flags; + isdn_ctrl ic; + + save_flags(flags); + cli(); + ic.driver = cs->myid; + ic.command = ISDN_STAT_RUN; + cs->iif.statcallb(&ic); + restore_flags(flags); + return 0; +} + +void +ll_stop(struct IsdnCardState *cs) +{ + isdn_ctrl ic; + + ic.command = ISDN_STAT_STOP; + ic.driver = cs->myid; + cs->iif.statcallb(&ic); + CallcFreeChan(cs); +} + +static void +ll_unload(struct IsdnCardState *cs) +{ + isdn_ctrl ic; + + ic.command = ISDN_STAT_UNLOAD; + ic.driver = cs->myid; + cs->iif.statcallb(&ic); + if (cs->status_buf) + kfree(cs->status_buf); + cs->status_read = NULL; + cs->status_write = NULL; + cs->status_end = NULL; + kfree(cs->dlog); +} + +static void +closecard(int cardnr) +{ + struct IsdnCardState *csta = cards[cardnr].cs; + + if (csta->bcs->BC_Close != NULL) { + csta->bcs->BC_Close(csta->bcs + 1); + csta->bcs->BC_Close(csta->bcs); + } + + discard_queue(&csta->rq); + discard_queue(&csta->sq); + if (csta->rcvbuf) { + kfree(csta->rcvbuf); + csta->rcvbuf = NULL; + } + if (csta->tx_skb) { + idev_kfree_skb(csta->tx_skb, FREE_WRITE); + csta->tx_skb = NULL; + } + if (csta->DC_Close != NULL) { + csta->DC_Close(csta); + } + csta->cardmsg(csta, CARD_RELEASE, NULL); + if (csta->dbusytimer.function != NULL) + del_timer(&csta->dbusytimer); + ll_unload(csta); +} + +HISAX_INITFUNC(static int init_card(struct IsdnCardState *cs)) +{ + int irq_cnt, cnt = 3; + long flags; + + if (!cs->irq) + return(cs->cardmsg(cs, CARD_INIT, NULL)); + save_flags(flags); + cli(); + irq_cnt = kstat_irqs(cs->irq); + printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], cs->irq, + irq_cnt); + if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax", cs)) { + printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n", + cs->irq); + restore_flags(flags); + return(1); + } + while (cnt) { + cs->cardmsg(cs, CARD_INIT, NULL); + sti(); + current->state = TASK_INTERRUPTIBLE; + /* Timeout 10ms */ + schedule_timeout((10*HZ)/1000); + restore_flags(flags); + printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], + cs->irq, kstat_irqs(cs->irq)); + if (kstat_irqs(cs->irq) == irq_cnt) { + printk(KERN_WARNING + "%s: IRQ(%d) getting no interrupts during init %d\n", + CardType[cs->typ], cs->irq, 4 - cnt); + if (cnt == 1) { + free_irq(cs->irq, cs); + return (2); + } else { + cs->cardmsg(cs, CARD_RESET, NULL); + cnt--; + } + } else { + cs->cardmsg(cs, CARD_TEST, NULL); + return(0); + } + } + restore_flags(flags); + return(3); +} + +HISAX_INITFUNC(static int +checkcard(int cardnr, char *id, int *busy_flag)) +{ + long flags; + int ret = 0; + struct IsdnCard *card = cards + cardnr; + struct IsdnCardState *cs; + + save_flags(flags); + cli(); + if (!(cs = (struct IsdnCardState *) + kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for IsdnCardState(card %d)\n", + cardnr + 1); + restore_flags(flags); + return (0); + } + memset(cs, 0, sizeof(struct IsdnCardState)); + card->cs = cs; + cs->chanlimit = 2; /* maximum B-channel number */ + cs->logecho = 0; /* No echo logging */ + cs->cardnr = cardnr; + cs->debug = L1_DEB_WARN; + cs->HW_Flags = 0; + cs->busy_flag = busy_flag; + cs->irq_flags = I4L_IRQ_FLAG; +#if TEI_PER_CARD +#else + test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); +#endif + cs->protocol = card->protocol; + + if ((card->typ > 0) && (card->typ <= ISDN_CTYPE_COUNT)) { + if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for dlog(card %d)\n", + cardnr + 1); + restore_flags(flags); + return (0); + } + if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for status_buf(card %d)\n", + cardnr + 1); + kfree(cs->dlog); + restore_flags(flags); + return (0); + } + cs->stlist = NULL; + cs->status_read = cs->status_buf; + cs->status_write = cs->status_buf; + cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1; + cs->typ = card->typ; + strcpy(cs->iif.id, id); + cs->iif.channels = 2; + cs->iif.maxbufsize = MAX_DATA_SIZE; + cs->iif.hl_hdrlen = MAX_HEADER_LEN; + cs->iif.features = + ISDN_FEATURE_L2_X75I | + ISDN_FEATURE_L2_HDLC | +// ISDN_FEATURE_L2_MODEM | + ISDN_FEATURE_L2_TRANS | + ISDN_FEATURE_L3_TRANS | +#ifdef CONFIG_HISAX_1TR6 + ISDN_FEATURE_P_1TR6 | +#endif +#ifdef CONFIG_HISAX_EURO + ISDN_FEATURE_P_EURO | +#endif +#ifdef CONFIG_HISAX_NI1 + ISDN_FEATURE_P_NI1 | +#endif + 0; + + cs->iif.command = HiSax_command; + cs->iif.writecmd = NULL; + cs->iif.writebuf_skb = HiSax_writebuf_skb; + cs->iif.readstat = HiSax_readstatus; + register_isdn(&cs->iif); + cs->myid = cs->iif.channels; + printk(KERN_INFO + "HiSax: Card %d Protocol %s Id=%s (%d)\n", cardnr + 1, + (card->protocol == ISDN_PTYPE_1TR6) ? "1TR6" : + (card->protocol == ISDN_PTYPE_EURO) ? "EDSS1" : + (card->protocol == ISDN_PTYPE_LEASED) ? "LEASED" : + (card->protocol == ISDN_PTYPE_NI1) ? "NI1" : + "NONE", cs->iif.id, cs->myid); + switch (card->typ) { +#if CARD_TELES0 + case ISDN_CTYPE_16_0: + case ISDN_CTYPE_8_0: + ret = setup_teles0(card); + break; +#endif +#if CARD_TELES3 + case ISDN_CTYPE_16_3: + case ISDN_CTYPE_PNP: + case ISDN_CTYPE_TELESPCMCIA: + case ISDN_CTYPE_COMPAQ_ISA: + ret = setup_teles3(card); + break; +#endif +#if CARD_S0BOX + case ISDN_CTYPE_S0BOX: + ret = setup_s0box(card); + break; +#endif +#if CARD_TELESPCI + case ISDN_CTYPE_TELESPCI: + ret = setup_telespci(card); + break; +#endif +#if CARD_AVM_A1 + case ISDN_CTYPE_A1: + ret = setup_avm_a1(card); + break; +#endif +#if CARD_AVM_A1_PCMCIA + case ISDN_CTYPE_A1_PCMCIA: + ret = setup_avm_a1_pcmcia(card); + break; +#endif +#if CARD_FRITZPCI + case ISDN_CTYPE_FRITZPCI: + ret = setup_avm_pcipnp(card); + break; +#endif +#if CARD_ELSA + case ISDN_CTYPE_ELSA: + case ISDN_CTYPE_ELSA_PNP: + case ISDN_CTYPE_ELSA_PCMCIA: + case ISDN_CTYPE_ELSA_PCI: + ret = setup_elsa(card); + break; +#endif +#if CARD_IX1MICROR2 + case ISDN_CTYPE_IX1MICROR2: + ret = setup_ix1micro(card); + break; +#endif +#if CARD_DIEHLDIVA + case ISDN_CTYPE_DIEHLDIVA: + ret = setup_diva(card); + break; +#endif +#if CARD_ASUSCOM + case ISDN_CTYPE_ASUSCOM: + ret = setup_asuscom(card); + break; +#endif +#if CARD_TELEINT + case ISDN_CTYPE_TELEINT: + ret = setup_TeleInt(card); + break; +#endif +#if CARD_SEDLBAUER + case ISDN_CTYPE_SEDLBAUER: + case ISDN_CTYPE_SEDLBAUER_PCMCIA: + case ISDN_CTYPE_SEDLBAUER_FAX: + ret = setup_sedlbauer(card); + break; +#endif +#if CARD_SPORTSTER + case ISDN_CTYPE_SPORTSTER: + ret = setup_sportster(card); + break; +#endif +#if CARD_MIC + case ISDN_CTYPE_MIC: + ret = setup_mic(card); + break; +#endif +#if CARD_NETJET + case ISDN_CTYPE_NETJET: + ret = setup_netjet(card); + break; +#endif +#if CARD_HFCS + case ISDN_CTYPE_TELES3C: + case ISDN_CTYPE_ACERP10: + ret = setup_hfcs(card); + break; +#endif +#if CARD_HFC_PCI + case ISDN_CTYPE_HFC_PCI: + ret = setup_hfcpci(card); + break; +#endif +#if CARD_NICCY + case ISDN_CTYPE_NICCY: + ret = setup_niccy(card); + break; +#endif +#if CARD_AMD7930 + case ISDN_CTYPE_AMD7930: + ret = setup_amd7930(card); + break; +#endif +#if CARD_ISURF + case ISDN_CTYPE_ISURF: + ret = setup_isurf(card); + break; +#endif +#if CARD_HSTSAPHIR + case ISDN_CTYPE_HSTSAPHIR: + ret = setup_saphir(card); + break; +#endif +#if CARD_TESTEMU + case ISDN_CTYPE_TESTEMU: + ret = setup_testemu(card); + break; +#endif +#if CARD_BKM_A4T + case ISDN_CTYPE_BKM_A4T: + ret = setup_bkm_a4t(card); + break; +#endif +#if CARD_SCT_QUADRO + case ISDN_CTYPE_SCT_QUADRO: + ret = setup_sct_quadro(card); + break; +#endif +#if CARD_GAZEL + case ISDN_CTYPE_GAZEL: + ret = setup_gazel(card); + break; +#endif + default: + printk(KERN_WARNING + "HiSax: Support for %s Card not selected\n", + CardType[card->typ]); + ll_unload(cs); + restore_flags(flags); + return (0); + } + } else { + printk(KERN_WARNING + "HiSax: Card Type %d out of range\n", + card->typ); + restore_flags(flags); + return (0); + } + if (!ret) { + ll_unload(cs); + restore_flags(flags); + return (0); + } + if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for isac rcvbuf\n"); + return (1); + } + cs->rcvidx = 0; + cs->tx_skb = NULL; + cs->tx_cnt = 0; + cs->event = 0; + cs->tqueue.next = 0; + cs->tqueue.sync = 0; + cs->tqueue.data = cs; + + skb_queue_head_init(&cs->rq); + skb_queue_head_init(&cs->sq); + + init_bcstate(cs, 0); + init_bcstate(cs, 1); + ret = init_card(cs); + if (ret) { + closecard(cardnr); + restore_flags(flags); + return (0); + } + init_tei(cs, cs->protocol); + CallcNewChan(cs); + /* ISAR needs firmware download first */ + if (!test_bit(HW_ISAR, &cs->HW_Flags)) + ll_run(cs); + restore_flags(flags); + return (1); +} + +HISAX_INITFUNC(void +HiSax_shiftcards(int idx)) +{ + int i; + + for (i = idx; i < (HISAX_MAX_CARDS - 1); i++) + memcpy(&cards[i], &cards[i + 1], sizeof(cards[i])); +} + +HISAX_INITFUNC(int +HiSax_inithardware(int *busy_flag)) +{ + int foundcards = 0; + int i = 0; + int t = ','; + int flg = 0; + char *id; + char *next_id = HiSax_id; + char ids[20]; + + if (strchr(HiSax_id, ',')) + t = ','; + else if (strchr(HiSax_id, '%')) + t = '%'; + + while (i < nrcards) { + if (cards[i].typ < 1) + break; + id = next_id; + if ((next_id = strchr(id, t))) { + *next_id++ = 0; + strcpy(ids, id); + flg = i + 1; + } else { + next_id = id; + if (flg >= i) + strcpy(ids, id); + else + sprintf(ids, "%s%d", id, i); + } + if (checkcard(i, ids, busy_flag)) { + foundcards++; + i++; + } else { + printk(KERN_WARNING "HiSax: Card %s not installed !\n", + CardType[cards[i].typ]); + if (cards[i].cs) + kfree((void *) cards[i].cs); + cards[i].cs = NULL; + HiSax_shiftcards(i); + } + } + return foundcards; +} + +void +HiSax_closecard(int cardnr) +{ + int i,last=nrcards - 1; + + if (cardnr>last) + return; + if (cards[cardnr].cs) { + ll_stop(cards[cardnr].cs); + release_tei(cards[cardnr].cs); + closecard(cardnr); + if (cards[cardnr].cs->irq) + free_irq(cards[cardnr].cs->irq, cards[cardnr].cs); + kfree((void *) cards[cardnr].cs); + cards[cardnr].cs = NULL; + } + i = cardnr; + while (i!=last) { + cards[i] = cards[i+1]; + i++; + } + nrcards--; +} + +void +HiSax_reportcard(int cardnr) +{ + struct IsdnCardState *cs = cards[cardnr].cs; + struct PStack *stptr; + struct l3_process *pc; + int j, i = 1; + + printk(KERN_DEBUG "HiSax: reportcard No %d\n", cardnr + 1); + printk(KERN_DEBUG "HiSax: Type %s\n", CardType[cs->typ]); + printk(KERN_DEBUG "HiSax: debuglevel %x\n", cs->debug); + printk(KERN_DEBUG "HiSax: HiSax_reportcard address 0x%lX\n", + (ulong) & HiSax_reportcard); + printk(KERN_DEBUG "HiSax: cs 0x%lX\n", (ulong) cs); + printk(KERN_DEBUG "HiSax: HW_Flags %x bc0 flg %x bc0 flg %x\n", + cs->HW_Flags, cs->bcs[0].Flag, cs->bcs[1].Flag); + printk(KERN_DEBUG "HiSax: bcs 0 mode %d ch%d\n", + cs->bcs[0].mode, cs->bcs[0].channel); + printk(KERN_DEBUG "HiSax: bcs 1 mode %d ch%d\n", + cs->bcs[1].mode, cs->bcs[1].channel); + printk(KERN_DEBUG "HiSax: cs setstack_d 0x%lX\n", (ulong) cs->setstack_d); + printk(KERN_DEBUG "HiSax: cs stl 0x%lX\n", (ulong) & (cs->stlist)); + stptr = cs->stlist; + while (stptr != NULL) { + printk(KERN_DEBUG "HiSax: dst%d 0x%lX\n", i, (ulong) stptr); + printk(KERN_DEBUG "HiSax: dst%d stp 0x%lX\n", i, (ulong) stptr->l1.stlistp); + printk(KERN_DEBUG "HiSax: dst%d l1.l1hw 0x%lX\n", i, (ulong) stptr->l1.l1hw); + printk(KERN_DEBUG "HiSax: tei %d sapi %d\n", + stptr->l2.tei, stptr->l2.sap); + printk(KERN_DEBUG "HiSax: man 0x%lX\n", (ulong) stptr->ma.layer); + pc = stptr->l3.proc; + while (pc) { + printk(KERN_DEBUG "HiSax: l3proc %x 0x%lX\n", pc->callref, + (ulong) pc); + printk(KERN_DEBUG "HiSax: state %d st 0x%lX chan 0x%lX\n", + pc->state, (ulong) pc->st, (ulong) pc->chan); + pc = pc->next; + } + stptr = stptr->next; + i++; + } + for (j = 0; j < 2; j++) { + printk(KERN_DEBUG "HiSax: ch%d 0x%lX\n", j, + (ulong) & cs->channel[j]); + stptr = cs->channel[j].b_st; + i = 1; + while (stptr != NULL) { + printk(KERN_DEBUG "HiSax: b_st%d 0x%lX\n", i, (ulong) stptr); + printk(KERN_DEBUG "HiSax: man 0x%lX\n", (ulong) stptr->ma.layer); + stptr = stptr->next; + i++; + } + } +} + + __initfunc(int HiSax_init(void)) { int i; - + #ifdef MODULE int nzproto = 0; #ifdef CONFIG_HISAX_ELSA if (type[0] == ISDN_CTYPE_ELSA_PCMCIA) { /* we have exported and return in this case */ +#ifndef COMPAT_HAS_NEW_SYMTAB + register_symtab(&hisax_syms_elsa); +#endif return 0; } #endif #ifdef CONFIG_HISAX_SEDLBAUER if (type[0] == ISDN_CTYPE_SEDLBAUER_PCMCIA) { /* we have to export and return in this case */ +#ifndef COMPAT_HAS_NEW_SYMTAB + register_symtab(&hisax_syms_sedl); +#endif + return 0; + } +#endif +#ifdef CONFIG_HISAX_AVM_A1_PCMCIA + if (type[0] == ISDN_CTYPE_A1_PCMCIA) { + /* we have to export and return in this case */ +#ifndef COMPAT_HAS_NEW_SYMTAB + register_symtab(&hisax_syms_avm_a1); +#endif return 0; } #endif #endif - HiSaxVersion(); nrcards = 0; + HiSaxVersion(); #ifdef MODULE if (id) /* If id= string used */ HiSax_id = id; - for (i = 0; i < 16; i++) { + for (i = 0; i < HISAX_MAX_CARDS; i++) { cards[i].typ = type[i]; if (protocol[i]) { cards[i].protocol = protocol[i]; @@ -476,6 +1481,7 @@ case ISDN_CTYPE_16_3: case ISDN_CTYPE_TELESPCMCIA: case ISDN_CTYPE_A1: + case ISDN_CTYPE_A1_PCMCIA: case ISDN_CTYPE_ELSA_PNP: case ISDN_CTYPE_ELSA_PCMCIA: case ISDN_CTYPE_IX1MICROR2: @@ -484,16 +1490,32 @@ case ISDN_CTYPE_TELEINT: case ISDN_CTYPE_SEDLBAUER: case ISDN_CTYPE_SEDLBAUER_PCMCIA: + case ISDN_CTYPE_SEDLBAUER_FAX: case ISDN_CTYPE_SPORTSTER: case ISDN_CTYPE_MIC: case ISDN_CTYPE_TELES3C: + case ISDN_CTYPE_ACERP10: + case ISDN_CTYPE_S0BOX: + case ISDN_CTYPE_FRITZPCI: + case ISDN_CTYPE_HSTSAPHIR: + case ISDN_CTYPE_GAZEL: + cards[i].para[0] = irq[i]; + cards[i].para[1] = io[i]; + break; + case ISDN_CTYPE_ISURF: cards[i].para[0] = irq[i]; cards[i].para[1] = io[i]; + cards[i].para[2] = mem[i]; break; case ISDN_CTYPE_ELSA_PCI: case ISDN_CTYPE_NETJET: case ISDN_CTYPE_AMD7930: - case ISDN_CTYPE_DBRI: + case ISDN_CTYPE_TELESPCI: + break; + case ISDN_CTYPE_BKM_A4T: + break; + case ISDN_CTYPE_SCT_QUADRO: + cards[i].para[0] = irq[i]; break; } } @@ -507,29 +1529,32 @@ HiSax_id = HiSaxID; if (!HiSaxID[0]) strcpy(HiSaxID, "HiSax"); - for (i = 0; i < 16; i++) + for (i = 0; i < HISAX_MAX_CARDS; i++) if (cards[i].typ > 0) nrcards++; printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", nrcards, (nrcards > 1) ? "s" : ""); CallcNew(); + Isdnl3New(); Isdnl2New(); TeiNew(); Isdnl1New(); if (HiSax_inithardware(NULL)) { /* Install only, if at least one card found */ - /* No symbols to export, hide all symbols */ - #ifdef MODULE - EXPORT_NO_SYMBOLS; +#ifndef COMPAT_HAS_NEW_SYMTAB + /* No symbols to export, hide all symbols */ + register_symtab(NULL); printk(KERN_INFO "HiSax: module installed\n"); -#endif +#endif /* COMPAT_HAS_NEW_SYMTAB */ +#endif /* MODULE */ return (0); } else { Isdnl1Free(); TeiFree(); Isdnl2Free(); + Isdnl3Free(); CallcFree(); return -EIO; } @@ -539,13 +1564,27 @@ void cleanup_module(void) { - HiSax_closehardware(); + int cardnr = nrcards -1; + long flags; + + save_flags(flags); + cli(); + while(cardnr>=0) + HiSax_closecard(cardnr--); + Isdnl1Free(); + TeiFree(); + Isdnl2Free(); + Isdnl3Free(); + CallcFree(); + restore_flags(flags); printk(KERN_INFO "HiSax module removed\n"); } +#endif #ifdef CONFIG_HISAX_ELSA int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) { +#ifdef MODULE int i; int nzproto = 0; @@ -553,10 +1592,10 @@ HiSaxVersion(); if (id) /* If id= string used */ HiSax_id = id; - /* Initialize all 16 structs, even though we only accept + /* Initialize all 8 structs, even though we only accept two pcmcia cards */ - for (i = 0; i < 16; i++) { + for (i = 0; i < HISAX_MAX_CARDS; i++) { cards[i].para[0] = irq[i]; cards[i].para[1] = io[i]; cards[i].typ = type[i]; @@ -575,7 +1614,7 @@ HiSax_id = HiSaxID; if (!HiSaxID[0]) strcpy(HiSaxID, "HiSax"); - for (i = 0; i < 16; i++) + for (i = 0; i < HISAX_MAX_CARDS; i++) if (cards[i].typ > 0) nrcards++; printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", @@ -583,16 +1622,71 @@ Isdnl1New(); CallcNew(); + Isdnl3New(); Isdnl2New(); TeiNew(); HiSax_inithardware(busy_flag); printk(KERN_NOTICE "HiSax: module installed\n"); +#endif return (0); } #endif + #ifdef CONFIG_HISAX_SEDLBAUER int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) { +#ifdef MODULE + int i; + int nzproto = 0; + + nrcards = 0; + HiSaxVersion(); + if (id) /* If id= string used */ + HiSax_id = id; + /* Initialize all 8 structs, even though we only accept + two pcmcia cards + */ + for (i = 0; i < HISAX_MAX_CARDS; i++) { + cards[i].para[0] = irq[i]; + cards[i].para[1] = io[i]; + cards[i].typ = type[i]; + if (protocol[i]) { + cards[i].protocol = protocol[i]; + nzproto++; + } + } + cards[0].para[0] = pcm_irq; + cards[0].para[1] = (int)pcm_iob; + cards[0].protocol = prot; + cards[0].typ = ISDN_CTYPE_SEDLBAUER_PCMCIA; + nzproto = 1; + + if (!HiSax_id) + HiSax_id = HiSaxID; + if (!HiSaxID[0]) + strcpy(HiSaxID, "HiSax"); + for (i = 0; i < HISAX_MAX_CARDS; i++) + if (cards[i].typ > 0) + nrcards++; + printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", + nrcards, (nrcards > 1) ? "s" : ""); + + CallcNew(); + Isdnl3New(); + Isdnl2New(); + Isdnl1New(); + TeiNew(); + HiSax_inithardware(busy_flag); + printk(KERN_NOTICE "HiSax: module installed\n"); +#endif + return (0); +} +#endif + +#ifdef CONFIG_HISAX_AVM_A1_PCMCIA +int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) +{ +#ifdef MODULE int i; int nzproto = 0; @@ -615,14 +1709,14 @@ cards[0].para[0] = pcm_irq; cards[0].para[1] = (int)pcm_iob; cards[0].protocol = prot; - cards[0].typ = ISDN_CTYPE_SEDLBAUER_PCMCIA; + cards[0].typ = ISDN_CTYPE_A1_PCMCIA; nzproto = 1; if (!HiSax_id) HiSax_id = HiSaxID; if (!HiSaxID[0]) strcpy(HiSaxID, "HiSax"); - for (i = 0; i < 16; i++) + for (i = 0; i < HISAX_MAX_CARDS; i++) if (cards[i].typ > 0) nrcards++; printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", @@ -630,11 +1724,12 @@ Isdnl1New(); CallcNew(); + Isdnl3New(); Isdnl2New(); TeiNew(); HiSax_inithardware(busy_flag); printk(KERN_NOTICE "HiSax: module installed\n"); +#endif return (0); } #endif -#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/diva.c linux.pre11.3/drivers/isdn/hisax/diva.c --- linux.vanilla/drivers/isdn/hisax/diva.c Sun Nov 8 15:10:14 1998 +++ linux.pre11.3/drivers/isdn/hisax/diva.c Mon Jul 19 23:59:33 1999 @@ -1,13 +1,37 @@ -/* $Id: diva.c,v 1.5 1998/02/02 13:29:38 keil Exp $ +/* $Id: diva.c,v 1.12 1999/07/12 21:05:04 keil Exp $ * diva.c low level stuff for Eicon.Diehl Diva Family ISDN cards * - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) * * Thanks to Eicon Technology Diehl GmbH & Co. oHG for documents and informations * * * $Log: diva.c,v $ + * Revision 1.12 1999/07/12 21:05:04 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 1.11 1999/07/01 08:11:29 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 1.10 1998/11/15 23:54:31 keil + * changes from 2.0 + * + * Revision 1.9 1998/06/27 22:52:03 keil + * support for Diva 2.01 + * + * Revision 1.8 1998/05/25 12:57:46 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * + * Revision 1.7 1998/04/15 16:42:36 keil + * new init code + * new PCI init (2.1.94) + * + * Revision 1.6 1998/03/07 22:56:57 tsbogend + * made HiSax working on Linux/Alpha + * * Revision 1.5 1998/02/02 13:29:38 keil * fast io * @@ -31,13 +55,16 @@ #include "hisax.h" #include "isac.h" #include "hscx.h" +#include "ipac.h" #include "isdnl1.h" #include +#ifndef COMPAT_HAS_NEW_PCI #include +#endif extern const char *CardType[]; -const char *Diva_revision = "$Revision: 1.5 $"; +const char *Diva_revision = "$Revision: 1.12 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -47,6 +74,8 @@ #define DIVA_ISA_ISAC_DATA 2 #define DIVA_ISA_ISAC_ADR 6 #define DIVA_ISA_CTRL 7 +#define DIVA_IPAC_ADR 0 +#define DIVA_IPAC_DATA 1 #define DIVA_PCI_ISAC_DATA 8 #define DIVA_PCI_ISAC_ADR 0xc @@ -55,6 +84,8 @@ /* SUB Types */ #define DIVA_ISA 1 #define DIVA_PCI 2 +#define DIVA_IPAC_ISA 3 +#define DIVA_IPAC_PCI 4 /* PCI stuff */ #define PCI_VENDOR_EICON_DIEHL 0x1133 @@ -62,10 +93,12 @@ #define PCI_DIVA20_ID 0xe002 #define PCI_DIVA20PRO_U_ID 0xe003 #define PCI_DIVA20_U_ID 0xe004 +#define PCI_DIVA_201 0xe005 /* CTRL (Read) */ #define DIVA_IRQ_STAT 0x01 #define DIVA_EEPROM_SDA 0x02 + /* CTRL (Write) */ #define DIVA_IRQ_REQ 0x01 #define DIVA_RESET 0x08 @@ -76,6 +109,13 @@ #define DIVA_ISA_LED_B 0x40 #define DIVA_IRQ_CLR 0x80 +/* Siemens PITA */ +#define PITA_MISC_REG 0x1c +#define PITA_PARA_SOFTRESET 0x01000000 +#define PITA_PARA_MPX_MODE 0x04000000 +#define PITA_INT0_ENABLE 0x00020000 +#define PITA_INT0_STATUS 0x00000002 + static inline u_char readreg(unsigned int ale, unsigned int adr, u_char off) { @@ -120,6 +160,22 @@ outsb(adr, data, size); } +static inline u_char +memreadreg(unsigned long adr, u_char off) +{ + return(0xff & *((unsigned int *) + (((unsigned int *)adr) + off))); +} + +static inline void +memwritereg(unsigned long adr, u_char off, u_char data) +{ + register u_char *p; + + p = (unsigned char *)(((unsigned int *)adr) + off); + *p = data; +} + /* Interface functions */ static u_char @@ -140,13 +196,37 @@ readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0, data, size); } -static void +static void WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size) { writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0, data, size); } static u_char +ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset) +{ + return (readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset+0x80)); +} + +static void +WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) +{ + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset|0x80, value); +} + +static void +ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) +{ + readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size); +} + +static void +WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) +{ + writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size); +} + +static u_char ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { return(readreg(cs->hw.diva.hscx_adr, @@ -160,6 +240,44 @@ cs->hw.diva.hscx, offset + (hscx ? 0x40 : 0), value); } +static u_char +MemReadISAC_IPAC(struct IsdnCardState *cs, u_char offset) +{ + return (memreadreg(cs->hw.diva.cfg_reg, offset+0x80)); +} + +static void +MemWriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) +{ + memwritereg(cs->hw.diva.cfg_reg, offset|0x80, value); +} + +static void +MemReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) +{ + while(size--) + *data++ = memreadreg(cs->hw.diva.cfg_reg, 0x80); +} + +static void +MemWriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) +{ + while(size--) + memwritereg(cs->hw.diva.cfg_reg, 0x80, *data++); +} + +static u_char +MemReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) +{ + return(memreadreg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0))); +} + +static void +MemWriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) +{ + memwritereg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0), value); +} + /* * fast interrupt HSCX stuff goes here */ @@ -168,21 +286,21 @@ cs->hw.diva.hscx, reg + (nr ? 0x40 : 0)) #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.diva.hscx_adr, \ cs->hw.diva.hscx, reg + (nr ? 0x40 : 0), data) - + #define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.diva.hscx_adr, \ cs->hw.diva.hscx, (nr ? 0x40 : 0), ptr, cnt) - + #define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.diva.hscx_adr, \ cs->hw.diva.hscx, (nr ? 0x40 : 0), ptr, cnt) - + #include "hscx_irq.c" static void diva_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u_char val, sval, stat = 0; - int cnt=8; + u_char val, sval; + int cnt=5; if (!cs) { printk(KERN_WARNING "Diva: Spurious interrupt!\n"); @@ -190,43 +308,421 @@ } while (((sval = bytein(cs->hw.diva.ctrl)) & DIVA_IRQ_REQ) && cnt) { val = readreg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_ISTA + 0x40); - if (val) { + if (val) hscx_int_main(cs, val); - stat |= 1; - } val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA); - if (val) { + if (val) isac_interrupt(cs, val); - stat |= 2; - } cnt--; } if (!cnt) printk(KERN_WARNING "Diva: IRQ LOOP\n"); - if (stat & 1) { - writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0xFF); - writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0xFF); - writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0x0); - writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0x0); - } - if (stat & 2) { - writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0xFF); - writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0x0); + writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0x0); + writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0x0); + writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0x0); +} + +static void +diva_irq_ipac_isa(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char ista,val; + int icnt=5; + + if (!cs) { + printk(KERN_WARNING "Diva: Spurious interrupt!\n"); + return; + } + ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA); +Start_IPACISA: + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); + if (ista & 0x0f) { + val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, HSCX_ISTA + 0x40); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) + hscx_int_main(cs, val); + } + if (ista & 0x20) { + val = 0xfe & readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA + 0x80); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA); + if ((ista & 0x3f) && icnt) { + icnt--; + goto Start_IPACISA; + } + if (!icnt) + printk(KERN_WARNING "DIVA IPAC IRQ LOOP\n"); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xFF); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xC0); +} + +static inline void +MemwaitforCEC(struct IsdnCardState *cs, int hscx) +{ + int to = 50; + + while ((MemReadHSCX(cs, hscx, HSCX_STAR) & 0x04) && to) { + udelay(1); + to--; + } + if (!to) + printk(KERN_WARNING "HiSax: waitforCEC timeout\n"); +} + + +static inline void +MemwaitforXFW(struct IsdnCardState *cs, int hscx) +{ + int to = 50; + + while ((!(MemReadHSCX(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) { + udelay(1); + to--; + } + if (!to) + printk(KERN_WARNING "HiSax: waitforXFW timeout\n"); +} + +static inline void +MemWriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u_char data) +{ + long flags; + + save_flags(flags); + cli(); + MemwaitforCEC(cs, hscx); + MemWriteHSCX(cs, hscx, HSCX_CMDR, data); + restore_flags(flags); +} + +static void +Memhscx_empty_fifo(struct BCState *bcs, int count) +{ + u_char *ptr; + struct IsdnCardState *cs = bcs->cs; + long flags; + int cnt; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hscx_empty_fifo"); + + if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "hscx_empty_fifo: incoming packet too large"); + MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); + bcs->hw.hscx.rcvidx = 0; + return; + } + save_flags(flags); + cli(); + ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; + cnt = count; + while (cnt--) + *ptr++ = memreadreg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0); + MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); + ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; + bcs->hw.hscx.rcvidx += count; + restore_flags(flags); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "hscx_empty_fifo %c cnt %d", + bcs->hw.hscx.hscx ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); } } +static void +Memhscx_fill_fifo(struct BCState *bcs) +{ + struct IsdnCardState *cs = bcs->cs; + int more, count, cnt; + int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; + u_char *ptr,*p; + long flags; + + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hscx_fill_fifo"); + + if (!bcs->tx_skb) + return; + if (bcs->tx_skb->len <= 0) + return; + + more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; + if (bcs->tx_skb->len > fifo_size) { + more = !0; + count = fifo_size; + } else + count = bcs->tx_skb->len; + cnt = count; + MemwaitforXFW(cs, bcs->hw.hscx.hscx); + save_flags(flags); + cli(); + p = ptr = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.hscx.count += count; + while(cnt--) + memwritereg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0, + *p++); + MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa); + restore_flags(flags); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "hscx_fill_fifo %c cnt %d", + bcs->hw.hscx.hscx ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } +} + +static inline void +Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) +{ + u_char r; + struct BCState *bcs = cs->bcs + hscx; + struct sk_buff *skb; + int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; + int count; + + if (!test_bit(BC_FLG_INIT, &bcs->Flag)) + return; + + if (val & 0x80) { /* RME */ + r = MemReadHSCX(cs, hscx, HSCX_RSTA); + if ((r & 0xf0) != 0xa0) { + if (!(r & 0x80)) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX invalid frame"); + if ((r & 0x40) && bcs->mode) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX RDO mode=%d", + bcs->mode); + if (!(r & 0x20)) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX CRC error"); + MemWriteHSCXCMDR(cs, hscx, 0x80); + } else { + count = MemReadHSCX(cs, hscx, HSCX_RBCL) & ( + test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f); + if (count == 0) + count = fifo_size; + Memhscx_empty_fifo(bcs, count); + if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { + if (cs->debug & L1_DEB_HSCX_FIFO) + debugl1(cs, "HX Frame %d", count); + if (!(skb = dev_alloc_skb(count))) + printk(KERN_WARNING "HSCX: receive out of memory\n"); + else { + SET_SKB_FREE(skb); + memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); + skb_queue_tail(&bcs->rqueue, skb); + } + } + } + bcs->hw.hscx.rcvidx = 0; + hscx_sched_event(bcs, B_RCVBUFREADY); + } + if (val & 0x40) { /* RPF */ + Memhscx_empty_fifo(bcs, fifo_size); + if (bcs->mode == L1_MODE_TRANS) { + /* receive audio data */ + if (!(skb = dev_alloc_skb(fifo_size))) + printk(KERN_WARNING "HiSax: receive out of memory\n"); + else { + SET_SKB_FREE(skb); + memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); + skb_queue_tail(&bcs->rqueue, skb); + } + bcs->hw.hscx.rcvidx = 0; + hscx_sched_event(bcs, B_RCVBUFREADY); + } + } + if (val & 0x10) { /* XPR */ + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + Memhscx_fill_fifo(bcs); + return; + } else { + if (bcs->st->lli.l1writewakeup && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) + bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count); + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + bcs->hw.hscx.count = 0; + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.hscx.count = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + Memhscx_fill_fifo(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + hscx_sched_event(bcs, B_XMTBUFREADY); + } + } +} + +static inline void +Memhscx_int_main(struct IsdnCardState *cs, u_char val) +{ + + u_char exval; + struct BCState *bcs; + + if (val & 0x01) { + bcs = cs->bcs + 1; + exval = MemReadHSCX(cs, 1, HSCX_EXIR); + if (exval & 0x40) { + if (bcs->mode == 1) + Memhscx_fill_fifo(bcs); + else { + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.hscx.count); + bcs->tx_cnt += bcs->hw.hscx.count; + bcs->hw.hscx.count = 0; + } + MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX B EXIR %x Lost TX", exval); + } + } else if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX B EXIR %x", exval); + } + if (val & 0xf8) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX B interrupt %x", val); + Memhscx_interrupt(cs, val, 1); + } + if (val & 0x02) { + bcs = cs->bcs; + exval = MemReadHSCX(cs, 0, HSCX_EXIR); + if (exval & 0x40) { + if (bcs->mode == L1_MODE_TRANS) + Memhscx_fill_fifo(bcs); + else { + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.hscx.count); + bcs->tx_cnt += bcs->hw.hscx.count; + bcs->hw.hscx.count = 0; + } + MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX A EXIR %x Lost TX", exval); + } + } else if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX A EXIR %x", exval); + } + if (val & 0x04) { + exval = MemReadHSCX(cs, 0, HSCX_ISTA); + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX A interrupt %x", exval); + Memhscx_interrupt(cs, exval, 0); + } +} + +static void +diva_irq_ipac_pci(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char ista,val; + int icnt=5; + u_char *cfg; + + if (!cs) { + printk(KERN_WARNING "Diva: Spurious interrupt!\n"); + return; + } + cfg = (u_char *) cs->hw.diva.pci_cfg; + val = *cfg; + if (!(val & PITA_INT0_STATUS)) + return; /* other shared IRQ */ + *cfg = PITA_INT0_STATUS; /* Reset pending INT0 */ + ista = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA); +Start_IPACPCI: + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); + if (ista & 0x0f) { + val = memreadreg(cs->hw.diva.cfg_reg, HSCX_ISTA + 0x40); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) + Memhscx_int_main(cs, val); + } + if (ista & 0x20) { + val = 0xfe & memreadreg(cs->hw.diva.cfg_reg, ISAC_ISTA + 0x80); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA); + if ((ista & 0x3f) && icnt) { + icnt--; + goto Start_IPACPCI; + } + if (!icnt) + printk(KERN_WARNING "DIVA IPAC PCI IRQ LOOP\n"); + memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xFF); + memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xC0); +} + void release_io_diva(struct IsdnCardState *cs) { int bytecnt; - - del_timer(&cs->hw.diva.tl); - if (cs->subtyp == DIVA_ISA) + + if (cs->subtyp == DIVA_IPAC_PCI) { + u_int *cfg = (unsigned int *)cs->hw.diva.pci_cfg; + + *cfg = 0; /* disable INT0/1 */ + *cfg = 2; /* reset pending INT0 */ + iounmap((void *)cs->hw.diva.cfg_reg); + iounmap((void *)cs->hw.diva.pci_cfg); + return; + } else if (cs->subtyp != DIVA_IPAC_ISA) { + del_timer(&cs->hw.diva.tl); + if (cs->hw.diva.cfg_reg) + byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */ + } + if ((cs->subtyp == DIVA_ISA) || (cs->subtyp == DIVA_IPAC_ISA)) bytecnt = 8; else bytecnt = 32; if (cs->hw.diva.cfg_reg) { - byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */ release_region(cs->hw.diva.cfg_reg, bytecnt); } } @@ -238,19 +734,43 @@ save_flags(flags); sti(); - cs->hw.diva.ctrl_reg = 0; /* Reset On */ - byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - cs->hw.diva.ctrl_reg |= DIVA_RESET; /* Reset Off */ - byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - if (cs->subtyp == DIVA_ISA) - cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A; - else - cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A; - byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); + if (cs->subtyp == DIVA_IPAC_ISA) { + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10*HZ)/1000); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10*HZ)/1000); + 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; + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10*HZ)/1000); + *ireg = PITA_PARA_MPX_MODE; + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10*HZ)/1000); + memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0); + } else { /* DIVA 2.0 */ + cs->hw.diva.ctrl_reg = 0; /* Reset On */ + byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10*HZ)/1000); + cs->hw.diva.ctrl_reg |= DIVA_RESET; /* Reset Off */ + byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10*HZ)/1000); + if (cs->subtyp == DIVA_ISA) + cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A; + else { + /* Workaround PCI9060 */ + byteout(cs->hw.diva.pci_cfg + 0x69, 9); + cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A; + } + byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); + } + restore_flags(flags); } #define DIVA_ASSIGN 1 @@ -260,6 +780,8 @@ { int blink = 0; + if ((cs->subtyp == DIVA_IPAC_ISA) || (cs->subtyp == DIVA_IPAC_PCI)) + return; del_timer(&cs->hw.diva.tl); if (cs->hw.diva.status & DIVA_ASSIGN) cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ? @@ -272,14 +794,14 @@ if (cs->hw.diva.status & 0xf000) cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ? DIVA_ISA_LED_B : DIVA_PCI_LED_B; - else if (cs->hw.diva.status & 0x0f00) { + else if (cs->hw.diva.status & 0x0f00) { cs->hw.diva.ctrl_reg ^= (DIVA_ISA == cs->subtyp) ? DIVA_ISA_LED_B : DIVA_PCI_LED_B; blink = 500; } else cs->hw.diva.ctrl_reg &= ~((DIVA_ISA == cs->subtyp) ? DIVA_ISA_LED_B : DIVA_PCI_LED_B); - + byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); if (blink) { init_timer(&cs->hw.diva.tl); @@ -291,6 +813,8 @@ static int Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg) { + u_int *ireg; + switch (mt) { case CARD_RESET: reset_diva(cs); @@ -298,37 +822,35 @@ case CARD_RELEASE: release_io_diva(cs); return(0); - case CARD_SETIRQ: - return(request_irq(cs->irq, &diva_interrupt, - I4L_IRQ_FLAG, "HiSax", cs)); case CARD_INIT: - clear_pending_isac_ints(cs); - clear_pending_hscx_ints(cs); - initisac(cs); - inithscx(cs); + if (cs->subtyp == DIVA_IPAC_PCI) { + ireg = (unsigned int *)cs->hw.diva.pci_cfg; + *ireg = PITA_INT0_ENABLE; + } + inithscxisac(cs, 3); return(0); case CARD_TEST: return(0); - case MDL_REMOVE_REQ: + case (MDL_REMOVE | REQUEST): cs->hw.diva.status = 0; break; - case MDL_ASSIGN_REQ: + case (MDL_ASSIGN | REQUEST): cs->hw.diva.status |= DIVA_ASSIGN; break; case MDL_INFO_SETUP: - if ((int)arg) + if ((long)arg) cs->hw.diva.status |= 0x0200; else cs->hw.diva.status |= 0x0100; break; case MDL_INFO_CONN: - if ((int)arg) + if ((long)arg) cs->hw.diva.status |= 0x2000; else cs->hw.diva.status |= 0x1000; break; case MDL_INFO_REL: - if ((int)arg) { + if ((long)arg) { cs->hw.diva.status &= ~0x2000; cs->hw.diva.status &= ~0x0200; } else { @@ -337,18 +859,24 @@ } break; } - diva_led_handler(cs); + if ((cs->subtyp != DIVA_IPAC_ISA) && (cs->subtyp != DIVA_IPAC_PCI)) + diva_led_handler(cs); return(0); } - - -static int pci_index __initdata = 0; +#ifdef COMPAT_HAS_NEW_PCI +static struct pci_dev *dev_diva __initdata = NULL; +static struct pci_dev *dev_diva_u __initdata = NULL; +static struct pci_dev *dev_diva201 __initdata = NULL; +#else +static int pci_index __initdata = 0; +#endif __initfunc(int setup_diva(struct IsdnCard *card)) { int bytecnt; + u_char val; struct IsdnCardState *cs = card->cs; char tmp[64]; @@ -358,18 +886,75 @@ return(0); cs->hw.diva.status = 0; if (card->para[1]) { - cs->subtyp = DIVA_ISA; cs->hw.diva.ctrl_reg = 0; cs->hw.diva.cfg_reg = card->para[1]; - cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL; - cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA; - cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA; - cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR; - cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR; + val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR, + cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID); + printk(KERN_INFO "Diva: IPAC version %x\n", val); + if (val == 1) { + cs->subtyp = DIVA_IPAC_ISA; + cs->hw.diva.ctrl = 0; + cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA; + cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA; + cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR; + cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + } else { + cs->subtyp = DIVA_ISA; + cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL; + cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA; + cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA; + cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR; + cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR; + } cs->irq = card->para[0]; bytecnt = 8; } else { #if CONFIG_PCI +#ifdef COMPAT_HAS_NEW_PCI + if (!pci_present()) { + printk(KERN_ERR "Diva: no PCI bus present\n"); + return(0); + } + + cs->subtyp = 0; + if ((dev_diva = pci_find_device(PCI_VENDOR_EICON_DIEHL, + PCI_DIVA20_ID, dev_diva))) { + cs->subtyp = DIVA_PCI; + cs->irq = dev_diva->irq; + cs->hw.diva.cfg_reg = dev_diva->base_address[2] + & PCI_BASE_ADDRESS_IO_MASK; + } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_EICON_DIEHL, + PCI_DIVA20_U_ID, dev_diva_u))) { + cs->subtyp = DIVA_PCI; + cs->irq = dev_diva_u->irq; + cs->hw.diva.cfg_reg = dev_diva_u->base_address[2] + & PCI_BASE_ADDRESS_IO_MASK; + } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_EICON_DIEHL, + PCI_DIVA_201, dev_diva201))) { + cs->subtyp = DIVA_IPAC_PCI; + cs->irq = dev_diva201->irq; + cs->hw.diva.pci_cfg = + (ulong) ioremap((dev_diva201->base_address[0] + & PCI_BASE_ADDRESS_IO_MASK), 4096); + cs->hw.diva.cfg_reg = + (ulong) ioremap((dev_diva201->base_address[1] + & PCI_BASE_ADDRESS_IO_MASK), 4096); + } else { + printk(KERN_WARNING "Diva: No PCI card found\n"); + return(0); + } + + if (!cs->irq) { + printk(KERN_WARNING "Diva: No IRQ for PCI card found\n"); + return(0); + } + + if (!cs->hw.diva.cfg_reg) { + printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n"); + return(0); + } +#else u_char pci_bus, pci_device_fn, pci_irq; u_int pci_ioaddr; @@ -380,9 +965,13 @@ == PCIBIOS_SUCCESSFUL) cs->subtyp = DIVA_PCI; else if (pcibios_find_device(PCI_VENDOR_EICON_DIEHL, - PCI_DIVA20_ID, pci_index, &pci_bus, &pci_device_fn) + PCI_DIVA20_U_ID, pci_index, &pci_bus, &pci_device_fn) == PCIBIOS_SUCCESSFUL) cs->subtyp = DIVA_PCI; + else if (pcibios_find_device(PCI_VENDOR_EICON_DIEHL, + PCI_DIVA_201, pci_index, &pci_bus, &pci_device_fn) + == PCIBIOS_SUCCESSFUL) + cs->subtyp = DIVA_IPAC_PCI; else break; /* get IRQ */ @@ -390,8 +979,23 @@ PCI_INTERRUPT_LINE, &pci_irq); /* get IO address */ - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_2, &pci_ioaddr); + if (cs->subtyp == DIVA_IPAC_PCI) { + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_0, &pci_ioaddr); + cs->hw.diva.pci_cfg = (ulong) ioremap(pci_ioaddr, + 4096); + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_1, &pci_ioaddr); + cs->hw.diva.cfg_reg = (ulong) ioremap(pci_ioaddr, + 4096); + } else { + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_1, &pci_ioaddr); + cs->hw.diva.pci_cfg = pci_ioaddr & ~3; + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_2, &pci_ioaddr); + cs->hw.diva.cfg_reg = pci_ioaddr & ~3; + } if (cs->subtyp) break; } @@ -399,65 +1003,103 @@ printk(KERN_WARNING "Diva: No PCI card found\n"); return(0); } + pci_index++; if (!pci_irq) { printk(KERN_WARNING "Diva: No IRQ for PCI card found\n"); return(0); } - if (!pci_ioaddr) { printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n"); return(0); } - pci_ioaddr &= ~3; /* remove io/mem flag */ - cs->hw.diva.cfg_reg = pci_ioaddr; - cs->hw.diva.ctrl = pci_ioaddr + DIVA_PCI_CTRL; - cs->hw.diva.isac = pci_ioaddr + DIVA_PCI_ISAC_DATA; - cs->hw.diva.hscx = pci_ioaddr + DIVA_HSCX_DATA; - cs->hw.diva.isac_adr = pci_ioaddr + DIVA_PCI_ISAC_ADR; - cs->hw.diva.hscx_adr = pci_ioaddr + DIVA_HSCX_ADR; cs->irq = pci_irq; - bytecnt = 32; +#endif /* COMPAT_HAS_NEW_PCI */ + cs->irq_flags |= SA_SHIRQ; #else printk(KERN_WARNING "Diva: cfgreg 0 and NO_PCI_BIOS\n"); printk(KERN_WARNING "Diva: unable to config DIVA PCI\n"); return (0); #endif /* CONFIG_PCI */ + if (cs->subtyp == DIVA_IPAC_PCI) { + cs->hw.diva.ctrl = 0; + cs->hw.diva.isac = 0; + cs->hw.diva.hscx = 0; + cs->hw.diva.isac_adr = 0; + cs->hw.diva.hscx_adr = 0; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + bytecnt = 0; + } else { + cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL; + cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA; + cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA; + cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR; + cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR; + bytecnt = 32; + } } printk(KERN_INFO - "Diva: %s card configured at 0x%x IRQ %d\n", - (cs->subtyp == DIVA_ISA) ? "ISA" : "PCI", + "Diva: %s card configured at %#lx IRQ %d\n", + (cs->subtyp == DIVA_PCI) ? "PCI" : + (cs->subtyp == DIVA_ISA) ? "ISA" : + (cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" : "IPAC PCI", cs->hw.diva.cfg_reg, cs->irq); - if (check_region(cs->hw.diva.cfg_reg, bytecnt)) { - printk(KERN_WARNING - "HiSax: %s config port %x-%x already in use\n", - CardType[card->typ], - cs->hw.diva.cfg_reg, - cs->hw.diva.cfg_reg + bytecnt); - return (0); - } else { - request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn"); + if ((cs->subtyp == DIVA_IPAC_PCI) || (cs->subtyp == DIVA_PCI)) + printk(KERN_INFO "Diva: %s PCI space at %#lx\n", + (cs->subtyp == DIVA_PCI) ? "PCI" : "IPAC PCI", + cs->hw.diva.pci_cfg); + if (cs->subtyp != DIVA_IPAC_PCI) { + if (check_region(cs->hw.diva.cfg_reg, bytecnt)) { + printk(KERN_WARNING + "HiSax: %s config port %lx-%lx already in use\n", + CardType[card->typ], + cs->hw.diva.cfg_reg, + cs->hw.diva.cfg_reg + bytecnt); + return (0); + } else { + request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn"); + } } - reset_diva(cs); - cs->hw.diva.tl.function = (void *) diva_led_handler; - cs->hw.diva.tl.data = (long) cs; - init_timer(&cs->hw.diva.tl); - cs->readisac = &ReadISAC; - cs->writeisac = &WriteISAC; - cs->readisacfifo = &ReadISACfifo; - cs->writeisacfifo = &WriteISACfifo; cs->BC_Read_Reg = &ReadHSCX; cs->BC_Write_Reg = &WriteHSCX; cs->BC_Send_Data = &hscx_fill_fifo; cs->cardmsg = &Diva_card_msg; - - ISACVersion(cs, "Diva:"); - if (HscxVersion(cs, "Diva:")) { - printk(KERN_WARNING + if (cs->subtyp == DIVA_IPAC_ISA) { + cs->readisac = &ReadISAC_IPAC; + cs->writeisac = &WriteISAC_IPAC; + cs->readisacfifo = &ReadISACfifo_IPAC; + cs->writeisacfifo = &WriteISACfifo_IPAC; + cs->irq_func = &diva_irq_ipac_isa; + val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ID); + printk(KERN_INFO "Diva: IPAC version %x\n", val); + } else if (cs->subtyp == DIVA_IPAC_PCI) { + cs->readisac = &MemReadISAC_IPAC; + cs->writeisac = &MemWriteISAC_IPAC; + cs->readisacfifo = &MemReadISACfifo_IPAC; + cs->writeisacfifo = &MemWriteISACfifo_IPAC; + cs->BC_Read_Reg = &MemReadHSCX; + cs->BC_Write_Reg = &MemWriteHSCX; + cs->BC_Send_Data = &Memhscx_fill_fifo; + cs->irq_func = &diva_irq_ipac_pci; + val = memreadreg(cs->hw.diva.cfg_reg, IPAC_ID); + printk(KERN_INFO "Diva: IPAC version %x\n", val); + } else { /* DIVA 2.0 */ + cs->hw.diva.tl.function = (void *) diva_led_handler; + cs->hw.diva.tl.data = (long) cs; + init_timer(&cs->hw.diva.tl); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->irq_func = &diva_interrupt; + ISACVersion(cs, "Diva:"); + if (HscxVersion(cs, "Diva:")) { + printk(KERN_WARNING "Diva: wrong HSCX versions check IO address\n"); - release_io_diva(cs); - return (0); + release_io_diva(cs); + return (0); + } } return (1); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/elsa.c linux.pre11.3/drivers/isdn/hisax/elsa.c --- linux.vanilla/drivers/isdn/hisax/elsa.c Sun Nov 8 15:10:14 1998 +++ linux.pre11.3/drivers/isdn/hisax/elsa.c Mon Jul 19 23:59:33 1999 @@ -1,13 +1,48 @@ -/* $Id: elsa.c,v 2.6 1998/02/02 13:29:40 keil Exp $ +/* $Id: elsa.c,v 2.14 1999/07/12 21:05:07 keil Exp $ * elsa.c low level stuff for Elsa isdn cards * - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) + * + * This file is (c) under GNU PUBLIC LICENSE + * For changes and modifications please read + * ../../../Documentation/isdn/HiSax.cert * * Thanks to Elsa GmbH for documents and informations * + * Klaus Lichtenwalder (Klaus.Lichtenwalder@WebForum.DE) + * for ELSA PCMCIA support + * * * $Log: elsa.c,v $ + * Revision 2.14 1999/07/12 21:05:07 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 2.13 1999/07/01 08:11:31 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 2.12 1998/11/15 23:54:35 keil + * changes from 2.0 + * + * Revision 2.11 1998/08/20 13:50:34 keil + * More support for hybrid modem (not working yet) + * + * Revision 2.10 1998/08/13 23:36:22 keil + * HiSax 3.1 - don't work stable with current LinkLevel + * + * Revision 2.9 1998/05/25 12:57:48 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * + * Revision 2.8 1998/04/15 16:41:42 keil + * QS3000 PCI support + * new init code + * new PCI init (2.1.94) + * + * Revision 2.7 1998/03/07 22:56:58 tsbogend + * made HiSax working on Linux/Alpha + * * Revision 2.6 1998/02/02 13:29:40 keil * fast io * @@ -29,15 +64,6 @@ * Revision 2.0 1997/06/26 11:02:40 keil * New Layer and card interface * - * Revision 1.14 1997/04/13 19:53:25 keil - * Fixed QS1000 init, change in IRQ check delay for SMP - * - * Revision 1.13 1997/04/07 22:58:07 keil - * need include config.h - * - * Revision 1.12 1997/04/06 22:54:14 keil - * Using SKB's - * * old changes removed KKe * */ @@ -51,14 +77,18 @@ #include "hscx.h" #include "isdnl1.h" #include +#ifndef COMPAT_HAS_NEW_PCI #include +#endif +#include +#include extern const char *CardType[]; -const char *Elsa_revision = "$Revision: 2.6 $"; +const char *Elsa_revision = "$Revision: 2.14 $"; const char *Elsa_Types[] = {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro", - "PCMCIA", "QS 1000", "QS 3000", "QS 1000 PCI"}; + "PCMCIA", "QS 1000", "QS 3000", "QS 1000 PCI", "QS 3000 PCI"}; const char *ITACVer[] = {"?0?", "?1?", "?2?", "?3?", "?4?", "V2.2", @@ -87,11 +117,13 @@ #define ELSA_QS1000 7 #define ELSA_QS3000 8 #define ELSA_QS1000PCI 9 +#define ELSA_QS3000PCI 10 /* PCI stuff */ #define PCI_VENDOR_ELSA 0x1048 #define PCI_QS1000_ID 0x1000 - +#define PCI_QS3000_ID 0x3000 +#define ELSA_PCI_IRQ_MASK 0x04 /* ITAC Registeradressen (only Microlink PC) */ #define ITAC_SYS 0x34 @@ -128,6 +160,40 @@ #define ELSA_BAD_PWR 2 #define ELSA_ASSIGN 4 +#define RS_ISR_PASS_LIMIT 256 +#define _INLINE_ inline +#define FLG_MODEM_ACTIVE 1 +/* IPAC AUX */ +#define ELSA_IPAC_LINE_LED 0x40 /* Bit 6 Gelbe LED */ +#define ELSA_IPAC_STAT_LED 0x80 /* Bit 7 Gruene LED */ + +static struct arcofi_msg ARCOFI_XOP_F = + {NULL,0,2,{0xa1,0x3f,0,0,0,0,0,0,0,0}}; /* Normal OP */ +static struct arcofi_msg ARCOFI_XOP_1 = + {&ARCOFI_XOP_F,0,2,{0xa1,0x31,0,0,0,0,0,0,0,0}}; /* PWR UP */ +static struct arcofi_msg ARCOFI_SOP_F = + {&ARCOFI_XOP_1,0,10,{0xa1,0x1f,0x00,0x50,0x10,0x00,0x00,0x80,0x02,0x12}}; +static struct arcofi_msg ARCOFI_COP_9 = + {&ARCOFI_SOP_F,0,10,{0xa1,0x29,0x80,0xcb,0xe9,0x88,0x00,0xc8,0xd8,0x80}}; /* RX */ +static struct arcofi_msg ARCOFI_COP_8 = + {&ARCOFI_COP_9,0,10,{0xa1,0x28,0x49,0x31,0x8,0x13,0x6e,0x88,0x2a,0x61}}; /* TX */ +static struct arcofi_msg ARCOFI_COP_7 = + {&ARCOFI_COP_8,0,4,{0xa1,0x27,0x80,0x80,0,0,0,0,0,0}}; /* GZ */ +static struct arcofi_msg ARCOFI_COP_6 = + {&ARCOFI_COP_7,0,6,{0xa1,0x26,0,0,0x82,0x7c,0,0,0,0}}; /* GRL GRH */ +static struct arcofi_msg ARCOFI_COP_5 = + {&ARCOFI_COP_6,0,4,{0xa1,0x25,0xbb,0x4a,0,0,0,0,0,0}}; /* GTX */ +static struct arcofi_msg ARCOFI_VERSION = + {NULL,1,2,{0xa0,0,0,0,0,0,0,0,0,0}}; +static struct arcofi_msg ARCOFI_XOP_0 = + {NULL,0,2,{0xa1,0x30,0,0,0,0,0,0,0,0}}; /* PWR Down */ + +static void set_arcofi(struct IsdnCardState *cs, int bc); + +#if ARCOFI_USE +#include "elsa_ser.c" +#endif + static inline u_char readreg(unsigned int ale, unsigned int adr, u_char off) { @@ -296,12 +362,27 @@ { struct IsdnCardState *cs = dev_id; u_char val; - int icnt=20; + int icnt=5; if (!cs) { printk(KERN_WARNING "Elsa: Spurious interrupt!\n"); return; } + if ((cs->typ == ISDN_CTYPE_ELSA_PCMCIA) && (*cs->busy_flag == 1)) { + /* The card tends to generate interrupts while being removed + causing us to just crash the kernel. bad. */ + printk(KERN_WARNING "Elsa: card not available!\n"); + return; + } +#if ARCOFI_USE + if (cs->hw.elsa.MFlag) { + val = serial_inp(cs, UART_IIR); + if (!(val & UART_IIR_NO_INT)) { + debugl1(cs,"IIR %02x", val); + rs_interrupt_elsa(intno, cs); + } + } +#endif val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40); Start_HSCX: if (val) { @@ -338,6 +419,14 @@ cs->hw.elsa.counter++; } } + if (cs->hw.elsa.MFlag) { + val = serial_inp(cs, UART_MCR); + val ^= 0x8; + serial_outp(cs, UART_MCR, val); + val = serial_inp(cs, UART_MCR); + val ^= 0x8; + serial_outp(cs, UART_MCR, val); + } if (cs->hw.elsa.trig) byteout(cs->hw.elsa.trig, 0x00); writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0x0); @@ -350,25 +439,28 @@ { struct IsdnCardState *cs = dev_id; u_char ista,val; - char tmp[64]; - int icnt=20; + int icnt=5; if (!cs) { printk(KERN_WARNING "Elsa: Spurious interrupt!\n"); return; } - if ((cs->typ == ISDN_CTYPE_ELSA_PCMCIA) && (*cs->busy_flag == 1)) { - /* The card tends to generate interrupts while being removed - causing us to just crash the kernel. bad. */ - printk(KERN_WARNING "Elsa: card not available!\n"); - return; + val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */ + if (!(val & ELSA_PCI_IRQ_MASK)) + return; +#if ARCOFI_USE + if (cs->hw.elsa.MFlag) { + val = serial_inp(cs, UART_IIR); + if (!(val & UART_IIR_NO_INT)) { + debugl1(cs,"IIR %02x", val); + rs_interrupt_elsa(intno, cs); + } } +#endif ista = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA); Start_IPAC: - if (cs->debug & L1_DEB_IPAC) { - sprintf(tmp, "IPAC ISTA %02X", ista); - debugl1(cs, tmp); - } + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); if (ista & 0x0f) { val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40); if (ista & 0x01) @@ -407,17 +499,27 @@ int bytecnt = 8; del_timer(&cs->hw.elsa.tl); + clear_arcofi(cs); if (cs->hw.elsa.ctrl) byteout(cs->hw.elsa.ctrl, 0); /* LEDs Out */ - if ((cs->subtyp == ELSA_PCFPRO) || - (cs->subtyp == ELSA_QS3000) || - (cs->subtyp == ELSA_PCF)) - bytecnt = 16; if (cs->subtyp == ELSA_QS1000PCI) { byteout(cs->hw.elsa.cfg + 0x4c, 0x01); /* disable IRQ */ + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff); bytecnt = 2; release_region(cs->hw.elsa.cfg, 0x80); } + if (cs->subtyp == ELSA_QS3000PCI) { + byteout(cs->hw.elsa.cfg + 0x4c, 0x03); /* disable ELSA PCI IRQ */ + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff); + release_region(cs->hw.elsa.cfg, 0x80); + } + if ((cs->subtyp == ELSA_PCFPRO) || + (cs->subtyp == ELSA_QS3000) || + (cs->subtyp == ELSA_PCF) || + (cs->subtyp == ELSA_QS3000PCI)) { + bytecnt = 16; + release_modem(cs); + } if (cs->hw.elsa.base) release_region(cs->hw.elsa.base, bytecnt); } @@ -445,45 +547,35 @@ if (cs->hw.elsa.trig) byteout(cs->hw.elsa.trig, 0xff); } - if (cs->subtyp == ELSA_QS1000PCI) { + if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) { save_flags(flags); sti(); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x20); current->state = TASK_INTERRUPTIBLE; - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x00); current->state = TASK_INTERRUPTIBLE; - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xc0); - schedule(); + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ restore_flags(flags); - byteout(cs->hw.elsa.cfg + 0x4c, 0x41); /* enable ELSA PCI IRQ */ + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x0); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0x3c); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff); + if (cs->subtyp == ELSA_QS1000PCI) + byteout(cs->hw.elsa.cfg + 0x4c, 0x41); /* enable ELSA PCI IRQ */ + else if (cs->subtyp == ELSA_QS3000PCI) + byteout(cs->hw.elsa.cfg + 0x4c, 0x43); /* enable ELSA PCI IRQ */ } } -const u_char ARCOFI_VERSION[] = {2,0xa0,0}; -const u_char ARCOFI_COP_5[] = {4,0xa1,0x25,0xbb,0x4a}; /* GTX */ -const u_char ARCOFI_COP_6[] = {6,0xa1,0x26,0,0,0x82,0x7c}; /* GRL GRH */ -const u_char ARCOFI_COP_7[] = {4,0xa1,0x27,0x80,0x80}; /* GZ */ -const u_char ARCOFI_COP_8[] = {10,0xa1,0x28,0x49,0x31,0x8,0x13,0x6e,0x88,0x2a,0x61}; /* TX */ -const u_char ARCOFI_COP_9[] = {10,0xa1,0x29,0x80,0xcb,0x9e,0x88,0x00,0xc8,0xd8,0x80}; /* RX */ -const u_char ARCOFI_XOP_0[] = {2,0xa1,0x30}; /* PWR Down */ -const u_char ARCOFI_XOP_1[] = {2,0xa1,0x31}; /* PWR Down */ -const u_char ARCOFI_XOP_F[] = {2,0xa1,0x3f}; /* PWR Down */ -const u_char ARCOFI_SOP_F[] = {10,0xa1,0x1f,0x00,0x50,0x10,0x00,0x00,0x80,0x02,0x12}; - static void -init_arcofi(struct IsdnCardState *cs) { - send_arcofi(cs, ARCOFI_COP_5); - send_arcofi(cs, ARCOFI_COP_6); - send_arcofi(cs, ARCOFI_COP_7); - send_arcofi(cs, ARCOFI_COP_8); - send_arcofi(cs, ARCOFI_COP_9); - send_arcofi(cs, ARCOFI_SOP_F); - send_arcofi(cs, ARCOFI_XOP_F); +set_arcofi(struct IsdnCardState *cs, int bc) { + cs->dc.isac.arcofi_bc = bc; + arcofi_fsm(cs, ARCOFI_START, &ARCOFI_COP_5); + interruptible_sleep_on(&cs->dc.isac.arcofi_wait); } -static void +static int check_arcofi(struct IsdnCardState *cs) { #if ARCOFI_USE @@ -492,24 +584,24 @@ char *t; u_char *p; - if (!cs->mon_tx) - if (!(cs->mon_tx=kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) { + if (!cs->dc.isac.mon_tx) + if (!(cs->dc.isac.mon_tx=kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC MON TX out of buffers!"); - return; + return(0); } - send_arcofi(cs, ARCOFI_VERSION); - if (test_and_clear_bit(HW_MON1_TX_END, &cs->HW_Flags)) { - if (test_and_clear_bit(HW_MON1_RX_END, &cs->HW_Flags)) { - sprintf(tmp, "Arcofi response received %d bytes", cs->mon_rxp); - debugl1(cs, tmp); - p = cs->mon_rx; + cs->dc.isac.arcofi_bc = 0; + arcofi_fsm(cs, ARCOFI_START, &ARCOFI_VERSION); + interruptible_sleep_on(&cs->dc.isac.arcofi_wait); + if (!test_and_clear_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags)) { + debugl1(cs, "Arcofi response received %d bytes", cs->dc.isac.mon_rxp); + p = cs->dc.isac.mon_rx; t = tmp; t += sprintf(tmp, "Arcofi data"); - QuickHex(t, p, cs->mon_rxp); + QuickHex(t, p, cs->dc.isac.mon_rxp); debugl1(cs, tmp); - if ((cs->mon_rxp == 2) && (cs->mon_rx[0] == 0xa0)) { - switch(cs->mon_rx[1]) { + if ((cs->dc.isac.mon_rxp == 2) && (cs->dc.isac.mon_rx[0] == 0xa0)) { + switch(cs->dc.isac.mon_rx[1]) { case 0x80: debugl1(cs, "Arcofi 2160 detected"); arcofi_present = 1; @@ -528,11 +620,9 @@ } } else debugl1(cs, "undefined Monitor response"); - cs->mon_rxp = 0; - } - } else if (cs->mon_tx) { - sprintf(tmp, "Arcofi not detected"); - debugl1(cs, tmp); + cs->dc.isac.mon_rxp = 0; + } else if (cs->dc.isac.mon_tx) { + debugl1(cs, "Arcofi not detected"); } if (arcofi_present) { if (cs->subtyp==ELSA_QS1000) { @@ -572,9 +662,12 @@ "Elsa: %s detected modem at 0x%x\n", Elsa_Types[cs->subtyp], cs->hw.elsa.base+8); - init_arcofi(cs); + arcofi_fsm(cs, ARCOFI_START, &ARCOFI_XOP_0); + interruptible_sleep_on(&cs->dc.isac.arcofi_wait); + return(1); } #endif + return(0); } static void @@ -582,8 +675,7 @@ { int blink = 0; - if ((cs->subtyp == ELSA_PCMCIA) && - (cs->subtyp == ELSA_QS1000PCI)) + if (cs->subtyp == ELSA_PCMCIA) return; del_timer(&cs->hw.elsa.tl); if (cs->hw.elsa.status & ELSA_ASSIGN) @@ -602,7 +694,16 @@ } else cs->hw.elsa.ctrl_reg &= ~ELSA_LINE_LED; - byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); + if ((cs->subtyp == ELSA_QS1000PCI) || + (cs->subtyp == ELSA_QS3000PCI)) { + u_char led = 0xff; + if (cs->hw.elsa.ctrl_reg & ELSA_LINE_LED) + led ^= ELSA_IPAC_LINE_LED; + if (cs->hw.elsa.ctrl_reg & ELSA_STAT_LED) + led ^= ELSA_IPAC_STAT_LED; + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, led); + } else + byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); if (blink) { init_timer(&cs->hw.elsa.tl); cs->hw.elsa.tl.expires = jiffies + ((blink * HZ) / 1000); @@ -613,8 +714,9 @@ static int Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - int pwr, ret = 0; - long flags; + int len, ret = 0; + u_char *msg; + long flags; switch (mt) { case CARD_RESET: @@ -623,29 +725,25 @@ case CARD_RELEASE: release_io_elsa(cs); return(0); - case CARD_SETIRQ: - if (cs->subtyp == ELSA_QS1000PCI) - ret = request_irq(cs->irq, &elsa_interrupt_ipac, - I4L_IRQ_FLAG, "HiSax", cs); - else - ret = request_irq(cs->irq, &elsa_interrupt, - I4L_IRQ_FLAG, "HiSax", cs); - return(ret); case CARD_INIT: - if (cs->hw.elsa.trig) - byteout(cs->hw.elsa.trig, 0xff); - clear_pending_isac_ints(cs); - clear_pending_hscx_ints(cs); - initisac(cs); - inithscx(cs); - if (cs->subtyp == ELSA_QS1000) { + cs->debug |= L1_DEB_IPAC; + inithscxisac(cs, 1); + if ((cs->subtyp == ELSA_QS1000) || + (cs->subtyp == ELSA_QS3000)) + { byteout(cs->hw.elsa.timer, 0); - byteout(cs->hw.elsa.trig, 0xff); } + if (cs->hw.elsa.trig) + byteout(cs->hw.elsa.trig, 0xff); + inithscxisac(cs, 2); return(0); case CARD_TEST: - if ((cs->subtyp != ELSA_PCMCIA) && - (cs->subtyp != ELSA_QS1000PCI)) { + if ((cs->subtyp == ELSA_PCMCIA) || + (cs->subtyp == ELSA_QS1000PCI)) { + return(0); + } else if (cs->subtyp == ELSA_QS3000PCI) { + ret = 0; + } else { save_flags(flags); cs->hw.elsa.counter = 0; sti(); @@ -653,48 +751,51 @@ cs->hw.elsa.status |= ELSA_TIMER_AKTIV; byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); byteout(cs->hw.elsa.timer, 0); - } else - return(0); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout((110*HZ)/1000); /* Timeout 110ms */ - restore_flags(flags); - cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT; - byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); - cs->hw.elsa.status &= ~ELSA_TIMER_AKTIV; - printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n", - cs->hw.elsa.counter); - if (abs(cs->hw.elsa.counter - 13) < 3) { - printk(KERN_INFO "Elsa: timer and irq OK\n"); - ret = 0; - } else { - printk(KERN_WARNING - "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n", - cs->hw.elsa.counter, cs->irq); - ret = 1; + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((110*HZ)/1000); + restore_flags(flags); + cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT; + byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); + cs->hw.elsa.status &= ~ELSA_TIMER_AKTIV; + printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n", + cs->hw.elsa.counter); + if (abs(cs->hw.elsa.counter - 13) < 3) { + printk(KERN_INFO "Elsa: timer and irq OK\n"); + ret = 0; + } else { + printk(KERN_WARNING + "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n", + cs->hw.elsa.counter, cs->irq); + ret = 1; + } + } +#if ARCOFI_USE + if (check_arcofi(cs)) { + init_modem(cs); } - check_arcofi(cs); +#endif elsa_led_handler(cs); return(ret); - case MDL_REMOVE_REQ: + case (MDL_REMOVE | REQUEST): cs->hw.elsa.status &= 0; break; - case MDL_ASSIGN_REQ: + case (MDL_ASSIGN | REQUEST): cs->hw.elsa.status |= ELSA_ASSIGN; break; case MDL_INFO_SETUP: - if ((int) arg) + if ((long) arg) cs->hw.elsa.status |= 0x0200; else cs->hw.elsa.status |= 0x0100; break; case MDL_INFO_CONN: - if ((int) arg) + if ((long) arg) cs->hw.elsa.status |= 0x2000; else cs->hw.elsa.status |= 0x1000; break; case MDL_INFO_REL: - if ((int) arg) { + if ((long) arg) { cs->hw.elsa.status &= ~0x2000; cs->hw.elsa.status &= ~0x0200; } else { @@ -703,13 +804,23 @@ } break; case CARD_AUX_IND: + if (cs->hw.elsa.MFlag) { + if (!arg) + return(0); + msg = arg; + len = *msg; + msg++; + modem_write_cmd(cs, msg, len); + } break; } - pwr = bytein(cs->hw.elsa.ale); - if (pwr & 0x08) - cs->hw.elsa.status |= ELSA_BAD_PWR; - else - cs->hw.elsa.status &= ~ELSA_BAD_PWR; + if (cs->typ == ISDN_CTYPE_ELSA) { + int pwr = bytein(cs->hw.elsa.ale); + if (pwr & 0x08) + cs->hw.elsa.status |= ELSA_BAD_PWR; + else + cs->hw.elsa.status &= ~ELSA_BAD_PWR; + } elsa_led_handler(cs); return(ret); } @@ -778,7 +889,12 @@ return (CARD_portlist[i]); } +#ifdef COMPAT_HAS_NEW_PCI +static struct pci_dev *dev_qs1000 __initdata = NULL; +static struct pci_dev *dev_qs3000 __initdata = NULL; +#else static int pci_index __initdata = 0; +#endif int setup_elsa(struct IsdnCard *card) @@ -793,6 +909,7 @@ printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp)); cs->hw.elsa.ctrl_reg = 0; cs->hw.elsa.status = 0; + cs->hw.elsa.MFlag = 0; if (cs->typ == ISDN_CTYPE_ELSA) { cs->hw.elsa.base = card->para[0]; printk(KERN_INFO "Elsa: Microlink IO probing\n"); @@ -886,6 +1003,52 @@ cs->irq); } else if (cs->typ == ISDN_CTYPE_ELSA_PCI) { #if CONFIG_PCI +#ifdef COMPAT_HAS_NEW_PCI + if (!pci_present()) { + printk(KERN_ERR "Elsa: no PCI bus present\n"); + return(0); + } + cs->subtyp = 0; + if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ELSA, PCI_QS1000_ID, + dev_qs1000))) { + cs->subtyp = ELSA_QS1000PCI; + cs->irq = dev_qs1000->irq; + cs->hw.elsa.cfg = dev_qs1000->base_address[1] & + PCI_BASE_ADDRESS_IO_MASK; + cs->hw.elsa.base = dev_qs1000->base_address[3] & + PCI_BASE_ADDRESS_IO_MASK; + } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ELSA, + PCI_QS3000_ID, dev_qs3000))) { + cs->subtyp = ELSA_QS3000PCI; + cs->irq = dev_qs3000->irq; + cs->hw.elsa.cfg = dev_qs3000->base_address[1] & + PCI_BASE_ADDRESS_IO_MASK; + cs->hw.elsa.base = dev_qs3000->base_address[3] & + PCI_BASE_ADDRESS_IO_MASK; + } else { + printk(KERN_WARNING "Elsa: No PCI card found\n"); + return(0); + } + if (!cs->irq) { + printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n"); + return(0); + } + + if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) { + printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n"); + return(0); + } + if ((cs->hw.elsa.cfg & 0xff) || (cs->hw.elsa.base & 0xf)) { + printk(KERN_WARNING "Elsa: You may have a wrong PCI bios\n"); + printk(KERN_WARNING "Elsa: If your system hangs now, read\n"); + printk(KERN_WARNING "Elsa: Documentation/isdn/README.HiSax\n"); + printk(KERN_WARNING "Elsa: Waiting 5 sec to sync discs\n"); + save_flags(flags); + sti(); + HZDELAY(500); /* wait 500*10 ms */ + restore_flags(flags); + } +#else u_char pci_bus, pci_device_fn, pci_irq; u_int pci_ioaddr; @@ -895,6 +1058,10 @@ PCI_QS1000_ID, pci_index, &pci_bus, &pci_device_fn) == PCIBIOS_SUCCESSFUL) cs->subtyp = ELSA_QS1000PCI; + else if (pcibios_find_device(PCI_VENDOR_ELSA, + PCI_QS3000_ID, pci_index, &pci_bus, &pci_device_fn) + == PCIBIOS_SUCCESSFUL) + cs->subtyp = ELSA_QS3000PCI; else break; /* get IRQ */ @@ -915,6 +1082,7 @@ printk(KERN_WARNING "Elsa: No PCI card found\n"); return(0); } + pci_index++; if (!pci_irq) { printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n"); return(0); @@ -926,13 +1094,15 @@ } pci_ioaddr &= ~3; /* remove io/mem flag */ cs->hw.elsa.base = pci_ioaddr; - cs->hw.elsa.ale = pci_ioaddr; - cs->hw.elsa.isac = pci_ioaddr +1; - cs->hw.elsa.hscx = pci_ioaddr +1; cs->irq = pci_irq; +#endif /* COMPAT_HAS_NEW_PCI */ + cs->hw.elsa.ale = cs->hw.elsa.base; + cs->hw.elsa.isac = cs->hw.elsa.base +1; + cs->hw.elsa.hscx = cs->hw.elsa.base +1; test_and_set_bit(HW_IPAC, &cs->HW_Flags); cs->hw.elsa.timer = 0; cs->hw.elsa.trig = 0; + cs->irq_flags |= SA_SHIRQ; printk(KERN_INFO "Elsa: %s defined at 0x%x/0x%x IRQ %d\n", Elsa_Types[cs->subtyp], @@ -957,6 +1127,7 @@ break; case ELSA_PCFPRO: case ELSA_PCF: + case ELSA_QS3000PCI: bytecnt = 16; break; case ELSA_QS1000PCI: @@ -980,7 +1151,7 @@ } else { request_region(cs->hw.elsa.base, bytecnt, "elsa isdn"); } - if (cs->subtyp == ELSA_QS1000PCI) { + if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) { if (check_region(cs->hw.elsa.cfg, 0x80)) { printk(KERN_WARNING "HiSax: %s pci port %x-%x already in use\n", @@ -993,6 +1164,7 @@ request_region(cs->hw.elsa.cfg, 0x80, "elsa isdn pci"); } } + init_arcofi(cs); cs->hw.elsa.tl.function = (void *) elsa_led_handler; cs->hw.elsa.tl.data = (long) cs; init_timer(&cs->hw.elsa.tl); @@ -1020,16 +1192,17 @@ } printk(KERN_INFO "Elsa: timer OK; resetting card\n"); } - reset_elsa(cs); cs->BC_Read_Reg = &ReadHSCX; cs->BC_Write_Reg = &WriteHSCX; cs->BC_Send_Data = &hscx_fill_fifo; cs->cardmsg = &Elsa_card_msg; - if (cs->subtyp == ELSA_QS1000PCI) { + reset_elsa(cs); + if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) { cs->readisac = &ReadISAC_IPAC; cs->writeisac = &WriteISAC_IPAC; cs->readisacfifo = &ReadISACfifo_IPAC; cs->writeisacfifo = &WriteISACfifo_IPAC; + cs->irq_func = &elsa_interrupt_ipac; val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ID); printk(KERN_INFO "Elsa: IPAC version %x\n", val); } else { @@ -1037,6 +1210,7 @@ cs->writeisac = &WriteISAC; cs->readisacfifo = &ReadISACfifo; cs->writeisacfifo = &WriteISACfifo; + cs->irq_func = &elsa_interrupt; ISACVersion(cs, "Elsa:"); if (HscxVersion(cs, "Elsa:")) { printk(KERN_WARNING @@ -1056,4 +1230,3 @@ } return (1); } - diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/elsa_ser.c linux.pre11.3/drivers/isdn/hisax/elsa_ser.c --- linux.vanilla/drivers/isdn/hisax/elsa_ser.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/elsa_ser.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,750 @@ +#include +#include + +#define MAX_MODEM_BUF 256 +#define WAKEUP_CHARS (MAX_MODEM_BUF/2) +#define RS_ISR_PASS_LIMIT 256 +#define BASE_BAUD ( 1843200 / 16 ) + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +//#define SERIAL_DEBUG_OPEN 1 +//#define SERIAL_DEBUG_INTR 1 +//#define SERIAL_DEBUG_FLOW 1 +#undef SERIAL_DEBUG_OPEN +#undef SERIAL_DEBUG_INTR +#undef SERIAL_DEBUG_FLOW +#undef SERIAL_DEBUG_REG +//#define SERIAL_DEBUG_REG 1 + +#ifdef SERIAL_DEBUG_REG +static u_char deb[32]; +const char *ModemIn[] = {"RBR","IER","IIR","LCR","MCR","LSR","MSR","SCR"}; +const char *ModemOut[] = {"THR","IER","FCR","LCR","MCR","LSR","MSR","SCR"}; +#endif + +static char *MInit_1 = "AT&F&C1E0&D2\r\0"; +static char *MInit_2 = "ATL2M1S64=13\r\0"; +static char *MInit_3 = "AT+FCLASS=0\r\0"; +static char *MInit_4 = "ATV1S2=128X1\r\0"; +static char *MInit_5 = "AT\\V8\\N3\r\0"; +static char *MInit_6 = "ATL0M0&G0%E1\r\0"; +static char *MInit_7 = "AT%L1%M0%C3\r\0"; + +static char *MInit_speed28800 = "AT%G0%B28800\r\0"; + +static char *MInit_dialout = "ATs7=60 x1 d\r\0"; +static char *MInit_dialin = "ATs7=60 x1 a\r\0"; + + +static inline unsigned int serial_in(struct IsdnCardState *cs, int offset) +{ +#ifdef SERIAL_DEBUG_REG + u_int val = inb(cs->hw.elsa.base + 8 + offset); + debugl1(cs,"in %s %02x",ModemIn[offset], val); + return(val); +#else + return inb(cs->hw.elsa.base + 8 + offset); +#endif +} + +static inline unsigned int serial_inp(struct IsdnCardState *cs, int offset) +{ +#ifdef SERIAL_DEBUG_REG +#ifdef CONFIG_SERIAL_NOPAUSE_IO + u_int val = inb(cs->hw.elsa.base + 8 + offset); + debugl1(cs,"inp %s %02x",ModemIn[offset], val); +#else + u_int val = inb_p(cs->hw.elsa.base + 8 + offset); + debugl1(cs,"inP %s %02x",ModemIn[offset], val); +#endif + return(val); +#else +#ifdef CONFIG_SERIAL_NOPAUSE_IO + return inb(cs->hw.elsa.base + 8 + offset); +#else + return inb_p(cs->hw.elsa.base + 8 + offset); +#endif +#endif +} + +static inline void serial_out(struct IsdnCardState *cs, int offset, int value) +{ +#ifdef SERIAL_DEBUG_REG + debugl1(cs,"out %s %02x",ModemOut[offset], value); +#endif + outb(value, cs->hw.elsa.base + 8 + offset); +} + +static inline void serial_outp(struct IsdnCardState *cs, int offset, + int value) +{ +#ifdef SERIAL_DEBUG_REG +#ifdef CONFIG_SERIAL_NOPAUSE_IO + debugl1(cs,"outp %s %02x",ModemOut[offset], value); +#else + debugl1(cs,"outP %s %02x",ModemOut[offset], value); +#endif +#endif +#ifdef CONFIG_SERIAL_NOPAUSE_IO + outb(value, cs->hw.elsa.base + 8 + offset); +#else + outb_p(value, cs->hw.elsa.base + 8 + offset); +#endif +} + +/* + * This routine is called to set the UART divisor registers to match + * the specified baud rate for a serial port. + */ +static void change_speed(struct IsdnCardState *cs, int baud) +{ + int quot = 0, baud_base; + unsigned cval, fcr = 0; + int bits; + unsigned long flags; + + + /* byte size and parity */ + cval = 0x03; bits = 10; + /* Determine divisor based on baud rate */ + baud_base = BASE_BAUD; + quot = baud_base / baud; + /* If the quotient is ever zero, default to 9600 bps */ + if (!quot) + quot = baud_base / 9600; + + /* Set up FIFO's */ + if ((baud_base / quot) < 2400) + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; + else + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8; + serial_outp(cs, UART_FCR, fcr); + /* CTS flow control flag and modem status interrupts */ + cs->hw.elsa.IER &= ~UART_IER_MSI; + cs->hw.elsa.IER |= UART_IER_MSI; + serial_outp(cs, UART_IER, cs->hw.elsa.IER); + + debugl1(cs,"modem quot=0x%x", quot); + save_flags(flags); + cli(); + serial_outp(cs, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ + serial_outp(cs, UART_DLL, quot & 0xff); /* LS of divisor */ + serial_outp(cs, UART_DLM, quot >> 8); /* MS of divisor */ + serial_outp(cs, UART_LCR, cval); /* reset DLAB */ + serial_inp(cs, UART_RX); + restore_flags(flags); +} + +static int mstartup(struct IsdnCardState *cs) +{ + unsigned long flags; + int retval=0; + + + save_flags(flags); cli(); + + /* + * Clear the FIFO buffers and disable them + * (they will be reenabled in change_speed()) + */ + serial_outp(cs, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT)); + + /* + * At this point there's no way the LSR could still be 0xFF; + * if it is, then bail out, because there's likely no UART + * here. + */ + if (serial_inp(cs, UART_LSR) == 0xff) { + retval = -ENODEV; + goto errout; + } + + /* + * Clear the interrupt registers. + */ + (void) serial_inp(cs, UART_RX); + (void) serial_inp(cs, UART_IIR); + (void) serial_inp(cs, UART_MSR); + + /* + * Now, initialize the UART + */ + serial_outp(cs, UART_LCR, UART_LCR_WLEN8); /* reset DLAB */ + + cs->hw.elsa.MCR = 0; + cs->hw.elsa.MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2; + serial_outp(cs, UART_MCR, cs->hw.elsa.MCR); + + /* + * Finally, enable interrupts + */ + cs->hw.elsa.IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; + serial_outp(cs, UART_IER, cs->hw.elsa.IER); /* enable interrupts */ + + /* + * And clear the interrupt registers again for luck. + */ + (void)serial_inp(cs, UART_LSR); + (void)serial_inp(cs, UART_RX); + (void)serial_inp(cs, UART_IIR); + (void)serial_inp(cs, UART_MSR); + + cs->hw.elsa.transcnt = cs->hw.elsa.transp = 0; + cs->hw.elsa.rcvcnt = cs->hw.elsa.rcvp =0; + + /* + * and set the speed of the serial port + */ + change_speed(cs, BASE_BAUD); + cs->hw.elsa.MFlag = 1; +errout: + restore_flags(flags); + return retval; +} + +/* + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. + */ +static void mshutdown(struct IsdnCardState *cs) +{ + unsigned long flags; + + +#ifdef SERIAL_DEBUG_OPEN + printk(KERN_DEBUG"Shutting down serial ...."); +#endif + + save_flags(flags); cli(); /* Disable interrupts */ + + /* + * clear delta_msr_wait queue to avoid mem leaks: we may free the irq + * here so the queue might never be waken up + */ + + cs->hw.elsa.IER = 0; + serial_outp(cs, UART_IER, 0x00); /* disable all intrs */ + cs->hw.elsa.MCR &= ~UART_MCR_OUT2; + + /* disable break condition */ + serial_outp(cs, UART_LCR, serial_inp(cs, UART_LCR) & ~UART_LCR_SBC); + + cs->hw.elsa.MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); + serial_outp(cs, UART_MCR, cs->hw.elsa.MCR); + + /* disable FIFO's */ + serial_outp(cs, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT)); + serial_inp(cs, UART_RX); /* read data port to reset things */ + + restore_flags(flags); +#ifdef SERIAL_DEBUG_OPEN + printk(" done\n"); +#endif +} + +inline int +write_modem(struct BCState *bcs) { + int ret=0; + struct IsdnCardState *cs = bcs->cs; + int count, len, fp, buflen; + long flags; + + if (!bcs->tx_skb) + return 0; + if (bcs->tx_skb->len <= 0) + return 0; + save_flags(flags); + cli(); + buflen = MAX_MODEM_BUF - cs->hw.elsa.transcnt; + len = MIN(buflen, bcs->tx_skb->len); + fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp; + fp &= (MAX_MODEM_BUF -1); + count = MIN(len, MAX_MODEM_BUF - fp); + if (count < len) { + memcpy(cs->hw.elsa.transbuf + fp, bcs->tx_skb->data, count); + skb_pull(bcs->tx_skb, count); + cs->hw.elsa.transcnt += count; + ret = count; + count = len - count; + fp = 0; + } + memcpy((cs->hw.elsa.transbuf + fp), bcs->tx_skb->data, count); + skb_pull(bcs->tx_skb, count); + cs->hw.elsa.transcnt += count; + ret += count; + + if (cs->hw.elsa.transcnt && + !(cs->hw.elsa.IER & UART_IER_THRI)) { + cs->hw.elsa.IER |= UART_IER_THRI; + serial_outp(cs, UART_IER, cs->hw.elsa.IER); + } + restore_flags(flags); + return(ret); +} + +inline void +modem_fill(struct BCState *bcs) { + + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + write_modem(bcs); + return; + } else { + if (bcs->st->lli.l1writewakeup && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) + bcs->st->lli.l1writewakeup(bcs->st, + bcs->hw.hscx.count); + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.hscx.count = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + write_modem(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + hscx_sched_event(bcs, B_XMTBUFREADY); + } +} + +static inline void receive_chars(struct IsdnCardState *cs, + int *status) +{ + unsigned char ch; + struct sk_buff *skb; + + do { + ch = serial_in(cs, UART_RX); + if (cs->hw.elsa.rcvcnt >= MAX_MODEM_BUF) + break; + cs->hw.elsa.rcvbuf[cs->hw.elsa.rcvcnt++] = ch; +#ifdef SERIAL_DEBUG_INTR + printk("DR%02x:%02x...", ch, *status); +#endif + if (*status & (UART_LSR_BI | UART_LSR_PE | + UART_LSR_FE | UART_LSR_OE)) { + +#ifdef SERIAL_DEBUG_INTR + printk("handling exept...."); +#endif + } + *status = serial_inp(cs, UART_LSR); + } while (*status & UART_LSR_DR); + if (cs->hw.elsa.MFlag == 2) { + if (!(skb = dev_alloc_skb(cs->hw.elsa.rcvcnt))) + printk(KERN_WARNING "ElsaSER: receive out of memory\n"); + else { + memcpy(skb_put(skb, cs->hw.elsa.rcvcnt), cs->hw.elsa.rcvbuf, + cs->hw.elsa.rcvcnt); + skb_queue_tail(& cs->hw.elsa.bcs->rqueue, skb); + } + hscx_sched_event(cs->hw.elsa.bcs, B_RCVBUFREADY); + } else { + char tmp[128]; + char *t = tmp; + + t += sprintf(t, "modem read cnt %d", cs->hw.elsa.rcvcnt); + QuickHex(t, cs->hw.elsa.rcvbuf, cs->hw.elsa.rcvcnt); + debugl1(cs, tmp); + } + cs->hw.elsa.rcvcnt = 0; +} + +static inline void transmit_chars(struct IsdnCardState *cs, int *intr_done) +{ + int count; + + debugl1(cs, "transmit_chars: p(%x) cnt(%x)", cs->hw.elsa.transp, + cs->hw.elsa.transcnt); + + if (cs->hw.elsa.transcnt <= 0) { + cs->hw.elsa.IER &= ~UART_IER_THRI; + serial_out(cs, UART_IER, cs->hw.elsa.IER); + return; + } + count = 16; + do { + serial_outp(cs, UART_TX, cs->hw.elsa.transbuf[cs->hw.elsa.transp++]); + if (cs->hw.elsa.transp >= MAX_MODEM_BUF) + cs->hw.elsa.transp=0; + if (--cs->hw.elsa.transcnt <= 0) + break; + } while (--count > 0); + if ((cs->hw.elsa.transcnt < WAKEUP_CHARS) && (cs->hw.elsa.MFlag==2)) + modem_fill(cs->hw.elsa.bcs); + +#ifdef SERIAL_DEBUG_INTR + printk("THRE..."); +#endif + if (intr_done) + *intr_done = 0; + if (cs->hw.elsa.transcnt <= 0) { + cs->hw.elsa.IER &= ~UART_IER_THRI; + serial_outp(cs, UART_IER, cs->hw.elsa.IER); + } +} + +#if 0 +static inline void check_modem_status(struct IsdnCardState *cs) +{ + int status; + struct async_struct *info = cs->hw.elsa.info; + struct async_icount *icount; + + status = serial_inp(info, UART_MSR); + + if (status & UART_MSR_ANY_DELTA) { + icount = &info->state->icount; + /* update input line counters */ + if (status & UART_MSR_TERI) + icount->rng++; + if (status & UART_MSR_DDSR) + icount->dsr++; + if (status & UART_MSR_DDCD) { + icount->dcd++; + } + if (status & UART_MSR_DCTS) + icount->cts++; +// wake_up_interruptible(&info->delta_msr_wait); + } + + if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { +#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR)) + printk("ttys%d CD now %s...", info->line, + (status & UART_MSR_DCD) ? "on" : "off"); +#endif + if (status & UART_MSR_DCD) +// wake_up_interruptible(&info->open_wait); +; + else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_CALLOUT_NOHUP))) { +#ifdef SERIAL_DEBUG_OPEN + printk("doing serial hangup..."); +#endif + if (info->tty) + tty_hangup(info->tty); + } + } +#if 0 + if (info->flags & ASYNC_CTS_FLOW) { + if (info->tty->hw_stopped) { + if (status & UART_MSR_CTS) { +#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) + printk("CTS tx start..."); +#endif + info->tty->hw_stopped = 0; + info->IER |= UART_IER_THRI; + serial_outp(info, UART_IER, info->IER); +// rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); + return; + } + } else { + if (!(status & UART_MSR_CTS)) { +#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) + printk("CTS tx stop..."); +#endif + info->tty->hw_stopped = 1; + info->IER &= ~UART_IER_THRI; + serial_outp(info, UART_IER, info->IER); + } + } + } +#endif 0 +} +#endif + +static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs) +{ + int status, iir, msr; + int pass_counter = 0; + +#ifdef SERIAL_DEBUG_INTR + printk("rs_interrupt_single(%d)...", irq); +#endif + + do { + status = serial_inp(cs, UART_LSR); + debugl1(cs,"rs LSR %02x", status); +#ifdef SERIAL_DEBUG_INTR + printk("status = %x...", status); +#endif + if (status & UART_LSR_DR) + receive_chars(cs, &status); + if (status & UART_LSR_THRE) + transmit_chars(cs, 0); + if (pass_counter++ > RS_ISR_PASS_LIMIT) { + printk("rs_single loop break.\n"); + break; + } + iir = serial_inp(cs, UART_IIR); + debugl1(cs,"rs IIR %02x", iir); + if ((iir & 0xf) == 0) { + msr = serial_inp(cs, UART_MSR); + debugl1(cs,"rs MSR %02x", msr); + } + } while (!(iir & UART_IIR_NO_INT)); +#ifdef SERIAL_DEBUG_INTR + printk("end.\n"); +#endif +} + +extern int open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs); +extern void modehscx(struct BCState *bcs, int mode, int bc); +extern void hscx_l2l1(struct PStack *st, int pr, void *arg); + +void +close_elsastate(struct BCState *bcs) +{ + struct sk_buff *skb; + + modehscx(bcs, 0, bcs->channel); + if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { + if (bcs->hw.hscx.rcvbuf) { + if (bcs->mode != L1_MODE_MODEM) + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + } + while ((skb = skb_dequeue(&bcs->rqueue))) { + idev_kfree_skb(skb, FREE_READ); + } + while ((skb = skb_dequeue(&bcs->squeue))) { + idev_kfree_skb(skb, FREE_WRITE); + } + if (bcs->tx_skb) { + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + } + } +} + +void +modem_write_cmd(struct IsdnCardState *cs, u_char *buf, int len) { + int count, fp; + u_char *msg = buf; + long flags; + + if (!len) + return; + save_flags(flags); + cli(); + if (len > (MAX_MODEM_BUF - cs->hw.elsa.transcnt)) { + restore_flags(flags); + return; + } + fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp; + fp &= (MAX_MODEM_BUF -1); + count = MIN(len, MAX_MODEM_BUF - fp); + if (count < len) { + memcpy(cs->hw.elsa.transbuf + fp, msg, count); + cs->hw.elsa.transcnt += count; + msg += count; + count = len - count; + fp = 0; + } + memcpy(cs->hw.elsa.transbuf + fp, msg, count); + cs->hw.elsa.transcnt += count; + if (cs->hw.elsa.transcnt && + !(cs->hw.elsa.IER & UART_IER_THRI)) { + cs->hw.elsa.IER |= UART_IER_THRI; + serial_outp(cs, UART_IER, cs->hw.elsa.IER); + } + restore_flags(flags); +} + +void +modem_set_init(struct IsdnCardState *cs) { + long flags; + int timeout; + +#define RCV_DELAY 20000 + save_flags(flags); + sti(); + modem_write_cmd(cs, MInit_1, strlen(MInit_1)); + timeout = 1000; + while(timeout-- && cs->hw.elsa.transcnt) + udelay(1000); + debugl1(cs, "msi tout=%d", timeout); + udelay(RCV_DELAY); + modem_write_cmd(cs, MInit_2, strlen(MInit_2)); + timeout = 1000; + while(timeout-- && cs->hw.elsa.transcnt) + udelay(1000); + debugl1(cs, "msi tout=%d", timeout); + udelay(RCV_DELAY); + modem_write_cmd(cs, MInit_3, strlen(MInit_3)); + timeout = 1000; + while(timeout-- && cs->hw.elsa.transcnt) + udelay(1000); + debugl1(cs, "msi tout=%d", timeout); + udelay(RCV_DELAY); + modem_write_cmd(cs, MInit_4, strlen(MInit_4)); + timeout = 1000; + while(timeout-- && cs->hw.elsa.transcnt) + udelay(1000); + debugl1(cs, "msi tout=%d", timeout); + udelay(RCV_DELAY ); + modem_write_cmd(cs, MInit_5, strlen(MInit_5)); + timeout = 1000; + while(timeout-- && cs->hw.elsa.transcnt) + udelay(1000); + debugl1(cs, "msi tout=%d", timeout); + udelay(RCV_DELAY); + modem_write_cmd(cs, MInit_6, strlen(MInit_6)); + timeout = 1000; + while(timeout-- && cs->hw.elsa.transcnt) + udelay(1000); + debugl1(cs, "msi tout=%d", timeout); + udelay(RCV_DELAY); + modem_write_cmd(cs, MInit_7, strlen(MInit_7)); + timeout = 1000; + while(timeout-- && cs->hw.elsa.transcnt) + udelay(1000); + debugl1(cs, "msi tout=%d", timeout); + udelay(RCV_DELAY); + restore_flags(flags); +} + +void +modem_set_dial(struct IsdnCardState *cs, int outgoing) { + long flags; + int timeout; +#define RCV_DELAY 20000 + + save_flags(flags); + sti(); + modem_write_cmd(cs, MInit_speed28800, strlen(MInit_speed28800)); + timeout = 1000; + while(timeout-- && cs->hw.elsa.transcnt) + udelay(1000); + debugl1(cs, "msi tout=%d", timeout); + udelay(RCV_DELAY); + if (outgoing) + modem_write_cmd(cs, MInit_dialout, strlen(MInit_dialout)); + else + modem_write_cmd(cs, MInit_dialin, strlen(MInit_dialin)); + timeout = 1000; + while(timeout-- && cs->hw.elsa.transcnt) + udelay(1000); + debugl1(cs, "msi tout=%d", timeout); + udelay(RCV_DELAY); + restore_flags(flags); +} + +void +modem_l2l1(struct PStack *st, int pr, void *arg) +{ + struct sk_buff *skb = arg; + long flags; + + if (pr == (PH_DATA | REQUEST)) { + save_flags(flags); + cli(); + if (st->l1.bcs->tx_skb) { + skb_queue_tail(&st->l1.bcs->squeue, skb); + restore_flags(flags); + } else { + st->l1.bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + st->l1.bcs->hw.hscx.count = 0; + restore_flags(flags); + write_modem(st->l1.bcs); + } + } else if (pr == (PH_ACTIVATE | REQUEST)) { + test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); + set_arcofi(st->l1.bcs->cs, st->l1.bc); + mstartup(st->l1.bcs->cs); + modem_set_dial(st->l1.bcs->cs, test_bit(FLG_ORIG, &st->l2.flag)); + st->l1.bcs->cs->hw.elsa.MFlag=2; + } else if (pr == (PH_DEACTIVATE | REQUEST)) { + test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + st->l1.bcs->cs->dc.isac.arcofi_bc = st->l1.bc; + arcofi_fsm(st->l1.bcs->cs, ARCOFI_START, &ARCOFI_XOP_0); + interruptible_sleep_on(&st->l1.bcs->cs->dc.isac.arcofi_wait); + st->l1.bcs->cs->hw.elsa.MFlag=1; + } else { + printk(KERN_WARNING"ElsaSer: unknown pr %x\n", pr); + } +} + +int +setstack_elsa(struct PStack *st, struct BCState *bcs) +{ + + bcs->channel = st->l1.bc; + switch (st->l1.mode) { + case L1_MODE_HDLC: + case L1_MODE_TRANS: + if (open_hscxstate(st->l1.hardware, bcs)) + return (-1); + st->l2.l2l1 = hscx_l2l1; + break; + case L1_MODE_MODEM: + bcs->mode = L1_MODE_MODEM; + if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { + bcs->hw.hscx.rcvbuf = bcs->cs->hw.elsa.rcvbuf; + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + } + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->event = 0; + bcs->hw.hscx.rcvidx = 0; + bcs->tx_cnt = 0; + bcs->cs->hw.elsa.bcs = bcs; + st->l2.l2l1 = modem_l2l1; + break; + } + st->l1.bcs = bcs; + setstack_manager(st); + bcs->st = st; + setstack_l1_B(st); + return (0); +} + +void +init_modem(struct IsdnCardState *cs) { + + cs->bcs[0].BC_SetStack = setstack_elsa; + cs->bcs[1].BC_SetStack = setstack_elsa; + cs->bcs[0].BC_Close = close_elsastate; + cs->bcs[1].BC_Close = close_elsastate; + if (!(cs->hw.elsa.rcvbuf = kmalloc(MAX_MODEM_BUF, + GFP_ATOMIC))) { + printk(KERN_WARNING + "Elsa: No modem mem hw.elsa.rcvbuf\n"); + return; + } + if (!(cs->hw.elsa.transbuf = kmalloc(MAX_MODEM_BUF, + GFP_ATOMIC))) { + printk(KERN_WARNING + "Elsa: No modem mem hw.elsa.transbuf\n"); + kfree(cs->hw.elsa.rcvbuf); + cs->hw.elsa.rcvbuf = NULL; + return; + } + if (mstartup(cs)) { + printk(KERN_WARNING "Elsa: problem startup modem\n"); + } + modem_set_init(cs); +} + +void +release_modem(struct IsdnCardState *cs) { + + cs->hw.elsa.MFlag = 0; + if (cs->hw.elsa.transbuf) { + if (cs->hw.elsa.rcvbuf) { + mshutdown(cs); + kfree(cs->hw.elsa.rcvbuf); + cs->hw.elsa.rcvbuf = NULL; + } + kfree(cs->hw.elsa.transbuf); + cs->hw.elsa.transbuf = NULL; + } +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/foreign.c linux.pre11.3/drivers/isdn/hisax/foreign.c --- linux.vanilla/drivers/isdn/hisax/foreign.c Wed Mar 24 10:55:17 1999 +++ linux.pre11.3/drivers/isdn/hisax/foreign.c Mon Jul 19 23:59:33 1999 @@ -1,780 +0,0 @@ -/* $Id: foreign.c,v 1.1 1998/11/09 07:48:48 baccala Exp $ - * - * HiSax ISDN driver - foreign chipset interface - * - * Author Brent Baccala (baccala@FreeSoft.org) - * - * - * - * $Log: foreign.c,v $ - * Revision 1.1 1998/11/09 07:48:48 baccala - * Initial DBRI ISDN code. Sometimes works (brings up the link and you - * can telnet through it), sometimes doesn't (crashes the machine) - * - * Revision 1.2 1998/02/12 23:07:10 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.1 1998/02/03 23:20:51 keil - * New files for SPARC isdn support - * - * Revision 1.1 1998/01/08 04:17:12 baccala - * ISDN comes to the Sparc. Key points: - * - * - Existing ISDN HiSax driver provides all the smarts - * - it compiles, runs, talks to an isolated phone switch, connects - * to a Cisco, pings go through - * - AMD 7930 support only (no DBRI yet) - * - no US NI-1 support (may not work on US phone system - untested) - * - periodic packet loss, apparently due to lost interrupts - * - ISDN sometimes freezes, requiring reboot before it will work again - * - * The code is unreliable enough to be consider alpha - * - * - * - */ - -#define __NO_VERSION__ -#include "hisax.h" -#include "isac.h" -#include "isdnl1.h" -#include "foreign.h" -#include "rawhdlc.h" -#include - -static const char *foreign_revision = "$Revision: 1.1 $"; - -#define RCV_BUFSIZE 1024 /* Size of raw receive buffer in bytes */ -#define RCV_BUFBLKS 4 /* Number of blocks to divide buffer into - * (must divide RCV_BUFSIZE) */ - -static void Bchan_fill_fifo(struct BCState *, struct sk_buff *); - -static void -Bchan_xmt_bh(struct BCState *bcs) -{ - struct sk_buff *skb; - - if (bcs->hw.foreign.tx_skb != NULL) { - dev_kfree_skb(bcs->hw.foreign.tx_skb); - bcs->hw.foreign.tx_skb = NULL; - } - - if ((skb = skb_dequeue(&bcs->squeue))) { - Bchan_fill_fifo(bcs, skb); - } else { - clear_bit(BC_FLG_BUSY, &bcs->Flag); - bcs->event |= 1 << B_XMTBUFREADY; - queue_task(&bcs->tqueue, &tq_immediate); - mark_bh(IMMEDIATE_BH); - } -} - -static void -Bchan_xmit_callback(struct BCState *bcs) -{ - queue_task(&bcs->hw.foreign.tq_xmt, &tq_immediate); - mark_bh(IMMEDIATE_BH); -} - -/* B channel transmission: two modes (three, if you count L1_MODE_NULL) - * - * L1_MODE_HDLC - We need to do HDLC encapsulation before transmiting - * the packet (i.e. make_raw_hdlc_data). Since this can be a - * time-consuming operation, our completion callback just schedules - * a bottom half to do encapsulation for the next packet. In between, - * the link will just idle - * - * L1_MODE_TRANS - Data goes through, well, transparent. No HDLC encap, - * and we can't just let the link idle, so the "bottom half" actually - * gets called during the top half (it's our callback routine in this case), - * but it's a lot faster now since we don't call make_raw_hdlc_data - */ - -static void -Bchan_fill_fifo(struct BCState *bcs, struct sk_buff *skb) -{ - struct IsdnCardState *cs = bcs->cs; - struct foreign_hw *hw = &bcs->hw.foreign; - int len; - - if ((cs->debug & L1_DEB_HSCX) || (cs->debug & L1_DEB_HSCX_FIFO)) { - char tmp[2048]; - char *t = tmp; - - t += sprintf(t, "Bchan_fill_fifo %c cnt %d", - bcs->channel ? 'B' : 'A', skb->len); - if (cs->debug & L1_DEB_HSCX_FIFO) - QuickHex(t, skb->data, skb->len); - debugl1(cs, tmp); - } - - if (hw->doHDLCprocessing) { - len = make_raw_hdlc_data(skb->data, skb->len, - bcs->hw.foreign.tx_buff, RAW_BUFMAX); - if (len > 0) - cs->hw.foreign->bxmit(0, bcs->channel, - bcs->hw.foreign.tx_buff, len, - (void *) &Bchan_xmit_callback, - (void *) bcs); - dev_kfree_skb(skb); - } else { - cs->hw.foreign->bxmit(0, bcs->channel, - skb->data, skb->len, - (void *) &Bchan_xmit_callback, - (void *) bcs); - bcs->hw.foreign.tx_skb = skb; - } -} - -static void -Bchan_mode(struct BCState *bcs, int mode, int bc) -{ - struct IsdnCardState *cs = bcs->cs; - - if (cs->debug & L1_DEB_HSCX) { - char tmp[40]; - sprintf(tmp, "foreign mode %d bchan %d/%d", - mode, bc, bcs->channel); - debugl1(cs, tmp); - } - bcs->mode = mode; -} - -/* Bchan_l2l1 is the entry point for upper layer routines that want to - * transmit on the B channel. PH_DATA_REQ is a normal packet that - * we either start transmitting (if idle) or queue (if busy). - * PH_PULL_REQ can be called to request a callback message (PH_PULL_CNF) - * once the link is idle. After a "pull" callback, the upper layer - * routines can use PH_PULL_IND to send data. - */ - -static void -Bchan_l2l1(struct PStack *st, int pr, void *arg) -{ - struct sk_buff *skb = arg; - - switch (pr) { - case (PH_DATA_REQ): - if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) { - skb_queue_tail(&st->l1.bcs->squeue, skb); - } else { - test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - Bchan_fill_fifo(st->l1.bcs, skb); - } - break; - case (PH_PULL_IND): - if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) { - printk(KERN_WARNING "foreign: this shouldn't happen\n"); - break; - } - test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - Bchan_fill_fifo(st->l1.bcs, skb); - break; - case (PH_PULL_REQ): - if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) { - clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - st->l1.l1l2(st, PH_PULL_CNF, NULL); - } else - set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - break; - } -} - -/* -**************************************************************************** -***************** Receiver callback and bottom half ************************ -**************************************************************************** -*/ - -/* Bchan_recv_done() is called when a frame has been completely decoded - * into hw->rv_skb and we're ready to hand it off to the HiSax upper - * layer. If a "large" packet is received, stick rv_skb on the - * receive queue and alloc a new (large) skb to act as buffer for - * future receives. If a small packet is received, leave rv_skb - * alone, alloc a new skb of the correct size, and copy the packet - * into it. In any case, flag the channel as B_RCVBUFREADY and - * queue the upper layer's task. - */ - -static void -Bchan_recv_done(struct BCState *bcs, unsigned int len) -{ - struct IsdnCardState *cs = bcs->cs; - struct foreign_hw *hw = &bcs->hw.foreign; - struct sk_buff *skb; - - if (cs->debug & L1_DEB_HSCX_FIFO) { - char tmp[2048]; - char *t = tmp; - - t += sprintf(t, "Bchan_rcv %c cnt %d (%x)", bcs->channel ? 'B' : 'A', len, hw->rv_skb->tail); - QuickHex(t, hw->rv_skb->tail, len); - debugl1(cs, tmp); - } - - if (len > HSCX_BUFMAX/2) { - /* Large packet received */ - - if (!(skb = dev_alloc_skb(HSCX_BUFMAX))) { - printk(KERN_WARNING "foreign: receive out of memory\n"); - } else { - skb_put(hw->rv_skb, len); - skb_queue_tail(&bcs->rqueue, hw->rv_skb); - hw->rv_skb = skb; - - bcs->event |= 1 << B_RCVBUFREADY; - queue_task(&bcs->tqueue, &tq_immediate); - mark_bh(IMMEDIATE_BH); - } - } else { - /* Small packet received */ - - if (!(skb = dev_alloc_skb(len))) { - printk(KERN_WARNING "foreign: receive out of memory\n"); - } else { - memcpy(skb_put(skb, len), hw->rv_skb->tail, len); - skb_queue_tail(&bcs->rqueue, skb); - - bcs->event |= 1 << B_RCVBUFREADY; - queue_task(&bcs->tqueue, &tq_immediate); - mark_bh(IMMEDIATE_BH); - } - } -} - -/* Bchan_recv_callback()'s behavior depends on whether we're doing local - * HDLC processing. If so, receive into hw->rv_buff and queue Bchan_rcv_bh - * to decode the HDLC at leisure. Otherwise, receive directly into hw->rv_skb - * and call Bchan_recv_done(). In either case, prepare a new buffer for - * further receives and hand it to the hardware driver. - */ - -static void -Bchan_recv_callback(struct BCState *bcs, int error, unsigned int len) -{ - struct IsdnCardState *cs = bcs->cs; - struct foreign_hw *hw = &bcs->hw.foreign; - - if (hw->doHDLCprocessing) { - - hw->rv_buff_in += RCV_BUFSIZE/RCV_BUFBLKS; - hw->rv_buff_in %= RCV_BUFSIZE; - - if (hw->rv_buff_in != hw->rv_buff_out) { - cs->hw.foreign->brecv(0, bcs->channel, - hw->rv_buff + hw->rv_buff_in, - RCV_BUFSIZE/RCV_BUFBLKS, - (void *) &Bchan_recv_callback, - (void *) bcs); - - } - queue_task(&hw->tq_rcv, &tq_immediate); - mark_bh(IMMEDIATE_BH); - - } else { - if (error) { - char tmp[256]; - sprintf(tmp, "B channel %c receive error %x", - bcs->channel ? 'B' : 'A', error); - debugl1(cs, tmp); - } else { - Bchan_recv_done(bcs, len); - } - cs->hw.foreign->brecv(0, bcs->channel, - hw->rv_skb->tail, HSCX_BUFMAX, - (void *) &Bchan_recv_callback, - (void *) bcs); - - } -} - -/* Bchan_rcv_bh() is a "shim" bottom half handler stuck in between - * Bchan_recv_callback() and the HiSax upper layer if we need to - * do local HDLC processing. - */ - -static void -Bchan_rcv_bh(struct BCState *bcs) -{ - struct IsdnCardState *cs = bcs->cs; - struct foreign_hw *hw = &bcs->hw.foreign; - struct sk_buff *skb; - int len; - - if (cs->debug & L1_DEB_HSCX) { - char tmp[1024]; - - sprintf(tmp, "foreign_Bchan_rcv (%d/%d)", - hw->rv_buff_in, hw->rv_buff_out); - debugl1(cs, tmp); - } - - do { - if (cs->debug & L1_DEB_HSCX) { - char tmp[1024]; - - QuickHex(tmp, hw->rv_buff + hw->rv_buff_out, - RCV_BUFSIZE/RCV_BUFBLKS); - debugl1(cs, tmp); - } - - while ((len = read_raw_hdlc_data(hw->hdlc_state, - hw->rv_buff + hw->rv_buff_out, RCV_BUFSIZE/RCV_BUFBLKS, - hw->rv_skb->tail, HSCX_BUFMAX))) { - if (len > 0) { - Bchan_recv_done(bcs, len); - } else { - char tmp[256]; - sprintf(tmp, "B channel %c receive error", - bcs->channel ? 'B' : 'A'); - debugl1(cs, tmp); - } - } - - if (hw->rv_buff_in == hw->rv_buff_out) { - /* Buffer was filled up - need to restart receiver */ - cs->hw.foreign->brecv(0, bcs->channel, - hw->rv_buff + hw->rv_buff_in, - RCV_BUFSIZE/RCV_BUFBLKS, - (void *) &Bchan_recv_callback, - (void *) bcs); - } - - hw->rv_buff_out += RCV_BUFSIZE/RCV_BUFBLKS; - hw->rv_buff_out %= RCV_BUFSIZE; - - } while (hw->rv_buff_in != hw->rv_buff_out); -} - -static void -Bchan_close(struct BCState *bcs) -{ - struct IsdnCardState *cs = bcs->cs; - struct sk_buff *skb; - - Bchan_mode(bcs, 0, 0); - cs->hw.foreign->bclose(0, bcs->channel); - - if (test_bit(BC_FLG_INIT, &bcs->Flag)) { - while ((skb = skb_dequeue(&bcs->rqueue))) { - dev_kfree_skb(skb); - } - while ((skb = skb_dequeue(&bcs->squeue))) { - dev_kfree_skb(skb); - } - } - test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); -} - -static int -Bchan_open(struct BCState *bcs) -{ - struct IsdnCardState *cs = bcs->cs; - struct foreign_hw *hw = &bcs->hw.foreign; - - if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { - skb_queue_head_init(&bcs->rqueue); - skb_queue_head_init(&bcs->squeue); - } - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - - hw->doHDLCprocessing = 0; - if (bcs->mode == L1_MODE_HDLC) { - if (cs->hw.foreign->bopen(0, bcs->channel, 1, 0xff) == -1) { - if (cs->hw.foreign->bopen(0, bcs->channel, 0, 0xff) == -1) { - return (-1); - } - hw->doHDLCprocessing = 1; - } - } else { - if (cs->hw.foreign->bopen(0, bcs->channel, 0, 0xff) == -1) { - return (-1); - } - } - - hw->rv_buff_in = 0; - hw->rv_buff_out = 0; - hw->tx_skb = NULL; - init_hdlc_state(hw->hdlc_state, 0); - cs->hw.foreign->brecv(0, bcs->channel, - hw->rv_buff + hw->rv_buff_in, - RCV_BUFSIZE/RCV_BUFBLKS, - (void *) &Bchan_recv_callback, (void *) bcs); - - bcs->event = 0; - bcs->tx_cnt = 0; - return (0); -} - -static void -Bchan_init(struct BCState *bcs) -{ - if (!(bcs->hw.foreign.tx_buff = kmalloc(RAW_BUFMAX, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for foreign.tx_buff\n"); - return; - } - if (!(bcs->hw.foreign.rv_buff = kmalloc(RCV_BUFSIZE, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for foreign.rv_buff\n"); - return; - } - if (!(bcs->hw.foreign.rv_skb = dev_alloc_skb(HSCX_BUFMAX))) { - printk(KERN_WARNING - "HiSax: No memory for foreign.rv_skb\n"); - return; - } - if (!(bcs->hw.foreign.hdlc_state = kmalloc(sizeof(struct hdlc_state), - GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for foreign.hdlc_state\n"); - return; - } - - bcs->hw.foreign.tq_rcv.sync = 0; - bcs->hw.foreign.tq_rcv.routine = (void (*)(void *)) &Bchan_rcv_bh; - bcs->hw.foreign.tq_rcv.data = (void *) bcs; - - bcs->hw.foreign.tq_xmt.sync = 0; - bcs->hw.foreign.tq_xmt.routine = (void (*)(void *)) &Bchan_xmt_bh; - bcs->hw.foreign.tq_xmt.data = (void *) bcs; -} - -static void -Bchan_manl1(struct PStack *st, int pr, - void *arg) -{ - switch (pr) { - case (PH_ACTIVATE_REQ): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - Bchan_mode(st->l1.bcs, st->l1.mode, st->l1.bc); - st->l1.l1man(st, PH_ACTIVATE_CNF, NULL); - break; - case (PH_DEACTIVATE_REQ): - if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) - Bchan_mode(st->l1.bcs, 0, 0); - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - break; - } -} - -int -setstack_foreign(struct PStack *st, struct BCState *bcs) -{ - if (Bchan_open(bcs)) - return (-1); - st->l1.bcs = bcs; - st->l2.l2l1 = Bchan_l2l1; - st->ma.manl1 = Bchan_manl1; - setstack_manager(st); - bcs->st = st; - return (0); -} - - -static void -foreign_drecv_callback(void *arg, int error, unsigned int count) -{ - struct IsdnCardState *cs = (struct IsdnCardState *) arg; - static struct tq_struct task = {0, 0, (void *) &DChannel_proc_rcv, 0}; - struct sk_buff *skb; - - /* NOTE: This function is called directly from an interrupt handler */ - - if (1) { - if (!(skb = alloc_skb(count, GFP_ATOMIC))) - printk(KERN_WARNING "HiSax: D receive out of memory\n"); - else { - memcpy(skb_put(skb, count), cs->rcvbuf, count); - skb_queue_tail(&cs->rq, skb); - } - - task.data = (void *) cs; - queue_task(&task, &tq_immediate); - mark_bh(IMMEDIATE_BH); - } - - if (cs->debug & L1_DEB_ISAC_FIFO) { - char tmp[128]; - char *t = tmp; - - t += sprintf(t, "foreign Drecv cnt %d", count); - if (error) t += sprintf(t, " ERR %x", error); - QuickHex(t, cs->rcvbuf, count); - debugl1(cs, tmp); - } - - cs->hw.foreign->drecv(0, cs->rcvbuf, MAX_DFRAME_LEN, - &foreign_drecv_callback, cs); -} - -static void -foreign_dxmit_callback(void *arg, int error) -{ - struct IsdnCardState *cs = (struct IsdnCardState *) arg; - static struct tq_struct task = {0, 0, (void *) &DChannel_proc_xmt, 0}; - - /* NOTE: This function is called directly from an interrupt handler */ - - /* may wish to do retransmission here, if error indicates collision */ - - if (cs->debug & L1_DEB_ISAC_FIFO) { - char tmp[128]; - char *t = tmp; - - t += sprintf(t, "foreign Dxmit cnt %d", cs->tx_skb->len); - if (error) t += sprintf(t, " ERR %x", error); - QuickHex(t, cs->tx_skb->data, cs->tx_skb->len); - debugl1(cs, tmp); - } - - cs->tx_skb = NULL; - - task.data = (void *) cs; - queue_task(&task, &tq_immediate); - mark_bh(IMMEDIATE_BH); -} - -static void -foreign_Dchan_l2l1(struct PStack *st, int pr, void *arg) -{ - struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; - struct sk_buff *skb = arg; - char str[64]; - - switch (pr) { - case (PH_DATA_REQ): - if (cs->tx_skb) { - skb_queue_tail(&cs->sq, skb); -#ifdef L2FRAME_DEBUG /* psa */ - if (cs->debug & L1_DEB_LAPD) - Logl2Frame(cs, skb, "PH_DATA Queued", 0); -#endif - } else { - if ((cs->dlogflag) && (!(skb->data[2] & 1))) { - /* I-FRAME */ - LogFrame(cs, skb->data, skb->len); - sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei); - dlogframe(cs, skb->data+4, skb->len-4, - str); - } - cs->tx_skb = skb; - cs->tx_cnt = 0; -#ifdef L2FRAME_DEBUG /* psa */ - if (cs->debug & L1_DEB_LAPD) - Logl2Frame(cs, skb, "PH_DATA", 0); -#endif - cs->hw.foreign->dxmit(0, skb->data, skb->len, - &foreign_dxmit_callback, cs); - } - break; - case (PH_PULL_IND): - if (cs->tx_skb) { - if (cs->debug & L1_DEB_WARN) - debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); - skb_queue_tail(&cs->sq, skb); - break; - } - if ((cs->dlogflag) && (!(skb->data[2] & 1))) { /* I-FRAME */ - LogFrame(cs, skb->data, skb->len); - sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei); - dlogframe(cs, skb->data + 4, skb->len - 4, - str); - } - cs->tx_skb = skb; - cs->tx_cnt = 0; -#ifdef L2FRAME_DEBUG /* psa */ - if (cs->debug & L1_DEB_LAPD) - Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); -#endif - cs->hw.foreign->dxmit(0, cs->tx_skb->data, cs->tx_skb->len, - &foreign_dxmit_callback, cs); - break; - case (PH_PULL_REQ): -#ifdef L2FRAME_DEBUG /* psa */ - if (cs->debug & L1_DEB_LAPD) - debugl1(cs, "-> PH_REQUEST_PULL"); -#endif - if (!cs->tx_skb) { - test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - st->l1.l1l2(st, PH_PULL_CNF, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - break; - } -} - -int -setDstack_foreign(struct PStack *st, struct IsdnCardState *cs) -{ - st->l2.l2l1 = foreign_Dchan_l2l1; - if (! cs->rcvbuf) { - printk("setDstack_foreign: No cs->rcvbuf!\n"); - } else { - cs->hw.foreign->drecv(0, cs->rcvbuf, MAX_DFRAME_LEN, - &foreign_drecv_callback, cs); - } - return (0); -} - -static void -manl1_msg(struct IsdnCardState *cs, int msg, void *arg) { - struct PStack *st; - - st = cs->stlist; - while (st) { - st->ma.manl1(st, msg, arg); - st = st->next; - } -} - -void -foreign_l1cmd(struct IsdnCardState *cs, int msg, void *arg) -{ - u_char val; - char tmp[32]; - - if (cs->debug & L1_DEB_ISAC) { - sprintf(tmp, "foreign_l1cmd msg %x", msg); - debugl1(cs, tmp); - } - - switch(msg) { - case PH_RESET_REQ: - cs->hw.foreign->liu_deactivate(0); - manl1_msg(cs, PH_POWERUP_CNF, NULL); - break; - case PH_ENABLE_REQ: - break; - case PH_INFO3_REQ: - cs->hw.foreign->liu_activate(0,0); - break; - case PH_TESTLOOP_REQ: - break; - default: - if (cs->debug & L1_DEB_WARN) { - sprintf(tmp, "foreign_l1cmd unknown %4x", msg); - debugl1(cs, tmp); - } - break; - } -} - -static void -foreign_new_ph(struct IsdnCardState *cs) -{ - switch (cs->hw.foreign->get_liu_state(0)) { - case 3: - manl1_msg(cs, PH_POWERUP_CNF, NULL); - break; - - case 7: - manl1_msg(cs, PH_I4_P8_IND, NULL); - break; - - case 8: - manl1_msg(cs, PH_RSYNC_IND, NULL); - break; - } -} - -/* LIU state change callback */ - -static void -foreign_liu_callback(struct IsdnCardState *cs) -{ - static struct tq_struct task = {0, 0, (void *) &foreign_new_ph, 0}; - - if (!cs) - return; - - if (cs->debug & L1_DEB_ISAC) { - char tmp[32]; - sprintf(tmp, "foreign LIU state %d", - cs->hw.foreign->get_liu_state(0)); - debugl1(cs, tmp); - } - - task.data = (void *) cs; - queue_task(&task, &tq_immediate); - mark_bh(IMMEDIATE_BH); -} - -static void init_foreign(struct IsdnCardState *cs) -{ - Bchan_init(&cs->bcs[0]); - Bchan_init(&cs->bcs[1]); - cs->bcs[0].BC_SetStack = setstack_foreign; - cs->bcs[1].BC_SetStack = setstack_foreign; - cs->bcs[0].BC_Close = Bchan_close; - cs->bcs[1].BC_Close = Bchan_close; - Bchan_mode(cs->bcs, 0, 0); - Bchan_mode(cs->bcs + 1, 0, 0); -} - -static int -foreign_card_msg(struct IsdnCardState *cs, int mt, void *arg) -{ - switch (mt) { - case CARD_RESET: - return(0); - case CARD_RELEASE: - return(0); - case CARD_SETIRQ: - return(0); - case CARD_INIT: - cs->l1cmd = foreign_l1cmd; - cs->setstack_d = setDstack_foreign; - cs->hw.foreign->liu_init(0, &foreign_liu_callback, - (void *)cs); - init_foreign(cs); - return(0); - case CARD_TEST: - return(0); - } - return(0); -} - -#if CARD_AMD7930 -extern struct foreign_interface amd7930_foreign_interface; -#endif - -#if CARD_DBRI -extern struct foreign_interface dbri_foreign_interface; -#endif - -__initfunc(int -setup_foreign(struct IsdnCard *card)) -{ - struct IsdnCardState *cs = card->cs; - char tmp[64]; - - strcpy(tmp, foreign_revision); - printk(KERN_INFO "HiSax: Foreign chip driver Rev. %s\n", - HiSax_getrev(tmp)); - -#if CARD_AMD7930 - if (cs->typ == ISDN_CTYPE_AMD7930) { - cs->hw.foreign = &amd7930_foreign_interface; - cs->irq = cs->hw.foreign->get_irqnum(0); - if (cs->irq == 0) - return (0); - cs->cardmsg = &foreign_card_msg; - return (1); - } -#endif - -#if CARD_DBRI - if (cs->typ == ISDN_CTYPE_DBRI) { - cs->hw.foreign = &dbri_foreign_interface; - cs->irq = cs->hw.foreign->get_irqnum(0); - if (cs->irq == 0) - return (0); - cs->cardmsg = &foreign_card_msg; - return (1); - } -#endif - - return(0); -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/foreign.h linux.pre11.3/drivers/isdn/hisax/foreign.h --- linux.vanilla/drivers/isdn/hisax/foreign.h Wed Mar 24 10:55:17 1999 +++ linux.pre11.3/drivers/isdn/hisax/foreign.h Mon Jul 19 23:59:33 1999 @@ -1,193 +0,0 @@ -/* $Id: foreign.h,v 1.1 1998/11/09 07:48:57 baccala Exp $ - * - * HiSax ISDN driver - foreign chipset interface - * - * Author Brent Baccala (baccala@FreeSoft.org) - * - * - * - * $Log: foreign.h,v $ - * Revision 1.1 1998/11/09 07:48:57 baccala - * Initial DBRI ISDN code. Sometimes works (brings up the link and you - * can telnet through it), sometimes doesn't (crashes the machine) - * - */ - -/* - * ISDN operations - * - * Many of these routines take an "int dev" argument, which is simply - * an index into the drivers[] array. Currently, we only support a - * single foreign chip, so the value should always be 0. B channel - * operations require an "int chan", which should be 0 for channel B1 - * and 1 for channel B2 - * - * int get_irqnum(int dev) - * - * returns the interrupt number being used by the chip. ISDN4linux - * uses this number to watch the interrupt during initialization and - * make sure something is happening. - * - * int get_liu_state(int dev) - * - * returns the current state of the ISDN Line Interface Unit (LIU) - * as a number between 2 (state F2) and 7 (state F7). 0 may also be - * returned if the chip doesn't exist or the LIU hasn't been - * activated. The meanings of the states are defined in I.430, ISDN - * BRI Physical Layer Interface. The most important two states are - * F3 (shutdown) and F7 (syncronized). - * - * void liu_init(int dev, void (*callback)(void *), void *callback_arg) - * - * initializes the LIU and optionally registers a callback to be - * signaled upon a change of LIU state. The callback will be called - * with a single opaque callback_arg. Once the callback has been - * triggered, get_liu_state can be used to determine the LIU - * current state. - * - * void liu_activate(int dev, int priority) - * - * requests LIU activation at a given D-channel priority. - * Successful activatation is achieved upon entering state F7, which - * will trigger any callback previously registered with - * liu_init. - * - * void liu_deactivate(int dev) - * - * deactivates LIU. Outstanding D and B channel transactions are - * terminated rudely and without callback notification. LIU change - * of state callback will be triggered, however. - * - * void dxmit(int dev, __u8 *buffer, unsigned int count, - * void (*callback)(void *, int), void *callback_arg) - * - * transmits a packet - specified with buffer, count - over the D-channel - * interface. Buffer should begin with the LAPD address field and - * end with the information field. FCS and flag sequences should not - * be included, nor is bit-stuffing required - all these functions are - * performed by the chip. The callback function will be called - * DURING THE TOP HALF OF AN INTERRUPT HANDLER and will be passed - * both the arbitrary callback_arg and an integer error indication: - * - * 0 - successful transmission; ready for next packet - * non-0 - error value - * - * The callback routine should defer any time-consuming operations - * to a bottom-half handler; however, dxmit may be called - * from within the callback to request back-to-back transmission of - * a second packet (without repeating the priority/collision mechanism) - * - * A comment about the "collision detect" error, which is signalled - * whenever the echoed D-channel data didn't match the transmitted - * data. This is part of ISDN's normal multi-drop T-interface - * operation, indicating that another device has attempted simultaneous - * transmission, but can also result from line noise. An immediate - * requeue via dxmit is suggested, but repeated collision - * errors may indicate a more serious problem. - * - * void drecv(int dev, __u8 *buffer, unsigned int size, - * void (*callback)(void *, int, unsigned int), - * void *callback_arg) - * - * register a buffer - buffer, size - into which a D-channel packet - * can be received. The callback function will be called DURING - * THE TOP HALF OF AN INTERRUPT HANDLER and will be passed an - * arbitrary callback_arg, an integer error indication and the length - * of the received packet, which will start with the address field, - * end with the information field, and not contain flag or FCS - * bytes. Bit-stuffing will already have been corrected for. - * Possible values of second callback argument "error": - * - * 0 - successful reception - * non-0 - error value - * - * int bopen(int dev, int chan, int hdlcmode, u_char xmit_idle_char) - * - * This function should be called before any other operations on a B - * channel. mode is either non-0 to (de)encapsulate using HDLC or 0 - * for transparent operation. In addition to arranging for interrupt - * handling and channel multiplexing, it sets the xmit_idle_char - * which is transmitted on the interface when no data buffer is - * available. Suggested values are: 0 for ISDN audio; FF for HDLC - * mark idle; 7E for HDLC flag idle. Returns 0 on a successful - * open; -1 on error. - * - * If the chip doesn't support HDLC encapsulation (the Am7930 - * doesn't), an error will be returned opening L1_MODE_HDLC; the - * HiSax driver should retry with L1_MODE_TRANS, then be prepared to - * bit-stuff the data before shipping it to the driver. - * - * void bclose(int dev, int chan) - * - * Shuts down a B channel when no longer in use. - * - * void bxmit(int dev, int chan, __u8 *buffer, unsigned int count, - * void (*callback)(void *, int), void *callback_arg) - * - * transmits a data block - specified with buffer, count - over the - * B channel interface specified by dev/chan. In mode L1_MODE_HDLC, - * a complete HDLC frames should be relayed with a single bxmit. - * The callback function will be called DURING THE TOP HALF OF AN - * INTERRUPT HANDLER and will be passed the arbitrary callback_arg - * and an integer error indication: - * - * 0 - successful transmission; ready for next packet - * non-0 - error - * - * The callback routine should defer any time-consuming operations - * to a bottom-half handler; however, bxmit may be called - * from within the callback to request back-to-back transmission of - * another data block - * - * void brecv(int dev, int chan, __u8 *buffer, unsigned int size, - * void (*callback)(void *, int, unsigned int), void *callback_arg) - * - * receive a raw data block - specified with buffer, size - over the - * B channel interface specified by dev/chan. The callback function - * will be called DURING THE TOP HALF OF AN INTERRUPT HANDLER and - * will be passed the arbitrary callback_arg, an integer error - * indication and the length of the received packet. In HDLC mode, - * the packet will start with the address field, end with the - * information field, and will not contain flag or FCS bytes. - * Bit-stuffing will already have been corrected for. - * - * Possible values of second callback argument "error": - * - * 0 - successful reception - * non-0 - error value - * - * The callback routine should defer any time-consuming operations - * to a bottom-half handler; however, brecv may be called - * from within the callback to register another buffer and ensure - * continuous B channel reception without loss of data - * */ - -struct foreign_interface { - int (*get_irqnum)(int dev); - int (*get_liu_state)(int dev); - void (*liu_init)(int dev, void (*callback)(void *), void *callback_arg); - void (*liu_activate)(int dev, int priority); - void (*liu_deactivate)(int dev); - void (*dxmit)(int dev, __u8 *buffer, unsigned int count, - void (*callback)(void *, int), - void *callback_arg); - void (*drecv)(int dev, __u8 *buffer, unsigned int size, - void (*callback)(void *, int, unsigned int), - void *callback_arg); - int (*bopen)(int dev, unsigned int chan, - int hdlcmode, u_char xmit_idle_char); - void (*bclose)(int dev, unsigned int chan); - void (*bxmit)(int dev, unsigned int chan, - __u8 *buffer, unsigned long count, - void (*callback)(void *, int), - void *callback_arg); - void (*brecv)(int dev, unsigned int chan, - __u8 *buffer, unsigned long size, - void (*callback)(void *, int, unsigned int), - void *callback_arg); - - struct foreign_interface *next; -}; - -extern struct foreign_interface amd7930_foreign_interface; -extern struct foreign_interface dbri_foreign_interface; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/fsm.c linux.pre11.3/drivers/isdn/hisax/fsm.c --- linux.vanilla/drivers/isdn/hisax/fsm.c Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/hisax/fsm.c Mon Jul 19 23:59:33 1999 @@ -1,4 +1,4 @@ -/* $Id: fsm.c,v 1.7 1997/11/06 17:09:13 keil Exp $ +/* $Id: fsm.c,v 1.10 1998/11/15 23:54:39 keil Exp $ * Author Karsten Keil (keil@temic-ech.spacenet.de) * based on the teles driver from Jan den Ouden @@ -7,6 +7,18 @@ * Fritz Elfert * * $Log: fsm.c,v $ + * Revision 1.10 1998/11/15 23:54:39 keil + * changes from 2.0 + * + * Revision 1.9 1998/03/26 07:10:02 paul + * The jumpmatrix table in struct Fsm was an array of "int". This is not + * large enough for pointers to functions on Linux/Alpha (instant crash + * on "insmod hisax). Now there is a typedef for the pointer to function. + * This also prevents warnings about "incompatible pointer types". + * + * Revision 1.8 1998/03/07 22:56:59 tsbogend + * made HiSax working on Linux/Alpha + * * Revision 1.7 1997/11/06 17:09:13 keil * New 2.1 init code * @@ -41,18 +53,18 @@ { int i; - fsm->jumpmatrix = (int *) - kmalloc(4L * fsm->state_count * fsm->event_count, GFP_KERNEL); - memset(fsm->jumpmatrix, 0, 4L * fsm->state_count * fsm->event_count); + fsm->jumpmatrix = (FSMFNPTR *) + kmalloc(sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL); + memset(fsm->jumpmatrix, 0, sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count); for (i = 0; i < fncount; i++) if ((fnlist[i].state>=fsm->state_count) || (fnlist[i].event>=fsm->event_count)) { - printk(KERN_ERR "FsmNew Error line %d st(%d/%d) ev(%d/%d)\n", - i,fnlist[i].state,fsm->state_count, - fnlist[i].event,fsm->event_count); + printk(KERN_ERR "FsmNew Error line %d st(%ld/%ld) ev(%ld/%ld)\n", + i,(long)fnlist[i].state,(long)fsm->state_count, + (long)fnlist[i].event,(long)fsm->event_count); } else fsm->jumpmatrix[fsm->state_count * fnlist[i].event + - fnlist[i].state] = (int) fnlist[i].routine; + fnlist[i].state] = (FSMFNPTR) fnlist[i].routine; } void @@ -64,31 +76,26 @@ int FsmEvent(struct FsmInst *fi, int event, void *arg) { - void (*r) (struct FsmInst *, int, void *); - char str[80]; + FSMFNPTR r; if ((fi->state>=fi->fsm->state_count) || (event >= fi->fsm->event_count)) { - printk(KERN_ERR "FsmEvent Error st(%d/%d) ev(%d/%d)\n", - fi->state,fi->fsm->state_count,event,fi->fsm->event_count); + printk(KERN_ERR "FsmEvent Error st(%ld/%ld) ev(%d/%ld)\n", + (long)fi->state,(long)fi->fsm->state_count,event,(long)fi->fsm->event_count); return(1); } - r = (void (*)) fi->fsm->jumpmatrix[fi->fsm->state_count * event + fi->state]; + r = fi->fsm->jumpmatrix[fi->fsm->state_count * event + fi->state]; if (r) { - if (fi->debug) { - sprintf(str, "State %s Event %s", + if (fi->debug) + fi->printdebug(fi, "State %s Event %s", fi->fsm->strState[fi->state], fi->fsm->strEvent[event]); - fi->printdebug(fi, str); - } r(fi, event, arg); return (0); } else { - if (fi->debug) { - sprintf(str, "State %s Event %s no routine", + if (fi->debug) + fi->printdebug(fi, "State %s Event %s no routine", fi->fsm->strState[fi->state], fi->fsm->strEvent[event]); - fi->printdebug(fi, str); - } return (!0); } } @@ -96,25 +103,18 @@ void FsmChangeState(struct FsmInst *fi, int newstate) { - char str[80]; - fi->state = newstate; - if (fi->debug) { - sprintf(str, "ChangeState %s", + if (fi->debug) + fi->printdebug(fi, "ChangeState %s", fi->fsm->strState[newstate]); - fi->printdebug(fi, str); - } } static void FsmExpireTimer(struct FsmTimer *ft) { #if FSM_TIMER_DEBUG - if (ft->fi->debug) { - char str[40]; - sprintf(str, "FsmExpireTimer %lx", (long) ft); - ft->fi->printdebug(ft->fi, str); - } + if (ft->fi->debug) + ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft); #endif FsmEvent(ft->fi, ft->event, ft->arg); } @@ -126,11 +126,8 @@ ft->tl.function = (void *) FsmExpireTimer; ft->tl.data = (long) ft; #if FSM_TIMER_DEBUG - if (ft->fi->debug) { - char str[40]; - sprintf(str, "FsmInitTimer %lx", (long) ft); - ft->fi->printdebug(ft->fi, str); - } + if (ft->fi->debug) + ft->fi->printdebug(ft->fi, "FsmInitTimer %lx", (long) ft); #endif init_timer(&ft->tl); } @@ -139,11 +136,8 @@ FsmDelTimer(struct FsmTimer *ft, int where) { #if FSM_TIMER_DEBUG - if (ft->fi->debug) { - char str[40]; - sprintf(str, "FsmDelTimer %lx %d", (long) ft, where); - ft->fi->printdebug(ft->fi, str); - } + if (ft->fi->debug) + ft->fi->printdebug(ft->fi, "FsmDelTimer %lx %d", (long) ft, where); #endif del_timer(&ft->tl); } @@ -154,11 +148,9 @@ { #if FSM_TIMER_DEBUG - if (ft->fi->debug) { - char str[40]; - sprintf(str, "FsmAddTimer %lx %d %d", (long) ft, millisec, where); - ft->fi->printdebug(ft->fi, str); - } + if (ft->fi->debug) + ft->fi->printdebug(ft->fi, "FsmAddTimer %lx %d %d", + (long) ft, millisec, where); #endif if (ft->tl.next || ft->tl.prev) { @@ -180,11 +172,9 @@ { #if FSM_TIMER_DEBUG - if (ft->fi->debug) { - char str[40]; - sprintf(str, "FsmRestartTimer %lx %d %d", (long) ft, millisec, where); - ft->fi->printdebug(ft->fi, str); - } + if (ft->fi->debug) + ft->fi->printdebug(ft->fi, "FsmRestartTimer %lx %d %d", + (long) ft, millisec, where); #endif if (ft->tl.next || ft->tl.prev) @@ -194,25 +184,4 @@ ft->arg = arg; ft->tl.expires = jiffies + (millisec * HZ) / 1000; add_timer(&ft->tl); -} - -void -jiftime(char *s, long mark) -{ - s += 8; - - *s-- = '\0'; - *s-- = mark % 10 + '0'; - mark /= 10; - *s-- = mark % 10 + '0'; - mark /= 10; - *s-- = '.'; - *s-- = mark % 10 + '0'; - mark /= 10; - *s-- = mark % 6 + '0'; - mark /= 6; - *s-- = ':'; - *s-- = mark % 10 + '0'; - mark /= 10; - *s-- = mark % 10 + '0'; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/gazel.c linux.pre11.3/drivers/isdn/hisax/gazel.c --- linux.vanilla/drivers/isdn/hisax/gazel.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/gazel.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,745 @@ +/* $Id: gazel.c,v 2.3 1999/07/12 21:05:09 keil Exp $ + + * gazel.c low level stuff for Gazel isdn cards + * + * Author BeWan Systems + * based on source code from Karsten Keil + * + * $Log: gazel.c,v $ + * Revision 2.3 1999/07/12 21:05:09 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 2.1 1999/07/08 21:26:17 keil + * new card + * + * Revision 1.0 1999/28/06 + * Initial revision + * + */ +#define __NO_VERSION__ +#include "hisax.h" +#include "isac.h" +#include "hscx.h" +#include "isdnl1.h" +#include "ipac.h" +#include +#ifndef COMPAT_HAS_NEW_PCI +#include +#endif + +extern const char *CardType[]; +const char *gazel_revision = "$Revision: 2.3 $"; + +#define R647 1 +#define R685 2 +#define R753 3 +#define R742 4 + +/* Gazel R685 stuff */ +#define GAZEL_MANUFACTURER 0x10b5 +#define GAZEL_R685 0x1030 +#define GAZEL_R753 0x1152 +#define GAZEL_DJINN_ITOO 0x1151 + +#define PLX_CNTRL 0x50 /* registre de controle PLX */ +#define RESET_GAZEL 0x4 +#define RESET_9050 0x40000000 +#define PLX_INCSR 0x4C /* registre d'IT du 9050 */ +#define INT_ISAC_EN 0x8 /* 1 = enable IT isac */ +#define INT_ISAC 0x20 /* 1 = IT isac en cours */ +#define INT_HSCX_EN 0x1 /* 1 = enable IT hscx */ +#define INT_HSCX 0x4 /* 1 = IT hscx en cours */ +#define INT_PCI_EN 0x40 /* 1 = enable IT PCI */ +#define INT_IPAC_EN 0x3 /* enable IT ipac */ + + +#define byteout(addr,val) outb(val,addr) +#define bytein(addr) inb(addr) + +static inline u_char +readreg(unsigned int adr, u_short off) +{ + return bytein(adr + off); +} + +static inline void +writereg(unsigned int adr, u_short off, u_char data) +{ + byteout(adr + off, data); +} + + +static inline void +read_fifo(unsigned int adr, u_char * data, int size) +{ + insb(adr, data, size); +} + +static void +write_fifo(unsigned int adr, u_char * data, int size) +{ + outsb(adr, data, size); +} + +static inline u_char +readreg_ipac(unsigned int adr, u_short off) +{ + register u_char ret; + long flags; + + save_flags(flags); + cli(); + byteout(adr, off); + ret = bytein(adr + 4); + restore_flags(flags); + return ret; +} + +static inline void +writereg_ipac(unsigned int adr, u_short off, u_char data) +{ + long flags; + + save_flags(flags); + cli(); + byteout(adr, off); + byteout(adr + 4, data); + restore_flags(flags); +} + + +static inline void +read_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size) +{ + byteout(adr, off); + insb(adr + 4, data, size); +} + +static void +write_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size) +{ + byteout(adr, off); + outsb(adr + 4, data, size); +} + +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) +{ + u_short off2 = offset; + + switch (cs->subtyp) { + case R647: + off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); + case R685: + return (readreg(cs->hw.gazel.isac, off2)); + case R753: + case R742: + return (readreg_ipac(cs->hw.gazel.ipac, 0x80 + off2)); + } + return 0; +} + +static void +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) +{ + u_short off2 = offset; + + switch (cs->subtyp) { + case R647: + off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); + case R685: + writereg(cs->hw.gazel.isac, off2, value); + break; + case R753: + case R742: + writereg_ipac(cs->hw.gazel.ipac, 0x80 + off2, value); + break; + } +} + +static void +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + switch (cs->subtyp) { + case R647: + case R685: + read_fifo(cs->hw.gazel.isacfifo, data, size); + break; + case R753: + case R742: + read_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size); + break; + } +} + +static void +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + switch (cs->subtyp) { + case R647: + case R685: + write_fifo(cs->hw.gazel.isacfifo, data, size); + break; + case R753: + case R742: + write_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size); + break; + } +} + +static void +ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size) +{ + switch (cs->subtyp) { + case R647: + case R685: + read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size); + break; + case R753: + case R742: + read_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size); + break; + } +} + +static void +WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size) +{ + switch (cs->subtyp) { + case R647: + case R685: + write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size); + break; + case R753: + case R742: + write_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size); + break; + } +} + +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) +{ + u_short off2 = offset; + + switch (cs->subtyp) { + case R647: + off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); + case R685: + return (readreg(cs->hw.gazel.hscx[hscx], off2)); + case R753: + case R742: + return (readreg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2)); + } + return 0; +} + +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) +{ + u_short off2 = offset; + + switch (cs->subtyp) { + case R647: + off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); + case R685: + writereg(cs->hw.gazel.hscx[hscx], off2, value); + break; + case R753: + case R742: + writereg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2, value); + break; + } +} + +/* + * fast interrupt HSCX stuff goes here + */ + +#define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg) +#define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data) +#define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt) + +#include "hscx_irq.c" + +static void +gazel_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ +#define MAXCOUNT 5 + struct IsdnCardState *cs = dev_id; + u_char valisac, valhscx; + int count = 0; + + if (!cs) { + printk(KERN_WARNING "Gazel: Spurious interrupt!\n"); + return; + } + do { + valhscx = ReadHSCX(cs, 1, HSCX_ISTA); + if (valhscx) + hscx_int_main(cs, valhscx); + valisac = ReadISAC(cs, ISAC_ISTA); + if (valisac) + isac_interrupt(cs, valisac); + count++; + } while ((valhscx || valisac) && (count < MAXCOUNT)); + + WriteHSCX(cs, 0, HSCX_MASK, 0xFF); + WriteHSCX(cs, 1, HSCX_MASK, 0xFF); + WriteISAC(cs, ISAC_MASK, 0xFF); + WriteISAC(cs, ISAC_MASK, 0x0); + WriteHSCX(cs, 0, HSCX_MASK, 0x0); + WriteHSCX(cs, 1, HSCX_MASK, 0x0); +} + + +static void +gazel_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char ista, val; + int count = 0; + + if (!cs) { + printk(KERN_WARNING "Gazel: Spurious interrupt!\n"); + return; + } + ista = ReadISAC(cs, IPAC_ISTA - 0x80); + do { + if (ista & 0x0f) { + val = ReadHSCX(cs, 1, HSCX_ISTA); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) { + hscx_int_main(cs, val); + } + } + if (ista & 0x20) { + val = 0xfe & ReadISAC(cs, ISAC_ISTA); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = ReadISAC(cs, IPAC_ISTA - 0x80); + count++; + } + while ((ista & 0x3f) && (count < MAXCOUNT)); + + WriteISAC(cs, IPAC_MASK - 0x80, 0xFF); + WriteISAC(cs, IPAC_MASK - 0x80, 0xC0); +} +void +release_io_gazel(struct IsdnCardState *cs) +{ + unsigned int i; + + switch (cs->subtyp) { + case R647: + for (i = 0x0000; i < 0xC000; i += 0x1000) + release_region(i + cs->hw.gazel.hscx[0], 16); + release_region(0xC000 + cs->hw.gazel.hscx[0], 1); + break; + + case R685: + release_region(cs->hw.gazel.hscx[0], 0x100); + release_region(cs->hw.gazel.cfg_reg, 0x80); + break; + + case R753: + release_region(cs->hw.gazel.ipac, 0x8); + release_region(cs->hw.gazel.cfg_reg, 0x80); + break; + + case R742: + release_region(cs->hw.gazel.ipac, 8); + break; + } +} + +static int +reset_gazel(struct IsdnCardState *cs) +{ + long flags; + unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg; + + switch (cs->subtyp) { + case R647: + save_flags(flags); + cli(); + writereg(addr, 0, 0); + HZDELAY(10); + writereg(addr, 0, 1); + HZDELAY(2); + restore_flags(flags); + break; + case R685: + plxcntrl = inl(addr + PLX_CNTRL); + plxcntrl |= (RESET_9050 + RESET_GAZEL); + outl(plxcntrl, addr + PLX_CNTRL); + plxcntrl &= ~(RESET_9050 + RESET_GAZEL); + HZDELAY(4); + outl(plxcntrl, addr + PLX_CNTRL); + HZDELAY(10); + outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR); + break; + case R753: + plxcntrl = inl(addr + PLX_CNTRL); + plxcntrl |= (RESET_9050 + RESET_GAZEL); + outl(plxcntrl, addr + PLX_CNTRL); + plxcntrl &= ~(RESET_9050 + RESET_GAZEL); + WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20); + HZDELAY(4); + outl(plxcntrl, addr + PLX_CNTRL); + HZDELAY(10); + WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00); + WriteISAC(cs, IPAC_ACFG - 0x80, 0xff); + WriteISAC(cs, IPAC_AOE - 0x80, 0x0); + WriteISAC(cs, IPAC_MASK - 0x80, 0xff); + WriteISAC(cs, IPAC_CONF - 0x80, 0x1); + outb(INT_IPAC_EN + INT_PCI_EN, addr + PLX_INCSR); + WriteISAC(cs, IPAC_MASK - 0x80, 0xc0); + break; + case R742: + WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20); + HZDELAY(4); + WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00); + WriteISAC(cs, IPAC_ACFG - 0x80, 0xff); + WriteISAC(cs, IPAC_AOE - 0x80, 0x0); + WriteISAC(cs, IPAC_MASK - 0x80, 0xff); + WriteISAC(cs, IPAC_CONF - 0x80, 0x1); + WriteISAC(cs, IPAC_MASK - 0x80, 0xc0); + break; + } + return (0); +} + +static int +Gazel_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + switch (mt) { + case CARD_RESET: + reset_gazel(cs); + return (0); + case CARD_RELEASE: + release_io_gazel(cs); + return (0); + case CARD_INIT: + inithscxisac(cs, 1); + if ((cs->subtyp==R647)||(cs->subtyp==R685)) { + int i; + for (i=0;i<(2+MAX_WAITING_CALLS);i++) { + cs->bcs[i].hw.hscx.tsaxr0 = 0x1f; + cs->bcs[i].hw.hscx.tsaxr1 = 0x23; + } + } + return (0); + case CARD_TEST: + return (0); + } + return (0); +} + +static int +reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs) +{ + unsigned int i, base = 0, adr = 0, len = 0; + long flags; + + save_flags(flags); + cli(); + + switch (cs->subtyp) { + case R647: + base = cs->hw.gazel.hscx[0]; + for (i = 0x0000; i < 0xC000; i += 0x1000) { + if (check_region(adr = (i + base), len = 16)) + goto error; + } + if (check_region(adr = (0xC000 + base), len = 1)) + goto error; + + for (i = 0x0000; i < 0xC000; i += 0x1000) + request_region(i + base, 16, "gazel"); + request_region(0xC000 + base, 1, "gazel"); + + break; + + case R685: + if (check_region(adr = cs->hw.gazel.hscx[0], len = 0x100)) + goto error; + if (check_region(adr = cs->hw.gazel.cfg_reg, len = 0x80)) + goto error; + + request_region(cs->hw.gazel.hscx[0], 0x100, "gazel"); + request_region(cs->hw.gazel.cfg_reg, 0x80, "gazel"); + break; + + case R753: + if (check_region(adr = cs->hw.gazel.ipac, len = 0x8)) + goto error; + if (check_region(adr = cs->hw.gazel.cfg_reg, len = 0x80)) + goto error; + + request_region(cs->hw.gazel.ipac, 0x8, "gazel"); + request_region(cs->hw.gazel.cfg_reg, 0x80, "gazel"); + break; + + case R742: + if (check_region(adr = cs->hw.gazel.ipac, len = 0x8)) + goto error; + request_region(cs->hw.gazel.ipac, 0x8, "gazel"); + break; + } + + restore_flags(flags); + return 0; + + error: + restore_flags(flags); + printk(KERN_WARNING "Gazel: %s io ports 0x%x-0x%x already in use\n", + CardType[cs->typ], adr, adr + len); + return 1; +} + +static int +setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs) +{ + printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n"); + // we got an irq parameter, assume it is an ISA card + // R742 decodes address even in not started... + // R647 returns FF if not present or not started + // eventually needs improvment + if (readreg_ipac(card->para[1], IPAC_ID) == 1) + cs->subtyp = R742; + else + cs->subtyp = R647; + + cs->hw.gazel.cfg_reg = card->para[1] + 0xC000; + cs->hw.gazel.ipac = card->para[1]; + cs->hw.gazel.isac = card->para[1] + 0x8000; + cs->hw.gazel.hscx[0] = card->para[1]; + cs->hw.gazel.hscx[1] = card->para[1] + 0x4000; + cs->irq = card->para[0]; + cs->hw.gazel.isacfifo = cs->hw.gazel.isac; + cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0]; + cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1]; + + switch (cs->subtyp) { + case R647: + printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n"); + cs->dc.isac.adf2 = 0x87; + printk(KERN_INFO + "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", + cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); + printk(KERN_INFO + "Gazel: hscx A:0x%X hscx B:0x%X\n", + cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); + + break; + case R742: + printk(KERN_INFO "Gazel: Card ISA R742 found\n"); + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + printk(KERN_INFO + "Gazel: config irq:%d ipac:0x%X\n", + cs->irq, cs->hw.gazel.ipac); + break; + } + + return (0); +} + +#ifdef COMPAT_HAS_NEW_PCI +static struct pci_dev *dev_tel __initdata = NULL; +#else +static int pci_index __initdata = 0; +#endif + +static int +setup_gazelpci(struct IsdnCardState *cs) +{ + u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0; + u_char pci_irq = 0, found; + u_int nbseek, seekcard; + + printk(KERN_WARNING "Gazel: PCI card automatic recognition\n"); + + found = 0; +#ifdef COMPAT_HAS_NEW_PCI + if (!pci_present()) { + printk(KERN_WARNING "Gazel: No PCI bus present\n"); + return 1; + } +#endif + seekcard = GAZEL_R685; + for (nbseek = 0; nbseek < 3; nbseek++) { +#ifdef COMPAT_HAS_NEW_PCI + if ((dev_tel = pci_find_device(GAZEL_MANUFACTURER, seekcard, dev_tel))) { + + pci_irq = dev_tel->irq; + pci_ioaddr0 = dev_tel->base_address[1]; + pci_ioaddr1 = dev_tel->base_address[2]; + found = 1; + } +#else + for (; pci_index < 0xff; pci_index++) { + u_char pci_bus, pci_device_fn; + + if (pcibios_find_device(GAZEL_MANUFACTURER, seekcard, + pci_index, &pci_bus, &pci_device_fn) + != PCIBIOS_SUCCESSFUL) + break; + /* get IRQ */ + pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_INTERRUPT_LINE, &pci_irq); + /* get IO address */ + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_1, &pci_ioaddr0); + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_2, &pci_ioaddr1); + found = 1; + break; + } +#endif /* COMPAT_HAS_NEW_PCI */ + if (found) + break; + else { + switch (seekcard) { + case GAZEL_R685: + seekcard = GAZEL_R753; + break; + case GAZEL_R753: + seekcard = GAZEL_DJINN_ITOO; + break; + } +#ifndef COMPAT_HAS_NEW_PCI + pci_index = 0; +#endif + } + } + if (!found) { + printk(KERN_WARNING "Gazel: No PCI card found\n"); + return (1); + } + if (!pci_irq) { + printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n"); + return 1; + } + cs->hw.gazel.pciaddr[0] = pci_ioaddr0; + cs->hw.gazel.pciaddr[1] = pci_ioaddr1; + + pci_ioaddr1 &= 0xfffe; + cs->hw.gazel.cfg_reg = pci_ioaddr0 & 0xfffe; + cs->hw.gazel.ipac = pci_ioaddr1; + cs->hw.gazel.isac = pci_ioaddr1 + 0x80; + cs->hw.gazel.hscx[0] = pci_ioaddr1; + cs->hw.gazel.hscx[1] = pci_ioaddr1 + 0x40; + cs->hw.gazel.isacfifo = cs->hw.gazel.isac; + cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0]; + cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1]; + cs->irq = pci_irq; + cs->irq_flags |= SA_SHIRQ; + + switch (seekcard) { + case GAZEL_R685: + printk(KERN_INFO "Gazel: Card PCI R685 found\n"); + cs->subtyp = R685; + cs->dc.isac.adf2 = 0x87; + printk(KERN_INFO + "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", + cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); + printk(KERN_INFO + "Gazel: hscx A:0x%X hscx B:0x%X\n", + cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); + break; + case GAZEL_R753: + case GAZEL_DJINN_ITOO: + printk(KERN_INFO "Gazel: Card PCI R753 found\n"); + cs->subtyp = R753; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + printk(KERN_INFO + "Gazel: config irq:%d ipac:0x%X cfg:0x%X\n", + cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg); + break; + } + + return (0); +} + +__initfunc(int + setup_gazel(struct IsdnCard *card)) +{ + struct IsdnCardState *cs = card->cs; + char tmp[64]; + u_char val; + + strcpy(tmp, gazel_revision); + printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp)); + + if (cs->typ != ISDN_CTYPE_GAZEL) + return (0); + + if (card->para[0]) { + if (setup_gazelisa(card, cs)) + return (0); + } else { + +#if CONFIG_PCI + if (setup_gazelpci(cs)) + return (0); +#else + printk(KERN_WARNING "Gazel: Card PCI requested and NO_PCI_BIOS, unable to config\n"); + return (0); +#endif /* CONFIG_PCI */ + } + + if (reserve_regions(card, cs)) { + return (0); + } + if (reset_gazel(cs)) { + printk(KERN_WARNING "Gazel: wrong IRQ\n"); + release_io_gazel(cs); + return (0); + } + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &Gazel_card_msg; + + switch (cs->subtyp) { + case R647: + case R685: + cs->irq_func = &gazel_interrupt; + ISACVersion(cs, "Gazel:"); + if (HscxVersion(cs, "Gazel:")) { + printk(KERN_WARNING + "Gazel: wrong HSCX versions check IO address\n"); + release_io_gazel(cs); + return (0); + } + break; + case R742: + case R753: + cs->irq_func = &gazel_interrupt_ipac; + val = ReadISAC(cs, IPAC_ID - 0x80); + printk(KERN_INFO "Gazel: IPAC version %x\n", val); + break; + } + + return (1); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/hfc_2bds0.c linux.pre11.3/drivers/isdn/hisax/hfc_2bds0.c --- linux.vanilla/drivers/isdn/hisax/hfc_2bds0.c Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/hisax/hfc_2bds0.c Mon Jul 19 23:59:33 1999 @@ -1,4 +1,4 @@ -/* $Id: hfc_2bds0.c,v 1.3 1998/02/12 23:07:22 keil Exp $ +/* $Id: hfc_2bds0.c,v 1.9 1999/07/01 08:11:35 keil Exp $ * * specific routines for CCD's HFC 2BDS0 * @@ -6,6 +6,25 @@ * * * $Log: hfc_2bds0.c,v $ + * Revision 1.9 1999/07/01 08:11:35 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 1.8 1998/11/15 23:54:40 keil + * changes from 2.0 + * + * Revision 1.7 1998/09/30 22:24:45 keil + * Fix missing line in setstack* + * + * Revision 1.6 1998/08/13 23:36:26 keil + * HiSax 3.1 - don't work stable with current LinkLevel + * + * Revision 1.5 1998/06/27 22:52:58 keil + * make 16.3c working with 3.0 + * + * Revision 1.4 1998/05/25 12:57:52 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * * Revision 1.3 1998/02/12 23:07:22 keil * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * @@ -46,11 +65,8 @@ } ret = bytein(cs->hw.hfcD.addr); #if HFC_REG_DEBUG - if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2)) { - char tmp[32]; - sprintf(tmp, "t3c RD %02x %02x", reg, ret); - debugl1(cs, tmp); - } + if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2)) + debugl1(cs, "t3c RD %02x %02x", reg, ret); #endif } else ret = bytein(cs->hw.hfcD.addr | 1); @@ -67,11 +83,8 @@ if (data) byteout(cs->hw.hfcD.addr, value); #if HFC_REG_DEBUG - if (cs->debug & L1_DEB_HSCX_FIFO && (data != HFCD_DATA_NODEB)) { - char tmp[16]; - sprintf(tmp, "t3c W%c %02x %02x", data ? 'D' : 'C', reg, value); - debugl1(cs, tmp); - } + if (cs->debug & L1_DEB_HSCX_FIFO && (data != HFCD_DATA_NODEB)) + debugl1(cs, "t3c W%c %02x %02x", data ? 'D' : 'C', reg, value); #endif } @@ -227,7 +240,6 @@ int chksum; long flags; u_char stat, cip; - char tmp[64]; if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "hfc_empty_fifo"); @@ -255,6 +267,7 @@ } else if (!(skb = dev_alloc_skb(count - 3))) printk(KERN_WARNING "HFC: receive out of memory\n"); else { + SET_SKB_FREE(skb); ptr = skb_put(skb, count - 3); idx = 0; cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel); @@ -272,7 +285,7 @@ sti(); debugl1(cs, "RFIFO BUSY error"); printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel); - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); skb = NULL; } else { cli(); @@ -283,14 +296,12 @@ WaitNoBusy(cs); stat = ReadReg(cs, HFCD_DATA, cip); sti(); - if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "hfc_empty_fifo %d chksum %x stat %x", + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x", bcs->channel, chksum, stat); - debugl1(cs, tmp); - } if (stat) { debugl1(cs, "FIFO CRC error"); - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); skb = NULL; } } @@ -315,14 +326,11 @@ int idx, fcnt; int count; u_char cip; - char tmp[64]; - - if (!bcs->hw.hfc.tx_skb) + if (!bcs->tx_skb) return; - if (bcs->hw.hfc.tx_skb->len <= 0) + if (bcs->tx_skb->len <= 0) return; - save_flags(flags); cli(); SelFiFo(cs, HFCB_SEND | HFCB_CHANNEL(bcs->channel)); @@ -335,12 +343,10 @@ bcs->hw.hfc.f2 = ReadReg(cs, HFCD_DATA, cip); bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_CHANNEL(bcs->channel)); sti(); - if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)", + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)", bcs->channel, bcs->hw.hfc.f1, bcs->hw.hfc.f2, bcs->hw.hfc.send[bcs->hw.hfc.f1]); - debugl1(cs, tmp); - } fcnt = bcs->hw.hfc.f1 - bcs->hw.hfc.f2; if (fcnt < 0) fcnt += 32; @@ -351,13 +357,11 @@ return; } count = GetFreeFifoBytes_B(bcs); - if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "hfc_fill_fifo %d count(%d/%d),%lx", - bcs->channel, bcs->hw.hfc.tx_skb->len, + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfc_fill_fifo %d count(%ld/%d),%lx", + bcs->channel, bcs->tx_skb->len, count, current->state); - debugl1(cs, tmp); - } - if (count < bcs->hw.hfc.tx_skb->len) { + if (count < bcs->tx_skb->len) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc_fill_fifo no fifo mem"); restore_flags(flags); @@ -368,26 +372,26 @@ cli(); WaitForBusy(cs); WaitNoBusy(cs); - WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->hw.hfc.tx_skb->data[idx++]); - while (idx < bcs->hw.hfc.tx_skb->len) { + WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx++]); + while (idx < bcs->tx_skb->len) { cli(); if (!WaitNoBusy(cs)) break; - WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->hw.hfc.tx_skb->data[idx]); + WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx]); sti(); idx++; } - if (idx != bcs->hw.hfc.tx_skb->len) { + if (idx != bcs->tx_skb->len) { sti(); debugl1(cs, "FIFO Send BUSY error"); printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel); } else { - bcs->tx_cnt -= bcs->hw.hfc.tx_skb->len; + bcs->tx_cnt -= bcs->tx_skb->len; if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->hw.hfc.tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hfc.tx_skb->len); - dev_kfree_skb(bcs->hw.hfc.tx_skb); - bcs->hw.hfc.tx_skb = NULL; + (PACKET_NOACK != bcs->tx_skb->pkt_type)) + bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len); + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + bcs->tx_skb = NULL; } WaitForBusy(cs); cli(); @@ -404,15 +408,12 @@ hfc_send_data(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - char tmp[32]; if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { hfc_fill_fifo(bcs); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else { - sprintf(tmp,"send_data %d blocked", bcs->channel); - debugl1(cs, tmp); - } + } else + debugl1(cs,"send_data %d blocked", bcs->channel); } void @@ -424,15 +425,13 @@ u_char f1, f2, cip; int receive, count = 5; struct sk_buff *skb; - char tmp[64]; save_flags(flags); Begin: count--; cli(); if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { - sprintf(tmp,"rec_data %d blocked", bcs->channel); - debugl1(cs, tmp); + debugl1(cs,"rec_data %d blocked", bcs->channel); restore_flags(flags); return; } @@ -445,11 +444,9 @@ f2 = ReadReg(cs, HFCD_DATA, cip); sti(); if (f1 != f2) { - if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "hfc rec %d f1(%d) f2(%d)", + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfc rec %d f1(%d) f2(%d)", bcs->channel, f1, f2); - debugl1(cs, tmp); - } cli(); z1 = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_REC | HFCB_CHANNEL(bcs->channel)); z2 = ReadZReg(cs, HFCB_FIFO | HFCB_Z2 | HFCB_REC | HFCB_CHANNEL(bcs->channel)); @@ -458,11 +455,9 @@ if (rcnt < 0) rcnt += cs->hw.hfcD.bfifosize; rcnt++; - if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "hfc rec %d z1(%x) z2(%x) cnt(%d)", + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)", bcs->channel, z1, z2, rcnt); - debugl1(cs, tmp); - } if ((skb = hfc_empty_fifo(bcs, rcnt))) { cli(); skb_queue_tail(&bcs->rqueue, skb); @@ -490,12 +485,9 @@ { struct IsdnCardState *cs = bcs->cs; - if (cs->debug & L1_DEB_HSCX) { - char tmp[40]; - sprintf(tmp, "HFCD bchannel mode %d bchan %d/%d", + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HFCD bchannel mode %d bchan %d/%d", mode, bc, bcs->channel); - debugl1(cs, tmp); - } bcs->mode = mode; bcs->channel = bc; switch (mode) { @@ -543,122 +535,99 @@ long flags; switch (pr) { - case (PH_DATA_REQ): + case (PH_DATA | REQUEST): save_flags(flags); cli(); - if (st->l1.bcs->hw.hfc.tx_skb) { + if (st->l1.bcs->tx_skb) { skb_queue_tail(&st->l1.bcs->squeue, skb); restore_flags(flags); } else { - st->l1.bcs->hw.hfc.tx_skb = skb; + st->l1.bcs->tx_skb = skb; /* test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); */ st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); restore_flags(flags); } break; - case (PH_PULL_IND): - if (st->l1.bcs->hw.hfc.tx_skb) { + case (PH_PULL | INDICATION): + if (st->l1.bcs->tx_skb) { printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); break; } save_flags(flags); cli(); /* test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); -*/ st->l1.bcs->hw.hfc.tx_skb = skb; +*/ st->l1.bcs->tx_skb = skb; st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); restore_flags(flags); break; - case (PH_PULL_REQ): - if (!st->l1.bcs->hw.hfc.tx_skb) { + case (PH_PULL | REQUEST): + if (!st->l1.bcs->tx_skb) { test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - st->l1.l1l2(st, PH_PULL_CNF, NULL); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); } else test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; + case (PH_ACTIVATE | REQUEST): + test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + mode_2bs0(st->l1.bcs, st->l1.mode, st->l1.bc); + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | REQUEST): + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | CONFIRM): + test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + mode_2bs0(st->l1.bcs, 0, st->l1.bc); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); + break; } } void close_2bs0(struct BCState *bcs) { - struct sk_buff *skb; - - mode_2bs0(bcs, 0, 0); + mode_2bs0(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - while ((skb = skb_dequeue(&bcs->rqueue))) { - dev_kfree_skb(skb); - } - while ((skb = skb_dequeue(&bcs->squeue))) { - dev_kfree_skb(skb); - } - if (bcs->hw.hfc.tx_skb) { - dev_kfree_skb(bcs->hw.hfc.tx_skb); - bcs->hw.hfc.tx_skb = NULL; + discard_queue(&bcs->rqueue); + discard_queue(&bcs->squeue); + if (bcs->tx_skb) { + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } } } static int -open_hfcstate(struct IsdnCardState *cs, - int bc) +open_hfcstate(struct IsdnCardState *cs, struct BCState *bcs) { - struct BCState *bcs = cs->bcs + bc; - if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { skb_queue_head_init(&bcs->rqueue); skb_queue_head_init(&bcs->squeue); } - bcs->hw.hfc.tx_skb = NULL; + bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); bcs->event = 0; bcs->tx_cnt = 0; return (0); } -static void -hfc_manl1(struct PStack *st, int pr, - void *arg) -{ - switch (pr) { - case (PH_ACTIVATE_REQ): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - mode_2bs0(st->l1.bcs, st->l1.mode, st->l1.bc); - st->l1.l1man(st, PH_ACTIVATE_CNF, NULL); - break; - case (PH_DEACTIVATE_REQ): - if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) - mode_2bs0(st->l1.bcs, 0, 0); - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - break; - } -} - int setstack_2b(struct PStack *st, struct BCState *bcs) { - if (open_hfcstate(st->l1.hardware, bcs->channel)) + bcs->channel = st->l1.bc; + if (open_hfcstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; st->l2.l2l1 = hfc_l2l1; - st->ma.manl1 = hfc_manl1; setstack_manager(st); bcs->st = st; + setstack_l1_B(st); return (0); } static void -manl1_msg(struct IsdnCardState *cs, int msg, void *arg) { - struct PStack *st; - - st = cs->stlist; - while (st) { - st->ma.manl1(st, msg, arg); - st = st->next; - } -} - -static void hfcd_bh(struct IsdnCardState *cs) { /* struct PStack *stptr; @@ -671,27 +640,27 @@ debugl1(cs, "D-Channel Busy cleared"); stptr = cs->stlist; while (stptr != NULL) { - stptr->l1.l1l2(stptr, PH_PAUSE_CNF, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); stptr = stptr->next; } } #endif if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { - switch (cs->ph_state) { + switch (cs->dc.hfcd.ph_state) { case (0): - manl1_msg(cs, PH_RESET_IND, NULL); + l1_msg(cs, HW_RESET | INDICATION, NULL); break; case (3): - manl1_msg(cs, PH_DEACT_IND, NULL); + l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL); break; case (8): - manl1_msg(cs, PH_RSYNC_IND, NULL); + l1_msg(cs, HW_RSYNC | INDICATION, NULL); break; case (6): - manl1_msg(cs, PH_INFO2_IND, NULL); + l1_msg(cs, HW_INFO2 | INDICATION, NULL); break; case (7): - manl1_msg(cs, PH_I4_P8_IND, NULL); + l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); break; default: break; @@ -722,7 +691,6 @@ int chksum; int count=5; u_char *ptr; - char tmp[64]; save_flags(flags); cli(); @@ -745,11 +713,9 @@ if (rcnt < 0) rcnt += cs->hw.hfcD.dfifosize; rcnt++; - if (cs->debug & L1_DEB_ISAC) { - sprintf(tmp, "hfcd recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)", + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "hfcd recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)", f1, f2, z1, z2, rcnt); - debugl1(cs, tmp); - } sti(); idx = 0; cip = HFCD_FIFO | HFCD_FIFO_OUT | HFCD_REC; @@ -771,6 +737,7 @@ while ((idx++ < rcnt) && WaitNoBusy(cs)) ReadReg(cs, HFCD_DATA_NODEB, cip); } else if ((skb = dev_alloc_skb(rcnt - 3))) { + SET_SKB_FREE(skb); ptr = skb_put(skb, rcnt - 3); while (idx < (rcnt - 3)) { cli(); @@ -785,7 +752,7 @@ sti(); debugl1(cs, "RFIFO D BUSY error"); printk(KERN_WARNING "HFC DFIFO channel BUSY Error\n"); - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); skb = NULL; } else { cli(); @@ -796,14 +763,12 @@ WaitNoBusy(cs); stat = ReadReg(cs, HFCD_DATA, cip); sti(); - if (cs->debug & L1_DEB_ISAC) { - sprintf(tmp, "empty_dfifo chksum %x stat %x", + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "empty_dfifo chksum %x stat %x", chksum, stat); - debugl1(cs, tmp); - } if (stat) { debugl1(cs, "FIFO CRC error"); - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); skb = NULL; } else { skb_queue_tail(&cs->rq, skb); @@ -837,7 +802,6 @@ int idx, fcnt; int count; u_char cip; - char tmp[64]; if (!cs->tx_skb) return; @@ -855,12 +819,10 @@ cs->hw.hfcD.f2 = ReadReg(cs, HFCD_DATA, cip) & 0xf; cs->hw.hfcD.send[cs->hw.hfcD.f1] = ReadZReg(cs, HFCD_FIFO | HFCD_Z1 | HFCD_SEND); sti(); - if (cs->debug & L1_DEB_ISAC) { - sprintf(tmp, "hfc_fill_Dfifo f1(%d) f2(%d) z1(%x)", + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "hfc_fill_Dfifo f1(%d) f2(%d) z1(%x)", cs->hw.hfcD.f1, cs->hw.hfcD.f2, cs->hw.hfcD.send[cs->hw.hfcD.f1]); - debugl1(cs, tmp); - } fcnt = cs->hw.hfcD.f1 - cs->hw.hfcD.f2; if (fcnt < 0) fcnt += 16; @@ -871,11 +833,9 @@ return; } count = GetFreeFifoBytes_D(cs); - if (cs->debug & L1_DEB_ISAC) { - sprintf(tmp, "hfc_fill_Dfifo count(%d/%d)", + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "hfc_fill_Dfifo count(%ld/%d)", cs->tx_skb->len, count); - debugl1(cs, tmp); - } if (count < cs->tx_skb->len) { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfc_fill_Dfifo no fifo mem"); @@ -905,7 +865,7 @@ cli(); WaitNoBusy(cs); ReadReg(cs, HFCD_DATA, HFCD_FIFO | HFCD_F1_INC | HFCD_SEND); - dev_kfree_skb(cs->tx_skb); + idev_kfree_skb(cs->tx_skb, FREE_WRITE); cs->tx_skb = NULL; sti(); WaitForBusy(cs); @@ -929,25 +889,20 @@ { u_char exval; struct BCState *bcs; - char tmp[32]; int count=15; long flags; - if (cs->debug & L1_DEB_ISAC) { - sprintf(tmp, "HFCD irq %x %s", val, + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "HFCD irq %x %s", val, test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ? "locked" : "unlocked"); - debugl1(cs, tmp); - } val &= cs->hw.hfcD.int_m1; if (val & 0x40) { /* TE state machine irq */ exval = cs->readisac(cs, HFCD_STATES) & 0xf; - if (cs->debug & L1_DEB_ISAC) { - sprintf(tmp, "ph_state chg %d->%d", cs->ph_state, + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcd.ph_state, exval); - debugl1(cs, tmp); - } - cs->ph_state = exval; + cs->dc.hfcd.ph_state = exval; sched_event_D(cs, D_L1STATECHANGE); val &= ~0x40; } @@ -983,23 +938,19 @@ if (cs->debug) debugl1(cs, "hfcd spurious 0x01 IRQ"); } else { - if (bcs->hw.hfc.tx_skb) { + if (bcs->tx_skb) { if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { hfc_fill_fifo(bcs); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else { - sprintf(tmp,"fill_data %d blocked", bcs->channel); - debugl1(cs, tmp); - } + } else + debugl1(cs,"fill_data %d blocked", bcs->channel); } else { - if ((bcs->hw.hfc.tx_skb = skb_dequeue(&bcs->squeue))) { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { hfc_fill_fifo(bcs); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else { - sprintf(tmp,"fill_data %d blocked", bcs->channel); - debugl1(cs, tmp); - } + } else + debugl1(cs,"fill_data %d blocked", bcs->channel); } else { hfc_sched_event(bcs, B_XMTBUFREADY); } @@ -1011,23 +962,19 @@ if (cs->debug) debugl1(cs, "hfcd spurious 0x02 IRQ"); } else { - if (bcs->hw.hfc.tx_skb) { + if (bcs->tx_skb) { if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { hfc_fill_fifo(bcs); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else { - sprintf(tmp,"fill_data %d blocked", bcs->channel); - debugl1(cs, tmp); - } + } else + debugl1(cs,"fill_data %d blocked", bcs->channel); } else { - if ((bcs->hw.hfc.tx_skb = skb_dequeue(&bcs->squeue))) { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { hfc_fill_fifo(bcs); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - } else { - sprintf(tmp,"fill_data %d blocked", bcs->channel); - debugl1(cs, tmp); - } + } else + debugl1(cs,"fill_data %d blocked", bcs->channel); } else { hfc_sched_event(bcs, B_XMTBUFREADY); } @@ -1052,7 +999,7 @@ } goto afterXPR; } else { - dev_kfree_skb(cs->tx_skb); + idev_kfree_skb(cs->tx_skb, FREE_WRITE); cs->tx_cnt = 0; cs->tx_skb = NULL; } @@ -1072,10 +1019,8 @@ if (cs->hw.hfcD.int_s1 && count--) { val = cs->hw.hfcD.int_s1; cs->hw.hfcD.int_s1 = 0; - if (cs->debug & L1_DEB_ISAC) { - sprintf(tmp, "HFCD irq %x loop %d", val, 15-count); - debugl1(cs, tmp); - } + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "HFCD irq %x loop %d", val, 15-count); } else val = 0; restore_flags(flags); @@ -1083,13 +1028,17 @@ } static void -HFCD_l2l1(struct PStack *st, int pr, void *arg) +HFCD_l1hw(struct PStack *st, int pr, void *arg) { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; - char str[64]; + switch (pr) { - case (PH_DATA_REQ): + case (PH_DATA | REQUEST): + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); if (cs->tx_skb) { skb_queue_tail(&cs->sq, skb); #ifdef L2FRAME_DEBUG /* psa */ @@ -1097,12 +1046,6 @@ Logl2Frame(cs, skb, "PH_DATA Queued", 0); #endif } else { - if ((cs->dlogflag) && (!(skb->data[2] & 1))) { /* I-FRAME */ - LogFrame(cs, skb->data, skb->len); - sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei); - dlogframe(cs, skb->data + 4, skb->len - 4, - str); - } cs->tx_skb = skb; cs->tx_cnt = 0; #ifdef L2FRAME_DEBUG /* psa */ @@ -1117,19 +1060,17 @@ } break; - case (PH_PULL_IND): + case (PH_PULL | INDICATION): if (cs->tx_skb) { if (cs->debug & L1_DEB_WARN) debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); skb_queue_tail(&cs->sq, skb); break; } - if ((cs->dlogflag) && (!(skb->data[2] & 1))) { /* I-FRAME */ + if (cs->debug & DEB_DLOG_HEX) LogFrame(cs, skb->data, skb->len); - sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei); - dlogframe(cs, skb->data + 4, skb->len - 4, - str); - } + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); cs->tx_skb = skb; cs->tx_cnt = 0; #ifdef L2FRAME_DEBUG /* psa */ @@ -1142,47 +1083,39 @@ } else debugl1(cs, "hfc_fill_dfifo blocked"); break; - case (PH_PULL_REQ): + case (PH_PULL | REQUEST): #ifdef L2FRAME_DEBUG /* psa */ if (cs->debug & L1_DEB_LAPD) debugl1(cs, "-> PH_REQUEST_PULL"); #endif if (!cs->tx_skb) { test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - st->l1.l1l2(st, PH_PULL_CNF, NULL); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); } else test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; - } -} - -void -hfcd_l1cmd(struct IsdnCardState *cs, int msg, void *arg) -{ - char tmp[32]; - switch(msg) { - case PH_RESET_REQ: + case (HW_RESET | REQUEST): cs->writeisac(cs, HFCD_STATES, HFCD_LOAD_STATE | 3); /* HFC ST 3 */ udelay(6); cs->writeisac(cs, HFCD_STATES, 3); /* HFC ST 2 */ cs->hw.hfcD.mst_m |= HFCD_MASTER; cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION); - manl1_msg(cs, PH_POWERUP_CNF, NULL); + l1_msg(cs, HW_POWERUP | CONFIRM, NULL); break; - case PH_ENABLE_REQ: + case (HW_ENABLE | REQUEST): cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION); break; - case PH_DEACT_ACK: + case (HW_DEACTIVATE | REQUEST): cs->hw.hfcD.mst_m &= ~HFCD_MASTER; cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); break; - case PH_INFO3_REQ: + case (HW_INFO3 | REQUEST): cs->hw.hfcD.mst_m |= HFCD_MASTER; cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); break; #if 0 - case PH_TESTLOOP_REQ: + case (HW_TESTLOOP | REQUEST): u_char val = 0; if (1 & (int) arg) val |= 0x0c; @@ -1208,10 +1141,8 @@ break; #endif default: - if (cs->debug & L1_DEB_WARN) { - sprintf(tmp, "hfcd_l1cmd unknown %4x", msg); - debugl1(cs, tmp); - } + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "hfcd_l1hw unknown pr %4x", pr); break; } } @@ -1219,7 +1150,7 @@ void setstack_hfcd(struct PStack *st, struct IsdnCardState *cs) { - st->l2.l2l1 = HFCD_l2l1; + st->l1.l1hw = HFCD_l1hw; } static void @@ -1234,7 +1165,7 @@ stptr = cs->stlist; while (stptr != NULL) { - stptr->l1.l1l2(stptr, PH_PAUSE_IND, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); stptr = stptr->next; } } @@ -1260,7 +1191,6 @@ init2bds0(struct IsdnCardState *cs)) { cs->setstack_d = setstack_hfcd; - cs->l1cmd = hfcd_l1cmd; cs->dbusytimer.function = (void *) hfc_dbusy_timer; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/hfc_2bs0.c linux.pre11.3/drivers/isdn/hisax/hfc_2bs0.c --- linux.vanilla/drivers/isdn/hisax/hfc_2bs0.c Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/hisax/hfc_2bs0.c Mon Jul 19 23:59:33 1999 @@ -1,11 +1,27 @@ -/* $Id: hfc_2bs0.c,v 1.4 1998/02/12 23:07:29 keil Exp $ +/* $Id: hfc_2bs0.c,v 1.9 1999/07/01 08:11:36 keil Exp $ * specific routines for CCD's HFC 2BS0 * - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) * * * $Log: hfc_2bs0.c,v $ + * Revision 1.9 1999/07/01 08:11:36 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 1.8 1998/11/15 23:54:43 keil + * changes from 2.0 + * + * Revision 1.7 1998/09/30 22:24:46 keil + * Fix missing line in setstack* + * + * Revision 1.6 1998/08/13 23:36:28 keil + * HiSax 3.1 - don't work stable with current LinkLevel + * + * Revision 1.5 1998/05/25 12:57:54 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * * Revision 1.4 1998/02/12 23:07:29 keil * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * @@ -109,7 +125,6 @@ int idx, cnt; int rcnt, z1, z2; u_char cip, f1, f2; - char tmp[64]; if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "hfc_clear_fifo"); @@ -129,21 +144,17 @@ z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel)); cnt = 32; while (((f1 != f2) || (z1 != z2)) && cnt--) { - if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "hfc clear %d f1(%d) f2(%d)", + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfc clear %d f1(%d) f2(%d)", bcs->channel, f1, f2); - debugl1(cs, tmp); - } rcnt = z1 - z2; if (rcnt < 0) rcnt += cs->hw.hfc.fifosize; if (rcnt) rcnt++; - if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "hfc clear %d z1(%x) z2(%x) cnt(%d)", + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfc clear %d z1(%x) z2(%x) cnt(%d)", bcs->channel, z1, z2, rcnt); - debugl1(cs, tmp); - } cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel); idx = 0; while ((idx < rcnt) && WaitNoBusy(cs)) { @@ -180,7 +191,6 @@ int idx; int chksum; u_char stat, cip; - char tmp[64]; if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "hfc_empty_fifo"); @@ -212,6 +222,7 @@ if (!(skb = dev_alloc_skb(count - 3))) printk(KERN_WARNING "HFC: receive out of memory\n"); else { + SET_SKB_FREE(skb); ptr = skb_put(skb, count - 3); idx = 0; cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel); @@ -222,7 +233,7 @@ if (idx != count - 3) { debugl1(cs, "RFIFO BUSY error"); printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel); - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); WaitNoBusy(cs); stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | HFC_CHANNEL(bcs->channel)); @@ -235,14 +246,12 @@ chksum += cs->BC_Read_Reg(cs, HFC_DATA, cip); WaitNoBusy(cs); stat = cs->BC_Read_Reg(cs, HFC_DATA, cip); - if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "hfc_empty_fifo %d chksum %x stat %x", + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x", bcs->channel, chksum, stat); - debugl1(cs, tmp); - } if (stat) { debugl1(cs, "FIFO CRC error"); - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); skb = NULL; } WaitNoBusy(cs); @@ -261,11 +270,10 @@ int idx, fcnt; int count; u_char cip; - char tmp[64]; - if (!bcs->hw.hfc.tx_skb) + if (!bcs->tx_skb) return; - if (bcs->hw.hfc.tx_skb->len <= 0) + if (bcs->tx_skb->len <= 0) return; save_flags(flags); @@ -281,12 +289,10 @@ WaitNoBusy(cs); bcs->hw.hfc.f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip); bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(bcs, HFC_Z1 | HFC_SEND | HFC_CHANNEL(bcs->channel)); - if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)", + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)", bcs->channel, bcs->hw.hfc.f1, bcs->hw.hfc.f2, bcs->hw.hfc.send[bcs->hw.hfc.f1]); - debugl1(cs, tmp); - } fcnt = bcs->hw.hfc.f1 - bcs->hw.hfc.f2; if (fcnt < 0) fcnt += 32; @@ -297,13 +303,11 @@ return; } count = GetFreeFifoBytes(bcs); - if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "hfc_fill_fifo %d count(%d/%d)", - bcs->channel, bcs->hw.hfc.tx_skb->len, + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfc_fill_fifo %d count(%ld/%d)", + bcs->channel, bcs->tx_skb->len, count); - debugl1(cs, tmp); - } - if (count < bcs->hw.hfc.tx_skb->len) { + if (count < bcs->tx_skb->len) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc_fill_fifo no fifo mem"); restore_flags(flags); @@ -311,18 +315,18 @@ } cip = HFC_CIP | HFC_FIFO_IN | HFC_SEND | HFC_CHANNEL(bcs->channel); idx = 0; - while ((idx < bcs->hw.hfc.tx_skb->len) && WaitNoBusy(cs)) - cs->BC_Write_Reg(cs, HFC_DATA_NODEB, cip, bcs->hw.hfc.tx_skb->data[idx++]); - if (idx != bcs->hw.hfc.tx_skb->len) { + while ((idx < bcs->tx_skb->len) && WaitNoBusy(cs)) + cs->BC_Write_Reg(cs, HFC_DATA_NODEB, cip, bcs->tx_skb->data[idx++]); + if (idx != bcs->tx_skb->len) { debugl1(cs, "FIFO Send BUSY error"); printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel); } else { - count = bcs->hw.hfc.tx_skb->len; + count = bcs->tx_skb->len; bcs->tx_cnt -= count; - if (PACKET_NOACK == bcs->hw.hfc.tx_skb->pkt_type) + if (PACKET_NOACK == bcs->tx_skb->pkt_type) count = -1; - dev_kfree_skb(bcs->hw.hfc.tx_skb); - bcs->hw.hfc.tx_skb = NULL; + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + bcs->tx_skb = NULL; WaitForBusy(cs); WaitNoBusy(cs); cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F1_INC | HFC_SEND | HFC_CHANNEL(bcs->channel)); @@ -343,7 +347,6 @@ u_char f1, f2, cip; int receive, transmit, count = 5; struct sk_buff *skb; - char tmp[64]; save_flags(flags); Begin: @@ -360,11 +363,9 @@ WaitNoBusy(cs); f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip); if (f1 != f2) { - if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "hfc rec %d f1(%d) f2(%d)", + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfc rec %d f1(%d) f2(%d)", bcs->channel, f1, f2); - debugl1(cs, tmp); - } WaitForBusy(cs); z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel)); z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel)); @@ -372,11 +373,9 @@ if (rcnt < 0) rcnt += cs->hw.hfc.fifosize; rcnt++; - if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "hfc rec %d z1(%x) z2(%x) cnt(%d)", + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)", bcs->channel, z1, z2, rcnt); - debugl1(cs, tmp); - } /* sti(); */ if ((skb = hfc_empty_fifo(bcs, rcnt))) { skb_queue_tail(&bcs->rqueue, skb); @@ -388,14 +387,14 @@ restore_flags(flags); udelay(1); cli(); - if (bcs->hw.hfc.tx_skb) { + if (bcs->tx_skb) { transmit = 1; test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); hfc_fill_fifo(bcs); if (test_bit(BC_FLG_BUSY, &bcs->Flag)) transmit = 0; } else { - if ((bcs->hw.hfc.tx_skb = skb_dequeue(&bcs->squeue))) { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { transmit = 1; test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); hfc_fill_fifo(bcs); @@ -417,13 +416,11 @@ { struct IsdnCardState *cs = bcs->cs; - if (cs->debug & L1_DEB_HSCX) { - char tmp[40]; - sprintf(tmp, "HFC 2BS0 mode %d bchan %d/%d", + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HFC 2BS0 mode %d bchan %d/%d", mode, bc, bcs->channel); - debugl1(cs, tmp); - } bcs->mode = mode; + bcs->channel = bc; switch (mode) { case (L1_MODE_NULL): @@ -468,57 +465,66 @@ long flags; switch (pr) { - case (PH_DATA_REQ): + case (PH_DATA | REQUEST): save_flags(flags); cli(); - if (st->l1.bcs->hw.hfc.tx_skb) { + if (st->l1.bcs->tx_skb) { skb_queue_tail(&st->l1.bcs->squeue, skb); restore_flags(flags); } else { - st->l1.bcs->hw.hfc.tx_skb = skb; + st->l1.bcs->tx_skb = skb; test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); restore_flags(flags); } break; - case (PH_PULL_IND): - if (st->l1.bcs->hw.hfc.tx_skb) { + case (PH_PULL | INDICATION): + if (st->l1.bcs->tx_skb) { printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); break; } save_flags(flags); cli(); test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - st->l1.bcs->hw.hfc.tx_skb = skb; + st->l1.bcs->tx_skb = skb; st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); restore_flags(flags); break; - case (PH_PULL_REQ): - if (!st->l1.bcs->hw.hfc.tx_skb) { + case (PH_PULL | REQUEST): + if (!st->l1.bcs->tx_skb) { test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - st->l1.l1l2(st, PH_PULL_CNF, NULL); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); } else test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; + case (PH_ACTIVATE | REQUEST): + test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + mode_hfc(st->l1.bcs, st->l1.mode, st->l1.bc); + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | REQUEST): + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | CONFIRM): + test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + mode_hfc(st->l1.bcs, 0, st->l1.bc); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); + break; } } + void close_hfcstate(struct BCState *bcs) { - struct sk_buff *skb; - - mode_hfc(bcs, 0, 0); + mode_hfc(bcs, 0, bcs->channel); if (test_bit(BC_FLG_INIT, &bcs->Flag)) { - while ((skb = skb_dequeue(&bcs->rqueue))) { - dev_kfree_skb(skb); - } - while ((skb = skb_dequeue(&bcs->squeue))) { - dev_kfree_skb(skb); - } - if (bcs->hw.hfc.tx_skb) { - dev_kfree_skb(bcs->hw.hfc.tx_skb); - bcs->hw.hfc.tx_skb = NULL; + discard_queue(&bcs->rqueue); + discard_queue(&bcs->squeue); + if (bcs->tx_skb) { + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } } @@ -526,50 +532,30 @@ } static int -open_hfcstate(struct IsdnCardState *cs, - int bc) +open_hfcstate(struct IsdnCardState *cs, struct BCState *bcs) { - struct BCState *bcs = cs->bcs + bc; - if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { skb_queue_head_init(&bcs->rqueue); skb_queue_head_init(&bcs->squeue); } - bcs->hw.hfc.tx_skb = NULL; + bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); bcs->event = 0; bcs->tx_cnt = 0; return (0); } -static void -hfc_manl1(struct PStack *st, int pr, - void *arg) -{ - switch (pr) { - case (PH_ACTIVATE_REQ): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - mode_hfc(st->l1.bcs, st->l1.mode, st->l1.bc); - st->l1.l1man(st, PH_ACTIVATE_CNF, NULL); - break; - case (PH_DEACTIVATE_REQ): - if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) - mode_hfc(st->l1.bcs, 0, 0); - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - break; - } -} - int setstack_hfc(struct PStack *st, struct BCState *bcs) { - if (open_hfcstate(st->l1.hardware, bcs->channel)) + bcs->channel = st->l1.bc; + if (open_hfcstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; st->l2.l2l1 = hfc_l2l1; - st->ma.manl1 = hfc_manl1; setstack_manager(st); bcs->st = st; + setstack_l1_B(st); return (0); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/hfc_pci.c linux.pre11.3/drivers/isdn/hisax/hfc_pci.c --- linux.vanilla/drivers/isdn/hisax/hfc_pci.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/hfc_pci.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,1498 @@ +/* $Id: hfc_pci.c,v 1.7 1999/07/14 21:24:20 werner Exp $ + + * hfc_pci.c low level driver for CCD´s hfc-pci based cards + * + * Author Werner Cornelius (werner@isdn4linux.de) + * based on existing driver for CCD hfc ISA cards + * + * Copyright 1999 by Werner Cornelius (werner@isdn4linux.de) + * Copyright 1999 by Karsten Keil (keil@isdn4linux.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, 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. + * + * $Log: hfc_pci.c,v $ + * Revision 1.7 1999/07/14 21:24:20 werner + * fixed memcpy problem when using E-channel feature + * + * Revision 1.6 1999/07/13 21:08:08 werner + * added echo channel logging feature. + * + * Revision 1.5 1999/07/12 21:05:10 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 1.4 1999/07/04 21:51:39 werner + * Changes to solve problems with irq sharing and smp machines + * Thanks to Karsten Keil and Alex Holden for giving aid with + * testing and debugging + * + * Revision 1.3 1999/07/01 09:43:19 keil + * removed additional schedules in timeouts + * + * Revision 1.2 1999/07/01 08:07:51 keil + * Initial version + * + * + * + */ + +#define __NO_VERSION__ +#include "hisax.h" +#include "hfc_pci.h" +#include "isdnl1.h" +#include +#ifndef COMPAT_HAS_NEW_PCI +#include +#endif +#include + +extern const char *CardType[]; + +static const char *hfcpci_revision = "$Revision: 1.7 $"; + +#if CONFIG_PCI +/*****************************/ +/* release D- and B-channels */ +/*****************************/ +void +releasehfcpci(struct IsdnCardState *cs) +{ + if (cs->bcs[0].hw.hfc.send) { + kfree(cs->bcs[0].hw.hfc.send); + cs->bcs[0].hw.hfc.send = NULL; + } + if (cs->bcs[1].hw.hfc.send) { + kfree(cs->bcs[1].hw.hfc.send); + cs->bcs[1].hw.hfc.send = NULL; + } +} + +/******************************************/ +/* free hardware resources used by driver */ +/******************************************/ +void +release_io_hfcpci(struct IsdnCardState *cs) +{ +#if CONFIG_PCI + pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, 0); /* disabe memory mapped ports + busmaster */ +#endif /* CONFIG_PCI */ + releasehfcpci(cs); + del_timer(&cs->hw.hfcpci.timer); + kfree(cs->hw.hfcpci.share_start); + cs->hw.hfcpci.share_start = NULL; + vfree(cs->hw.hfcpci.pci_io); +} + +/********************************************************************************/ +/* function called to reset the HFC PCI chip. A complete software reset of chip */ +/* and fifos is done. */ +/********************************************************************************/ +static void +reset_hfcpci(struct IsdnCardState *cs) +{ + long flags; + + 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 */ + 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 */ + save_flags(flags); + sti(); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ + Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */ + if (Read_hfc(cs, HFCPCI_STATUS) & 2) + printk(KERN_WARNING "HFC-PCI init bit busy\n"); + + cs->hw.hfcpci.fifo_en = 0x30; /* only D fifos enabled */ + Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); + + cs->hw.hfcpci.trm = 0; /* no echo connect */ + Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm); + + Write_hfc(cs, HFCPCI_CLKDEL, 0x0e); /* ST-Bit delay for TE-Mode */ + cs->hw.hfcpci.sctrl_e = HFCPCI_AUTO_AWAKE; + Write_hfc(cs, HFCPCI_SCTRL_E, cs->hw.hfcpci.sctrl_e); /* S/T Auto awake */ + cs->hw.hfcpci.bswapped = 0; /* no exchange */ + cs->hw.hfcpci.ctmt = HFCPCI_TIM3_125 | HFCPCI_AUTO_TIMER; + Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt); + + cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE; + cs->hw.hfcpci.int_m1 = HFCPCI_INTS_DTRANS | HFCPCI_INTS_DREC | + HFCPCI_INTS_L1STATE | HFCPCI_CLTIMER; + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); + + /* Clear already pending ints */ + if (Read_hfc(cs, HFCPCI_INT_S1)); + if (Read_hfc(cs, HFCPCI_INT_S2)); + + Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 2); /* HFC ST 2 */ + udelay(10); + Write_hfc(cs, HFCPCI_STATES, 2); /* HFC ST 2 */ + cs->hw.hfcpci.mst_m = HFCPCI_MASTER; /* HFC Master Mode */ + + Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); + cs->hw.hfcpci.sctrl = 0; + Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl); + cs->hw.hfcpci.sctrl_r = 0; + Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r); + restore_flags(flags); +} + +/***************************************************/ +/* Timer function called when kernel timer expires */ +/***************************************************/ +static void +hfcpci_Timer(struct IsdnCardState *cs) +{ + cs->hw.hfcpci.timer.expires = jiffies + 75; + /* WD RESET */ +/* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcpci.ctmt | 0x80); + add_timer(&cs->hw.hfcpci.timer); + */ +} + + +/*********************************/ +/* schedule a new D-channel task */ +/*********************************/ +static void +sched_event_D_pci(struct IsdnCardState *cs, int event) +{ + test_and_set_bit(event, &cs->event); + queue_task(&cs->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +/*********************************/ +/* schedule a new b_channel task */ +/*********************************/ +static void +hfcpci_sched_event(struct BCState *bcs, int event) +{ + bcs->event |= 1 << event; + queue_task(&bcs->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +/************************************************/ +/* select a b-channel entry matching and active */ +/************************************************/ +static +struct BCState * +Sel_BCS(struct IsdnCardState *cs, int channel) +{ + if (cs->bcs[0].mode && (cs->bcs[0].channel == channel)) + return (&cs->bcs[0]); + else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel)) + return (&cs->bcs[1]); + else + return (NULL); +} + +/*********************************************/ +/* read a complete B-frame out of the buffer */ +/*********************************************/ +static struct sk_buff +* +hfcpci_empty_fifo(struct BCState *bcs, bzfifo_type * bz, u_char * bdata, int count) +{ + u_char *ptr, *ptr1, new_f2; + struct sk_buff *skb; + struct IsdnCardState *cs = bcs->cs; + int flags, total, maxlen, new_z2; + z_type *zp; + + save_flags(flags); + sti(); + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hfcpci_empty_fifo"); + zp = &bz->za[bz->f2]; /* point to Z-Regs */ + new_z2 = zp->z2 + count; /* new position in fifo */ + if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) + new_z2 -= B_FIFO_SIZE; /* buffer wrap */ + new_f2 = (bz->f2 + 1) & MAX_B_FRAMES; + if ((count > HSCX_BUFMAX + 3) || (count < 4) || + (*(bdata + (zp->z1 - B_SUB_VAL)))) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "hfcpci_empty_fifo: incoming packet invalid length %d or crc", count); + bz->za[new_f2].z2 = new_z2; + bz->f2 = new_f2; /* next buffer */ + skb = NULL; + } else if (!(skb = dev_alloc_skb(count - 3))) + printk(KERN_WARNING "HFCPCI: receive out of memory\n"); + else { + SET_SKB_FREE(skb); + total = count; + count -= 3; + ptr = skb_put(skb, count); + + if (zp->z1 >= zp->z2) + maxlen = count; /* complete transfer */ + else + maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */ + + ptr1 = bdata + (zp->z2 - B_SUB_VAL); /* start of data */ + memcpy(ptr, ptr1, maxlen); /* copy data */ + count -= maxlen; + + if (count) { /* rest remaining */ + ptr += maxlen; + ptr1 = bdata; /* start of buffer */ + memcpy(ptr, ptr1, count); /* rest */ + } + bz->za[new_f2].z2 = new_z2; + bz->f2 = new_f2; /* next buffer */ + + } + restore_flags(flags); + return (skb); +} + +/*******************************/ +/* D-channel receive procedure */ +/*******************************/ +static +int +receive_dmsg(struct IsdnCardState *cs) +{ + struct sk_buff *skb; + int maxlen; + int rcnt, total; + int count = 5; + u_char *ptr, *ptr1; + dfifo_type *df; + z_type *zp; + + df = &((fifo_area *) (cs->hw.hfcpci.fifos))->d_chan.d_rx; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs, "rec_dmsg blocked"); + return (1); + } + while (((df->f1 & D_FREG_MASK) != (df->f2 & D_FREG_MASK)) && count--) { + zp = &df->za[df->f2 & D_FREG_MASK]; + rcnt = zp->z1 - zp->z2; + if (rcnt < 0) + rcnt += D_FIFO_SIZE; + rcnt++; + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "hfcpci recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)", + df->f1, df->f2, zp->z1, zp->z2, rcnt); + + if ((rcnt > MAX_DFRAME_LEN + 3) || (rcnt < 4) || + (df->data[zp->z1])) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "empty_fifo hfcpci paket inv. len %d or crc %d", rcnt, df->data[zp->z1]); + df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1); /* next buffer */ + df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + rcnt) & (D_FIFO_SIZE - 1); + } else if ((skb = dev_alloc_skb(rcnt - 3))) { + SET_SKB_FREE(skb); + total = rcnt; + rcnt -= 3; + ptr = skb_put(skb, rcnt); + + if (zp->z1 >= zp->z2) + maxlen = rcnt; /* complete transfer */ + else + maxlen = D_FIFO_SIZE - zp->z2; /* maximum */ + + ptr1 = df->data + zp->z2; /* start of data */ + memcpy(ptr, ptr1, maxlen); /* copy data */ + rcnt -= maxlen; + + if (rcnt) { /* rest remaining */ + ptr += maxlen; + ptr1 = df->data; /* start of buffer */ + memcpy(ptr, ptr1, rcnt); /* rest */ + } + df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1); /* next buffer */ + df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + total) & (D_FIFO_SIZE - 1); + + skb_queue_tail(&cs->rq, skb); + sched_event_D_pci(cs, D_RCVBUFREADY); + } else + printk(KERN_WARNING "HFC-PCI: D receive out of memory\n"); + } + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + return (1); +} + +/**********************************/ +/* B-channel main receive routine */ +/**********************************/ +void +main_rec_hfcpci(struct BCState *bcs) +{ + long flags; + struct IsdnCardState *cs = bcs->cs; + int rcnt; + int receive, count = 5; + struct sk_buff *skb; + bzfifo_type *bz; + u_char *bdata; + z_type *zp; + + + save_flags(flags); + if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) { + bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2; + bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2; + } else { + bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b1; + bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b1; + } + Begin: + count--; + cli(); + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs, "rec_data %d blocked", bcs->channel); + restore_flags(flags); + return; + } + sti(); + if (bz->f1 != bz->f2) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfcpci rec %d f1(%d) f2(%d)", + bcs->channel, bz->f1, bz->f2); + zp = &bz->za[bz->f2]; + + rcnt = zp->z1 - zp->z2; + if (rcnt < 0) + rcnt += B_FIFO_SIZE; + rcnt++; + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfcpci rec %d z1(%x) z2(%x) cnt(%d)", + bcs->channel, zp->z1, zp->z2, rcnt); + if ((skb = hfcpci_empty_fifo(bcs, bz, bdata, rcnt))) { + cli(); + skb_queue_tail(&bcs->rqueue, skb); + sti(); + hfcpci_sched_event(bcs, B_RCVBUFREADY); + } + rcnt = bz->f1 - bz->f2; + if (rcnt < 0) + rcnt += MAX_B_FRAMES + 1; + if (rcnt > 1) + receive = 1; + else + receive = 0; + } else + receive = 0; + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + if (count && receive) + goto Begin; + restore_flags(flags); + return; +} + +/**************************/ +/* D-channel send routine */ +/**************************/ +static void +hfcpci_fill_dfifo(struct IsdnCardState *cs) +{ + long flags; + int fcnt; + int count, new_z1, maxlen; + dfifo_type *df; + u_char *src, *dst, new_f1; + + if (!cs->tx_skb) + return; + if (cs->tx_skb->len <= 0) + return; + + df = &((fifo_area *) (cs->hw.hfcpci.fifos))->d_chan.d_tx; + + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "hfcpci_fill_Dfifo f1(%d) f2(%d) z1(f1)(%x)", + df->f1, df->f2, + df->za[df->f1 & D_FREG_MASK].z1); + fcnt = df->f1 - df->f2; /* frame count actually buffered */ + if (fcnt < 0) + fcnt += (MAX_D_FRAMES + 1); /* if wrap around */ + if (fcnt > (MAX_D_FRAMES - 1)) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "hfcpci_fill_Dfifo more as 14 frames"); + return; + } + /* now determine free bytes in FIFO buffer */ + count = df->za[df->f1 & D_FREG_MASK].z2 - df->za[df->f1 & D_FREG_MASK].z1; + if (count <= 0) + count += D_FIFO_SIZE; /* count now contains available bytes */ + + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "hfcpci_fill_Dfifo count(%ld/%d)", + cs->tx_skb->len, count); + if (count < cs->tx_skb->len) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "hfcpci_fill_Dfifo no fifo mem"); + return; + } + count = cs->tx_skb->len; /* get frame len */ + new_z1 = (df->za[df->f1 & D_FREG_MASK].z1 + count) & (D_FIFO_SIZE - 1); + new_f1 = ((df->f1 + 1) & D_FREG_MASK) | (D_FREG_MASK + 1); + src = cs->tx_skb->data; /* source pointer */ + dst = df->data + df->za[df->f1 & D_FREG_MASK].z1; + maxlen = D_FIFO_SIZE - df->za[df->f1 & D_FREG_MASK].z1; /* end fifo */ + if (maxlen > count) + maxlen = count; /* limit size */ + memcpy(dst, src, maxlen); /* first copy */ + + count -= maxlen; /* remaining bytes */ + if (count) { + dst = df->data; /* start of buffer */ + src += maxlen; /* new position */ + memcpy(dst, src, count); + } + save_flags(flags); + cli(); + df->za[new_f1 & D_FREG_MASK].z1 = new_z1; /* for next buffer */ + df->za[df->f1 & D_FREG_MASK].z1 = new_z1; /* new pos actual buffer */ + df->f1 = new_f1; /* next frame */ + restore_flags(flags); + + idev_kfree_skb(cs->tx_skb, FREE_WRITE); + cs->tx_skb = NULL; + return; +} + +/**************************/ +/* B-channel send routine */ +/**************************/ +static void +hfcpci_fill_fifo(struct BCState *bcs) +{ + struct IsdnCardState *cs = bcs->cs; + int flags, maxlen, fcnt; + int count, new_z1; + bzfifo_type *bz; + u_char *bdata; + u_char new_f1, *src, *dst; + + if (!bcs->tx_skb) + return; + if (bcs->tx_skb->len <= 0) + return; + + save_flags(flags); + sti(); + + if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) { + bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2; + bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txdat_b2; + } else { + bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b1; + bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txdat_b1; + } + + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfcpci_fill_fifo %d f1(%d) f2(%d) z1(f1)(%x)", + bcs->channel, bz->f1, bz->f2, + bz->za[bz->f1].z1); + + fcnt = bz->f1 - bz->f2; /* frame count actually buffered */ + if (fcnt < 0) + fcnt += (MAX_B_FRAMES + 1); /* if wrap around */ + if (fcnt > (MAX_B_FRAMES - 1)) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfcpci_fill_Bfifo more as 14 frames"); + restore_flags(flags); + return; + } + /* now determine free bytes in FIFO buffer */ + count = bz->za[bz->f1].z2 - bz->za[bz->f1].z1; + if (count <= 0) + count += B_FIFO_SIZE; /* count now contains available bytes */ + + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfcpci_fill_fifo %d count(%ld/%d),%lx", + bcs->channel, bcs->tx_skb->len, + count, current->state); + + if (count < bcs->tx_skb->len) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfcpci_fill_fifo no fifo mem"); + restore_flags(flags); + return; + } + count = bcs->tx_skb->len; /* get frame len */ + new_z1 = bz->za[bz->f1].z1 + count; /* new buffer Position */ + if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL)) + new_z1 -= B_FIFO_SIZE; /* buffer wrap */ + + new_f1 = ((bz->f1 + 1) & MAX_B_FRAMES); + src = bcs->tx_skb->data; /* source pointer */ + dst = bdata + (bz->za[bz->f1].z1 - B_SUB_VAL); + maxlen = (B_FIFO_SIZE + B_SUB_VAL) - bz->za[bz->f1].z1; /* end fifo */ + if (maxlen > count) + maxlen = count; /* limit size */ + memcpy(dst, src, maxlen); /* first copy */ + + count -= maxlen; /* remaining bytes */ + if (count) { + dst = bdata; /* start of buffer */ + src += maxlen; /* new position */ + memcpy(dst, src, count); + } + bcs->tx_cnt -= bcs->tx_skb->len; + if (bcs->st->lli.l1writewakeup && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) + bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len); + + cli(); + bz->za[new_f1].z1 = new_z1; /* for next buffer */ + bz->f1 = new_f1; /* next frame */ + restore_flags(flags); + + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + return; +} + +/***********************/ +/* set/reset echo mode */ +/***********************/ +int hfcpci_set_echo(struct IsdnCardState *cs, int i) +{ + if (cs->chanlimit > 1) + return(-EINVAL); + if (i) { + cs->logecho = 1; + cs->hw.hfcpci.trm |= 0x20; /* enable echo chan */ + cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_B2REC; + cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2RX; + } + else { + cs->logecho = 0; + cs->hw.hfcpci.trm &= ~0x20; /* enable echo chan */ + cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_B2REC; + cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2RX; + } + cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA; + cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA; + cs->hw.hfcpci.conn &= ~0x18; + cs->hw.hfcpci.ctmt &= ~2; + Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt); + Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r); + Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl); + Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn); + Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm); + Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + return(0); +} /* hfcpci_set_echo */ + +/*****************************/ +/* E-channel receive routine */ +/*****************************/ +static void receive_emsg(struct IsdnCardState *cs) +{ + long flags; + int rcnt; + int receive, count = 5; + bzfifo_type *bz; + u_char *bdata; + z_type *zp; + u_char *ptr, *ptr1, new_f2; + int total, maxlen, new_z2; + u_char e_buffer[256]; + + save_flags(flags); + bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2; + bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2; + Begin: + count--; + cli(); + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs, "echo_rec_data blocked"); + restore_flags(flags); + return; + } + sti(); + if (bz->f1 != bz->f2) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "hfcpci e_rec f1(%d) f2(%d)", + bz->f1, bz->f2); + zp = &bz->za[bz->f2]; + + rcnt = zp->z1 - zp->z2; + if (rcnt < 0) + rcnt += B_FIFO_SIZE; + rcnt++; + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "hfcpci e_rec z1(%x) z2(%x) cnt(%d)", + zp->z1, zp->z2, rcnt); + new_z2 = zp->z2 + rcnt; /* new position in fifo */ + if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) + new_z2 -= B_FIFO_SIZE; /* buffer wrap */ + new_f2 = (bz->f2 + 1) & MAX_B_FRAMES; + if ((rcnt > 256 + 3) || (count < 4) || + (*(bdata + (zp->z1 - B_SUB_VAL)))) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "hfcpci_empty_echan: incoming packet invalid length %d or crc", rcnt); + bz->za[new_f2].z2 = new_z2; + bz->f2 = new_f2; /* next buffer */ + } else { + total = rcnt; + rcnt -= 3; + ptr = e_buffer; + + if (zp->z1 >= zp->z2) + maxlen = rcnt; /* complete transfer */ + else + maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */ + + ptr1 = bdata + (zp->z2 - B_SUB_VAL); /* start of data */ + memcpy(ptr, ptr1, maxlen); /* copy data */ + rcnt -= maxlen; + + if (rcnt) { /* rest remaining */ + ptr += maxlen; + ptr1 = bdata; /* start of buffer */ + memcpy(ptr, ptr1, rcnt); /* rest */ + } + bz->za[new_f2].z2 = new_z2; + bz->f2 = new_f2; /* next buffer */ + if (cs->debug & DEB_DLOG_HEX) { + ptr = cs->dlog; + if ((total - 3) < MAX_DLOG_SPACE / 3 - 10) { + *ptr++ = 'E'; + *ptr++ = 'C'; + *ptr++ = 'H'; + *ptr++ = 'O'; + *ptr++ = ':'; + ptr += QuickHex(ptr, e_buffer, total - 3); + ptr--; + *ptr++ = '\n'; + *ptr = 0; + HiSax_putstatus(cs, NULL, cs->dlog); + } else + HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", total - 3); + } + + } + + rcnt = bz->f1 - bz->f2; + if (rcnt < 0) + rcnt += MAX_B_FRAMES + 1; + if (rcnt > 1) + receive = 1; + else + receive = 0; + } else + receive = 0; + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + if (count && receive) + goto Begin; + restore_flags(flags); + return; +} /* receive_emsg */ + +/*********************/ +/* Interrupt handler */ +/*********************/ +static void +hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char exval; + struct BCState *bcs; + int count = 15; + long flags; + u_char val, stat; + + if (!cs) { + printk(KERN_WARNING "HFC-PCI: Spurious interrupt!\n"); + return; + } + if (HFCPCI_ANYINT & (stat = Read_hfc(cs, HFCPCI_STATUS))) { + val = Read_hfc(cs, HFCPCI_INT_S1); + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "HFC-PCI: stat(%02x) s1(%02x)", stat, val); + } else + return; + + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "HFC-PCI irq %x %s", val, + test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ? + "locked" : "unlocked"); + val &= cs->hw.hfcpci.int_m1; + if (val & 0x40) { /* TE state machine irq */ + exval = Read_hfc(cs, HFCPCI_STATES) & 0xf; + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcpci.ph_state, + exval); + cs->dc.hfcpci.ph_state = exval; + sched_event_D_pci(cs, D_L1STATECHANGE); + val &= ~0x40; + } + while (val) { + save_flags(flags); + cli(); + if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + cs->hw.hfcpci.int_s1 |= val; + restore_flags(flags); + return; + } + if (cs->hw.hfcpci.int_s1 & 0x18) { + exval = val; + val = cs->hw.hfcpci.int_s1; + cs->hw.hfcpci.int_s1 = exval; + } + if (val & 0x08) { + if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1:0))) { + if (cs->debug) + debugl1(cs, "hfcpci spurious 0x08 IRQ"); + } else + main_rec_hfcpci(bcs); + } + if (val & 0x10) { + if (cs->logecho) + receive_emsg(cs); + else + if (!(bcs = Sel_BCS(cs, 1))) { + if (cs->debug) + debugl1(cs, "hfcpci spurious 0x10 IRQ"); + } else + main_rec_hfcpci(bcs); + } + if (val & 0x01) { + if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1:0))) { + if (cs->debug) + debugl1(cs, "hfcpci spurious 0x01 IRQ"); + } else { + if (bcs->tx_skb) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + hfcpci_sched_event(bcs, B_XMTBUFREADY); + } + } + } + } + if (val & 0x02) { + if (!(bcs = Sel_BCS(cs, 1))) { + if (cs->debug) + debugl1(cs, "hfcpci spurious 0x02 IRQ"); + } else { + if (bcs->tx_skb) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + hfcpci_sched_event(bcs, B_XMTBUFREADY); + } + } + } + } + if (val & 0x20) { /* receive dframe */ + receive_dmsg(cs); + } + if (val & 0x04) { /* dframe transmitted */ + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + sched_event_D_pci(cs, D_CLEARBUSY); + if (cs->tx_skb) { + if (cs->tx_skb->len) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else { + debugl1(cs, "hfcpci_fill_dfifo irq blocked"); + } + goto afterXPR; + } else { + idev_kfree_skb(cs->tx_skb, FREE_WRITE); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } + } + if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_cnt = 0; + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else { + debugl1(cs, "hfcpci_fill_dfifo irq blocked"); + } + } else + sched_event_D_pci(cs, D_XMTBUFREADY); + } + afterXPR: + if (cs->hw.hfcpci.int_s1 && count--) { + val = cs->hw.hfcpci.int_s1; + cs->hw.hfcpci.int_s1 = 0; + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "HFC-PCI irq %x loop %d", val, 15 - count); + } else + val = 0; + restore_flags(flags); + } +} + +/********************************************************************/ +/* timer callback for D-chan busy resolution. Currently no function */ +/********************************************************************/ +static void +hfcpci_dbusy_timer(struct IsdnCardState *cs) +{ +#if 0 + struct PStack *stptr; + if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { + if (cs->debug) + debugl1(cs, "D-Channel Busy"); + test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); + stptr = cs->stlist; + + while (stptr != NULL) { + stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); + stptr = stptr->next; + } + } +#endif +} + +/*************************************/ +/* Layer 1 D-channel hardware access */ +/*************************************/ +static void +HFCPCI_l1hw(struct PStack *st, int pr, void *arg) +{ + struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; + struct sk_buff *skb = arg; + + switch (pr) { + case (PH_DATA | REQUEST): + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + if (cs->tx_skb) { + skb_queue_tail(&cs->sq, skb); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA Queued", 0); +#endif + } else { + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "hfcpci_fill_dfifo blocked"); + + } + break; + case (PH_PULL | INDICATION): + if (cs->tx_skb) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); + skb_queue_tail(&cs->sq, skb); + break; + } + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "hfcpci_fill_dfifo blocked"); + break; + case (PH_PULL | REQUEST): +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + if (!cs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + break; + case (HW_RESET | REQUEST): + Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 3); /* HFC ST 3 */ + udelay(6); + Write_hfc(cs, HFCPCI_STATES, 3); /* HFC ST 2 */ + cs->hw.hfcpci.mst_m |= HFCPCI_MASTER; + Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); + Write_hfc(cs, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION); + l1_msg(cs, HW_POWERUP | CONFIRM, NULL); + break; + case (HW_ENABLE | REQUEST): + Write_hfc(cs, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION); + break; + case (HW_DEACTIVATE | REQUEST): + cs->hw.hfcpci.mst_m &= ~HFCPCI_MASTER; + Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); + break; + case (HW_INFO3 | REQUEST): + cs->hw.hfcpci.mst_m |= HFCPCI_MASTER; + Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); + break; +#if 0 + case (HW_TESTLOOP | REQUEST): + u_char val = 0; + if (1 & (int) arg) + val |= 0x0c; + if (2 & (int) arg) + val |= 0x3; + if (test_bit(HW_IOM1, &cs->HW_Flags)) { + /* IOM 1 Mode */ + if (!val) { + cs->writeisac(cs, ISAC_SPCR, 0xa); + cs->writeisac(cs, ISAC_ADF1, 0x2); + } else { + cs->writeisac(cs, ISAC_SPCR, val); + cs->writeisac(cs, ISAC_ADF1, 0xa); + } + } else { + /* IOM 2 Mode */ + cs->writeisac(cs, ISAC_SPCR, val); + if (val) + cs->writeisac(cs, ISAC_ADF1, 0x8); + else + cs->writeisac(cs, ISAC_ADF1, 0x0); + } + break; +#endif + default: + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "hfcpci_l1hw unknown pr %4x", pr); + break; + } +} + +/***********************************************/ +/* called during init setting l1 stack pointer */ +/***********************************************/ +void +setstack_hfcpci(struct PStack *st, struct IsdnCardState *cs) +{ + st->l1.l1hw = HFCPCI_l1hw; +} + +/**************************************/ +/* send B-channel data if not blocked */ +/**************************************/ +static void +hfcpci_send_data(struct BCState *bcs) +{ + struct IsdnCardState *cs = bcs->cs; + + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "send_data %d blocked", bcs->channel); +} + +/***************************************************************/ +/* activate/deactivate hardware for selected channels and mode */ +/***************************************************************/ +void +mode_hfcpci(struct BCState *bcs, int mode, int bc) +{ + struct IsdnCardState *cs = bcs->cs; + int flags; + + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HFCPCI bchannel mode %d bchan %d/%d", + mode, bc, bcs->channel); + bcs->mode = mode; + bcs->channel = bc; + if (cs->chanlimit > 1) { + cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */ + cs->hw.hfcpci.sctrl_e &= ~0x80; + } + else { + if (bc) { + cs->hw.hfcpci.bswapped = 1; /* B1 and B2 exchanged */ + cs->hw.hfcpci.sctrl_e |= 0x80; + bc = 0; /* B1 controller used */ + } + else { + cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */ + cs->hw.hfcpci.sctrl_e &= ~0x80; + } + } + save_flags(flags); + cli(); + switch (mode) { + case (L1_MODE_NULL): + if (bc) { + cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA; + cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA; + cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2; + cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC); + } else { + cs->hw.hfcpci.sctrl &= ~SCTRL_B1_ENA; + cs->hw.hfcpci.sctrl_r &= ~SCTRL_B1_ENA; + cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B1; + cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC); + } + break; + case (L1_MODE_TRANS): + if (bc) { + cs->hw.hfcpci.ctmt |= 2; + cs->hw.hfcpci.conn &= ~0x18; + cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA; + cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA; + cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2; + cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC); + } else { + cs->hw.hfcpci.ctmt |= 1; + cs->hw.hfcpci.conn &= ~0x3; + cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA; + cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA; + cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1; + cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC); + } + break; + case (L1_MODE_HDLC): + if (bc) { + cs->hw.hfcpci.ctmt &= ~2; + cs->hw.hfcpci.conn &= ~0x18; + cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA; + cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA; + cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2; + cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC); + } else { + cs->hw.hfcpci.ctmt &= ~1; + cs->hw.hfcpci.conn &= ~0x3; + cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA; + cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA; + cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1; + cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC); + } + break; + } + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + restore_flags(flags); + Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); + Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl); + Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r); + Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt); + Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn); +} + +/******************************/ +/* Layer2 -> Layer 1 Transfer */ +/******************************/ +static void +hfcpci_l2l1(struct PStack *st, int pr, void *arg) +{ + struct sk_buff *skb = arg; + long flags; + + switch (pr) { + case (PH_DATA | REQUEST): + save_flags(flags); + cli(); + if (st->l1.bcs->tx_skb) { + skb_queue_tail(&st->l1.bcs->squeue, skb); + restore_flags(flags); + } else { + st->l1.bcs->tx_skb = skb; +/* test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + */ st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); + restore_flags(flags); + } + break; + case (PH_PULL | INDICATION): + if (st->l1.bcs->tx_skb) { + printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); + break; + } + save_flags(flags); + cli(); +/* test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + */ st->l1.bcs->tx_skb = skb; + st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); + restore_flags(flags); + break; + case (PH_PULL | REQUEST): + if (!st->l1.bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + break; + case (PH_ACTIVATE | REQUEST): + test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + mode_hfcpci(st->l1.bcs, st->l1.mode, st->l1.bc); + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | REQUEST): + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | CONFIRM): + test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + mode_hfcpci(st->l1.bcs, 0, st->l1.bc); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); + break; + } +} + +/******************************************/ +/* deactivate B-channel access and queues */ +/******************************************/ +static void +close_hfcpci(struct BCState *bcs) +{ + mode_hfcpci(bcs, 0, bcs->channel); + if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { + discard_queue(&bcs->rqueue); + discard_queue(&bcs->squeue); + if (bcs->tx_skb) { + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + } + } +} + +/*************************************/ +/* init B-channel queues and control */ +/*************************************/ +static int +open_hfcpcistate(struct IsdnCardState *cs, struct BCState *bcs) +{ + if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + } + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->event = 0; + bcs->tx_cnt = 0; + return (0); +} + +/*********************************/ +/* inits the stack for B-channel */ +/*********************************/ +static int +setstack_2b(struct PStack *st, struct BCState *bcs) +{ + bcs->channel = st->l1.bc; + if (open_hfcpcistate(st->l1.hardware, bcs)) + return (-1); + st->l1.bcs = bcs; + st->l2.l2l1 = hfcpci_l2l1; + setstack_manager(st); + bcs->st = st; + setstack_l1_B(st); + return (0); +} + +/***************************/ +/* handle L1 state changes */ +/***************************/ +static void +hfcpci_bh(struct IsdnCardState *cs) +{ +/* struct PStack *stptr; + */ + if (!cs) + return; +#if 0 + if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { + if (cs->debug) + debugl1(cs, "D-Channel Busy cleared"); + stptr = cs->stlist; + while (stptr != NULL) { + stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); + stptr = stptr->next; + } + } +#endif + if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { + switch (cs->dc.hfcpci.ph_state) { + case (0): + l1_msg(cs, HW_RESET | INDICATION, NULL); + break; + case (3): + l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL); + break; + case (8): + l1_msg(cs, HW_RSYNC | INDICATION, NULL); + break; + case (6): + l1_msg(cs, HW_INFO2 | INDICATION, NULL); + break; + case (7): + l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); + break; + default: + break; + } + } + if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) + DChannel_proc_rcv(cs); + if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) + DChannel_proc_xmt(cs); +} + + +/*************************************/ +/* Alloc memory send data for queues */ +/*************************************/ +__initfunc(unsigned int + *init_send_hfcpci(int cnt)) +{ + int i, *send; + + if (!(send = kmalloc(cnt * sizeof(unsigned int), GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for hfcpci.send\n"); + return (NULL); + } + for (i = 0; i < cnt; i++) + send[i] = 0x1fff; + return (send); +} + +/********************************/ +/* called for card init message */ +/********************************/ +__initfunc(void + inithfcpci(struct IsdnCardState *cs)) +{ + cs->setstack_d = setstack_hfcpci; + cs->dbusytimer.function = (void *) hfcpci_dbusy_timer; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); + cs->tqueue.routine = (void *) (void *) hfcpci_bh; +#if 0 + if (!cs->hw.hfcpci.send) + cs->hw.hfcpci.send = init_send_hfcpci(16); +#endif + if (!cs->bcs[0].hw.hfc.send) + cs->bcs[0].hw.hfc.send = init_send_hfcpci(32); + if (!cs->bcs[1].hw.hfc.send) + cs->bcs[1].hw.hfc.send = init_send_hfcpci(32); + cs->BC_Send_Data = &hfcpci_send_data; + cs->bcs[0].BC_SetStack = setstack_2b; + cs->bcs[1].BC_SetStack = setstack_2b; + cs->bcs[0].BC_Close = close_hfcpci; + cs->bcs[1].BC_Close = close_hfcpci; + mode_hfcpci(cs->bcs, 0, 0); + mode_hfcpci(cs->bcs + 1, 0, 1); +} + + + +/*******************************************/ +/* handle card messages from control layer */ +/*******************************************/ +static int +hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + long flags; + + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "HFCPCI: card_msg %x", mt); + switch (mt) { + case CARD_RESET: + reset_hfcpci(cs); + return (0); + case CARD_RELEASE: + release_io_hfcpci(cs); + return (0); + case CARD_INIT: + inithfcpci(cs); + save_flags(flags); + sti(); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ + /* now switch timer interrupt off */ + cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER; + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + /* reinit mode reg */ + Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); + restore_flags(flags); + return (0); + case CARD_TEST: + return (0); + } + return (0); +} + + +/* this variable is used as card index when more than one cards are present */ +#ifdef COMPAT_HAS_NEW_PCI +static struct pci_dev *dev_hfcpci __initdata = NULL; +#else +static int pci_index __initdata = 0; +#endif + +#endif /* CONFIG_PCI */ + +__initfunc(int + setup_hfcpci(struct IsdnCard *card)) +{ + struct IsdnCardState *cs = card->cs; + char tmp[64]; + + strcpy(tmp, hfcpci_revision); + printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp)); +#if CONFIG_PCI + cs->hw.hfcpci.int_s1 = 0; +#if 0 + cs->hw.hfcpci.send = NULL; +#endif + cs->bcs[0].hw.hfc.send = NULL; + cs->bcs[1].hw.hfc.send = NULL; + cs->dc.hfcpci.ph_state = 0; + cs->hw.hfcpci.fifo = 255; + if (cs->typ == ISDN_CTYPE_HFC_PCI) { +#ifdef COMPAT_HAS_NEW_PCI + if (!pci_present()) { + printk(KERN_ERR "HFC-PCI: no PCI bus present\n"); + return (0); + } + if ((dev_hfcpci = pci_find_device(PCI_VENDOR_CCD, + PCI_CCD_PCI_ID, dev_hfcpci))) { + cs->hw.hfcpci.pci_bus = dev_hfcpci->bus->number; + cs->hw.hfcpci.pci_device_fn = dev_hfcpci->devfn; + cs->irq = dev_hfcpci->irq; + if (!cs->irq) { + printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n"); + return (0); + } + cs->hw.hfcpci.pci_io = (char *) + dev_hfcpci->base_address[1]; + } else { + printk(KERN_WARNING "HFC-PCI: No PCI card found\n"); + return (0); + } +#else + for (; pci_index < 255; pci_index++) { + unsigned char irq; + + if (pcibios_find_device(PCI_VENDOR_CCD, + PCI_CCD_PCI_ID, pci_index, + &cs->hw.hfcpci.pci_bus, &cs->hw.hfcpci.pci_device_fn) != 0) { + continue; + } + pcibios_read_config_byte(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, + PCI_INTERRUPT_LINE, &irq); + cs->irq = irq; + + pcibios_read_config_dword(cs->hw.hfcpci.pci_bus, + cs->hw.hfcpci.pci_device_fn, PCI_BASE_ADDRESS_1, + (void *) &cs->hw.hfcpci.pci_io); + break; + } + if (pci_index == 255) { + printk(KERN_WARNING "HFC-PCI: No card found\n"); + return (0); + } + pci_index++; +#endif /* COMPAT_HAS_NEW_PCI */ + if (!cs->hw.hfcpci.pci_io) { + printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n"); + return (0); + } + /* Allocate memory for FIFOS */ + /* Because the HFC-PCI needs a 32K physical alignment, we */ + /* need to allocate the double mem and align the address */ + if (!((void *) cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) { + printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n"); + return 0; + } + (ulong) cs->hw.hfcpci.fifos = + (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000; + pcibios_write_config_dword(cs->hw.hfcpci.pci_bus, + cs->hw.hfcpci.pci_device_fn, 0x80, + (u_int) virt_to_bus(cs->hw.hfcpci.fifos)); + cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256); + printk(KERN_INFO + "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n", + (u_int) cs->hw.hfcpci.pci_io, + (u_int) cs->hw.hfcpci.fifos, + (u_int) virt_to_bus(cs->hw.hfcpci.fifos), + cs->irq, HZ); + 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; /* disable alle interrupts */ + cs->hw.hfcpci.int_m1 = 0; + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); + /* At this point the needed PCI config is done */ + /* fifos are still not enabled */ + } else + return (0); /* no valid card type */ + + + cs->readisac = NULL; + cs->writeisac = NULL; + cs->readisacfifo = NULL; + cs->writeisacfifo = NULL; + cs->BC_Read_Reg = NULL; + cs->BC_Write_Reg = NULL; + cs->irq_func = &hfcpci_interrupt; + cs->irq_flags |= SA_SHIRQ; + + cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer; + cs->hw.hfcpci.timer.data = (long) cs; + init_timer(&cs->hw.hfcpci.timer); + + reset_hfcpci(cs); + cs->cardmsg = &hfcpci_card_msg; + return (1); +#else + printk(KERN_WARNING "HFC-PCI: NO_PCI_BIOS\n"); + return (0); +#endif /* CONFIG_PCI */ +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/hfc_pci.h linux.pre11.3/drivers/isdn/hisax/hfc_pci.h --- linux.vanilla/drivers/isdn/hisax/hfc_pci.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/hfc_pci.h Mon Jul 19 23:59:33 1999 @@ -0,0 +1,250 @@ +/* $Id: hfc_pci.h,v 1.3 1999/07/14 12:39:34 werner Exp $ + + * specific defines for CCD's HFC 2BDS0 PCI chips + * + * Author Werner Cornelius (werner@isdn4linux.de) + * + * Copyright 1999 by Werner Cornelius (werner@isdn4linux.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, 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. + * + * $Log: hfc_pci.h,v $ + * Revision 1.3 1999/07/14 12:39:34 werner + * Added changes for echo handling. + * + * Revision 1.2 1999/07/01 08:07:52 keil + * Initial version + * + * + * + */ + + +/* defines for PCI config */ + +#define PCI_VENDOR_CCD 0x1397 +#define PCI_CCD_PCI_ID 0x2BD0 +// #define PCI_VENDOR_CCD 0x1043 +// #define PCI_CCD_PCI_ID 0x675 +#define PCI_ENA_MEMIO 0x02 +#define PCI_ENA_MASTER 0x04 + + +/* GCI/IOM bus monitor registers */ + +#define HCFPCI_C_I 0x08 +#define HFCPCI_TRxR 0x0C +#define HFCPCI_MON1_D 0x28 +#define HFCPCI_MON2_D 0x2C + + +/* GCI/IOM bus timeslot registers */ + +#define HFCPCI_B1_SSL 0x80 +#define HFCPCI_B2_SSL 0x84 +#define HFCPCI_AUX1_SSL 0x88 +#define HFCPCI_AUX2_SSL 0x8C +#define HFCPCI_B1_RSL 0x90 +#define HFCPCI_B2_RSL 0x94 +#define HFCPCI_AUX1_RSL 0x98 +#define HFCPCI_AUX2_RSL 0x9C + +/* GCI/IOM bus data registers */ + +#define HFCPCI_B1_D 0xA0 +#define HFCPCI_B2_D 0xA4 +#define HFCPCI_AUX1_D 0xA8 +#define HFCPCI_AUX2_D 0xAC + +/* GCI/IOM bus configuration registers */ + +#define HFCPCI_MST_EMOD 0xB4 +#define HFCPCI_MST_MODE 0xB8 +#define HFCPCI_CONNECT 0xBC + + +/* Interrupt and status registers */ + +#define HFCPCI_FIFO_EN 0x44 +#define HFCPCI_TRM 0x48 +#define HFCPCI_B_MODE 0x4C +#define HFCPCI_CHIP_ID 0x58 +#define HFCPCI_CIRM 0x60 +#define HFCPCI_CTMT 0x64 +#define HFCPCI_INT_M1 0x68 +#define HFCPCI_INT_M2 0x6C +#define HFCPCI_INT_S1 0x78 +#define HFCPCI_INT_S2 0x7C +#define HFCPCI_STATUS 0x70 + +/* S/T section registers */ + +#define HFCPCI_STATES 0xC0 +#define HFCPCI_SCTRL 0xC4 +#define HFCPCI_SCTRL_E 0xC8 +#define HFCPCI_SCTRL_R 0xCC +#define HFCPCI_SQ 0xD0 +#define HFCPCI_CLKDEL 0xDC +#define HFCPCI_B1_REC 0xF0 +#define HFCPCI_B1_SEND 0xF0 +#define HFCPCI_B2_REC 0xF4 +#define HFCPCI_B2_SEND 0xF4 +#define HFCPCI_D_REC 0xF8 +#define HFCPCI_D_SEND 0xF8 +#define HFCPCI_E_REC 0xFC + + +/* bits in status register (READ) */ +#define HFCPCI_PCI_PROC 0x02 +#define HFCPCI_NBUSY 0x04 +#define HFCPCI_TIMER_ELAP 0x10 +#define HFCPCI_STATINT 0x20 +#define HFCPCI_FRAMEINT 0x40 +#define HFCPCI_ANYINT 0x80 + +/* bits in CTMT (Write) */ +#define HFCPCI_CLTIMER 0x80 +#define HFCPCI_TIM3_125 0x00 +#define HFCPCI_TIM25 0x10 +#define HFCPCI_TIM50 0x14 +#define HFCPCI_TIM400 0x18 +#define HFCPCI_TIM800 0x1C +#define HFCPCI_AUTO_TIMER 0x20 +#define HFCPCI_TRANSB2 0x02 +#define HFCPCI_TRANSB1 0x01 + +/* bits in CIRM (Write) */ +#define HFCPCI_AUX_MSK 0x07 +#define HFCPCI_RESET 0x08 +#define HFCPCI_B1_REV 0x40 +#define HFCPCI_B2_REV 0x80 + +/* bits in INT_M1 and INT_S1 */ +#define HFCPCI_INTS_B1TRANS 0x01 +#define HFCPCI_INTS_B2TRANS 0x02 +#define HFCPCI_INTS_DTRANS 0x04 +#define HFCPCI_INTS_B1REC 0x08 +#define HFCPCI_INTS_B2REC 0x10 +#define HFCPCI_INTS_DREC 0x20 +#define HFCPCI_INTS_L1STATE 0x40 +#define HFCPCI_INTS_TIMER 0x80 + +/* bits in INT_M2 */ +#define HFCPCI_PROC_TRANS 0x01 +#define HFCPCI_GCI_I_CHG 0x02 +#define HFCPCI_GCI_MON_REC 0x04 +#define HFCPCI_IRQ_ENABLE 0x08 +#define HFCPCI_PMESEL 0x80 + +/* bits in STATES */ +#define HFCPCI_STATE_MSK 0x0F +#define HFCPCI_LOAD_STATE 0x10 +#define HFCPCI_ACTIVATE 0x20 +#define HFCPCI_DO_ACTION 0x40 +#define HFCPCI_NT_G2_G3 0x80 + +/* bits in HFCD_MST_MODE */ +#define HFCPCI_MASTER 0x01 +#define HFCPCI_SLAVE 0x00 +/* remaining bits are for codecs control */ + +/* bits in HFCD_SCTRL */ +#define SCTRL_B1_ENA 0x01 +#define SCTRL_B2_ENA 0x02 +#define SCTRL_MODE_TE 0x00 +#define SCTRL_MODE_NT 0x04 +#define SCTRL_LOW_PRIO 0x08 +#define SCTRL_SQ_ENA 0x10 +#define SCTRL_TEST 0x20 +#define SCTRL_NONE_CAP 0x40 +#define SCTRL_PWR_DOWN 0x80 + +/* bits in SCTRL_E */ +#define HFCPCI_AUTO_AWAKE 0x01 +#define HFCPCI_DBIT_1 0x04 +#define HFCPCI_IGNORE_COL 0x08 +#define HFCPCI_CHG_B1_B2 0x80 + +/****************************/ +/* bits in FIFO_EN register */ +/****************************/ +#define HFCPCI_FIFOEN_B1 0x03 +#define HFCPCI_FIFOEN_B2 0x0C +#define HFCPCI_FIFOEN_DTX 0x10 +#define HFCPCI_FIFOEN_B2RX 0x08 + + +/***********************************/ +/* definitions of fifo memory area */ +/***********************************/ +#define MAX_D_FRAMES 15 +#define MAX_B_FRAMES 31 +#define B_SUB_VAL 0x200 +#define B_FIFO_SIZE (0x2000 - B_SUB_VAL) +#define D_FIFO_SIZE 512 +#define D_FREG_MASK 0xF + +typedef struct { + unsigned short z1; /* Z1 pointer 16 Bit */ + unsigned short z2; /* Z2 pointer 16 Bit */ + } z_type; + +typedef struct { + u_char data[D_FIFO_SIZE]; /* FIFO data space */ + u_char fill1[0x20A0-D_FIFO_SIZE]; /* reserved, do not use */ + u_char f1,f2; /* f pointers */ + u_char fill2[0x20C0-0x20A2]; /* reserved, do not use */ + z_type za[MAX_D_FRAMES+1]; /* mask index with D_FREG_MASK for access */ + u_char fill3[0x4000-0x2100]; /* align 16K */ + } dfifo_type; + +typedef struct { + z_type za[MAX_B_FRAMES+1]; /* only range 0x0..0x1F allowed */ + u_char f1,f2; /* f pointers */ + u_char fill[0x2100-0x2082]; /* alignment */ + } bzfifo_type; + + +typedef union { + struct { + dfifo_type d_tx; /* D-send channel */ + dfifo_type d_rx; /* D-receive channel */ + } d_chan; + struct { + u_char fill1[0x200]; + u_char txdat_b1[B_FIFO_SIZE]; + bzfifo_type txbz_b1; + + bzfifo_type txbz_b2; + u_char txdat_b2[B_FIFO_SIZE]; + + u_char fill2[D_FIFO_SIZE]; + + u_char rxdat_b1[B_FIFO_SIZE]; + bzfifo_type rxbz_b1; + + bzfifo_type rxbz_b2; + u_char rxdat_b2[B_FIFO_SIZE]; + } b_chans; + u_char fill[32768]; + } fifo_area; + + +#define Write_hfc(a,b,c) (*(((u_char *)a->hw.hfcpci.pci_io)+b) = c) +#define Read_hfc(a,b) (*(((u_char *)a->hw.hfcpci.pci_io)+b)) + +extern void main_irq_hcpci(struct BCState *bcs); +extern void inithfcpci(struct IsdnCardState *cs); +extern void releasehfcpci(struct IsdnCardState *cs); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/hfcscard.c linux.pre11.3/drivers/isdn/hisax/hfcscard.c --- linux.vanilla/drivers/isdn/hisax/hfcscard.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/hfcscard.c Mon Jul 19 23:59:33 1999 @@ -0,0 +1,203 @@ +/* $Id: hfcscard.c,v 1.3 1999/07/12 21:05:12 keil Exp $ + + * hfcscard.c low level stuff for hfcs based cards (Teles3c, ACER P10) + * + * Author Karsten Keil (keil@isdn4linux.de) + * + * + * $Log: hfcscard.c,v $ + * Revision 1.3 1999/07/12 21:05:12 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 1.2 1999/07/01 08:16:03 keil + * teles3c ---> hfcscard + * + * + * + */ + +#define __NO_VERSION__ +#include "hisax.h" +#include "hfc_2bds0.h" +#include "isdnl1.h" + +extern const char *CardType[]; + +static const char *hfcs_revision = "$Revision: 1.3 $"; + +static void +hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val, stat; + + if (!cs) { + printk(KERN_WARNING "HFCS: Spurious interrupt!\n"); + return; + } + if ((HFCD_ANYINT | HFCD_BUSY_NBUSY) & + (stat = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_STAT))) { + val = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_INT_S1); + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "HFCS: stat(%02x) s1(%02x)", stat, val); + hfc2bds0_interrupt(cs, val); + } else { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "HFCS: irq_no_irq stat(%02x)", stat); + } +} + +static void +hfcs_Timer(struct IsdnCardState *cs) +{ + cs->hw.hfcD.timer.expires = jiffies + 75; + /* WD RESET */ +/* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt | 0x80); + add_timer(&cs->hw.hfcD.timer); +*/ +} + +void +release_io_hfcs(struct IsdnCardState *cs) +{ + release2bds0(cs); + del_timer(&cs->hw.hfcD.timer); + if (cs->hw.hfcD.addr) + release_region(cs->hw.hfcD.addr, 2); +} + +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(); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((30*HZ)/1000); + 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 */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10*HZ)/1000); + if (cs->typ == ISDN_CTYPE_TELES3C) + cs->hw.hfcD.cirm |= HFCD_INTB; + else if (cs->typ == ISDN_CTYPE_ACERP10) + cs->hw.hfcD.cirm |= HFCD_INTA; + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CLKDEL, 0x0e); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_TEST, HFCD_AUTO_AWAKE); /* S/T Auto awake */ + cs->hw.hfcD.ctmt = HFCD_TIM25 | HFCD_AUTO_TIMER; + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); + cs->hw.hfcD.int_m2 = HFCD_IRQ_ENABLE; + cs->hw.hfcD.int_m1 = HFCD_INTS_B1TRANS | HFCD_INTS_B2TRANS | + HFCD_INTS_DTRANS | HFCD_INTS_B1REC | HFCD_INTS_B2REC | + HFCD_INTS_DREC | HFCD_INTS_L1STATE; + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M1, cs->hw.hfcD.int_m1); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M2, cs->hw.hfcD.int_m2); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, HFCD_LOAD_STATE | 2); /* HFC ST 2 */ + udelay(10); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, 2); /* HFC ST 2 */ + cs->hw.hfcD.mst_m = 0; + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, HFCD_MASTER); /* 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 +hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + long flags; + + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "HFCS: card_msg %x", mt); + switch (mt) { + case CARD_RESET: + reset_hfcs(cs); + return(0); + case CARD_RELEASE: + release_io_hfcs(cs); + return(0); + case CARD_INIT: + cs->hw.hfcD.timer.expires = jiffies + 75; + add_timer(&cs->hw.hfcD.timer); + init2bds0(cs); + save_flags(flags); + sti(); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((80*HZ)/1000); + cs->hw.hfcD.ctmt |= HFCD_TIM800; + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); + restore_flags(flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); +} + +__initfunc(int +setup_hfcs(struct IsdnCard *card)) +{ + struct IsdnCardState *cs = card->cs; + char tmp[64]; + + strcpy(tmp, hfcs_revision); + printk(KERN_INFO "HiSax: HFC-S driver Rev. %s\n", HiSax_getrev(tmp)); + cs->hw.hfcD.addr = card->para[1] & 0xfffe; + cs->irq = card->para[0]; + cs->hw.hfcD.cip = 0; + cs->hw.hfcD.int_s1 = 0; + cs->hw.hfcD.send = NULL; + cs->bcs[0].hw.hfc.send = NULL; + cs->bcs[1].hw.hfc.send = NULL; + cs->hw.hfcD.dfifosize = 512; + cs->dc.hfcd.ph_state = 0; + cs->hw.hfcD.fifo = 255; + if (cs->typ == ISDN_CTYPE_TELES3C) { + cs->hw.hfcD.bfifosize = 1024 + 512; + } else if (cs->typ == ISDN_CTYPE_ACERP10) { + cs->hw.hfcD.bfifosize = 7*1024 + 512; + } else + return (0); + if (check_region((cs->hw.hfcD.addr), 2)) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.hfcD.addr, + cs->hw.hfcD.addr + 2); + return (0); + } else { + request_region(cs->hw.hfcD.addr, 2, "HFCS isdn"); + } + printk(KERN_INFO + "HFCS: defined at 0x%x IRQ %d HZ %d\n", + cs->hw.hfcD.addr, + cs->irq, HZ); + if (cs->typ == ISDN_CTYPE_TELES3C) { + /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */ + outb(0x00, cs->hw.hfcD.addr); + outb(0x56, cs->hw.hfcD.addr | 1); + } else if (cs->typ == ISDN_CTYPE_ACERP10) { + /* Acer P10 IO ADR is 0x300 */ + outb(0x00, cs->hw.hfcD.addr); + outb(0x57, cs->hw.hfcD.addr | 1); + } + set_cs_func(cs); + cs->hw.hfcD.timer.function = (void *) hfcs_Timer; + cs->hw.hfcD.timer.data = (long) cs; + init_timer(&cs->hw.hfcD.timer); + reset_hfcs(cs); + cs->cardmsg = &hfcs_card_msg; + cs->irq_func = &hfcs_interrupt; + return (1); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/hisax.h linux.pre11.3/drivers/isdn/hisax/hisax.h --- linux.vanilla/drivers/isdn/hisax/hisax.h Wed Mar 24 10:55:17 1999 +++ linux.pre11.3/drivers/isdn/hisax/hisax.h Mon Jul 19 23:59:33 1999 @@ -1,8 +1,62 @@ -/* $Id: hisax.h,v 2.14 1998/02/11 17:28:04 keil Exp $ +/* $Id: hisax.h,v 2.30 1999/07/14 12:38:38 werner Exp $ * Basic declarations, defines and prototypes * * $Log: hisax.h,v $ + * Revision 2.30 1999/07/14 12:38:38 werner + * Added changes for echo channel handling + * + * Revision 2.29 1999/07/12 21:05:14 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 2.28 1999/07/05 23:51:46 werner + * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl + * hisaxctrl id 10 + * + * Revision 2.27 1999/07/01 08:11:38 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 2.26 1998/11/15 23:54:45 keil + * changes from 2.0 + * + * Revision 2.25 1998/09/30 22:28:42 keil + * More work for ISAR support + * + * Revision 2.24 1998/08/20 13:50:39 keil + * More support for hybrid modem (not working yet) + * + * Revision 2.23 1998/08/13 23:36:31 keil + * HiSax 3.1 - don't work stable with current LinkLevel + * + * Revision 2.22 1998/07/15 15:01:28 calle + * Support for AVM passive PCMCIA cards: + * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0 + * + * Revision 2.21 1998/05/25 14:10:05 keil + * HiSax 3.0 + * X.75 and leased are working again. + * + * Revision 2.20 1998/05/25 12:57:57 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * + * Revision 2.19 1998/04/15 16:39:15 keil + * Add S0Box and Teles PCI support + * + * Revision 2.18 1998/03/26 07:10:04 paul + * The jumpmatrix table in struct Fsm was an array of "int". This is not + * large enough for pointers to functions on Linux/Alpha (instant crash + * on "insmod hisax). Now there is a typedef for the pointer to function. + * This also prevents warnings about "incompatible pointer types". + * + * Revision 2.17 1998/03/19 13:18:43 keil + * Start of a CAPI like interface for supplementary Service + * first service: SUSPEND + * + * Revision 2.16 1998/03/09 23:19:25 keil + * Changes for PCMCIA + * * Revision 2.14 1998/02/11 17:28:04 keil * Niccy PnP/PCI support * @@ -71,121 +125,104 @@ #include #include #include -#include +#include + +#define REQUEST 0 +#define CONFIRM 1 +#define INDICATION 2 +#define RESPONSE 3 + +#define HW_ENABLE 0x0000 +#define HW_RESET 0x0004 +#define HW_POWERUP 0x0008 +#define HW_ACTIVATE 0x0010 +#define HW_DEACTIVATE 0x0018 +#define HW_INFO2 0x0020 +#define HW_INFO3 0x0030 +#define HW_INFO4_P8 0x0040 +#define HW_INFO4_P10 0x0048 +#define HW_RSYNC 0x0060 +#define HW_TESTLOOP 0x0070 +#define CARD_RESET 0x00F0 +#define CARD_INIT 0x00F2 +#define CARD_RELEASE 0x00F3 +#define CARD_TEST 0x00F4 +#define CARD_AUX_IND 0x00F5 +#define CARD_LOAD_FIRM 0x00F6 + +#define PH_ACTIVATE 0x0100 +#define PH_DEACTIVATE 0x0110 +#define PH_DATA 0x0120 +#define PH_PULL 0x0130 +#define PH_TESTLOOP 0x0140 +#define PH_PAUSE 0x0150 +#define MPH_ACTIVATE 0x0180 +#define MPH_DEACTIVATE 0x0190 +#define MPH_INFORMATION 0x01A0 + +#define DL_ESTABLISH 0x0200 +#define DL_RELEASE 0x0210 +#define DL_DATA 0x0220 +#define DL_FLUSH 0x0224 +#define DL_UNIT_DATA 0x0230 +#define MDL_ASSIGN 0x0280 +#define MDL_REMOVE 0x0284 +#define MDL_ERROR 0x0288 +#define MDL_INFO_SETUP 0x02E0 +#define MDL_INFO_CONN 0x02E4 +#define MDL_INFO_REL 0x02E8 + +#define CC_SETUP 0x0300 +#define CC_RESUME 0x0304 +#define CC_MORE_INFO 0x0310 +#define CC_IGNORE 0x0320 +#define CC_REJECT 0x0324 +#define CC_SETUP_COMPL 0x0330 +#define CC_PROCEEDING 0x0340 +#define CC_ALERTING 0x0344 +#define CC_PROGRESS 0x0348 +#define CC_CONNECT 0x0350 +#define CC_CHARGE 0x0354 +#define CC_NOTIFY 0x0358 +#define CC_DISCONNECT 0x0360 +#define CC_RELEASE 0x0368 +#define CC_SUSPEND 0x0370 +#define CC_PROCEED_SEND 0x0374 +#define CC_REDIR 0x0378 +#define CC_T303 0x0383 +#define CC_T304 0x0384 +#define CC_T305 0x0385 +#define CC_T308_1 0x0388 +#define CC_T308_2 0x038A +#define CC_T309 0x0309 +#define CC_T310 0x0390 +#define CC_T313 0x0393 +#define CC_T318 0x0398 +#define CC_T319 0x0399 +#define CC_NOSETUP_RSP 0x03E0 +#define CC_SETUP_ERR 0x03E1 +#define CC_SUSPEND_ERR 0x03E2 +#define CC_RESUME_ERR 0x03E3 +#define CC_CONNECT_ERR 0x03E4 +#define CC_RELEASE_ERR 0x03E5 +#define CC_RESTART 0x03F4 +#define CC_TDSS1_IO 0x13F4 /* DSS1 IO user timer */ + +/* define maximum number of possible waiting incoming calls */ +#define MAX_WAITING_CALLS 2 -#define PH_ACTIVATE_REQ 0x0010 -#define PH_ACTIVATE_CNF 0x0011 -#define PH_ACTIVATE_IND 0x0012 -#define PH_DEACTIVATE_REQ 0x0020 -#define PH_DEACTIVATE_CNF 0x0021 -#define PH_DEACTIVATE_IND 0x0022 -#define PH_DEACT_REQ 0x0024 -#define PH_DEACT_CNF 0x0025 -#define PH_DEACT_IND 0x0026 -#define PH_DEACT_ACK 0x0027 -#define PH_TESTLOOP_REQ 0x0030 -#define PH_PAUSE_CNF 0x0035 -#define PH_PAUSE_IND 0x0036 -#define PH_PULL_REQ 0x0038 -#define PH_PULL_CNF 0x0039 -#define PH_PULL_IND 0x003A -#define PH_DATA_REQ 0x0040 -#define PH_DATA_IND 0x0042 - -#define PH_INFO3_REQ 0x0008 -#define PH_INFO2_IND 0x000A -#define PH_ENABLE_REQ 0x0004 -#define PH_RSYNC_IND 0x0006 -#define PH_RESET_REQ 0x0000 -#define PH_RESET_IND 0x0002 -#define PH_POWERUP_CNF 0x0003 -#define PH_ACTIV_REQ 0x000C -#define PH_I4_P8_IND 0x000D -#define PH_I4_P10_IND 0x000F - -#define MDL_ASSIGN_REQ 0x0050 -#define MDL_ASSIGN_IND 0x0052 -#define MDL_REMOVE_REQ 0x0054 -#define MDL_ERROR_REQ 0x0058 -#define MDL_ERROR_IND 0x005A -#define CARD_AUX_IND 0x005E - -#define DL_UNIT_DATA 6 -#define CC_ESTABLISH 7 -#define DL_ESTABLISH 8 -#define DL_DATA 9 - -#define CC_CONNECT 15 -#define DL_RELEASE 20 -#define DL_FLUSH 21 - -#define CC_REJECT 23 - -#define CC_SETUP_REQ 24 -#define CC_SETUP_CNF 25 -#define CC_SETUP_IND 26 -#define CC_SETUP_RSP 27 -#define CC_SETUP_COMPLETE_IND 28 - -#define CC_DISCONNECT_REQ 29 -#define CC_DISCONNECT_IND 30 - -#define CC_RELEASE_CNF 31 -#define CC_RELEASE_IND 32 -#define CC_RELEASE_REQ 33 - -#define CC_REJECT_REQ 34 - -#define CC_PROCEEDING_IND 35 - -#define CC_DLRL 36 -#define CC_DLEST 37 - -#define CC_ALERTING_REQ 38 -#define CC_ALERTING_IND 39 - -#define DL_STOP 40 -#define DL_START 41 - -#define MDL_INFO_SETUP 42 -#define MDL_INFO_CONN 43 -#define MDL_INFO_REL 44 -#define MDL_NOTEIPROC 46 - -#define LC_ESTABLISH 47 -#define LC_RELEASE 48 - -#define CC_INFO_CHARGE 52 - -#define CC_MORE_INFO 53 -#define CC_IGNORE 54 -#define CC_RESTART 55 - - -#define CC_T303 60 -#define CC_T304 61 -#define CC_T305 62 -#define CC_T308_1 64 -#define CC_T308_2 65 -#define CC_T310 66 -#define CC_T313 67 -#define CC_T318 68 -#define CC_T319 69 - -#define CC_NOSETUP_RSP_ERR 70 -#define CC_SETUP_ERR 71 -#define CC_CONNECT_ERR 72 -#define CC_RELEASE_ERR 73 - -#define CARD_RESET 0x1001 -#define CARD_SETIRQ 0x1002 -#define CARD_INIT 0x1003 -#define CARD_RELEASE 0x1004 -#define CARD_TEST 0x1005 #ifdef __KERNEL__ +/* include only l3dss1 specific process structures, but no other defines */ +#ifdef CONFIG_HISAX_EURO + #define l3dss1_process + #include "l3dss1.h" + #undef l3dss1_process +#endif CONFIG_HISAX_EURO + #define MAX_DFRAME_LEN 260 +#define MAX_DFRAME_LEN_L1 300 #define HSCX_BUFMAX 4096 #define MAX_DATA_SIZE (HSCX_BUFMAX - 4) #define MAX_DATA_MEM (HSCX_BUFMAX + 64) @@ -193,6 +230,8 @@ #define MAX_HEADER_LEN 4 #define MAX_WINDOW 8 #define MAX_MON_FRAME 32 +#define MAX_DLOG_SPACE 2048 +#define MAX_BLOG_SPACE 256 /* #define I4L_IRQ_FLAG SA_INTERRUPT */ #define I4L_IRQ_FLAG 0 @@ -201,8 +240,12 @@ * Statemachine */ +struct FsmInst; + +typedef void (* FSMFNPTR)(struct FsmInst *, int, void *); + struct Fsm { - int *jumpmatrix; + FSMFNPTR *jumpmatrix; int state_count, event_count; char **strEvent, **strState; }; @@ -213,7 +256,7 @@ int debug; void *userdata; int userint; - void (*printdebug) (struct FsmInst *, char *); + void (*printdebug) (struct FsmInst *, char *, ...); }; struct FsmNode { @@ -249,9 +292,10 @@ struct FsmInst l1m; struct FsmTimer timer; void (*l1l2) (struct PStack *, int, void *); - void (*l1man) (struct PStack *, int, void *); + void (*l1hw) (struct PStack *, int, void *); void (*l1tei) (struct PStack *, int, void *); int mode, bc; + int delay; }; #define GROUP_TEI 127 @@ -266,49 +310,57 @@ #define FLG_ORIG 2 #define FLG_MOD128 3 #define FLG_PEND_REL 4 -#define FLG_L3_INIT 5 -#define FLG_T200_RUN 6 +#define FLG_L3_INIT 5 +#define FLG_T200_RUN 6 #define FLG_ACK_PEND 7 #define FLG_REJEXC 8 #define FLG_OWN_BUSY 9 #define FLG_PEER_BUSY 10 #define FLG_DCHAN_BUSY 11 +#define FLG_L1_ACTIV 12 +#define FLG_ESTAB_PEND 13 +#define FLG_PTP 14 +#define FLG_FIXED_TEI 15 struct Layer2 { int tei; - int tei_wanted; int sap; int maxlen; unsigned int flag; - int vs, va, vr; + unsigned int vs, va, vr; int rc; - int window; - int sow; + unsigned int window; + unsigned int sow; struct sk_buff *windowar[MAX_WINDOW]; struct sk_buff_head i_queue; struct sk_buff_head ui_queue; void (*l2l1) (struct PStack *, int, void *); - void (*l2man) (struct PStack *, int, void *); void (*l2l3) (struct PStack *, int, void *); void (*l2tei) (struct PStack *, int, void *); struct FsmInst l2m; struct FsmTimer t200, t203; int T200, N200, T203; int debug; - char debug_id[32]; + char debug_id[16]; }; struct Layer3 { - void (*l3l4) (struct l3_process *, int, void *); + void (*l3l4) (struct PStack *, int, void *); + void (*l3ml3) (struct PStack *, int, void *); void (*l3l2) (struct PStack *, int, void *); + struct FsmInst l3m; + struct FsmTimer l3m_timer; + struct sk_buff_head squeue; struct l3_process *proc; struct l3_process *global; int N303; int debug; + char debug_id[8]; }; struct LLInterface { void (*l4l3) (struct PStack *, int, void *); + int (*l4l3_proto) (struct PStack *, isdn_ctrl *); void *userdata; void (*l1writewakeup) (struct PStack *, int); void (*l2writewakeup) (struct PStack *, int); @@ -321,20 +373,19 @@ struct FsmTimer t202; int T202, N202, debug; void (*layer) (struct PStack *, int, void *); - void (*manl1) (struct PStack *, int, void *); - void (*manl2) (struct PStack *, int, void *); }; +#define NO_CAUSE 254 struct Param { - int cause; - int loc; + u_char cause; + u_char loc; + u_char diag[6]; int bchannel; - setup_parm setup; /* from isdnif.h numbers and Serviceindicator */ - int chargeinfo; /* Charge Info - only for 1tr6 in - * the moment - */ + int chargeinfo; int spv; /* SPV Flag */ + setup_parm setup; /* from isdnif.h numbers and Serviceindicator */ + u_char moderate; /* transfer mode and rate (bearer octet 4) */ }; @@ -343,9 +394,17 @@ struct Layer1 l1; struct Layer2 l2; struct Layer3 l3; - struct LLInterface lli; + struct LLInterface lli; struct Management ma; int protocol; /* EDSS1 or 1TR6 */ + + /* protocol specific data fields */ + union + { u_char uuuu; /* only as dummy */ +#ifdef CONFIG_HISAX_EURO + dss1_stk_priv dss1; /* private dss1 data */ +#endif CONFIG_HISAX_EURO + } prot; }; struct l3_process { @@ -358,24 +417,69 @@ struct Channel *chan; struct PStack *st; struct l3_process *next; + ulong redir_result; + + /* protocol specific data fields */ + union + { u_char uuuu; /* only when euro not defined, avoiding empty union */ +#ifdef CONFIG_HISAX_EURO + dss1_proc_priv dss1; /* private dss1 data */ +#endif CONFIG_HISAX_EURO + } prot; }; struct hscx_hw { + int hscx; + int rcvidx; + int count; /* Current skb sent count */ + u_char *rcvbuf; /* B-Channel receive Buffer */ + u_char tsaxr0; + u_char tsaxr1; +}; + +struct isar_reg { + unsigned int Flags; + volatile u_char bstat; + volatile u_char iis; + volatile u_char cmsb; + volatile u_char clsb; + volatile u_char par[8]; +}; + +struct isar_hw { + int dpath; + int rcvidx; + int txcnt; + int mml; + u_char *rcvbuf; /* B-Channel receive Buffer */ + struct isar_reg *reg; +}; + +struct hdlc_stat_reg { + u_char cmd __attribute__((packed)); + u_char xml __attribute__((packed)); + u_char mode __attribute__((packed)); + u_char fill __attribute__((packed)); +}; + +struct hdlc_hw { + union { + u_int ctrl; + struct hdlc_stat_reg sr; + } ctrl; + u_int stat; int rcvidx; int count; /* Current skb sent count */ u_char *rcvbuf; /* B-Channel receive Buffer */ - struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ }; struct hfcB_hw { unsigned int *send; int f1; int f2; - struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ }; struct tiger_hw { - struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ u_int *send; u_int *s_irq; u_int *s_end; @@ -397,8 +501,7 @@ u_char s_state; }; -struct foreign_hw { - int doHDLCprocessing; +struct amd7930_hw { u_char *tx_buff; u_char *rv_buff; int rv_buff_in; @@ -407,9 +510,9 @@ struct hdlc_state *hdlc_state; struct tq_struct tq_rcv; struct tq_struct tq_xmt; - struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ }; + #define BC_FLG_INIT 1 #define BC_FLG_ACTIV 2 #define BC_FLG_BUSY 3 @@ -420,6 +523,7 @@ #define L1_MODE_NULL 0 #define L1_MODE_TRANS 1 #define L1_MODE_HDLC 2 +#define L1_MODE_MODEM 7 struct BCState { int channel; @@ -427,34 +531,26 @@ int Flag; struct IsdnCardState *cs; int tx_cnt; /* B-Channel transmit counter */ + struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ struct sk_buff_head rqueue; /* B-Channel receive Queue */ struct sk_buff_head squeue; /* B-Channel send Queue */ struct PStack *st; + u_char *blog; + struct timer_list transbusy; struct tq_struct tqueue; int event; int (*BC_SetStack) (struct PStack *, struct BCState *); void (*BC_Close) (struct BCState *); union { struct hscx_hw hscx; + struct hdlc_hw hdlc; + struct isar_hw isar; struct hfcB_hw hfc; struct tiger_hw tiger; - struct foreign_hw foreign; + struct amd7930_hw amd7930; } hw; }; -struct LcFsm { - int type; - int delay; - struct FsmInst lcfi; - struct Channel *ch; - void (*lccall) (struct LcFsm *, int, void *); - struct PStack *st; - int l2_establish; - int l2_start; - struct FsmTimer act_timer; - char debug_id[32]; -}; - struct Channel { struct PStack *b_st, *d_st; struct IsdnCardState *cs; @@ -462,11 +558,10 @@ int chan; int incoming; struct FsmInst fi; - struct LcFsm *lc_d; - struct LcFsm *lc_b; struct FsmTimer drel_timer, dial_timer; int debug; int l2_protocol, l2_active_protocol; + int l3_protocol; int data_open; struct l3_process *proc; setup_parm setup; /* from isdnif.h numbers and Serviceindicator */ @@ -487,21 +582,33 @@ unsigned int counter; unsigned int status; struct timer_list tl; + unsigned int MFlag; + struct BCState *bcs; + u_char *transbuf; + u_char *rcvbuf; + unsigned int transp; + unsigned int rcvp; + unsigned int transcnt; + unsigned int rcvcnt; + u_char IER; + u_char FCR; + u_char LCR; + u_char MCR; u_char ctrl_reg; -}; +}; struct teles3_hw { unsigned int cfg_reg; - unsigned int isac; - unsigned int hscx[2]; - unsigned int isacfifo; - unsigned int hscxfifo[2]; -}; + signed int isac; + signed int hscx[2]; + signed int isacfifo; + signed int hscxfifo[2]; +}; struct teles0_hw { unsigned int cfg_reg; unsigned int membase; -}; +}; struct avm_hw { unsigned int cfg_reg; @@ -510,7 +617,7 @@ unsigned int isacfifo; unsigned int hscxfifo[2]; unsigned int counter; -}; +}; struct ix1_hw { unsigned int cfg_reg; @@ -521,7 +628,8 @@ }; struct diva_hw { - unsigned int cfg_reg; + unsigned long cfg_reg; + unsigned long pci_cfg; unsigned int ctrl; unsigned int isac_adr; unsigned int isac; @@ -530,7 +638,7 @@ unsigned int status; struct timer_list tl; u_char ctrl_reg; -}; +}; struct asus_hw { unsigned int cfg_reg; @@ -559,6 +667,9 @@ unsigned int hscx; unsigned int reset_on; unsigned int reset_off; + struct isar_reg isar; + unsigned int chip; + unsigned int bus; }; struct spt_hw { @@ -566,7 +677,7 @@ unsigned int isac; unsigned int hscx[2]; unsigned char res_irq; -}; +}; struct mic_hw { unsigned int cfg_reg; @@ -587,6 +698,31 @@ unsigned char last_is0; }; +struct hfcPCI_hw { + unsigned char cirm; + unsigned char ctmt; + unsigned char conn; + unsigned char mst_m; + unsigned char int_m1; + unsigned char int_m2; + unsigned char int_s1; + unsigned char sctrl; + unsigned char sctrl_r; + unsigned char sctrl_e; + unsigned char trm; + unsigned char stat; + unsigned char fifo; + unsigned char fifo_en; + unsigned char bswapped; + /* unsigned int *send; */ + unsigned char pci_bus; + unsigned char pci_device_fn; + unsigned char *pci_io; /* start of PCI IO memory */ + void *share_start; /* shared memory for Fifos start */ + void *fifos; /* FIFO memory */ + struct timer_list timer; +}; + struct hfcD_hw { unsigned int addr; unsigned int bfifosize; @@ -608,24 +744,118 @@ struct timer_list timer; }; -#define HW_IOM1 0 -#define HW_IPAC 1 -#define FLG_TWO_DCHAN 4 -#define FLG_L1_DBUSY 5 -#define FLG_DBUSY_TIMER 6 -#define FLG_LOCK_ATOMIC 7 -#define HW_MON0_RX_END 8 -#define HW_MON1_RX_END 9 -#define HW_MON0_TX_END 10 -#define HW_MON1_TX_END 11 +struct isurf_hw { + unsigned int reset; + unsigned int isac; + unsigned int isar; + struct isar_reg isar_r; +}; + +struct saphir_hw { + unsigned int cfg_reg; + unsigned int ale; + unsigned int isac; + unsigned int hscx; + struct timer_list timer; +}; + +struct bkm_hw { + unsigned int base; + /* A4T stuff */ + unsigned int isac_adr; + unsigned int isac_ale; + unsigned int jade_adr; + unsigned int jade_ale; + /* Scitel Quadro stuff */ + unsigned int plx_adr; + unsigned int data_adr; +}; + +struct gazel_hw { + unsigned int cfg_reg; + unsigned int pciaddr[2]; + signed int ipac; + signed int isac; + signed int hscx[2]; + signed int isacfifo; + signed int hscxfifo[2]; + unsigned char timeslot; + unsigned char iom2; +}; + +#ifdef CONFIG_HISAX_TESTEMU +struct te_hw { + unsigned char *sfifo; + unsigned char *sfifo_w; + unsigned char *sfifo_r; + unsigned char *sfifo_e; + int sfifo_cnt; + unsigned int stat; +#ifdef COMPAT_HAS_NEW_WAITQ + wait_queue_head_t rwaitq; + wait_queue_head_t swaitq; +#else + struct wait_queue *rwaitq; + struct wait_queue *swaitq; +#endif +}; +#endif + +struct arcofi_msg { + struct arcofi_msg *next; + u_char receive; + u_char len; + u_char msg[10]; +}; + +struct isac_chip { + int ph_state; + u_char *mon_tx; + u_char *mon_rx; + int mon_txp; + int mon_txc; + int mon_rxp; + struct arcofi_msg *arcofi_list; + struct timer_list arcofitimer; +#ifdef COMPAT_HAS_NEW_WAITQ + wait_queue_head_t arcofi_wait; +#else + struct wait_queue *arcofi_wait; +#endif + u_char arcofi_bc; + u_char arcofi_state; + u_char mocr; + u_char adf2; +}; + +struct hfcd_chip { + int ph_state; +}; + +struct hfcpci_chip { + int ph_state; +}; + +#define HW_IOM1 0 +#define HW_IPAC 1 +#define HW_ISAR 2 +#define FLG_TWO_DCHAN 4 +#define FLG_L1_DBUSY 5 +#define FLG_DBUSY_TIMER 6 +#define FLG_LOCK_ATOMIC 7 +#define FLG_ARCOFI_TIMER 8 +#define FLG_ARCOFI_ERROR 9 struct IsdnCardState { unsigned char typ; unsigned char subtyp; int protocol; unsigned int irq; - int HW_Flags; + unsigned long irq_flags; + int HW_Flags; int *busy_flag; + int chanlimit; /* limited number of B-chans to use */ + int logecho; /* log echo if supported by card */ union { struct elsa_hw elsa; struct teles0_hw teles0; @@ -640,8 +870,15 @@ struct mic_hw mic; struct njet_hw njet; struct hfcD_hw hfcD; + struct hfcPCI_hw hfcpci; struct ix1_hw niccy; - struct foreign_interface *foreign; + struct isurf_hw isurf; + struct saphir_hw saphir; +#ifdef CONFIG_HISAX_TESTEMU + struct te_hw te; +#endif + struct bkm_hw ax; + struct gazel_hw gazel; } hw; int myid; isdn_if iif; @@ -657,10 +894,21 @@ void (*BC_Write_Reg) (struct IsdnCardState *, int, u_char, u_char); void (*BC_Send_Data) (struct BCState *); int (*cardmsg) (struct IsdnCardState *, int, void *); - void (*l1cmd) (struct IsdnCardState *, int, void *); - struct Channel channel[2]; - struct BCState bcs[2]; + void (*setstack_d) (struct PStack *, struct IsdnCardState *); + void (*DC_Close) (struct IsdnCardState *); + void (*irq_func) (int, void *, struct pt_regs *); + struct Channel channel[2+MAX_WAITING_CALLS]; + struct BCState bcs[2+MAX_WAITING_CALLS]; struct PStack *stlist; + struct sk_buff_head rq, sq; /* D-channel queues */ + int cardnr; + char *dlog; + int debug; + union { + struct isac_chip isac; + struct hfcd_chip hfcd; + struct hfcpci_chip hfcpci; + } dc; u_char *rcvbuf; int rcvidx; struct sk_buff *tx_skb; @@ -668,19 +916,6 @@ int event; struct tq_struct tqueue; struct timer_list dbusytimer; - struct sk_buff_head rq, sq; /* D-channel queues */ - int ph_state; - int cardnr; - int dlogflag; - char *dlogspace; - int debug; - u_char *mon_tx; - u_char *mon_rx; - int mon_txp; - int mon_txc; - int mon_rxp; - u_char mocr; - void (*setstack_d) (struct PStack *, struct IsdnCardState *); }; #define MON0_RX 1 @@ -688,6 +923,8 @@ #define MON0_TX 4 #define MON1_TX 8 +#define HISAX_MAX_CARDS 8 + #define ISDN_CTYPE_16_0 1 #define ISDN_CTYPE_8_0 2 #define ISDN_CTYPE_16_3 3 @@ -712,19 +949,37 @@ #define ISDN_CTYPE_SEDLBAUER_PCMCIA 22 #define ISDN_CTYPE_AMD7930 23 #define ISDN_CTYPE_NICCY 24 -#define ISDN_CTYPE_DBRI 25 +#define ISDN_CTYPE_S0BOX 25 +#define ISDN_CTYPE_A1_PCMCIA 26 +#define ISDN_CTYPE_FRITZPCI 27 +#define ISDN_CTYPE_SEDLBAUER_FAX 28 +#define ISDN_CTYPE_ISURF 29 +#define ISDN_CTYPE_ACERP10 30 +#define ISDN_CTYPE_HSTSAPHIR 31 +#define ISDN_CTYPE_BKM_A4T 32 +#define ISDN_CTYPE_SCT_QUADRO 33 +#define ISDN_CTYPE_GAZEL 34 +#define ISDN_CTYPE_HFC_PCI 35 +#define ISDN_CTYPE_COUNT 35 -#define ISDN_CTYPE_COUNT 25 #ifdef ISDN_CHIP_ISAC #undef ISDN_CHIP_ISAC #endif +#ifndef __initfunc +#define __initfunc(__arginit) __arginit +#endif + +#ifndef __initdata +#define __initdata +#endif + #define HISAX_INITFUNC(__arginit) __initfunc(__arginit) #define HISAX_INITDATA __initdata #ifdef CONFIG_HISAX_16_0 -#define CARD_TELES0 (1<< ISDN_CTYPE_16_0) | (1<< ISDN_CTYPE_8_0) +#define CARD_TELES0 1 #ifndef ISDN_CHIP_ISAC #define ISDN_CHIP_ISAC 1 #endif @@ -733,8 +988,7 @@ #endif #ifdef CONFIG_HISAX_16_3 -#define CARD_TELES3 (1<< ISDN_CTYPE_16_3) | (1<< ISDN_CTYPE_PNP) | \ - (1<< ISDN_CTYPE_TELESPCMCIA) | (1<< ISDN_CTYPE_COMPAQ_ISA) +#define CARD_TELES3 1 #ifndef ISDN_CHIP_ISAC #define ISDN_CHIP_ISAC 1 #endif @@ -742,18 +996,44 @@ #define CARD_TELES3 0 #endif +#ifdef CONFIG_HISAX_TELESPCI +#define CARD_TELESPCI 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_TELESPCI 0 +#endif + #ifdef CONFIG_HISAX_AVM_A1 -#define CARD_AVM_A1 (1<< ISDN_CTYPE_A1) -#ifndef ISDN_CHIP_ISAC +#define CARD_AVM_A1 1 +#ifndef ISDN_CHIP_ISAC #define ISDN_CHIP_ISAC 1 #endif #else #define CARD_AVM_A1 0 #endif +#ifdef CONFIG_HISAX_AVM_A1_PCMCIA +#define CARD_AVM_A1_PCMCIA 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_AVM_A1_PCMCIA 0 +#endif + +#ifdef CONFIG_HISAX_FRITZPCI +#define CARD_FRITZPCI 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_FRITZPCI 0 +#endif + #ifdef CONFIG_HISAX_ELSA -#define CARD_ELSA (1<< ISDN_CTYPE_ELSA) | (1<< ISDN_CTYPE_ELSA_PNP) | \ - (1<< ISDN_CTYPE_ELSA_PCMCIA) | (1<< ISDN_CTYPE_ELSA_PCI) +#define CARD_ELSA 1 #ifndef ISDN_CHIP_ISAC #define ISDN_CHIP_ISAC 1 #endif @@ -765,9 +1045,8 @@ #define CARD_ELSA 0 #endif - #ifdef CONFIG_HISAX_IX1MICROR2 -#define CARD_IX1MICROR2 (1 << ISDN_CTYPE_IX1MICROR2) +#define CARD_IX1MICROR2 1 #ifndef ISDN_CHIP_ISAC #define ISDN_CHIP_ISAC 1 #endif @@ -776,7 +1055,7 @@ #endif #ifdef CONFIG_HISAX_DIEHLDIVA -#define CARD_DIEHLDIVA (1 << ISDN_CTYPE_DIEHLDIVA) +#define CARD_DIEHLDIVA 1 #ifndef ISDN_CHIP_ISAC #define ISDN_CHIP_ISAC 1 #endif @@ -785,7 +1064,7 @@ #endif #ifdef CONFIG_HISAX_ASUSCOM -#define CARD_ASUSCOM (1 << ISDN_CTYPE_ASUSCOM) +#define CARD_ASUSCOM 1 #ifndef ISDN_CHIP_ISAC #define ISDN_CHIP_ISAC 1 #endif @@ -794,7 +1073,7 @@ #endif #ifdef CONFIG_HISAX_TELEINT -#define CARD_TELEINT (1 << ISDN_CTYPE_TELEINT) +#define CARD_TELEINT 1 #ifndef ISDN_CHIP_ISAC #define ISDN_CHIP_ISAC 1 #endif @@ -803,7 +1082,7 @@ #endif #ifdef CONFIG_HISAX_SEDLBAUER -#define CARD_SEDLBAUER (1 << ISDN_CTYPE_SEDLBAUER) | (1 << ISDN_CTYPE_SEDLBAUER_PCMCIA) +#define CARD_SEDLBAUER 1 #ifndef ISDN_CHIP_ISAC #define ISDN_CHIP_ISAC 1 #endif @@ -812,7 +1091,7 @@ #endif #ifdef CONFIG_HISAX_SPORTSTER -#define CARD_SPORTSTER (1 << ISDN_CTYPE_SPORTSTER) +#define CARD_SPORTSTER 1 #ifndef ISDN_CHIP_ISAC #define ISDN_CHIP_ISAC 1 #endif @@ -821,7 +1100,7 @@ #endif #ifdef CONFIG_HISAX_MIC -#define CARD_MIC (1 << ISDN_CTYPE_MIC) +#define CARD_MIC 1 #ifndef ISDN_CHIP_ISAC #define ISDN_CHIP_ISAC 1 #endif @@ -830,7 +1109,7 @@ #endif #ifdef CONFIG_HISAX_NETJET -#define CARD_NETJET (1 << ISDN_CTYPE_NETJET) +#define CARD_NETJET 1 #ifndef ISDN_CHIP_ISAC #define ISDN_CHIP_ISAC 1 #endif @@ -838,20 +1117,27 @@ #define CARD_NETJET 0 #endif -#ifdef CONFIG_HISAX_TELES3C -#define CARD_TELES3C (1<< ISDN_CTYPE_TELES3C) +#ifdef CONFIG_HISAX_HFCS +#define CARD_HFCS 1 #else -#define CARD_TELES3C 0 +#define CARD_HFCS 0 +#endif + +#ifdef CONFIG_HISAX_HFC_PCI +#define CARD_HFC_PCI 1 +extern int hfcpci_set_echo(struct IsdnCardState *, int); +#else +#define CARD_HFC_PCI 0 #endif #ifdef CONFIG_HISAX_AMD7930 -#define CARD_AMD7930 (1 << ISDN_CTYPE_AMD7930) +#define CARD_AMD7930 1 #else #define CARD_AMD7930 0 #endif #ifdef CONFIG_HISAX_NICCY -#define CARD_NICCY (1 << ISDN_CTYPE_NICCY) +#define CARD_NICCY 1 #ifndef ISDN_CHIP_ISAC #define ISDN_CHIP_ISAC 1 #endif @@ -859,18 +1145,68 @@ #define CARD_NICCY 0 #endif -#ifdef CONFIG_HISAX_DBRI -#define CARD_DBRI (1 << ISDN_CTYPE_DBRI) +#ifdef CONFIG_HISAX_ISURF +#define CARD_ISURF 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_ISURF 0 +#endif + +#ifdef CONFIG_HISAX_S0BOX +#define CARD_S0BOX 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_S0BOX 0 +#endif + +#ifdef CONFIG_HISAX_HSTSAPHIR +#define CARD_HSTSAPHIR 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif #else -#define CARD_DBRI 0 +#define CARD_HSTSAPHIR 0 #endif +#ifdef CONFIG_HISAX_TESTEMU +#define CARD_TESTEMU 1 +#define ISDN_CTYPE_TESTEMU 99 +#undef ISDN_CTYPE_COUNT +#define ISDN_CTYPE_COUNT ISDN_CTYPE_TESTEMU +#else +#define CARD_TESTEMU 0 +#endif -#define SUPORTED_CARDS (CARD_TELES0 | CARD_TELES3 | CARD_AVM_A1 | CARD_ELSA \ - | CARD_IX1MICROR2 | CARD_DIEHLDIVA | CARD_ASUSCOM \ - | CARD_TELEINT | CARD_SEDLBAUER | CARD_SPORTSTER \ - | CARD_MIC | CARD_NETJET | CARD_TELES3C | CARD_AMD7930 \ - | CARD_NICCY | CARD_DBRI) +#ifdef CONFIG_HISAX_BKM_A4T +#define CARD_BKM_A4T 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_BKM_A4T 0 +#endif + +#ifdef CONFIG_HISAX_SCT_QUADRO +#define CARD_SCT_QUADRO 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_SCT_QUADRO 0 +#endif + +#ifdef CONFIG_HISAX_GAZEL +#define CARD_GAZEL 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_GAZEL 0 +#endif #define TEI_PER_CARD 0 @@ -883,25 +1219,38 @@ #undef TEI_PER_CARD #define TEI_PER_CARD 1 #define HISAX_EURO_SENDCOMPLETE 1 -#ifdef CONFIG_HISAX_ML +#define EXT_BEARER_CAPS 1 +#define HISAX_SEND_STD_LLC_IE 1 +#ifdef CONFIG_HISAX_NO_SENDCOMPLETE #undef HISAX_EURO_SENDCOMPLETE #endif +#ifdef CONFIG_HISAX_NO_LLC +#undef HISAX_SEND_STD_LLC_IE +#endif #undef HISAX_DE_AOC #ifdef CONFIG_DE_AOC #define HISAX_DE_AOC 1 #endif #endif -#if TEI_PER_CARD -#undef TEI_FIXED -#endif +/* L1 Debug */ +#define L1_DEB_WARN 0x01 +#define L1_DEB_INTSTAT 0x02 +#define L1_DEB_ISAC 0x04 +#define L1_DEB_ISAC_FIFO 0x08 +#define L1_DEB_HSCX 0x10 +#define L1_DEB_HSCX_FIFO 0x20 +#define L1_DEB_LAPD 0x40 +#define L1_DEB_IPAC 0x80 +#define L1_DEB_RECEIVE_FRAME 0x100 +#define L1_DEB_MONITOR 0x200 +#define DEB_DLOG_HEX 0x400 +#define DEB_DLOG_VERBOSE 0x800 -#undef PTP_DATA_LINK +#define L2FRAME_DEBUG -#ifdef PTP_DATA_LINK -#undef TEI_FIXED -#define TEI_FIXED 0 -#define LAYER2_WATCHING +#ifdef L2FRAME_DEBUG +extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir); #endif struct IsdnCard { @@ -911,17 +1260,26 @@ struct IsdnCardState *cs; }; -void setstack_isdnl2(struct PStack *st, char *debug_id); -int HiSax_inithardware(int *); -void HiSax_closehardware(void); +void init_bcstate(struct IsdnCardState *cs, int bc); void setstack_HiSax(struct PStack *st, struct IsdnCardState *cs); unsigned int random_ri(void); -void setstack_isdnl3(struct PStack *st, struct Channel *chanp); void HiSax_addlist(struct IsdnCardState *sp, struct PStack *st); +void HiSax_rmlist(struct IsdnCardState *sp, struct PStack *st); + +void setstack_l1_B(struct PStack *st); + +void setstack_tei(struct PStack *st); +void setstack_manager(struct PStack *st); + +void setstack_isdnl2(struct PStack *st, char *debug_id); void releasestack_isdnl2(struct PStack *st); +void setstack_transl2(struct PStack *st); +void releasestack_transl2(struct PStack *st); + +void setstack_l3dc(struct PStack *st, struct Channel *chanp); +void setstack_l3bc(struct PStack *st, struct Channel *chanp); void releasestack_isdnl3(struct PStack *st); -void HiSax_rmlist(struct IsdnCardState *sp, struct PStack *st); u_char *findie(u_char * p, int size, u_char ie, int wanted_set); int getcallref(u_char * p); @@ -937,20 +1295,18 @@ void FsmRestartTimer(struct FsmTimer *ft, int millisec, int event, void *arg, int where); void FsmDelTimer(struct FsmTimer *ft, int where); -void jiftime(char *s, long mark); +int jiftime(char *s, long mark); int HiSax_command(isdn_ctrl * ic); int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb); -void HiSax_putstatus(struct IsdnCardState *csta, char *buf); +void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...); +void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args); void HiSax_reportcard(int cardnr); int QuickHex(char *txt, u_char * p, int cnt); -void LogFrame(struct IsdnCardState *sp, u_char * p, int size); -void dlogframe(struct IsdnCardState *sp, u_char * p, int size, char *comment); +void LogFrame(struct IsdnCardState *cs, u_char * p, int size); +void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir); void iecpy(u_char * dest, u_char * iestart, int ieoffset); -void setstack_transl2(struct PStack *st); -void releasestack_transl2(struct PStack *st); -void setstack_tei(struct PStack *st); -void setstack_manager(struct PStack *st); +int discard_queue(struct sk_buff_head *q); #ifdef ISDN_CHIP_ISAC void setstack_isac(struct PStack *st, struct IsdnCardState *cs); #endif /* ISDN_CHIP_ISAC */ @@ -958,18 +1314,21 @@ #define HZDELAY(jiffs) {int tout = jiffs; while (tout--) udelay(1000000/HZ);} -int ll_run(struct IsdnCardState *csta); -void ll_stop(struct IsdnCardState *csta); +int ll_run(struct IsdnCardState *cs); +void ll_stop(struct IsdnCardState *cs); void CallcNew(void); void CallcFree(void); -int CallcNewChan(struct IsdnCardState *csta); -void CallcFreeChan(struct IsdnCardState *csta); +int CallcNewChan(struct IsdnCardState *cs); +void CallcFreeChan(struct IsdnCardState *cs); void Isdnl1New(void); void Isdnl1Free(void); void Isdnl2New(void); void Isdnl2Free(void); -void init_tei(struct IsdnCardState *sp, int protocol); -void release_tei(struct IsdnCardState *sp); +void Isdnl3New(void); +void Isdnl3Free(void); +void init_tei(struct IsdnCardState *cs, int protocol); +void release_tei(struct IsdnCardState *cs); char *HiSax_getrev(const char *revision); void TeiNew(void); void TeiFree(void); +int certification_check(int output); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/hscx.c linux.pre11.3/drivers/isdn/hisax/hscx.c --- linux.vanilla/drivers/isdn/hisax/hscx.c Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/hisax/hscx.c Mon Jul 19 23:59:34 1999 @@ -1,11 +1,43 @@ -/* $Id: hscx.c,v 1.7 1998/02/12 23:07:36 keil Exp $ +/* $Id: hscx.c,v 1.17 1999/07/01 08:11:41 keil Exp $ * hscx.c HSCX specific routines * - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) * * * $Log: hscx.c,v $ + * Revision 1.17 1999/07/01 08:11:41 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 1.16 1998/11/15 23:54:48 keil + * changes from 2.0 + * + * Revision 1.15 1998/08/20 13:50:42 keil + * More support for hybrid modem (not working yet) + * + * Revision 1.14 1998/08/13 23:36:33 keil + * HiSax 3.1 - don't work stable with current LinkLevel + * + * Revision 1.13 1998/06/26 22:03:28 keil + * send flags between hdlc frames + * + * Revision 1.12 1998/06/09 18:26:01 keil + * PH_DEACTIVATE B-channel every time signaled to higher layer + * + * Revision 1.11 1998/05/25 14:10:07 keil + * HiSax 3.0 + * X.75 and leased are working again. + * + * Revision 1.10 1998/05/25 12:57:59 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * + * Revision 1.9 1998/04/15 16:45:33 keil + * new init code + * + * Revision 1.8 1998/03/19 13:16:24 keil + * fix the correct release of the hscx + * * Revision 1.7 1998/02/12 23:07:36 keil * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * @@ -30,6 +62,7 @@ #define __NO_VERSION__ #include "hisax.h" #include "hscx.h" +#include "isac.h" #include "isdnl1.h" #include @@ -56,21 +89,20 @@ modehscx(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; - int hscx = bcs->channel; + int hscx = bcs->hw.hscx.hscx; - if (cs->debug & L1_DEB_HSCX) { - char tmp[40]; - sprintf(tmp, "hscx %c mode %d ichan %d", + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hscx %c mode %d ichan %d", 'A' + hscx, mode, bc); - debugl1(cs, tmp); - } bcs->mode = mode; - cs->BC_Write_Reg(cs, hscx, HSCX_CCR1, 0x85); + bcs->channel = bc; cs->BC_Write_Reg(cs, hscx, HSCX_XAD1, 0xFF); cs->BC_Write_Reg(cs, hscx, HSCX_XAD2, 0xFF); cs->BC_Write_Reg(cs, hscx, HSCX_RAH2, 0xFF); cs->BC_Write_Reg(cs, hscx, HSCX_XBCH, 0x0); cs->BC_Write_Reg(cs, hscx, HSCX_RLCR, 0x0); + cs->BC_Write_Reg(cs, hscx, HSCX_CCR1, + test_bit(HW_IPAC, &cs->HW_Flags) ? 0x82 : 0x85); cs->BC_Write_Reg(cs, hscx, HSCX_CCR2, 0x30); cs->BC_Write_Reg(cs, hscx, HSCX_XCCR, 7); cs->BC_Write_Reg(cs, hscx, HSCX_RCCR, 7); @@ -81,23 +113,25 @@ if (bc == 0) { cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, - test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : 0x2f); + test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0); cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, - test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : 0x2f); + test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0); } else { - cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0x3); - cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0x3); + cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, bcs->hw.hscx.tsaxr1); + cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, bcs->hw.hscx.tsaxr1); } switch (mode) { case (L1_MODE_NULL): - cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0xff); - cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0xff); + cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0x1f); + cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0x1f); cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x84); break; case (L1_MODE_TRANS): cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0xe4); break; case (L1_MODE_HDLC): + cs->BC_Write_Reg(cs, hscx, HSCX_CCR1, + test_bit(HW_IPAC, &cs->HW_Flags) ? 0x8a : 0x8d); cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x8c); break; } @@ -114,89 +148,106 @@ mark_bh(IMMEDIATE_BH); } -static void +void hscx_l2l1(struct PStack *st, int pr, void *arg) { struct sk_buff *skb = arg; long flags; switch (pr) { - case (PH_DATA_REQ): + case (PH_DATA | REQUEST): save_flags(flags); cli(); - if (st->l1.bcs->hw.hscx.tx_skb) { + if (st->l1.bcs->tx_skb) { skb_queue_tail(&st->l1.bcs->squeue, skb); restore_flags(flags); } else { - st->l1.bcs->hw.hscx.tx_skb = skb; + st->l1.bcs->tx_skb = skb; test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); st->l1.bcs->hw.hscx.count = 0; restore_flags(flags); st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); } break; - case (PH_PULL_IND): - if (st->l1.bcs->hw.hscx.tx_skb) { + case (PH_PULL | INDICATION): + if (st->l1.bcs->tx_skb) { printk(KERN_WARNING "hscx_l2l1: this shouldn't happen\n"); break; } test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - st->l1.bcs->hw.hscx.tx_skb = skb; + st->l1.bcs->tx_skb = skb; st->l1.bcs->hw.hscx.count = 0; st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); break; - case (PH_PULL_REQ): - if (!st->l1.bcs->hw.hscx.tx_skb) { + case (PH_PULL | REQUEST): + if (!st->l1.bcs->tx_skb) { test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - st->l1.l1l2(st, PH_PULL_CNF, NULL); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); } else test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; + case (PH_ACTIVATE | REQUEST): + test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + modehscx(st->l1.bcs, st->l1.mode, st->l1.bc); + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | REQUEST): + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | CONFIRM): + test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + modehscx(st->l1.bcs, 0, st->l1.bc); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); + break; } - } void close_hscxstate(struct BCState *bcs) { - struct sk_buff *skb; - - modehscx(bcs, 0, 0); + modehscx(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { if (bcs->hw.hscx.rcvbuf) { kfree(bcs->hw.hscx.rcvbuf); bcs->hw.hscx.rcvbuf = NULL; } - while ((skb = skb_dequeue(&bcs->rqueue))) { - dev_kfree_skb(skb); - } - while ((skb = skb_dequeue(&bcs->squeue))) { - dev_kfree_skb(skb); + if (bcs->blog) { + kfree(bcs->blog); + bcs->blog = NULL; } - if (bcs->hw.hscx.tx_skb) { - dev_kfree_skb(bcs->hw.hscx.tx_skb); - bcs->hw.hscx.tx_skb = NULL; + discard_queue(&bcs->rqueue); + discard_queue(&bcs->squeue); + if (bcs->tx_skb) { + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } } } -static int -open_hscxstate(struct IsdnCardState *cs, - int bc) +int +open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs) { - struct BCState *bcs = cs->bcs + bc; - if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { printk(KERN_WARNING - "HiSax: No memory for hscx.rcvbuf\n"); + "HiSax: No memory for hscx.rcvbuf\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); return (1); } + if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for bcs->blog\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + return (2); + } skb_queue_head_init(&bcs->rqueue); skb_queue_head_init(&bcs->squeue); } - bcs->hw.hscx.tx_skb = NULL; + bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); bcs->event = 0; bcs->hw.hscx.rcvidx = 0; @@ -204,77 +255,78 @@ return (0); } -static void -hscx_manl1(struct PStack *st, int pr, - void *arg) -{ - switch (pr) { - case (PH_ACTIVATE_REQ): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - modehscx(st->l1.bcs, st->l1.mode, st->l1.bc); - st->l1.l1man(st, PH_ACTIVATE_CNF, NULL); - break; - case (PH_DEACTIVATE_REQ): - if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) - modehscx(st->l1.bcs, 0, 0); - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - break; - } -} - int setstack_hscx(struct PStack *st, struct BCState *bcs) { - if (open_hscxstate(st->l1.hardware, bcs->channel)) + bcs->channel = st->l1.bc; + if (open_hscxstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; st->l2.l2l1 = hscx_l2l1; - st->ma.manl1 = hscx_manl1; setstack_manager(st); bcs->st = st; + setstack_l1_B(st); return (0); } HISAX_INITFUNC(void clear_pending_hscx_ints(struct IsdnCardState *cs)) { - int val; - char tmp[64]; + int val, eval; val = cs->BC_Read_Reg(cs, 1, HSCX_ISTA); - sprintf(tmp, "HSCX B ISTA %x", val); - debugl1(cs, tmp); + debugl1(cs, "HSCX B ISTA %x", val); if (val & 0x01) { - val = cs->BC_Read_Reg(cs, 1, HSCX_EXIR); - sprintf(tmp, "HSCX B EXIR %x", val); - debugl1(cs, tmp); - } else if (val & 0x02) { - val = cs->BC_Read_Reg(cs, 0, HSCX_EXIR); - sprintf(tmp, "HSCX A EXIR %x", val); - debugl1(cs, tmp); + eval = cs->BC_Read_Reg(cs, 1, HSCX_EXIR); + debugl1(cs, "HSCX B EXIR %x", eval); + } + if (val & 0x02) { + eval = cs->BC_Read_Reg(cs, 0, HSCX_EXIR); + debugl1(cs, "HSCX A EXIR %x", eval); } val = cs->BC_Read_Reg(cs, 0, HSCX_ISTA); - sprintf(tmp, "HSCX A ISTA %x", val); - debugl1(cs, tmp); + debugl1(cs, "HSCX A ISTA %x", val); val = cs->BC_Read_Reg(cs, 1, HSCX_STAR); - sprintf(tmp, "HSCX B STAR %x", val); - debugl1(cs, tmp); + debugl1(cs, "HSCX B STAR %x", val); val = cs->BC_Read_Reg(cs, 0, HSCX_STAR); - sprintf(tmp, "HSCX A STAR %x", val); - debugl1(cs, tmp); + debugl1(cs, "HSCX A STAR %x", val); + /* disable all IRQ */ cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0xFF); cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0xFF); - cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0); - cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0); } -HISAX_INITFUNC(void +HISAX_INITFUNC(void inithscx(struct IsdnCardState *cs)) { cs->bcs[0].BC_SetStack = setstack_hscx; cs->bcs[1].BC_SetStack = setstack_hscx; cs->bcs[0].BC_Close = close_hscxstate; cs->bcs[1].BC_Close = close_hscxstate; + cs->bcs[0].hw.hscx.hscx = 0; + cs->bcs[1].hw.hscx.hscx = 1; + cs->bcs[0].hw.hscx.tsaxr0 = 0x2f; + cs->bcs[0].hw.hscx.tsaxr1 = 3; + cs->bcs[1].hw.hscx.tsaxr0 = 0x2f; + cs->bcs[1].hw.hscx.tsaxr1 = 3; modehscx(cs->bcs, 0, 0); modehscx(cs->bcs + 1, 0, 0); +} + +HISAX_INITFUNC(void +inithscxisac(struct IsdnCardState *cs, int part)) +{ + if (part & 1) { + clear_pending_isac_ints(cs); + clear_pending_hscx_ints(cs); + initisac(cs); + inithscx(cs); + } + if (part & 2) { + /* Reenable all IRQ */ + cs->writeisac(cs, ISAC_MASK, 0); + cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0); + cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0); + /* RESET Receiver and Transmitter */ + cs->writeisac(cs, ISAC_CMDR, 0x41); + } } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/hscx.h linux.pre11.3/drivers/isdn/hisax/hscx.h --- linux.vanilla/drivers/isdn/hisax/hscx.h Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/hisax/hscx.h Mon Jul 19 23:59:34 1999 @@ -1,4 +1,4 @@ -/* $Id: hscx.h,v 1.3 1997/07/27 21:38:35 keil Exp $ +/* $Id: hscx.h,v 1.4 1998/04/15 16:45:34 keil Exp $ * hscx.h HSCX specific defines * @@ -6,6 +6,9 @@ * * * $Log: hscx.h,v $ + * Revision 1.4 1998/04/15 16:45:34 keil + * new init code + * * Revision 1.3 1997/07/27 21:38:35 keil * new B-channel interface * @@ -44,3 +47,4 @@ extern void modehscx(struct BCState *bcs, int mode, int bc); extern void clear_pending_hscx_ints(struct IsdnCardState *cs); extern void inithscx(struct IsdnCardState *cs); +extern void inithscxisac(struct IsdnCardState *cs, int part); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/hscx_irq.c linux.pre11.3/drivers/isdn/hisax/hscx_irq.c --- linux.vanilla/drivers/isdn/hisax/hscx_irq.c Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/hisax/hscx_irq.c Mon Jul 19 23:59:34 1999 @@ -1,12 +1,27 @@ -/* $Id: hscx_irq.c,v 1.7 1998/02/12 23:07:37 keil Exp $ +/* $Id: hscx_irq.c,v 1.12 1999/07/01 08:11:42 keil Exp $ * hscx_irq.c low level b-channel stuff for Siemens HSCX * - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) * * This is an include file for fast inline IRQ stuff * * $Log: hscx_irq.c,v $ + * Revision 1.12 1999/07/01 08:11:42 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 1.11 1998/11/15 23:54:49 keil + * changes from 2.0 + * + * Revision 1.10 1998/08/13 23:36:35 keil + * HiSax 3.1 - don't work stable with current LinkLevel + * + * Revision 1.9 1998/06/24 14:44:51 keil + * Fix recovery of TX IRQ loss + * + * Revision 1.8 1998/04/10 10:35:22 paul + * fixed (silly?) warnings from egcs on Alpha. + * * Revision 1.7 1998/02/12 23:07:37 keil * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * @@ -85,7 +100,7 @@ if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "hscx_empty_fifo: incoming packet too large"); - WriteHSCXCMDR(cs, bcs->channel, 0x80); + WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); bcs->hw.hscx.rcvidx = 0; return; } @@ -93,17 +108,16 @@ bcs->hw.hscx.rcvidx += count; save_flags(flags); cli(); - READHSCXFIFO(cs, bcs->channel, ptr, count); - WriteHSCXCMDR(cs, bcs->channel, 0x80); + READHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count); + WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); restore_flags(flags); if (cs->debug & L1_DEB_HSCX_FIFO) { - char tmp[256]; - char *t = tmp; + char *t = bcs->blog; t += sprintf(t, "hscx_empty_fifo %c cnt %d", - bcs->channel ? 'B' : 'A', count); + bcs->hw.hscx.hscx ? 'B' : 'A', count); QuickHex(t, ptr, count); - debugl1(cs, tmp); + debugl1(cs, bcs->blog); } } @@ -120,36 +134,35 @@ if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "hscx_fill_fifo"); - if (!bcs->hw.hscx.tx_skb) + if (!bcs->tx_skb) return; - if (bcs->hw.hscx.tx_skb->len <= 0) + if (bcs->tx_skb->len <= 0) return; more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; - if (bcs->hw.hscx.tx_skb->len > fifo_size) { + if (bcs->tx_skb->len > fifo_size) { more = !0; count = fifo_size; } else - count = bcs->hw.hscx.tx_skb->len; + count = bcs->tx_skb->len; - waitforXFW(cs, bcs->channel); + waitforXFW(cs, bcs->hw.hscx.hscx); save_flags(flags); cli(); - ptr = bcs->hw.hscx.tx_skb->data; - skb_pull(bcs->hw.hscx.tx_skb, count); + ptr = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); bcs->tx_cnt -= count; bcs->hw.hscx.count += count; - WRITEHSCXFIFO(cs, bcs->channel, ptr, count); - WriteHSCXCMDR(cs, bcs->channel, more ? 0x8 : 0xa); + WRITEHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count); + WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa); restore_flags(flags); if (cs->debug & L1_DEB_HSCX_FIFO) { - char tmp[256]; - char *t = tmp; + char *t = bcs->blog; t += sprintf(t, "hscx_fill_fifo %c cnt %d", - bcs->channel ? 'B' : 'A', count); + bcs->hw.hscx.hscx ? 'B' : 'A', count); QuickHex(t, ptr, count); - debugl1(cs, tmp); + debugl1(cs, bcs->blog); } } @@ -161,7 +174,6 @@ struct sk_buff *skb; int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; int count; - char tmp[32]; if (!test_bit(BC_FLG_INIT, &bcs->Flag)) return; @@ -173,11 +185,9 @@ if (cs->debug & L1_DEB_WARN) debugl1(cs, "HSCX invalid frame"); if ((r & 0x40) && bcs->mode) - if (cs->debug & L1_DEB_WARN) { - sprintf(tmp, "HSCX RDO mode=%d", + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX RDO mode=%d", bcs->mode); - debugl1(cs, tmp); - } if (!(r & 0x20)) if (cs->debug & L1_DEB_WARN) debugl1(cs, "HSCX CRC error"); @@ -189,13 +199,12 @@ count = fifo_size; hscx_empty_fifo(bcs, count); if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { - if (cs->debug & L1_DEB_HSCX_FIFO) { - sprintf(tmp, "HX Frame %d", count); - debugl1(cs, tmp); - } + if (cs->debug & L1_DEB_HSCX_FIFO) + debugl1(cs, "HX Frame %d", count); if (!(skb = dev_alloc_skb(count))) printk(KERN_WARNING "HSCX: receive out of memory\n"); else { + SET_SKB_FREE(skb); memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); skb_queue_tail(&bcs->rqueue, skb); } @@ -211,6 +220,7 @@ if (!(skb = dev_alloc_skb(fifo_size))) printk(KERN_WARNING "HiSax: receive out of memory\n"); else { + SET_SKB_FREE(skb); memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); skb_queue_tail(&bcs->rqueue, skb); } @@ -219,20 +229,20 @@ } } if (val & 0x10) { /* XPR */ - if (bcs->hw.hscx.tx_skb) { - if (bcs->hw.hscx.tx_skb->len) { + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { hscx_fill_fifo(bcs); return; } else { if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->hw.hscx.tx_skb->pkt_type)) + (PACKET_NOACK != bcs->tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count); - dev_kfree_skb(bcs->hw.hscx.tx_skb); + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); bcs->hw.hscx.count = 0; - bcs->hw.hscx.tx_skb = NULL; + bcs->tx_skb = NULL; } } - if ((bcs->hw.hscx.tx_skb = skb_dequeue(&bcs->squeue))) { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { bcs->hw.hscx.count = 0; test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); hscx_fill_fifo(bcs); @@ -249,73 +259,60 @@ u_char exval; struct BCState *bcs; - char tmp[32]; if (val & 0x01) { bcs = cs->bcs + 1; exval = READHSCX(cs, 1, HSCX_EXIR); - if (exval == 0x40) { + if (exval & 0x40) { if (bcs->mode == 1) hscx_fill_fifo(bcs); else { /* Here we lost an TX interrupt, so * restart transmitting the whole frame. */ - if (bcs->hw.hscx.tx_skb) { - skb_push(bcs->hw.hscx.tx_skb, bcs->hw.hscx.count); + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.hscx.count); bcs->tx_cnt += bcs->hw.hscx.count; bcs->hw.hscx.count = 0; } - WriteHSCXCMDR(cs, bcs->channel, 0x01); - if (cs->debug & L1_DEB_WARN) { - sprintf(tmp, "HSCX B EXIR %x Lost TX", exval); - debugl1(cs, tmp); - } + WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX B EXIR %x Lost TX", exval); } - } else if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "HSCX B EXIR %x", exval); - debugl1(cs, tmp); - } + } else if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX B EXIR %x", exval); } if (val & 0xf8) { - if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "HSCX B interrupt %x", val); - debugl1(cs, tmp); - } + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX B interrupt %x", val); hscx_interrupt(cs, val, 1); } if (val & 0x02) { bcs = cs->bcs; exval = READHSCX(cs, 0, HSCX_EXIR); - if (exval == 0x40) { + if (exval & 0x40) { if (bcs->mode == L1_MODE_TRANS) hscx_fill_fifo(bcs); else { /* Here we lost an TX interrupt, so * restart transmitting the whole frame. */ - if (bcs->hw.hscx.tx_skb) { - skb_push(bcs->hw.hscx.tx_skb, bcs->hw.hscx.count); + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.hscx.count); bcs->tx_cnt += bcs->hw.hscx.count; bcs->hw.hscx.count = 0; } - WriteHSCXCMDR(cs, bcs->channel, 0x01); - if (cs->debug & L1_DEB_WARN) { - sprintf(tmp, "HSCX A EXIR %x Lost TX", exval); - debugl1(cs, tmp); - } + WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX A EXIR %x Lost TX", exval); } - } else if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "HSCX A EXIR %x", exval); - debugl1(cs, tmp); - } + } else if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX A EXIR %x", exval); } if (val & 0x04) { exval = READHSCX(cs, 0, HSCX_ISTA); - if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "HSCX A interrupt %x", exval); - debugl1(cs, tmp); - } + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX A interrupt %x", exval); hscx_interrupt(cs, exval, 0); } } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/ipac.h linux.pre11.3/drivers/isdn/hisax/ipac.h --- linux.vanilla/drivers/isdn/hisax/ipac.h Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/hisax/ipac.h Mon Jul 19 23:59:34 1999 @@ -1,4 +1,4 @@ -/* $Id: ipac.h,v 1.2 1997/10/29 18:51:21 keil Exp $ +/* $Id: ipac.h,v 1.3 1998/04/15 16:48:09 keil Exp $ * ipac.h IPAC specific defines * @@ -6,6 +6,9 @@ * * * $Log: ipac.h,v $ + * Revision 1.3 1998/04/15 16:48:09 keil + * IPAC_ATX added + * * Revision 1.2 1997/10/29 18:51:21 keil * New files * @@ -26,6 +29,7 @@ #define IPAC_ACFG 0xC3 #define IPAC_AOE 0xC4 #define IPAC_ARX 0xC5 +#define IPAC_ATX 0xC5 #define IPAC_PITA1 0xC6 #define IPAC_PITA2 0xC7 #define IPAC_POTA1 0xC8 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isac.c linux.pre11.3/drivers/isdn/hisax/isac.c --- linux.vanilla/drivers/isdn/hisax/isac.c Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/hisax/isac.c Mon Jul 19 23:59:34 1999 @@ -1,11 +1,43 @@ -/* $Id: isac.c,v 1.12 1998/02/12 23:07:40 keil Exp $ +/* $Id: isac.c,v 1.21 1999/07/12 21:05:17 keil Exp $ * isac.c ISAC specific routines * - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) * + * This file is (c) under GNU PUBLIC LICENSE + * For changes and modifications please read + * ../../../Documentation/isdn/HiSax.cert * * $Log: isac.c,v $ + * Revision 1.21 1999/07/12 21:05:17 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 1.20 1999/07/09 08:23:06 keil + * Fix ISAC lost TX IRQ handling + * + * Revision 1.19 1999/07/01 08:11:43 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 1.18 1998/11/15 23:54:51 keil + * changes from 2.0 + * + * Revision 1.17 1998/08/13 23:36:37 keil + * HiSax 3.1 - don't work stable with current LinkLevel + * + * Revision 1.16 1998/05/25 12:58:01 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * + * Revision 1.15 1998/04/15 16:45:32 keil + * new init code + * + * Revision 1.14 1998/04/10 10:35:26 paul + * fixed (silly?) warnings from egcs on Alpha. + * + * Revision 1.13 1998/03/07 22:57:01 tsbogend + * made HiSax working on Linux/Alpha + * * Revision 1.12 1998/02/12 23:07:40 keil * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * @@ -47,6 +79,7 @@ #define __NO_VERSION__ #include "hisax.h" #include "isac.h" +#include "arcofi.h" #include "isdnl1.h" #include @@ -63,60 +96,47 @@ int val; val = cs->readisac(cs, ISAC_RBCH); - printk(KERN_INFO "%s ISAC version : %s\n", s, ISACVer[(val >> 5) & 3]); + printk(KERN_INFO "%s ISAC version (%x): %s\n", s, val, ISACVer[(val >> 5) & 3]); } static void ph_command(struct IsdnCardState *cs, unsigned int command) { - if (cs->debug & L1_DEB_ISAC) { - char tmp[32]; - sprintf(tmp, "ph_command %x", command); - debugl1(cs, tmp); - } + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ph_command %x", command); cs->writeisac(cs, ISAC_CIX0, (command << 2) | 3); } -static void -manl1_msg(struct IsdnCardState *cs, int msg, void *arg) { - struct PStack *st; - - st = cs->stlist; - while (st) { - st->ma.manl1(st, msg, arg); - st = st->next; - } -} static void isac_new_ph(struct IsdnCardState *cs) { - switch (cs->ph_state) { + switch (cs->dc.isac.ph_state) { case (ISAC_IND_RS): case (ISAC_IND_EI): ph_command(cs, ISAC_CMD_DUI); - manl1_msg(cs, PH_RESET_IND, NULL); + l1_msg(cs, HW_RESET | INDICATION, NULL); break; case (ISAC_IND_DID): - manl1_msg(cs, PH_DEACT_CNF, NULL); + l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL); break; case (ISAC_IND_DR): - manl1_msg(cs, PH_DEACT_IND, NULL); + l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL); break; case (ISAC_IND_PU): - manl1_msg(cs, PH_POWERUP_CNF, NULL); + l1_msg(cs, HW_POWERUP | CONFIRM, NULL); break; case (ISAC_IND_RSY): - manl1_msg(cs, PH_RSYNC_IND, NULL); + l1_msg(cs, HW_RSYNC | INDICATION, NULL); break; case (ISAC_IND_ARD): - manl1_msg(cs, PH_INFO2_IND, NULL); + l1_msg(cs, HW_INFO2 | INDICATION, NULL); break; case (ISAC_IND_AI8): - manl1_msg(cs, PH_I4_P8_IND, NULL); + l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); break; case (ISAC_IND_AI10): - manl1_msg(cs, PH_I4_P10_IND, NULL); + l1_msg(cs, HW_INFO4_P10 | INDICATION, NULL); break; default: break; @@ -130,13 +150,12 @@ if (!cs) return; - if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { if (cs->debug) debugl1(cs, "D-Channel Busy cleared"); stptr = cs->stlist; while (stptr != NULL) { - stptr->l1.l1l2(stptr, PH_PAUSE_CNF, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); stptr = stptr->next; } } @@ -146,14 +165,10 @@ DChannel_proc_rcv(cs); if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) DChannel_proc_xmt(cs); - if (test_and_clear_bit(D_RX_MON0, &cs->event)) - test_and_set_bit(HW_MON0_TX_END, &cs->HW_Flags); if (test_and_clear_bit(D_RX_MON1, &cs->event)) - test_and_set_bit(HW_MON1_TX_END, &cs->HW_Flags); - if (test_and_clear_bit(D_TX_MON0, &cs->event)) - test_and_set_bit(HW_MON0_RX_END, &cs->HW_Flags); + arcofi_fsm(cs, ARCOFI_RX_END, NULL); if (test_and_clear_bit(D_TX_MON1, &cs->event)) - test_and_set_bit(HW_MON1_RX_END, &cs->HW_Flags); + arcofi_fsm(cs, ARCOFI_TX_END, NULL); } void @@ -165,13 +180,10 @@ if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) debugl1(cs, "isac_empty_fifo"); - if ((cs->rcvidx + count) >= MAX_DFRAME_LEN) { - if (cs->debug & L1_DEB_WARN) { - char tmp[40]; - sprintf(tmp, "isac_empty_fifo overrun %d", + if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "isac_empty_fifo overrun %d", cs->rcvidx + count); - debugl1(cs, tmp); - } cs->writeisac(cs, ISAC_CMDR, 0x80); cs->rcvidx = 0; return; @@ -184,12 +196,11 @@ cs->writeisac(cs, ISAC_CMDR, 0x80); restore_flags(flags); if (cs->debug & L1_DEB_ISAC_FIFO) { - char tmp[128]; - char *t = tmp; + char *t = cs->dlog; t += sprintf(t, "isac_empty_fifo cnt %d", count); QuickHex(t, ptr, count); - debugl1(cs, tmp); + debugl1(cs, cs->dlog); } } @@ -231,12 +242,11 @@ cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); add_timer(&cs->dbusytimer); if (cs->debug & L1_DEB_ISAC_FIFO) { - char tmp[128]; - char *t = tmp; + char *t = cs->dlog; t += sprintf(t, "isac_fill_fifo cnt %d", count); QuickHex(t, ptr, count); - debugl1(cs, tmp); + debugl1(cs, cs->dlog); } } @@ -255,12 +265,9 @@ struct sk_buff *skb; unsigned int count; long flags; - char tmp[32]; - if (cs->debug & L1_DEB_ISAC) { - sprintf(tmp, "ISAC interrupt %x", val); - debugl1(cs, tmp); - } + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC interrupt %x", val); if (val & 0x80) { /* RME */ exval = cs->readisac(cs, ISAC_RSTA); if ((exval & 0x70) != 0x20) { @@ -283,6 +290,7 @@ if (!(skb = alloc_skb(count, GFP_ATOMIC))) printk(KERN_WARNING "HiSax: D receive out of memory\n"); else { + SET_SKB_FREE(skb); memcpy(skb_put(skb, count), cs->rcvbuf, count); skb_queue_tail(&cs->rq, skb); } @@ -310,7 +318,7 @@ isac_fill_fifo(cs); goto afterXPR; } else { - dev_kfree_skb(cs->tx_skb); + idev_kfree_skb(cs->tx_skb, FREE_WRITE); cs->tx_cnt = 0; cs->tx_skb = NULL; } @@ -323,12 +331,20 @@ } afterXPR: if (val & 0x04) { /* CISQ */ - cs->ph_state = (cs->readisac(cs, ISAC_CIX0) >> 2) & 0xf; - if (cs->debug & L1_DEB_ISAC) { - sprintf(tmp, "ph_state change %x", cs->ph_state); - debugl1(cs, tmp); + exval = cs->readisac(cs, ISAC_CIR0); + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC CIR0 %02X", exval ); + if (exval & 2) { + cs->dc.isac.ph_state = (exval >> 2) & 0xf; + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ph_state change %x", cs->dc.isac.ph_state); + isac_sched_event(cs, D_L1STATECHANGE); + } + if (exval & 1) { + exval = cs->readisac(cs, ISAC_CIR1); + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC CIR1 %02X", exval ); } - isac_sched_event(cs, D_L1STATECHANGE); } if (val & 0x02) { /* SIN */ /* never */ @@ -337,131 +353,149 @@ } if (val & 0x01) { /* EXI */ exval = cs->readisac(cs, ISAC_EXIR); - if (cs->debug & L1_DEB_WARN) { - sprintf(tmp, "ISAC EXIR %02x", exval); - debugl1(cs, tmp); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "ISAC EXIR %02x", exval); + if (exval & 0x80) { /* XMR */ + debugl1(cs, "ISAC XMR"); + printk(KERN_WARNING "HiSax: ISAC XMR\n"); } - if (exval & 0x04) { - v1 = cs->readisac(cs, ISAC_MOSR); - if (cs->debug & L1_DEB_WARN) { - sprintf(tmp, "ISAC MOSR %02x", v1); - debugl1(cs, tmp); + if (exval & 0x40) { /* XDU */ + debugl1(cs, "ISAC XDU"); + printk(KERN_WARNING "HiSax: ISAC XDU\n"); + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + isac_sched_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { /* Restart frame */ + skb_push(cs->tx_skb, cs->tx_cnt); + cs->tx_cnt = 0; + isac_fill_fifo(cs); + } else { + printk(KERN_WARNING "HiSax: ISAC XDU no skb\n"); + debugl1(cs, "ISAC XDU no skb"); } + } + if (exval & 0x04) { /* MOS */ + v1 = cs->readisac(cs, ISAC_MOSR); + if (cs->debug & L1_DEB_MONITOR) + debugl1(cs, "ISAC MOSR %02x", v1); #if ARCOFI_USE if (v1 & 0x08) { - if (!cs->mon_rx) { - if (!(cs->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) { + if (!cs->dc.isac.mon_rx) { + if (!(cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC MON RX out of memory!"); - cs->mocr &= 0xf0; - cs->mocr |= 0x0a; - cs->writeisac(cs, ISAC_MOCR, cs->mocr); + cs->dc.isac.mocr &= 0xf0; + cs->dc.isac.mocr |= 0x0a; + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); goto afterMONR0; } else - cs->mon_rxp = 0; + cs->dc.isac.mon_rxp = 0; } - if (cs->mon_rxp >= MAX_MON_FRAME) { - cs->mocr &= 0xf0; - cs->mocr |= 0x0a; - cs->writeisac(cs, ISAC_MOCR, cs->mocr); - cs->mon_rxp = 0; + if (cs->dc.isac.mon_rxp >= MAX_MON_FRAME) { + cs->dc.isac.mocr &= 0xf0; + cs->dc.isac.mocr |= 0x0a; + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->dc.isac.mon_rxp = 0; if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC MON RX overflow!"); goto afterMONR0; } - cs->mon_rx[cs->mon_rxp++] = cs->readisac(cs, ISAC_MOR0); - if (cs->debug & L1_DEB_WARN) { - sprintf(tmp, "ISAC MOR0 %02x", cs->mon_rx[cs->mon_rxp -1]); - debugl1(cs, tmp); - } - if (cs->mon_rxp == 1) { - cs->mocr |= 0x04; - cs->writeisac(cs, ISAC_MOCR, cs->mocr); + cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = cs->readisac(cs, ISAC_MOR0); + if (cs->debug & L1_DEB_MONITOR) + debugl1(cs, "ISAC MOR0 %02x", cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp -1]); + if (cs->dc.isac.mon_rxp == 1) { + cs->dc.isac.mocr |= 0x04; + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); } } afterMONR0: if (v1 & 0x80) { - if (!cs->mon_rx) { - if (!(cs->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) { + if (!cs->dc.isac.mon_rx) { + if (!(cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC MON RX out of memory!"); - cs->mocr &= 0x0f; - cs->mocr |= 0xa0; - cs->writeisac(cs, ISAC_MOCR, cs->mocr); + cs->dc.isac.mocr &= 0x0f; + cs->dc.isac.mocr |= 0xa0; + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); goto afterMONR1; } else - cs->mon_rxp = 0; + cs->dc.isac.mon_rxp = 0; } - if (cs->mon_rxp >= MAX_MON_FRAME) { - cs->mocr &= 0x0f; - cs->mocr |= 0xa0; - cs->writeisac(cs, ISAC_MOCR, cs->mocr); - cs->mon_rxp = 0; + if (cs->dc.isac.mon_rxp >= MAX_MON_FRAME) { + cs->dc.isac.mocr &= 0x0f; + cs->dc.isac.mocr |= 0xa0; + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->dc.isac.mon_rxp = 0; if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC MON RX overflow!"); goto afterMONR1; } - cs->mon_rx[cs->mon_rxp++] = cs->readisac(cs, ISAC_MOR1); - if (cs->debug & L1_DEB_WARN) { - sprintf(tmp, "ISAC MOR1 %02x", cs->mon_rx[cs->mon_rxp -1]); - debugl1(cs, tmp); - } - if (cs->mon_rxp == 1) { - cs->mocr |= 0x40; - cs->writeisac(cs, ISAC_MOCR, cs->mocr); - } + cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = cs->readisac(cs, ISAC_MOR1); + if (cs->debug & L1_DEB_MONITOR) + debugl1(cs, "ISAC MOR1 %02x", cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp -1]); + cs->dc.isac.mocr |= 0x40; + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); } afterMONR1: if (v1 & 0x04) { - cs->mocr &= 0xf0; - cs->mocr |= 0x0a; - cs->writeisac(cs, ISAC_MOCR, cs->mocr); + cs->dc.isac.mocr &= 0xf0; + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->dc.isac.mocr |= 0x0a; + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); isac_sched_event(cs, D_RX_MON0); } if (v1 & 0x40) { - cs->mocr &= 0x0f; - cs->mocr |= 0xa0; - cs->writeisac(cs, ISAC_MOCR, cs->mocr); + cs->dc.isac.mocr &= 0x0f; + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->dc.isac.mocr |= 0xa0; + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); isac_sched_event(cs, D_RX_MON1); } if (v1 & 0x02) { - if (!cs->mon_tx) { - cs->mocr &= 0xf0; - cs->mocr |= 0x0a; - cs->writeisac(cs, ISAC_MOCR, cs->mocr); + if ((!cs->dc.isac.mon_tx) || (cs->dc.isac.mon_txc && + (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc) && + !(v1 & 0x08))) { + cs->dc.isac.mocr &= 0xf0; + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->dc.isac.mocr |= 0x0a; + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); + if (cs->dc.isac.mon_txc && + (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) + isac_sched_event(cs, D_TX_MON0); goto AfterMOX0; } - if (cs->mon_txp >= cs->mon_txc) { - if (cs->mon_txc) - isac_sched_event(cs, D_TX_MON0); + if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) { + isac_sched_event(cs, D_TX_MON0); goto AfterMOX0; } cs->writeisac(cs, ISAC_MOX0, - cs->mon_tx[cs->mon_txp++]); - if (cs->debug & L1_DEB_WARN) { - sprintf(tmp, "ISAC %02x -> MOX0", cs->mon_tx[cs->mon_txp -1]); - debugl1(cs, tmp); - } + cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]); + if (cs->debug & L1_DEB_MONITOR) + debugl1(cs, "ISAC %02x -> MOX0", cs->dc.isac.mon_tx[cs->dc.isac.mon_txp -1]); } AfterMOX0: if (v1 & 0x20) { - if (!cs->mon_tx) { - cs->mocr &= 0x0f; - cs->mocr |= 0xa0; - cs->writeisac(cs, ISAC_MOCR, cs->mocr); + if ((!cs->dc.isac.mon_tx) || (cs->dc.isac.mon_txc && + (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc) && + !(v1 & 0x80))) { + cs->dc.isac.mocr &= 0x0f; + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->dc.isac.mocr |= 0xa0; + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); + if (cs->dc.isac.mon_txc && + (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) + isac_sched_event(cs, D_TX_MON1); goto AfterMOX1; } - if (cs->mon_txp >= cs->mon_txc) { - if (cs->mon_txc) - isac_sched_event(cs, D_TX_MON1); + if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) { + isac_sched_event(cs, D_TX_MON1); goto AfterMOX1; } cs->writeisac(cs, ISAC_MOX1, - cs->mon_tx[cs->mon_txp++]); - if (cs->debug & L1_DEB_WARN) { - sprintf(tmp, "ISAC %02x -> MOX1", cs->mon_tx[cs->mon_txp -1]); - debugl1(cs, tmp); - } + cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]); + if (cs->debug & L1_DEB_MONITOR) + debugl1(cs, "ISAC %02x -> MOX1", cs->dc.isac.mon_tx[cs->dc.isac.mon_txp -1]); } AfterMOX1: #endif @@ -470,14 +504,18 @@ } static void -ISAC_l2l1(struct PStack *st, int pr, void *arg) +ISAC_l1hw(struct PStack *st, int pr, void *arg) { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; - char str[64]; + int val; switch (pr) { - case (PH_DATA_REQ): + case (PH_DATA |REQUEST): + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); if (cs->tx_skb) { skb_queue_tail(&cs->sq, skb); #ifdef L2FRAME_DEBUG /* psa */ @@ -485,12 +523,6 @@ Logl2Frame(cs, skb, "PH_DATA Queued", 0); #endif } else { - if ((cs->dlogflag) && (!(skb->data[2] & 1))) { /* I-FRAME */ - LogFrame(cs, skb->data, skb->len); - sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei); - dlogframe(cs, skb->data + 4, skb->len - 4, - str); - } cs->tx_skb = skb; cs->tx_cnt = 0; #ifdef L2FRAME_DEBUG /* psa */ @@ -500,19 +532,17 @@ isac_fill_fifo(cs); } break; - case (PH_PULL_IND): + case (PH_PULL |INDICATION): if (cs->tx_skb) { if (cs->debug & L1_DEB_WARN) debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); skb_queue_tail(&cs->sq, skb); break; } - if ((cs->dlogflag) && (!(skb->data[2] & 1))) { /* I-FRAME */ + if (cs->debug & DEB_DLOG_HEX) LogFrame(cs, skb->data, skb->len); - sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei); - dlogframe(cs, skb->data + 4, skb->len - 4, - str); - } + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); cs->tx_skb = skb; cs->tx_cnt = 0; #ifdef L2FRAME_DEBUG /* psa */ @@ -521,46 +551,36 @@ #endif isac_fill_fifo(cs); break; - case (PH_PULL_REQ): + case (PH_PULL | REQUEST): #ifdef L2FRAME_DEBUG /* psa */ if (cs->debug & L1_DEB_LAPD) debugl1(cs, "-> PH_REQUEST_PULL"); #endif if (!cs->tx_skb) { test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - st->l1.l1l2(st, PH_PULL_CNF, NULL); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); } else test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; - } -} - -void -isac_l1cmd(struct IsdnCardState *cs, int msg, void *arg) -{ - u_char val; - char tmp[32]; - - switch(msg) { - case PH_RESET_REQ: - if ((cs->ph_state == ISAC_IND_EI) || - (cs->ph_state == ISAC_IND_DR) || - (cs->ph_state == ISAC_IND_RS)) + case (HW_RESET | REQUEST): + if ((cs->dc.isac.ph_state == ISAC_IND_EI) || + (cs->dc.isac.ph_state == ISAC_IND_DR) || + (cs->dc.isac.ph_state == ISAC_IND_RS)) ph_command(cs, ISAC_CMD_TIM); else ph_command(cs, ISAC_CMD_RS); break; - case PH_ENABLE_REQ: + case (HW_ENABLE | REQUEST): ph_command(cs, ISAC_CMD_TIM); break; - case PH_INFO3_REQ: + case (HW_INFO3 | REQUEST): ph_command(cs, ISAC_CMD_AR8); break; - case PH_TESTLOOP_REQ: + case (HW_TESTLOOP | REQUEST): val = 0; - if (1 & (int) arg) + if (1 & (long) arg) val |= 0x0c; - if (2 & (int) arg) + if (2 & (long) arg) val |= 0x3; if (test_bit(HW_IOM1, &cs->HW_Flags)) { /* IOM 1 Mode */ @@ -580,11 +600,21 @@ cs->writeisac(cs, ISAC_ADF1, 0x0); } break; - default: - if (cs->debug & L1_DEB_WARN) { - sprintf(tmp, "isac_l1cmd unknown %4x", msg); - debugl1(cs, tmp); + case (HW_DEACTIVATE | RESPONSE): + discard_queue(&cs->rq); + discard_queue(&cs->sq); + if (cs->tx_skb) { + idev_kfree_skb(cs->tx_skb, FREE_WRITE); + cs->tx_skb = NULL; } + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + isac_sched_event(cs, D_CLEARBUSY); + break; + default: + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "isac_l1hw unknown %04x", pr); break; } } @@ -592,23 +622,53 @@ void setstack_isac(struct PStack *st, struct IsdnCardState *cs) { - st->l2.l2l1 = ISAC_l2l1; + st->l1.l1hw = ISAC_l1hw; +} + +void +DC_Close_isac(struct IsdnCardState *cs) { + if (cs->dc.isac.mon_rx) { + kfree(cs->dc.isac.mon_rx); + cs->dc.isac.mon_rx = NULL; + } + if (cs->dc.isac.mon_tx) { + kfree(cs->dc.isac.mon_tx); + cs->dc.isac.mon_tx = NULL; + } } static void dbusy_timer_handler(struct IsdnCardState *cs) { struct PStack *stptr; + int rbch, star; if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { - if (cs->debug) - debugl1(cs, "D-Channel Busy"); - test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); - stptr = cs->stlist; - - while (stptr != NULL) { - stptr->l1.l1l2(stptr, PH_PAUSE_IND, NULL); - stptr = stptr->next; + rbch = cs->readisac(cs, ISAC_RBCH); + star = cs->readisac(cs, ISAC_STAR); + if (cs->debug) + debugl1(cs, "D-Channel Busy RBCH %02x STAR %02x", + rbch, star); + if (rbch & ISAC_RBCH_XAC) { /* D-Channel Busy */ + test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); + stptr = cs->stlist; + while (stptr != NULL) { + stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); + stptr = stptr->next; + } + } else { + /* discard frame; reset transceiver */ + test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags); + if (cs->tx_skb) { + idev_kfree_skb(cs->tx_skb, FREE_WRITE); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } else { + printk(KERN_WARNING "HiSax: ISAC D-Channel Busy no skb\n"); + debugl1(cs, "D-Channel Busy no skb"); + } + cs->writeisac(cs, ISAC_CMDR, 0x01); /* Transmitter reset */ + cs->irq_func(cs->irq, cs, NULL); } } } @@ -617,13 +677,15 @@ initisac(struct IsdnCardState *cs)) { cs->tqueue.routine = (void *) (void *) isac_bh; - cs->l1cmd = isac_l1cmd; cs->setstack_d = setstack_isac; + cs->DC_Close = DC_Close_isac; + cs->dc.isac.mon_tx = NULL; + cs->dc.isac.mon_rx = NULL; cs->dbusytimer.function = (void *) dbusy_timer_handler; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); cs->writeisac(cs, ISAC_MASK, 0xff); - cs->mocr = 0xaa; + cs->dc.isac.mocr = 0xaa; if (test_bit(HW_IOM1, &cs->HW_Flags)) { /* IOM 1 Mode */ cs->writeisac(cs, ISAC_ADF2, 0x0); @@ -633,7 +695,9 @@ cs->writeisac(cs, ISAC_MODE, 0xc9); } else { /* IOM 2 Mode */ - cs->writeisac(cs, ISAC_ADF2, 0x80); + if (!cs->dc.isac.adf2) + cs->dc.isac.adf2 = 0x80; + cs->writeisac(cs, ISAC_ADF2, cs->dc.isac.adf2); cs->writeisac(cs, ISAC_SQXR, 0x2f); cs->writeisac(cs, ISAC_SPCR, 0x00); cs->writeisac(cs, ISAC_STCR, 0x70); @@ -648,35 +712,24 @@ HISAX_INITFUNC(void clear_pending_isac_ints(struct IsdnCardState *cs)) { - int val; - char tmp[64]; + int val, eval; val = cs->readisac(cs, ISAC_STAR); - sprintf(tmp, "ISAC STAR %x", val); - debugl1(cs, tmp); + debugl1(cs, "ISAC STAR %x", val); val = cs->readisac(cs, ISAC_MODE); - sprintf(tmp, "ISAC MODE %x", val); - debugl1(cs, tmp); + debugl1(cs, "ISAC MODE %x", val); val = cs->readisac(cs, ISAC_ADF2); - sprintf(tmp, "ISAC ADF2 %x", val); - debugl1(cs, tmp); + debugl1(cs, "ISAC ADF2 %x", val); val = cs->readisac(cs, ISAC_ISTA); - sprintf(tmp, "ISAC ISTA %x", val); - debugl1(cs, tmp); + debugl1(cs, "ISAC ISTA %x", val); if (val & 0x01) { - val = cs->readisac(cs, ISAC_EXIR); - sprintf(tmp, "ISAC EXIR %x", val); - debugl1(cs, tmp); - } else if (val & 0x04) { - val = cs->readisac(cs, ISAC_CIR0); - sprintf(tmp, "ISAC CIR0 %x", val); - debugl1(cs, tmp); - cs->ph_state = (val >> 2) & 0xf; - } else { - cs->ph_state = (cs->readisac(cs, ISAC_CIX0) >> 2) & 0xf; + eval = cs->readisac(cs, ISAC_EXIR); + debugl1(cs, "ISAC EXIR %x", eval); } + val = cs->readisac(cs, ISAC_CIR0); + debugl1(cs, "ISAC CIR0 %x", val); + cs->dc.isac.ph_state = (val >> 2) & 0xf; isac_sched_event(cs, D_L1STATECHANGE); + /* Disable all IRQ */ cs->writeisac(cs, ISAC_MASK, 0xFF); - cs->writeisac(cs, ISAC_MASK, 0); - cs->writeisac(cs, ISAC_CMDR, 0x41); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isac.h linux.pre11.3/drivers/isdn/hisax/isac.h --- linux.vanilla/drivers/isdn/hisax/isac.h Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/hisax/isac.h Mon Jul 19 23:59:34 1999 @@ -1,4 +1,4 @@ -/* $Id: isac.h,v 1.4 1997/10/29 19:09:34 keil Exp $ +/* $Id: isac.h,v 1.5 1998/05/25 12:58:03 keil Exp $ * isac.h ISAC specific defines * @@ -6,6 +6,10 @@ * * * $Log: isac.h,v $ + * Revision 1.5 1998/05/25 12:58:03 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * * Revision 1.4 1997/10/29 19:09:34 keil * new L1 * @@ -26,16 +30,18 @@ #define ISAC_STAR 0x21 #define ISAC_CMDR 0x21 #define ISAC_EXIR 0x24 -#define ISAC_RBCH 0x2a #define ISAC_ADF2 0x39 #define ISAC_SPCR 0x30 #define ISAC_ADF1 0x38 #define ISAC_CIR0 0x31 #define ISAC_CIX0 0x31 +#define ISAC_CIR1 0x33 +#define ISAC_CIX1 0x33 #define ISAC_STCR 0x37 #define ISAC_MODE 0x22 #define ISAC_RSTA 0x27 #define ISAC_RBCL 0x25 +#define ISAC_RBCH 0x2A #define ISAC_TIMR 0x23 #define ISAC_SQXR 0x3b #define ISAC_MOSR 0x3a @@ -44,6 +50,8 @@ #define ISAC_MOX0 0x32 #define ISAC_MOR1 0x34 #define ISAC_MOX1 0x34 + +#define ISAC_RBCH_XAC 0x80 #define ISAC_CMD_TIM 0x0 #define ISAC_CMD_RS 0x1 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isar.c linux.pre11.3/drivers/isdn/hisax/isar.c --- linux.vanilla/drivers/isdn/hisax/isar.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/isar.c Mon Jul 19 23:59:34 1999 @@ -0,0 +1,942 @@ +/* $Id: isar.c,v 1.3 1999/07/01 08:11:45 keil Exp $ + + * isar.c ISAR (Siemens PSB 7110) specific routines + * + * Author Karsten Keil (keil@isdn4linux.de) + * + * + * $Log: isar.c,v $ + * Revision 1.3 1999/07/01 08:11:45 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 1.2 1998/11/15 23:54:53 keil + * changes from 2.0 + * + * Revision 1.1 1998/08/13 23:33:47 keil + * First version, only init + * + * + */ + +#define __NO_VERSION__ +#include "hisax.h" +#include "isar.h" +#include "isdnl1.h" +#include + +#define DBG_LOADFIRM 0 +#define DUMP_MBOXFRAME 2 + +#define MIN(a,b) ((aBC_Read_Reg(cs, 0, ISAR_HIA) & 1) && timeout) { + udelay(1); + timeout--; + } + if (!timeout) + printk(KERN_WARNING "HiSax: ISAR waitforHIA timeout\n"); + return(timeout); +} + + +int +sendmsg(struct IsdnCardState *cs, u_char his, u_char creg, u_char len, + u_char *msg) +{ + long flags; + int i; + + if (!waitforHIA(cs, 4000)) + return(0); +#if DUMP_MBOXFRAME + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "sendmsg(%02x,%02x,%d)", his, creg, len); +#endif + save_flags(flags); + cli(); + cs->BC_Write_Reg(cs, 0, ISAR_CTRL_H, creg); + cs->BC_Write_Reg(cs, 0, ISAR_CTRL_L, len); + cs->BC_Write_Reg(cs, 0, ISAR_WADR, 0); + if (msg && len) { + cs->BC_Write_Reg(cs, 1, ISAR_MBOX, msg[0]); + for (i=1; iBC_Write_Reg(cs, 2, ISAR_MBOX, msg[i]); +#if DUMP_MBOXFRAME>1 + if (cs->debug & L1_DEB_HSCX_FIFO) { + char tmp[256], *t; + + i = len; + while (i>0) { + t = tmp; + t += sprintf(t, "sendmbox cnt %d", len); + QuickHex(t, &msg[len-i], (i>64) ? 64:i); + debugl1(cs, tmp); + i -= 64; + } + } +#endif + } + cs->BC_Write_Reg(cs, 1, ISAR_HIS, his); + restore_flags(flags); + waitforHIA(cs, 10000); + return(1); +} + +/* Call only with IRQ disabled !!! */ +inline void +rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u_char *msg) +{ + int i; + + cs->BC_Write_Reg(cs, 1, ISAR_RADR, 0); + if (msg && ireg->clsb) { + msg[0] = cs->BC_Read_Reg(cs, 1, ISAR_MBOX); + for (i=1; i < ireg->clsb; i++) + msg[i] = cs->BC_Read_Reg(cs, 2, ISAR_MBOX); +#if DUMP_MBOXFRAME>1 + if (cs->debug & L1_DEB_HSCX_FIFO) { + char tmp[256], *t; + + i = ireg->clsb; + while (i>0) { + t = tmp; + t += sprintf(t, "rcv_mbox cnt %d", ireg->clsb); + QuickHex(t, &msg[ireg->clsb-i], (i>64) ? 64:i); + debugl1(cs, tmp); + i -= 64; + } + } +#endif + } + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); +} + +/* Call only with IRQ disabled !!! */ +inline void +get_irq_infos(struct IsdnCardState *cs, struct isar_reg *ireg) +{ + ireg->iis = cs->BC_Read_Reg(cs, 1, ISAR_IIS); + ireg->cmsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_H); + ireg->clsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_L); +#if DUMP_MBOXFRAME + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "rcv_mbox(%02x,%02x,%d)", ireg->iis, ireg->cmsb, + ireg->clsb); +#endif +} + +int +waitrecmsg(struct IsdnCardState *cs, u_char *len, + u_char *msg, int maxdelay) +{ + int timeout = 0; + long flags; + struct isar_reg *ir = cs->bcs[0].hw.isar.reg; + + + while((!(cs->BC_Read_Reg(cs, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) && + (timeout++ < maxdelay)) + udelay(1); + if (timeout >= maxdelay) { + printk(KERN_WARNING"isar recmsg IRQSTA timeout\n"); + return(0); + } + save_flags(flags); + cli(); + get_irq_infos(cs, ir); + rcv_mbox(cs, ir, msg); + *len = ir->clsb; + restore_flags(flags); + return(1); +} + +int +ISARVersion(struct IsdnCardState *cs, char *s) +{ + int ver; + u_char msg[] = ISAR_MSG_HWVER; + u_char tmp[64]; + u_char len; + int debug; + + cs->cardmsg(cs, CARD_RESET, NULL); + /* disable ISAR IRQ */ + cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); + debug = cs->debug; + cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO); + if (!sendmsg(cs, ISAR_HIS_VNR, 0, 3, msg)) + return(-1); + if (!waitrecmsg(cs, &len, tmp, 100000)) + return(-2); + cs->debug = debug; + if (cs->bcs[0].hw.isar.reg->iis == ISAR_IIS_VNR) { + if (len == 1) { + ver = tmp[0] & 0xf; + printk(KERN_INFO "%s ISAR version %d\n", s, ver); + return(ver); + } + return(-3); + } + return(-4); +} + +int +isar_load_firmware(struct IsdnCardState *cs, u_char *buf) +{ + int ret, size, cnt, debug; + u_char len, nom, noc; + u_short sadr, left, *sp; + u_char *p = buf; + u_char *msg, *tmpmsg, *mp, tmp[64]; + long flags; + struct isar_reg *ireg = cs->bcs[0].hw.isar.reg; + + struct {u_short sadr; + u_short len; + u_short d_key; + } blk_head; + +#define BLK_HEAD_SIZE 6 + if (1 != (ret = ISARVersion(cs, "Testing"))) { + printk(KERN_ERR"isar_load_firmware wrong isar version %d\n", ret); + return(1); + } + debug = cs->debug; +#if DBG_LOADFIRM<2 + cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO); +#endif + printk(KERN_DEBUG"isar_load_firmware buf %#lx\n", (u_long)buf); + if ((ret = verify_area(VERIFY_READ, (void *) p, sizeof(int)))) { + printk(KERN_ERR"isar_load_firmware verify_area ret %d\n", ret); + return ret; + } + if ((ret = copy_from_user(&size, p, sizeof(int)))) { + printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret); + return ret; + } + p += sizeof(int); + printk(KERN_DEBUG"isar_load_firmware size: %d\n", size); + if ((ret = verify_area(VERIFY_READ, (void *) p, size))) { + printk(KERN_ERR"isar_load_firmware verify_area ret %d\n", ret); + return ret; + } + cnt = 0; + /* disable ISAR IRQ */ + cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); + if (!(msg = kmalloc(256, GFP_KERNEL))) { + printk(KERN_ERR"isar_load_firmware no buffer\n"); + return (1); + } + if (!(tmpmsg = kmalloc(256, GFP_KERNEL))) { + printk(KERN_ERR"isar_load_firmware no tmp buffer\n"); + kfree(msg); + return (1); + } + while (cnt < size) { + if ((ret = copy_from_user(&blk_head, p, BLK_HEAD_SIZE))) { + printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret); + goto reterror; + } + cnt += BLK_HEAD_SIZE; + p += BLK_HEAD_SIZE; + printk(KERN_DEBUG"isar firmware block (%#x,%5d,%#x)\n", + blk_head.sadr, blk_head.len, blk_head.d_key & 0xff); + sadr = blk_head.sadr; + left = blk_head.len; + if (!sendmsg(cs, ISAR_HIS_DKEY, blk_head.d_key & 0xff, 0, NULL)) { + printk(KERN_ERR"isar sendmsg dkey failed\n"); + ret = 1;goto reterror; + } + if (!waitrecmsg(cs, &len, tmp, 100000)) { + printk(KERN_ERR"isar waitrecmsg dkey failed\n"); + ret = 1;goto reterror; + } + if ((ireg->iis != ISAR_IIS_DKEY) || ireg->cmsb || len) { + printk(KERN_ERR"isar wrong dkey response (%x,%x,%x)\n", + ireg->iis, ireg->cmsb, len); + ret = 1;goto reterror; + } + while (left>0) { + noc = MIN(126, left); + nom = 2*noc; + mp = msg; + *mp++ = sadr / 256; + *mp++ = sadr % 256; + left -= noc; + *mp++ = noc; + if ((ret = copy_from_user(tmpmsg, p, nom))) { + printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret); + goto reterror; + } + p += nom; + cnt += nom; + nom += 3; + sp = (u_short *)tmpmsg; +#if DBG_LOADFIRM + printk(KERN_DEBUG"isar: load %3d words at %04x\n", + noc, sadr); +#endif + sadr += noc; + while(noc) { + *mp++ = *sp / 256; + *mp++ = *sp % 256; + sp++; + noc--; + } + if (!sendmsg(cs, ISAR_HIS_FIRM, 0, nom, msg)) { + printk(KERN_ERR"isar sendmsg prog failed\n"); + ret = 1;goto reterror; + } + if (!waitrecmsg(cs, &len, tmp, 100000)) { + printk(KERN_ERR"isar waitrecmsg prog failed\n"); + ret = 1;goto reterror; + } + if ((ireg->iis != ISAR_IIS_FIRM) || ireg->cmsb || len) { + printk(KERN_ERR"isar wrong prog response (%x,%x,%x)\n", + ireg->iis, ireg->cmsb, len); + ret = 1;goto reterror; + } + } + printk(KERN_DEBUG"isar firmware block %5d words loaded\n", + blk_head.len); + } + msg[0] = 0xff; + msg[1] = 0xfe; + ireg->bstat = 0; + if (!sendmsg(cs, ISAR_HIS_STDSP, 0, 2, msg)) { + printk(KERN_ERR"isar sendmsg start dsp failed\n"); + ret = 1;goto reterror; + } + if (!waitrecmsg(cs, &len, tmp, 100000)) { + printk(KERN_ERR"isar waitrecmsg start dsp failed\n"); + ret = 1;goto reterror; + } + if ((ireg->iis != ISAR_IIS_STDSP) || ireg->cmsb || len) { + printk(KERN_ERR"isar wrong start dsp response (%x,%x,%x)\n", + ireg->iis, ireg->cmsb, len); + ret = 1;goto reterror; + } else + printk(KERN_DEBUG"isar start dsp success\n"); + /* NORMAL mode entered */ + /* Enable IRQs of ISAR */ + cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, ISAR_IRQSTA); + save_flags(flags); + sti(); + cnt = 1000; /* max 1s */ + while ((!ireg->bstat) && cnt) { + udelay(1000); + cnt--; + } + if (!cnt) { + printk(KERN_ERR"isar no general status event received\n"); + ret = 1;goto reterrflg; + } else { + printk(KERN_DEBUG"isar general status event %x\n", + ireg->bstat); + } + ireg->iis = 0; + if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) { + printk(KERN_ERR"isar sendmsg self tst failed\n"); + ret = 1;goto reterrflg; + } + cnt = 1000; /* max 10 ms */ + while ((ireg->iis != ISAR_IIS_DIAG) && cnt) { + udelay(10); + cnt--; + } + if (!cnt) { + printk(KERN_ERR"isar no self tst response\n"); + ret = 1;goto reterrflg; + } else if ((ireg->cmsb == ISAR_CTRL_STST) && (ireg->clsb == 1) + && (ireg->par[0] == 0)) { + printk(KERN_DEBUG"isar selftest OK\n"); + } else { + printk(KERN_DEBUG"isar selftest not OK %x/%x/%x\n", + ireg->cmsb, ireg->clsb, ireg->par[0]); + ret = 1;goto reterror; + } + ireg->iis = 0; + if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) { + printk(KERN_ERR"isar RQST SVN failed\n"); + ret = 1;goto reterror; + } + cnt = 10000; /* max 100 ms */ + while ((ireg->iis != ISAR_IIS_DIAG) && cnt) { + udelay(10); + cnt--; + } + if (!cnt) { + printk(KERN_ERR"isar no SVN response\n"); + ret = 1;goto reterrflg; + } else { + if ((ireg->cmsb == ISAR_CTRL_SWVER) && (ireg->clsb == 1)) + printk(KERN_DEBUG"isar software version %#x\n", + ireg->par[0]); + else { + printk(KERN_ERR"isar wrong swver response (%x,%x) cnt(%d)\n", + ireg->cmsb, ireg->clsb, cnt); + ret = 1;goto reterrflg; + } + } + cs->debug = debug; + isar_setup(cs); + ret = 0; +reterrflg: + restore_flags(flags); +reterror: + cs->debug = debug; + if (ret) + /* disable ISAR IRQ */ + cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); + kfree(msg); + kfree(tmpmsg); + return(ret); +} + +void +isar_sched_event(struct BCState *bcs, int event) +{ + bcs->event |= 1 << event; + queue_task(&bcs->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +static inline void +isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs) +{ + u_char *ptr; + struct sk_buff *skb; + struct isar_reg *ireg = bcs->hw.isar.reg; + + if (!ireg->clsb) { + debugl1(cs, "isar zero len frame"); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); + return; + } + switch (bcs->mode) { + case L1_MODE_NULL: + debugl1(cs, "isar mode 0 spurious IIS_RDATA %x/%x/%x", + ireg->iis, ireg->cmsb, ireg->clsb); + printk(KERN_WARNING"isar mode 0 spurious IIS_RDATA %x/%x/%x\n", + ireg->iis, ireg->cmsb, ireg->clsb); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); + break; + case L1_MODE_TRANS: + if ((skb = dev_alloc_skb(ireg->clsb))) { + SET_SKB_FREE(skb); + rcv_mbox(cs, ireg, (u_char *)skb_put(skb, ireg->clsb)); + skb_queue_tail(&bcs->rqueue, skb); + isar_sched_event(bcs, B_RCVBUFREADY); + } else { + printk(KERN_WARNING "HiSax: skb out of memory\n"); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); + } + break; + case L1_MODE_HDLC: + if ((bcs->hw.isar.rcvidx + ireg->clsb) > HSCX_BUFMAX) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "isar_rcv_frame: incoming packet too large"); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); + bcs->hw.isar.rcvidx = 0; + } else if (ireg->cmsb & HDLC_ERROR) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "isar frame error %x len %d", + ireg->cmsb, ireg->clsb); + bcs->hw.isar.rcvidx = 0; + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); + } else { + if (ireg->cmsb & HDLC_FSD) + bcs->hw.isar.rcvidx = 0; + ptr = bcs->hw.isar.rcvbuf + bcs->hw.isar.rcvidx; + bcs->hw.isar.rcvidx += ireg->clsb; + rcv_mbox(cs, ireg, ptr); + if (ireg->cmsb & HDLC_FED) { + if (bcs->hw.isar.rcvidx < 3) { /* last 2 bytes are the FCS */ + printk(KERN_WARNING "ISAR: HDLC frame too short(%d)\n", + bcs->hw.isar.rcvidx); + } else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx-2))) + printk(KERN_WARNING "ISAR: receive out of memory\n"); + else { + SET_SKB_FREE(skb); + memcpy(skb_put(skb, bcs->hw.isar.rcvidx-2), + bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx-2); + skb_queue_tail(&bcs->rqueue, skb); + isar_sched_event(bcs, B_RCVBUFREADY); + } + } + } + break; + default: + printk(KERN_ERR"isar_rcv_frame mode (%x)error\n", bcs->mode); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); + break; + } +} + +void +isar_fill_fifo(struct BCState *bcs) +{ + struct IsdnCardState *cs = bcs->cs; + int count; + u_char msb; + u_char *ptr; + long flags; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "isar_fill_fifo"); + if (!bcs->tx_skb) + return; + if (bcs->tx_skb->len <= 0) + return; + if (!(bcs->hw.isar.reg->bstat & + (bcs->hw.isar.dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2))) + return; + if (bcs->tx_skb->len > bcs->hw.isar.mml) { + msb = 0; + count = bcs->hw.isar.mml; + } else { + count = bcs->tx_skb->len; + msb = HDLC_FED; + } + if (!bcs->hw.isar.txcnt) + msb |= HDLC_FST; + save_flags(flags); + cli(); + ptr = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.isar.txcnt += count; + switch (bcs->mode) { + case L1_MODE_NULL: + printk(KERN_ERR"isar_fill_fifo wrong mode 0\n"); + break; + case L1_MODE_TRANS: + if (!sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA, + 0, count, ptr)) { + if (cs->debug) + debugl1(cs, "isar bin data send dp%d failed", + bcs->hw.isar.dpath); + } + break; + case L1_MODE_HDLC: + if (!sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA, + msb, count, ptr)) { + if (cs->debug) + debugl1(cs, "isar hdlc data send dp%d failed", + bcs->hw.isar.dpath); + } + break; + default: + printk(KERN_ERR"isar_fill_fifo mode (%x)error\n", bcs->mode); + break; + } + restore_flags(flags); +} + +inline +struct BCState *sel_bcs_isar(struct IsdnCardState *cs, u_char dpath) +{ + if ((!dpath) || (dpath == 3)) + return(NULL); + if (cs->bcs[0].hw.isar.dpath == dpath) + return(&cs->bcs[0]); + if (cs->bcs[1].hw.isar.dpath == dpath) + return(&cs->bcs[1]); + return(NULL); +} + +inline void +send_frames(struct BCState *bcs) +{ + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + isar_fill_fifo(bcs); + return; + } else { + if (bcs->st->lli.l1writewakeup && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) + bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.isar.txcnt); + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + bcs->hw.isar.txcnt = 0; + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.isar.txcnt = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + isar_fill_fifo(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + isar_sched_event(bcs, B_XMTBUFREADY); + } +} + +inline void +check_send(struct IsdnCardState *cs, u_char rdm) +{ + struct BCState *bcs; + + if (rdm & BSTAT_RDM1) { + if ((bcs = sel_bcs_isar(cs, 1))) { + if (bcs->mode) { + send_frames(bcs); + } + } + } + if (rdm & BSTAT_RDM2) { + if ((bcs = sel_bcs_isar(cs, 2))) { + if (bcs->mode) { + send_frames(bcs); + } + } + } + +} + +static char debbuf[64]; + +void +isar_int_main(struct IsdnCardState *cs) +{ + long flags; + struct isar_reg *ireg = cs->bcs[0].hw.isar.reg; + struct BCState *bcs; + + save_flags(flags); + cli(); + get_irq_infos(cs, ireg); + switch (ireg->iis & ISAR_IIS_MSCMSD) { + case ISAR_IIS_RDATA: + if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) { + isar_rcv_frame(cs, bcs); + } else { + debugl1(cs, "isar spurious IIS_RDATA %x/%x/%x", + ireg->iis, ireg->cmsb, ireg->clsb); + printk(KERN_WARNING"isar spurious IIS_RDATA %x/%x/%x\n", + ireg->iis, ireg->cmsb, ireg->clsb); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); + } + break; + case ISAR_IIS_GSTEV: + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); + ireg->bstat |= ireg->cmsb; + check_send(cs, ireg->cmsb); + break; + case ISAR_IIS_BSTEV: + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "Buffer STEV dpath%d msb(%x)", + ireg->iis>>6, ireg->cmsb); + break; + case ISAR_IIS_DIAG: + case ISAR_IIS_PSTRSP: + case ISAR_IIS_PSTEV: + case ISAR_IIS_BSTRSP: + case ISAR_IIS_IOM2RSP: + rcv_mbox(cs, ireg, (u_char *)ireg->par); + if ((cs->debug & (L1_DEB_HSCX | L1_DEB_HSCX_FIFO)) + == L1_DEB_HSCX) { + u_char *tp=debbuf; + + tp += sprintf(debbuf, "msg iis(%x) msb(%x)", + ireg->iis, ireg->cmsb); + QuickHex(tp, (u_char *)ireg->par, ireg->clsb); + debugl1(cs, debbuf); + } + break; + default: + rcv_mbox(cs, ireg, debbuf); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "unhandled msg iis(%x) ctrl(%x/%x)", + ireg->iis, ireg->cmsb, ireg->clsb); + break; + } + restore_flags(flags); +} + +void +setup_pump(struct BCState *bcs) { + struct IsdnCardState *cs = bcs->cs; + u_char dps = SET_DPS(bcs->hw.isar.dpath); + + switch (bcs->mode) { + case L1_MODE_NULL: + case L1_MODE_TRANS: + case L1_MODE_HDLC: + if (!sendmsg(cs, dps | ISAR_HIS_PUMPCFG, PMOD_BYPASS, 0, NULL)) { + if (cs->debug) + debugl1(cs, "isar pump bypass cfg dp%d failed", + bcs->hw.isar.dpath); + } + break; + } + if (!sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL)) { + if (cs->debug) + debugl1(cs, "isar pump status req dp%d failed", + bcs->hw.isar.dpath); + } +} + +void +setup_sart(struct BCState *bcs) { + struct IsdnCardState *cs = bcs->cs; + u_char dps = SET_DPS(bcs->hw.isar.dpath); + + switch (bcs->mode) { + case L1_MODE_NULL: + if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_DISABLE, 0, NULL)) { + if (cs->debug) + debugl1(cs, "isar sart disable dp%d failed", + bcs->hw.isar.dpath); + } + break; + case L1_MODE_TRANS: + if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_BINARY, 2, "\0\0")) { + if (cs->debug) + debugl1(cs, "isar sart binary dp%d failed", + bcs->hw.isar.dpath); + } + break; + case L1_MODE_HDLC: + if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1, "\0")) { + if (cs->debug) + debugl1(cs, "isar sart binary dp%d failed", + bcs->hw.isar.dpath); + } + break; + } + if (!sendmsg(cs, dps | ISAR_HIS_BSTREQ, 0, 0, NULL)) { + if (cs->debug) + debugl1(cs, "isar buf stat req dp%d failed", + bcs->hw.isar.dpath); + } +} + +void +setup_iom2(struct BCState *bcs) { + struct IsdnCardState *cs = bcs->cs; + u_char dps = SET_DPS(bcs->hw.isar.dpath); + u_char cmsb = 0, msg[5] = {0x10,0,0,0,0}; + + switch (bcs->mode) { + case L1_MODE_NULL: + /* dummy slot */ + msg[1] = msg[3] = bcs->hw.isar.dpath + 2; + break; + case L1_MODE_TRANS: + case L1_MODE_HDLC: + cmsb = 0x80; + if (bcs->channel) + msg[1] = msg[3] = 1; + break; + } + if (!sendmsg(cs, dps | ISAR_HIS_IOM2CFG, cmsb, 5, msg)) { + if (cs->debug) + debugl1(cs, "isar iom2 dp%d failed", bcs->hw.isar.dpath); + } + if (!sendmsg(cs, dps | ISAR_HIS_IOM2REQ, 0, 0, NULL)) { + if (cs->debug) + debugl1(cs, "isar IOM2 cfg req dp%d failed", + bcs->hw.isar.dpath); + } +} + +int +modeisar(struct BCState *bcs, int mode, int bc) +{ + struct IsdnCardState *cs = bcs->cs; + + /* Here we are selecting the best datapath for requested mode */ + if(bcs->mode == L1_MODE_NULL) { /* New Setup */ + bcs->channel = bc; + switch (mode) { + case L1_MODE_NULL: /* init */ + break; + case L1_MODE_TRANS: + case L1_MODE_HDLC: + /* best is datapath 2 */ + if (!test_and_set_bit(ISAR_DP2_USE, + &bcs->hw.isar.reg->Flags)) + bcs->hw.isar.dpath = 2; + else if (!test_and_set_bit(ISAR_DP1_USE, + &bcs->hw.isar.reg->Flags)) + bcs->hw.isar.dpath = 1; + else { + printk(KERN_ERR"isar modeisar both pathes in use\n"); + return(1); + } + break; + } + } + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "isar dp%d mode %d->%d ichan %d", + bcs->hw.isar.dpath, bcs->mode, mode, bc); + bcs->mode = mode; + setup_pump(bcs); + setup_sart(bcs); + setup_iom2(bcs); + if (bcs->mode == L1_MODE_NULL) { + /* Clear resources */ + if (bcs->hw.isar.dpath == 1) + test_and_clear_bit(ISAR_DP1_USE, &bcs->hw.isar.reg->Flags); + else if (bcs->hw.isar.dpath == 2) + test_and_clear_bit(ISAR_DP2_USE, &bcs->hw.isar.reg->Flags); + bcs->hw.isar.dpath = 0; + } + return(0); +} + +void +isar_setup(struct IsdnCardState *cs) +{ + u_char msg; + int i; + + /* Dpath 1, 2 */ + msg = 61; + for (i=0; i<2; i++) { + /* Buffer Config */ + if (!sendmsg(cs, (i ? ISAR_HIS_DPS2 : ISAR_HIS_DPS1) | + ISAR_HIS_P12CFG, 4, 1, &msg)) { + if (cs->debug) + debugl1(cs, "isar P%dCFG failed", i+1); + } + cs->bcs[i].hw.isar.mml = msg; + cs->bcs[i].mode = 0; + cs->bcs[i].hw.isar.dpath = i + 1; + modeisar(&cs->bcs[i], 0, 0); + } +} + +void +isar_l2l1(struct PStack *st, int pr, void *arg) +{ + struct sk_buff *skb = arg; + long flags; + + switch (pr) { + case (PH_DATA | REQUEST): + save_flags(flags); + cli(); + if (st->l1.bcs->tx_skb) { + skb_queue_tail(&st->l1.bcs->squeue, skb); + restore_flags(flags); + } else { + st->l1.bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + if (st->l1.bcs->cs->debug & L1_DEB_HSCX) + debugl1(st->l1.bcs->cs, "DRQ set BC_FLG_BUSY"); + st->l1.bcs->hw.isar.txcnt = 0; + restore_flags(flags); + st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); + } + break; + case (PH_PULL | INDICATION): + if (st->l1.bcs->tx_skb) { + printk(KERN_WARNING "isar_l2l1: this shouldn't happen\n"); + break; + } + test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + if (st->l1.bcs->cs->debug & L1_DEB_HSCX) + debugl1(st->l1.bcs->cs, "PUI set BC_FLG_BUSY"); + st->l1.bcs->tx_skb = skb; + st->l1.bcs->hw.isar.txcnt = 0; + st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); + break; + case (PH_PULL | REQUEST): + if (!st->l1.bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + break; + case (PH_ACTIVATE | REQUEST): + test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + modeisar(st->l1.bcs, st->l1.mode, st->l1.bc); + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | REQUEST): + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | CONFIRM): + test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + if (st->l1.bcs->cs->debug & L1_DEB_HSCX) + debugl1(st->l1.bcs->cs, "PDAC clear BC_FLG_BUSY"); + modeisar(st->l1.bcs, 0, st->l1.bc); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); + break; + } +} + +void +close_isarstate(struct BCState *bcs) +{ + modeisar(bcs, 0, bcs->channel); + if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { + if (bcs->hw.isar.rcvbuf) { + kfree(bcs->hw.isar.rcvbuf); + bcs->hw.isar.rcvbuf = NULL; + } + discard_queue(&bcs->rqueue); + discard_queue(&bcs->squeue); + if (bcs->tx_skb) { + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs, "closeisar clear BC_FLG_BUSY"); + } + } +} + +int +open_isarstate(struct IsdnCardState *cs, struct BCState *bcs) +{ + if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { + if (!(bcs->hw.isar.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for isar.rcvbuf\n"); + return (1); + } + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + } + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "openisar clear BC_FLG_BUSY"); + bcs->event = 0; + bcs->hw.isar.rcvidx = 0; + bcs->tx_cnt = 0; + return (0); +} + +int +setstack_isar(struct PStack *st, struct BCState *bcs) +{ + bcs->channel = st->l1.bc; + if (open_isarstate(st->l1.hardware, bcs)) + return (-1); + st->l1.bcs = bcs; + st->l2.l2l1 = isar_l2l1; + setstack_manager(st); + bcs->st = st; + setstack_l1_B(st); + return (0); +} + +HISAX_INITFUNC(void +initisar(struct IsdnCardState *cs)) +{ + cs->bcs[0].BC_SetStack = setstack_isar; + cs->bcs[1].BC_SetStack = setstack_isar; + cs->bcs[0].BC_Close = close_isarstate; + cs->bcs[1].BC_Close = close_isarstate; +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isar.h linux.pre11.3/drivers/isdn/hisax/isar.h --- linux.vanilla/drivers/isdn/hisax/isar.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/isar.h Mon Jul 19 23:59:34 1999 @@ -0,0 +1,95 @@ +/* $Id: isar.h,v 1.3 1999/07/01 08:11:46 keil Exp $ + * isar.h ISAR (Siemens PSB 7110) specific defines + * + * Author Karsten Keil (keil@isdn4linux.de) + * + * + * $Log: isar.h,v $ + * Revision 1.3 1999/07/01 08:11:46 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 1.2 1998/11/15 23:54:54 keil + * changes from 2.0 + * + * Revision 1.1 1998/08/13 23:33:48 keil + * First version, only init + * + * + */ + +#define ISAR_IRQMSK 0x04 +#define ISAR_IRQSTA 0x04 +#define ISAR_IRQBIT 0x75 +#define ISAR_CTRL_H 0x61 +#define ISAR_CTRL_L 0x60 +#define ISAR_IIS 0x58 +#define ISAR_IIA 0x58 +#define ISAR_HIS 0x50 +#define ISAR_HIA 0x50 +#define ISAR_MBOX 0x4c +#define ISAR_WADR 0x4a +#define ISAR_RADR 0x48 + +#define ISAR_HIS_VNR 0x14 +#define ISAR_HIS_DKEY 0x02 +#define ISAR_HIS_FIRM 0x1e +#define ISAR_HIS_STDSP 0x08 +#define ISAR_HIS_DIAG 0x05 +#define ISAR_HIS_P0CFG 0x3c +#define ISAR_HIS_P12CFG 0x24 +#define ISAR_HIS_SARTCFG 0x25 +#define ISAR_HIS_PUMPCFG 0x26 +#define ISAR_HIS_IOM2CFG 0x27 +#define ISAR_HIS_IOM2REQ 0x07 +#define ISAR_HIS_IOM2CTRL 0x2b +#define ISAR_HIS_BSTREQ 0x0c +#define ISAR_HIS_PSTREQ 0x0e +#define ISAR_HIS_SDATA 0x20 +#define ISAR_HIS_DPS1 0x40 +#define ISAR_HIS_DPS2 0x80 +#define SET_DPS(x) ((x<<6) & 0xc0) + +#define ISAR_IIS_MSCMSD 0x3f +#define ISAR_IIS_VNR 0x15 +#define ISAR_IIS_DKEY 0x03 +#define ISAR_IIS_FIRM 0x1f +#define ISAR_IIS_STDSP 0x09 +#define ISAR_IIS_DIAG 0x25 +#define ISAR_IIS_GSTEV 0x0 +#define ISAR_IIS_BSTEV 0x28 +#define ISAR_IIS_BSTRSP 0x2c +#define ISAR_IIS_PSTRSP 0x2e +#define ISAR_IIS_PSTEV 0x2a +#define ISAR_IIS_IOM2RSP 0x27 + +#define ISAR_IIS_RDATA 0x20 +#define ISAR_CTRL_SWVER 0x10 +#define ISAR_CTRL_STST 0x40 + +#define ISAR_MSG_HWVER {0x20, 0, 1} + +#define ISAR_DP1_USE 1 +#define ISAR_DP2_USE 2 + +#define PMOD_BYPASS 7 + +#define SMODE_DISABLE 0 +#define SMODE_HDLC 3 +#define SMODE_BINARY 4 + +#define HDLC_FED 0x40 +#define HDLC_FSD 0x20 +#define HDLC_FST 0x20 +#define HDLC_ERROR 0x1c + +#define BSTAT_RDM0 0x1 +#define BSTAT_RDM1 0x2 +#define BSTAT_RDM2 0x4 +#define BSTAT_RDM3 0x8 + + +extern int ISARVersion(struct IsdnCardState *cs, char *s); +extern int isar_load_firmware(struct IsdnCardState *cs, u_char *buf); +extern void isar_int_main(struct IsdnCardState *cs); +extern void initisar(struct IsdnCardState *cs); +extern void isar_fill_fifo(struct BCState *bcs); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isdnl1.c linux.pre11.3/drivers/isdn/hisax/isdnl1.c --- linux.vanilla/drivers/isdn/hisax/isdnl1.c Wed Mar 24 10:55:17 1999 +++ linux.pre11.3/drivers/isdn/hisax/isdnl1.c Mon Jul 19 23:59:34 1999 @@ -1,9 +1,13 @@ -/* $Id: isdnl1.c,v 2.18 1998/02/12 23:07:42 keil Exp $ +/* $Id: isdnl1.c,v 2.34 1999/07/09 13:50:15 keil Exp $ * isdnl1.c common low level stuff for Siemens Chipsetbased isdn cards * based on the teles driver from Jan den Ouden * - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) + * + * This file is (c) under GNU PUBLIC LICENSE + * For changes and modifications please read + * ../../../Documentation/isdn/HiSax.cert * * Thanks to Jan den Ouden * Fritz Elfert @@ -11,6 +15,52 @@ * * * $Log: isdnl1.c,v $ + * Revision 2.34 1999/07/09 13:50:15 keil + * remove unused variable + * + * Revision 2.33 1999/07/09 13:34:33 keil + * remove debug code + * + * Revision 2.32 1999/07/01 08:11:47 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 2.31 1998/11/15 23:54:56 keil + * changes from 2.0 + * + * Revision 2.30 1998/09/30 22:27:00 keil + * Add init of l1.Flags + * + * Revision 2.29 1998/09/27 23:54:43 keil + * cosmetics + * + * Revision 2.28 1998/09/27 12:52:23 keil + * Fix against segfault, if the driver cannot allocate an IRQ channel + * + * Revision 2.27 1998/08/13 23:36:39 keil + * HiSax 3.1 - don't work stable with current LinkLevel + * + * Revision 2.26 1998/07/15 15:01:31 calle + * Support for AVM passive PCMCIA cards: + * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0 + * + * Revision 2.25 1998/05/25 14:10:09 keil + * HiSax 3.0 + * X.75 and leased are working again. + * + * Revision 2.24 1998/05/25 12:58:04 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * + * Revision 2.22 1998/04/15 16:40:13 keil + * Add S0Box and Teles PCI support + * Fix cardnr overwrite bug + * + * Revision 2.21 1998/04/10 10:35:28 paul + * fixed (silly?) warnings from egcs on Alpha. + * + * Revision 2.20 1998/03/09 23:19:27 keil + * Changes for PCMCIA + * * Revision 2.18 1998/02/12 23:07:42 keil * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * @@ -79,102 +129,21 @@ * */ -const char *l1_revision = "$Revision: 2.18 $"; +const char *l1_revision = "$Revision: 2.34 $"; #define __NO_VERSION__ #include #include "hisax.h" #include "isdnl1.h" -#include -#if (LINUX_VERSION_CODE < 0x020150) /* 2.1.80 */ -#define kstat_irqs( PAR ) kstat.interrupts( (PAR) ) -#endif - +#define TIMER3_VALUE 7000 -#if CARD_TELES0 -extern int setup_teles0(struct IsdnCard *card); -#endif - -#if CARD_TELES3 -extern int setup_teles3(struct IsdnCard *card); -#endif - -#if CARD_AVM_A1 -extern int setup_avm_a1(struct IsdnCard *card); -#endif - -#if CARD_ELSA -extern int setup_elsa(struct IsdnCard *card); -#endif - -#if CARD_IX1MICROR2 -extern int setup_ix1micro(struct IsdnCard *card); -#endif - -#if CARD_DIEHLDIVA -extern int setup_diva(struct IsdnCard *card); -#endif - -#if CARD_ASUSCOM -extern int setup_asuscom(struct IsdnCard *card); -#endif - -#if CARD_TELEINT -extern int setup_TeleInt(struct IsdnCard *card); -#endif - -#if CARD_SEDLBAUER -extern int setup_sedlbauer(struct IsdnCard *card); -#endif - -#if CARD_SPORTSTER -extern int setup_sportster(struct IsdnCard *card); -#endif - -#if CARD_MIC -extern int setup_mic(struct IsdnCard *card); -#endif - -#if CARD_NETJET -extern int setup_netjet(struct IsdnCard *card); -#endif - -#if CARD_TELES3C -extern int setup_t163c(struct IsdnCard *card); -#endif - -#if CARD_AMD7930 || CARD_DBRI -extern int setup_foreign(struct IsdnCard *card); -#endif - -#if CARD_NICCY -extern int setup_niccy(struct IsdnCard *card); -#endif - -#define HISAX_STATUS_BUFSIZE 4096 -#define ISDN_CTRL_DEBUG 1 -#define INCLUDE_INLINE_FUNCS -#include -#include -const char *CardType[] = -{"No Card", "Teles 16.0", "Teles 8.0", "Teles 16.3", "Creatix/Teles PnP", - "AVM A1", "Elsa ML", "Elsa Quickstep", "Teles PCMCIA", "ITK ix1-micro Rev.2", - "Elsa PCMCIA", "Eicon.Diehl Diva", "ISDNLink", "TeleInt", "Teles 16.3c", - "Sedlbauer Speed Card", "USR Sportster", "ith mic Linux", "Elsa PCI", - "Compaq ISA", "NETjet", "Teles PCI", "Sedlbauer Speed Star (PCMCIA)", - "AMD 7930", "NICCY", "DBRI" -}; - -extern struct IsdnCard cards[]; -extern int nrcards; -extern char *HiSax_id; -extern struct IsdnBuffers *tracebuf; - -#define TIMER3_VALUE 7 +static +struct Fsm l1fsm_b = +{NULL, 0, 0, NULL, NULL}; static -struct Fsm l1fsm = +struct Fsm l1fsm_d = {NULL, 0, 0, NULL, NULL}; enum { @@ -187,9 +156,9 @@ ST_L1_F8, }; -#define L1_STATE_COUNT (ST_L1_F8+1) +#define L1D_STATE_COUNT (ST_L1_F8+1) -static char *strL1State[] = +static char *strL1DState[] = { "ST_L1_F2", "ST_L1_F3", @@ -201,7 +170,25 @@ }; enum { + ST_L1_NULL, + ST_L1_WAIT_ACT, + ST_L1_WAIT_DEACT, + ST_L1_ACTIV, +}; + +#define L1B_STATE_COUNT (ST_L1_ACTIV+1) + +static char *strL1BState[] = +{ + "ST_L1_NULL", + "ST_L1_WAIT_ACT", + "ST_L1_WAIT_DEACT", + "ST_L1_ACTIV", +}; + +enum { EV_PH_ACTIVATE, + EV_PH_DEACTIVATE, EV_RESET_IND, EV_DEACT_CNF, EV_DEACT_IND, @@ -219,6 +206,7 @@ static char *strL1Event[] = { "EV_PH_ACTIVATE", + "EV_PH_DEACTIVATE", "EV_RESET_IND", "EV_DEACT_CNF", "EV_DEACT_IND", @@ -231,154 +219,30 @@ "EV_TIMER3", }; -/* - * Find card with given driverId - */ -static inline struct IsdnCardState -*hisax_findcard(int driverid) -{ - int i; - - for (i = 0; i < nrcards; i++) - if (cards[i].cs) - if (cards[i].cs->myid == driverid) - return (cards[i].cs); - return (NULL); -} - -int -HiSax_readstatus(u_char * buf, int len, int user, int id, int channel) -{ - int count; - u_char *p; - struct IsdnCardState *csta = hisax_findcard(id); - - if (csta) { - for (p = buf, count = 0; count < len; p++, count++) { - if (user) - put_user(*csta->status_read++, p); - else - *p++ = *csta->status_read++; - if (csta->status_read > csta->status_end) - csta->status_read = csta->status_buf; - } - return count; - } else { - printk(KERN_ERR - "HiSax: if_readstatus called with invalid driverId!\n"); - return -ENODEV; - } -} - -#if ISDN_CTRL_DEBUG void -HiSax_putstatus(struct IsdnCardState *csta, char *buf) +debugl1(struct IsdnCardState *cs, char *fmt, ...) { - long flags; - int len, count, i; - u_char *p; - isdn_ctrl ic; - - save_flags(flags); - cli(); - count = 0; - len = strlen(buf); - - if (!csta) { - printk(KERN_WARNING "HiSax: No CardStatus for message %s", buf); - restore_flags(flags); - return; - } - for (p = buf, i = len; i > 0; i--, p++) { - *csta->status_write++ = *p; - if (csta->status_write > csta->status_end) - csta->status_write = csta->status_buf; - count++; - } - restore_flags(flags); - if (count) { - ic.command = ISDN_STAT_STAVAIL; - ic.driver = csta->myid; - ic.arg = count; - csta->iif.statcallb(&ic); - } -} -#else -#define KDEBUG_DEF -#include "../kdebug.h" - -static int DbgLineNr=0,DbgSequenzNr=1; - -void -HiSax_putstatus(struct IsdnCardState *csta, char *buf) -{ - char tmp[512]; + va_list args; + char tmp[8]; - if (DbgLineNr==23) - DbgLineNr=0; - sprintf(tmp, "%5d %s",DbgSequenzNr++,buf); - gput_str(tmp,0,DbgLineNr++); -} -#endif - -int -ll_run(struct IsdnCardState *csta) -{ - long flags; - isdn_ctrl ic; - - save_flags(flags); - cli(); - ic.driver = csta->myid; - ic.command = ISDN_STAT_RUN; - csta->iif.statcallb(&ic); - restore_flags(flags); - return 0; -} - -void -ll_stop(struct IsdnCardState *csta) -{ - isdn_ctrl ic; - - ic.command = ISDN_STAT_STOP; - ic.driver = csta->myid; - csta->iif.statcallb(&ic); - CallcFreeChan(csta); -} - -static void -ll_unload(struct IsdnCardState *csta) -{ - isdn_ctrl ic; - - ic.command = ISDN_STAT_UNLOAD; - ic.driver = csta->myid; - csta->iif.statcallb(&ic); - if (csta->status_buf) - kfree(csta->status_buf); - csta->status_read = NULL; - csta->status_write = NULL; - csta->status_end = NULL; - kfree(csta->dlogspace); -} - -void -debugl1(struct IsdnCardState *cs, char *msg) -{ - char tmp[1024], tm[32]; - - jiftime(tm, jiffies); - sprintf(tmp, "%s Card %d %s\n", tm, cs->cardnr + 1, msg); - HiSax_putstatus(cs, tmp); + va_start(args, fmt); + sprintf(tmp, "Card%d ", cs->cardnr + 1); + VHiSax_putstatus(cs, tmp, fmt, args); + va_end(args); } static void -l1m_debug(struct FsmInst *fi, char *s) +l1m_debug(struct FsmInst *fi, char *fmt, ...) { + va_list args; struct PStack *st = fi->userdata; + struct IsdnCardState *cs = st->l1.hardware; + char tmp[8]; - debugl1(st->l1.hardware, s); + va_start(args, fmt); + sprintf(tmp, "Card%d ", cs->cardnr + 1); + VHiSax_putstatus(cs, tmp, fmt, args); + va_end(args); } void @@ -389,9 +253,9 @@ st = cs->stlist; while (st) { if (test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags)) - st->l1.l1man(st, PH_ACTIVATE_CNF, NULL); + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); else - st->l1.l1man(st, PH_ACTIVATE_IND, NULL); + st->l1.l1l2(st, PH_ACTIVATE | INDICATION, NULL); st = st->next; } } @@ -404,8 +268,8 @@ st = cs->stlist; while (st) { if (test_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - st->l1.l1l2(st, PH_PAUSE_CNF, NULL); - st->l1.l1man(st, PH_DEACTIVATE_IND, NULL); + st->l1.l1l2(st, PH_PAUSE | CONFIRM, NULL); + st->l1.l1l2(st, PH_DEACTIVATE | INDICATION, NULL); st = st->next; } test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags); @@ -422,7 +286,7 @@ stptr = cs->stlist; while (stptr != NULL) if (test_and_clear_bit(FLG_L1_PULL_REQ, &stptr->l1.Flags)) { - stptr->l1.l1l2(stptr, PH_PULL_CNF, NULL); + stptr->l1.l1l2(stptr, PH_PULL | CONFIRM, NULL); break; } else stptr = stptr->next; @@ -434,7 +298,6 @@ struct sk_buff *skb, *nskb; struct PStack *stptr = cs->stlist; int found, tei, sapi; - char tmp[64]; if (stptr) if (test_bit(FLG_L1_ACTTIMER, &stptr->l1.Flags)) @@ -445,19 +308,27 @@ Logl2Frame(cs, skb, "PH_DATA", 1); #endif stptr = cs->stlist; + if (skb->len<3) { + debugl1(cs, "D-channel frame too short(%d)",skb->len); + idev_kfree_skb(skb, FREE_READ); + return; + } + if ((skb->data[0] & 1) || !(skb->data[1] &1)) { + debugl1(cs, "D-channel frame wrong EA0/EA1"); + idev_kfree_skb(skb, FREE_READ); + return; + } sapi = skb->data[0] >> 2; tei = skb->data[1] >> 1; - + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 1); if (tei == GROUP_TEI) { - if (sapi == CTRL_SAPI) { /* sapi 0 */ - if (cs->dlogflag) { - LogFrame(cs, skb->data, skb->len); - dlogframe(cs, skb->data + 3, skb->len - 3, - "Q.931 frame network->user broadcast"); - } + if (sapi == CTRL_SAPI) { /* sapi 0 */ while (stptr != NULL) { if ((nskb = skb_clone(skb, GFP_ATOMIC))) - stptr->l1.l1l2(stptr, PH_DATA_IND, nskb); + stptr->l1.l1l2(stptr, PH_DATA | INDICATION, nskb); else printk(KERN_WARNING "HiSax: isdn broadcast buffer shortage\n"); stptr = stptr->next; @@ -465,37 +336,24 @@ } else if (sapi == TEI_SAPI) { while (stptr != NULL) { if ((nskb = skb_clone(skb, GFP_ATOMIC))) - stptr->l1.l1tei(stptr, PH_DATA_IND, nskb); + stptr->l1.l1tei(stptr, PH_DATA | INDICATION, nskb); else printk(KERN_WARNING "HiSax: tei broadcast buffer shortage\n"); stptr = stptr->next; } } - dev_kfree_skb(skb); - } else if (sapi == CTRL_SAPI) { + idev_kfree_skb(skb, FREE_READ); + } else if (sapi == CTRL_SAPI) { /* sapi 0 */ found = 0; while (stptr != NULL) if (tei == stptr->l2.tei) { - stptr->l1.l1l2(stptr, PH_DATA_IND, skb); + stptr->l1.l1l2(stptr, PH_DATA | INDICATION, skb); found = !0; break; } else stptr = stptr->next; - if (!found) { - /* BD 10.10.95 - * Print out D-Channel msg not processed - * by isdn4linux - */ - - if ((!(skb->data[0] >> 2)) && (!(skb->data[2] & 0x01))) { - sprintf(tmp, - "Q.931 frame network->user with tei %d (not for us)", - skb->data[1] >> 1); - LogFrame(cs, skb->data, skb->len); - dlogframe(cs, skb->data + 4, skb->len - 4, tmp); - } - dev_kfree_skb(skb); - } + if (!found) + idev_kfree_skb(skb, FREE_READ); } } } @@ -505,14 +363,18 @@ { struct PStack *st = bcs->st; - if (test_bit(BC_FLG_BUSY, &bcs->Flag)) + if (test_bit(BC_FLG_BUSY, &bcs->Flag)) { + debugl1(bcs->cs, "BC_BUSY Error"); return; + } if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags)) - st->l1.l1l2(st, PH_PULL_CNF, NULL); - if (!test_bit(BC_FLG_ACTIV, &bcs->Flag)) - if (!test_bit(BC_FLG_BUSY, &bcs->Flag) && (!skb_queue_len(&bcs->squeue))) - st->ma.manl1(st, PH_DEACTIVATE_CNF, 0); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + if (!test_bit(BC_FLG_ACTIV, &bcs->Flag)) { + if (!test_bit(BC_FLG_BUSY, &bcs->Flag) && (!skb_queue_len(&bcs->squeue))) { + st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL); + } + } } static void @@ -520,8 +382,12 @@ { struct sk_buff *skb; + if (bcs->st->l1.l1m.state == ST_L1_WAIT_ACT) { + FsmDelTimer(&bcs->st->l1.timer, 4); + FsmEvent(&bcs->st->l1.l1m, EV_TIMER_ACT, NULL); + } while ((skb = skb_dequeue(&bcs->rqueue))) { - bcs->st->l1.l1l2(bcs->st, PH_DATA_IND, skb); + bcs->st->l1.l1l2(bcs->st, PH_DATA | INDICATION, skb); } } @@ -581,443 +447,6 @@ bcs->Flag = 0; } -static void -closecard(int cardnr) -{ - struct IsdnCardState *csta = cards[cardnr].cs; - struct sk_buff *skb; - - if (csta->bcs->BC_Close != NULL) { - csta->bcs->BC_Close(csta->bcs + 1); - csta->bcs->BC_Close(csta->bcs); - } - - if (csta->rcvbuf) { - kfree(csta->rcvbuf); - csta->rcvbuf = NULL; - } - while ((skb = skb_dequeue(&csta->rq))) { - dev_kfree_skb(skb); - } - while ((skb = skb_dequeue(&csta->sq))) { - dev_kfree_skb(skb); - } - if (csta->tx_skb) { - dev_kfree_skb(csta->tx_skb); - csta->tx_skb = NULL; - } - if (csta->mon_rx) { - kfree(csta->mon_rx); - csta->mon_rx = NULL; - } - if (csta->mon_tx) { - kfree(csta->mon_tx); - csta->mon_tx = NULL; - } - csta->cardmsg(csta, CARD_RELEASE, NULL); - del_timer(&csta->dbusytimer); - ll_unload(csta); -} - -HISAX_INITFUNC(static int init_card(struct IsdnCardState *cs)) -{ - int irq_cnt, cnt = 3; - long flags; - - save_flags(flags); - cli(); - irq_cnt = kstat_irqs(cs->irq); - printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], cs->irq, - irq_cnt); - if (cs->cardmsg(cs, CARD_SETIRQ, NULL)) { - printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n", - cs->irq); - return(1); - } - while (cnt) { - cs->cardmsg(cs, CARD_INIT, NULL); - sti(); - current->state = TASK_INTERRUPTIBLE; - /* Timeout 10ms */ - schedule_timeout((10 * HZ) / 1000); - restore_flags(flags); - printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], - cs->irq, kstat_irqs(cs->irq)); - if (kstat_irqs(cs->irq) == irq_cnt) { - printk(KERN_WARNING - "%s: IRQ(%d) getting no interrupts during init %d\n", - CardType[cs->typ], cs->irq, 4 - cnt); - if (cnt == 1) { - free_irq(cs->irq, cs); - return (2); - } else { - cs->cardmsg(cs, CARD_RESET, NULL); - cnt--; - } - } else { - cs->cardmsg(cs, CARD_TEST, NULL); - return(0); - } - } - restore_flags(flags); - return(3); -} - -HISAX_INITFUNC(static int -checkcard(int cardnr, char *id, int *busy_flag)) -{ - long flags; - int ret = 0; - struct IsdnCard *card = cards + cardnr; - struct IsdnCardState *cs; - - save_flags(flags); - cli(); - if (!(cs = (struct IsdnCardState *) - kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for IsdnCardState(card %d)\n", - cardnr + 1); - restore_flags(flags); - return (0); - } - card->cs = cs; - cs->cardnr = cardnr; - cs->debug = L1_DEB_WARN; - cs->HW_Flags = 0; - cs->busy_flag = busy_flag; -#if TEI_PER_CARD -#else - test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); -#endif - cs->protocol = card->protocol; - - if ((card->typ > 0) && (card->typ < 31)) { - if (!((1 << card->typ) & SUPORTED_CARDS)) { - printk(KERN_WARNING - "HiSax: Support for %s Card not selected\n", - CardType[card->typ]); - restore_flags(flags); - return (0); - } - } else { - printk(KERN_WARNING - "HiSax: Card Type %d out of range\n", - card->typ); - restore_flags(flags); - return (0); - } - if (!(cs->dlogspace = kmalloc(4096, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for dlogspace(card %d)\n", - cardnr + 1); - restore_flags(flags); - return (0); - } - if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for status_buf(card %d)\n", - cardnr + 1); - kfree(cs->dlogspace); - restore_flags(flags); - return (0); - } - cs->stlist = NULL; - cs->dlogflag = 0; - cs->mon_tx = NULL; - cs->mon_rx = NULL; - cs->status_read = cs->status_buf; - cs->status_write = cs->status_buf; - cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1; - cs->typ = card->typ; - strcpy(cs->iif.id, id); - cs->iif.channels = 2; - cs->iif.maxbufsize = MAX_DATA_SIZE; - cs->iif.hl_hdrlen = MAX_HEADER_LEN; - cs->iif.features = - ISDN_FEATURE_L2_X75I | - ISDN_FEATURE_L2_HDLC | - ISDN_FEATURE_L2_TRANS | - ISDN_FEATURE_L3_TRANS | -#ifdef CONFIG_HISAX_1TR6 - ISDN_FEATURE_P_1TR6 | -#endif -#ifdef CONFIG_HISAX_EURO - ISDN_FEATURE_P_EURO | -#endif -#ifdef CONFIG_HISAX_NI1 - ISDN_FEATURE_P_NI1 | -#endif - 0; - - cs->iif.command = HiSax_command; - cs->iif.writecmd = NULL; - cs->iif.writebuf_skb = HiSax_writebuf_skb; - cs->iif.readstat = HiSax_readstatus; - register_isdn(&cs->iif); - cs->myid = cs->iif.channels; - printk(KERN_INFO - "HiSax: Card %d Protocol %s Id=%s (%d)\n", cardnr + 1, - (card->protocol == ISDN_PTYPE_1TR6) ? "1TR6" : - (card->protocol == ISDN_PTYPE_EURO) ? "EDSS1" : - (card->protocol == ISDN_PTYPE_LEASED) ? "LEASED" : - (card->protocol == ISDN_PTYPE_NI1) ? "NI1" : - "NONE", cs->iif.id, cs->myid); - switch (card->typ) { -#if CARD_TELES0 - case ISDN_CTYPE_16_0: - case ISDN_CTYPE_8_0: - ret = setup_teles0(card); - break; -#endif -#if CARD_TELES3 - case ISDN_CTYPE_16_3: - case ISDN_CTYPE_PNP: - case ISDN_CTYPE_TELESPCMCIA: - case ISDN_CTYPE_COMPAQ_ISA: - ret = setup_teles3(card); - break; -#endif -#if CARD_AVM_A1 - case ISDN_CTYPE_A1: - ret = setup_avm_a1(card); - break; -#endif -#if CARD_ELSA - case ISDN_CTYPE_ELSA: - case ISDN_CTYPE_ELSA_PNP: - case ISDN_CTYPE_ELSA_PCMCIA: - case ISDN_CTYPE_ELSA_PCI: - ret = setup_elsa(card); - break; -#endif -#if CARD_IX1MICROR2 - case ISDN_CTYPE_IX1MICROR2: - ret = setup_ix1micro(card); - break; -#endif -#if CARD_DIEHLDIVA - case ISDN_CTYPE_DIEHLDIVA: - ret = setup_diva(card); - break; -#endif -#if CARD_ASUSCOM - case ISDN_CTYPE_ASUSCOM: - ret = setup_asuscom(card); - break; -#endif -#if CARD_TELEINT - case ISDN_CTYPE_TELEINT: - ret = setup_TeleInt(card); - break; -#endif -#if CARD_SEDLBAUER - case ISDN_CTYPE_SEDLBAUER: - case ISDN_CTYPE_SEDLBAUER_PCMCIA: - ret = setup_sedlbauer(card); - break; -#endif -#if CARD_SPORTSTER - case ISDN_CTYPE_SPORTSTER: - ret = setup_sportster(card); - break; -#endif -#if CARD_MIC - case ISDN_CTYPE_MIC: - ret = setup_mic(card); - break; -#endif -#if CARD_NETJET - case ISDN_CTYPE_NETJET: - ret = setup_netjet(card); - break; -#endif -#if CARD_TELES3C - case ISDN_CTYPE_TELES3C: - ret = setup_t163c(card); - break; -#endif -#if CARD_NICCY - case ISDN_CTYPE_NICCY: - ret = setup_niccy(card); - break; -#endif -#if CARD_AMD7930 || CARD_DBRI - case ISDN_CTYPE_AMD7930: - case ISDN_CTYPE_DBRI: - ret = setup_foreign(card); - break; -#endif - default: - printk(KERN_WARNING "HiSax: Unknown Card Typ %d\n", - card->typ); - ll_unload(cs); - restore_flags(flags); - return (0); - } - if (!ret) { - ll_unload(cs); - restore_flags(flags); - return (0); - } - if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for isac rcvbuf\n"); - return (1); - } - cs->rcvidx = 0; - cs->tx_skb = NULL; - cs->tx_cnt = 0; - cs->event = 0; - cs->tqueue.next = 0; - cs->tqueue.sync = 0; - cs->tqueue.data = cs; - - skb_queue_head_init(&cs->rq); - skb_queue_head_init(&cs->sq); - - init_bcstate(cs, 0); - init_bcstate(cs, 1); - ret = init_card(cs); - if (ret) { - closecard(cardnr); - restore_flags(flags); - return (0); - } - init_tei(cs, cs->protocol); - CallcNewChan(cs); - ll_run(cs); - cs->l1cmd(cs, PH_RESET_REQ, NULL); - restore_flags(flags); - return (1); -} - -HISAX_INITFUNC(void -HiSax_shiftcards(int idx)) -{ - int i; - - for (i = idx; i < 15; i++) - memcpy(&cards[i], &cards[i + 1], sizeof(cards[i])); -} - -HISAX_INITFUNC(int -HiSax_inithardware(int *busy_flag)) -{ - int foundcards = 0; - int i = 0; - int t = ','; - int flg = 0; - char *id; - char *next_id = HiSax_id; - char ids[20]; - - if (strchr(HiSax_id, ',')) - t = ','; - else if (strchr(HiSax_id, '%')) - t = '%'; - - while (i < nrcards) { - if (cards[i].typ < 1) - break; - id = next_id; - if ((next_id = strchr(id, t))) { - *next_id++ = 0; - strcpy(ids, id); - flg = i + 1; - } else { - next_id = id; - if (flg >= i) - strcpy(ids, id); - else - sprintf(ids, "%s%d", id, i); - } - if (checkcard(i, ids, busy_flag)) { - foundcards++; - i++; - } else { - printk(KERN_WARNING "HiSax: Card %s not installed !\n", - CardType[cards[i].typ]); - if (cards[i].cs) - kfree((void *) cards[i].cs); - cards[i].cs = NULL; - HiSax_shiftcards(i); - } - } - return foundcards; -} - -void -HiSax_closehardware(void) -{ - int i; - long flags; - - save_flags(flags); - cli(); - for (i = 0; i < nrcards; i++) - if (cards[i].cs) { - ll_stop(cards[i].cs); - release_tei(cards[i].cs); - closecard(i); - free_irq(cards[i].cs->irq, cards[i].cs); - kfree((void *) cards[i].cs); - cards[i].cs = NULL; - } - Isdnl1Free(); - TeiFree(); - Isdnl2Free(); - CallcFree(); - restore_flags(flags); -} - -void -HiSax_reportcard(int cardnr) -{ - struct IsdnCardState *cs = cards[cardnr].cs; - struct PStack *stptr; - struct l3_process *pc; - int j, i = 1; - - printk(KERN_DEBUG "HiSax: reportcard No %d\n", cardnr + 1); - printk(KERN_DEBUG "HiSax: Type %s\n", CardType[cs->typ]); - printk(KERN_DEBUG "HiSax: debuglevel %x\n", cs->debug); - printk(KERN_DEBUG "HiSax: HiSax_reportcard address 0x%lX\n", - (ulong) & HiSax_reportcard); - printk(KERN_DEBUG "HiSax: cs 0x%lX\n", (ulong) cs); - printk(KERN_DEBUG "HiSax: cs stl 0x%lX\n", (ulong) & (cs->stlist)); - stptr = cs->stlist; - while (stptr != NULL) { - printk(KERN_DEBUG "HiSax: dst%d 0x%lX\n", i, (ulong) stptr); - printk(KERN_DEBUG "HiSax: dst%d stp 0x%lX\n", i, (ulong) stptr->l1.stlistp); - printk(KERN_DEBUG "HiSax: tei %d sapi %d\n", - stptr->l2.tei, stptr->l2.sap); - printk(KERN_DEBUG "HiSax: man 0x%lX\n", (ulong) stptr->ma.layer); - pc = stptr->l3.proc; - while (pc) { - printk(KERN_DEBUG "HiSax: l3proc %x 0x%lX\n", pc->callref, - (ulong) pc); - printk(KERN_DEBUG "HiSax: state %d st 0x%lX chan 0x%lX\n", - pc->state, (ulong) pc->st, (ulong) pc->chan); - pc = pc->next; - } - stptr = stptr->next; - i++; - } - for (j = 0; j < 2; j++) { - printk(KERN_DEBUG "HiSax: ch%d 0x%lX\n", j, - (ulong) & cs->channel[j]); - stptr = cs->channel[j].b_st; - i = 1; - while (stptr != NULL) { - printk(KERN_DEBUG "HiSax: b_st%d 0x%lX\n", i, (ulong) stptr); - printk(KERN_DEBUG "HiSax: man 0x%lX\n", (ulong) stptr->ma.layer); - stptr = stptr->next; - i++; - } - } -} - #ifdef L2FRAME_DEBUG /* psa */ char * @@ -1052,7 +481,7 @@ } } -static char tmp[20]; +static char tmpdeb[32]; char * l2frames(u_char * ptr) @@ -1061,7 +490,7 @@ case 1: case 5: case 9: - sprintf(tmp, "%s[%d](nr %d)", l2cmd(ptr[2]), ptr[3] & 1, ptr[3] >> 1); + sprintf(tmpdeb, "%s[%d](nr %d)", l2cmd(ptr[2]), ptr[3] & 1, ptr[3] >> 1); break; case 0x6f: case 0x0f: @@ -1070,36 +499,33 @@ case 0x63: case 0x87: case 0xaf: - sprintf(tmp, "%s[%d]", l2cmd(ptr[2]), (ptr[2] & 0x10) >> 4); + sprintf(tmpdeb, "%s[%d]", l2cmd(ptr[2]), (ptr[2] & 0x10) >> 4); break; default: if (!(ptr[2] & 1)) { - sprintf(tmp, "I[%d](ns %d, nr %d)", ptr[3] & 1, ptr[2] >> 1, ptr[3] >> 1); + sprintf(tmpdeb, "I[%d](ns %d, nr %d)", ptr[3] & 1, ptr[2] >> 1, ptr[3] >> 1); break; } else return "invalid command"; } - return tmp; + return tmpdeb; } void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir) { - char tmp[132]; u_char *ptr; ptr = skb->data; if (ptr[0] & 1 || !(ptr[1] & 1)) - debugl1(cs, "Addres not LAPD"); - else { - sprintf(tmp, "%s %s: %s%c (sapi %d, tei %d)", + debugl1(cs, "Address not LAPD"); + else + debugl1(cs, "%s %s: %s%c (sapi %d, tei %d)", (dir ? "<-" : "->"), buf, l2frames(ptr), ((ptr[0] & 2) >> 1) == dir ? 'C' : 'R', ptr[0] >> 2, ptr[1] >> 1); - debugl1(cs, tmp); - } } #endif @@ -1113,11 +539,10 @@ l1_deact_cnf(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; - struct IsdnCardState *cs = st->l1.hardware; FsmChangeState(fi, ST_L1_F3); if (test_bit(FLG_L1_ACTIVATING, &st->l1.Flags)) - cs->l1cmd(cs, PH_ENABLE_REQ, NULL); + st->l1.l1hw(st, HW_ENABLE | REQUEST, NULL); } static void @@ -1126,24 +551,23 @@ struct PStack *st = fi->userdata; FsmChangeState(fi, ST_L1_F3); - if (!test_bit(FLG_L1_T3RUN, &st->l1.Flags)) { +// if (!test_bit(FLG_L1_T3RUN, &st->l1.Flags)) { FsmDelTimer(&st->l1.timer, 1); FsmAddTimer(&st->l1.timer, 550, EV_TIMER_DEACT, NULL, 2); test_and_set_bit(FLG_L1_DEACTTIMER, &st->l1.Flags); - } +// } } static void l1_power_up(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; - struct IsdnCardState *cs = st->l1.hardware; if (test_bit(FLG_L1_ACTIVATING, &st->l1.Flags)) { FsmChangeState(fi, ST_L1_F4); - cs->l1cmd(cs, PH_INFO3_REQ, NULL); + st->l1.l1hw(st, HW_INFO3 | REQUEST, NULL); FsmDelTimer(&st->l1.timer, 1); - FsmAddTimer(&st->l1.timer, TIMER3_VALUE * HZ, EV_TIMER3, NULL, 2); + FsmAddTimer(&st->l1.timer, TIMER3_VALUE, EV_TIMER3, NULL, 2); test_and_set_bit(FLG_L1_T3RUN, &st->l1.Flags); } else FsmChangeState(fi, ST_L1_F3); @@ -1165,20 +589,18 @@ l1_info2_ind(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; - struct IsdnCardState *cs = st->l1.hardware; FsmChangeState(fi, ST_L1_F6); - cs->l1cmd(cs, PH_INFO3_REQ, NULL); + st->l1.l1hw(st, HW_INFO3 | REQUEST, NULL); } static void l1_info4_ind(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; - struct IsdnCardState *cs = st->l1.hardware; FsmChangeState(fi, ST_L1_F7); - cs->l1cmd(cs, PH_INFO3_REQ, NULL); + st->l1.l1hw(st, HW_INFO3 | REQUEST, NULL); if (test_and_clear_bit(FLG_L1_DEACTTIMER, &st->l1.Flags)) FsmDelTimer(&st->l1.timer, 4); if (!test_bit(FLG_L1_ACTIVATED, &st->l1.Flags)) { @@ -1193,50 +615,61 @@ l1_timer3(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; - struct IsdnCardState *cs = st->l1.hardware; - + test_and_clear_bit(FLG_L1_T3RUN, &st->l1.Flags); - if (test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags)) - L1deactivated(cs); - if (st->l1.l1m.state != ST_L1_F6) - FsmChangeState(fi, ST_L1_F3); + if (test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags)) + L1deactivated(st->l1.hardware); + if (st->l1.l1m.state != ST_L1_F6) { + FsmChangeState(fi, ST_L1_F3); + st->l1.l1hw(st, HW_ENABLE | REQUEST, NULL); + } } static void l1_timer_act(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; - struct IsdnCardState *cs = st->l1.hardware; test_and_clear_bit(FLG_L1_ACTTIMER, &st->l1.Flags); test_and_set_bit(FLG_L1_ACTIVATED, &st->l1.Flags); - L1activated(cs); + L1activated(st->l1.hardware); } static void l1_timer_deact(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; - struct IsdnCardState *cs = st->l1.hardware; test_and_clear_bit(FLG_L1_DEACTTIMER, &st->l1.Flags); test_and_clear_bit(FLG_L1_ACTIVATED, &st->l1.Flags); - L1deactivated(cs); - cs->l1cmd(cs, PH_DEACT_ACK, NULL); + L1deactivated(st->l1.hardware); + st->l1.l1hw(st, HW_DEACTIVATE | RESPONSE, NULL); } static void l1_activate(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; - struct IsdnCardState *cs = st->l1.hardware; - cs->l1cmd(cs, PH_RESET_REQ, NULL); + st->l1.l1hw(st, HW_RESET | REQUEST, NULL); } -static struct FsmNode L1FnList[] HISAX_INITDATA = +static void +l1_activate_no(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + if ((!test_bit(FLG_L1_DEACTTIMER, &st->l1.Flags)) && (!test_bit(FLG_L1_T3RUN, &st->l1.Flags))) { + test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags); + L1deactivated(st->l1.hardware); + } +} + +static struct FsmNode L1DFnList[] HISAX_INITDATA = { {ST_L1_F3, EV_PH_ACTIVATE, l1_activate}, + {ST_L1_F6, EV_PH_ACTIVATE, l1_activate_no}, + {ST_L1_F8, EV_PH_ACTIVATE, l1_activate_no}, {ST_L1_F3, EV_RESET_IND, l1_reset}, {ST_L1_F4, EV_RESET_IND, l1_reset}, {ST_L1_F5, EV_RESET_IND, l1_reset}, @@ -1280,86 +713,159 @@ {ST_L1_F8, EV_TIMER_DEACT, l1_timer_deact}, }; -#define L1_FN_COUNT (sizeof(L1FnList)/sizeof(struct FsmNode)) +#define L1D_FN_COUNT (sizeof(L1DFnList)/sizeof(struct FsmNode)) + +static void +l1b_activate(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + FsmChangeState(fi, ST_L1_WAIT_ACT); + FsmAddTimer(&st->l1.timer, st->l1.delay, EV_TIMER_ACT, NULL, 2); +} + +static void +l1b_deactivate(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + FsmChangeState(fi, ST_L1_WAIT_DEACT); + FsmAddTimer(&st->l1.timer, 10, EV_TIMER_DEACT, NULL, 2); +} + +static void +l1b_timer_act(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + FsmChangeState(fi, ST_L1_ACTIV); + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); +} + +static void +l1b_timer_deact(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + FsmChangeState(fi, ST_L1_NULL); + st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL); +} + +static struct FsmNode L1BFnList[] HISAX_INITDATA = +{ + {ST_L1_NULL, EV_PH_ACTIVATE, l1b_activate}, + {ST_L1_WAIT_ACT, EV_TIMER_ACT, l1b_timer_act}, + {ST_L1_ACTIV, EV_PH_DEACTIVATE, l1b_deactivate}, + {ST_L1_WAIT_DEACT, EV_TIMER_DEACT, l1b_timer_deact}, +}; + +#define L1B_FN_COUNT (sizeof(L1BFnList)/sizeof(struct FsmNode)) HISAX_INITFUNC(void Isdnl1New(void)) { - l1fsm.state_count = L1_STATE_COUNT; - l1fsm.event_count = L1_EVENT_COUNT; - l1fsm.strEvent = strL1Event; - l1fsm.strState = strL1State; - FsmNew(&l1fsm, L1FnList, L1_FN_COUNT); + l1fsm_d.state_count = L1D_STATE_COUNT; + l1fsm_d.event_count = L1_EVENT_COUNT; + l1fsm_d.strEvent = strL1Event; + l1fsm_d.strState = strL1DState; + FsmNew(&l1fsm_d, L1DFnList, L1D_FN_COUNT); + l1fsm_b.state_count = L1B_STATE_COUNT; + l1fsm_b.event_count = L1_EVENT_COUNT; + l1fsm_b.strEvent = strL1Event; + l1fsm_b.strState = strL1BState; + FsmNew(&l1fsm_b, L1BFnList, L1B_FN_COUNT); } void Isdnl1Free(void) { - FsmFree(&l1fsm); + FsmFree(&l1fsm_d); + FsmFree(&l1fsm_b); } static void -dch_manl1(struct PStack *st, int pr, - void *arg) +dch_l2l1(struct PStack *st, int pr, void *arg) { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; - char tmp[32]; switch (pr) { - case PH_ACTIVATE_REQ: - if (cs->debug) { - sprintf(tmp, "PH_ACTIVATE_REQ %s", - strL1State[st->l1.l1m.state]); - debugl1(cs, tmp); - } + case (PH_DATA | REQUEST): + case (PH_PULL | REQUEST): + case (PH_PULL |INDICATION): + st->l1.l1hw(st, pr, arg); + break; + case (PH_ACTIVATE | REQUEST): + if (cs->debug) + debugl1(cs, "PH_ACTIVATE_REQ %s", + strL1DState[st->l1.l1m.state]); if (test_bit(FLG_L1_ACTIVATED, &st->l1.Flags)) - st->l1.l1man(st, PH_ACTIVATE_CNF, NULL); + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); else { test_and_set_bit(FLG_L1_ACTIVATING, &st->l1.Flags); FsmEvent(&st->l1.l1m, EV_PH_ACTIVATE, arg); } break; - case PH_DEACTIVATE_REQ: - if (cs->debug) { - sprintf(tmp, "PH_DEACTIVATE_REQ %s", - strL1State[st->l1.l1m.state]); - debugl1(cs, tmp); - } - break; - case PH_TESTLOOP_REQ: - if (1 & (int) arg) + case (PH_TESTLOOP | REQUEST): + if (1 & (long) arg) debugl1(cs, "PH_TEST_LOOP B1"); - if (2 & (int) arg) + if (2 & (long) arg) debugl1(cs, "PH_TEST_LOOP B2"); - if (!(3 & (int) arg)) + if (!(3 & (long) arg)) debugl1(cs, "PH_TEST_LOOP DISABLED"); - cs->l1cmd(cs, PH_TESTLOOP_REQ, arg); - break; - case PH_RESET_IND: - FsmEvent(&st->l1.l1m, EV_RESET_IND, arg); - break; - case PH_DEACT_CNF: - FsmEvent(&st->l1.l1m, EV_DEACT_CNF, arg); - break; - case PH_DEACT_IND: - FsmEvent(&st->l1.l1m, EV_DEACT_IND, arg); - break; - case PH_POWERUP_CNF: - FsmEvent(&st->l1.l1m, EV_POWER_UP, arg); - break; - case PH_RSYNC_IND: - FsmEvent(&st->l1.l1m, EV_RSYNC_IND, arg); + st->l1.l1hw(st, HW_TESTLOOP | REQUEST, arg); break; - case PH_INFO2_IND: - FsmEvent(&st->l1.l1m, EV_INFO2_IND, arg); + default: + if (cs->debug) + debugl1(cs, "dch_l2l1 msg %04X unhandled", pr); break; - case PH_I4_P8_IND: - case PH_I4_P10_IND: - FsmEvent(&st->l1.l1m, EV_INFO4_IND, arg); + } +} + +void +l1_msg(struct IsdnCardState *cs, int pr, void *arg) { + struct PStack *st; + + st = cs->stlist; + + while (st) { + switch(pr) { + case (HW_RESET | INDICATION): + FsmEvent(&st->l1.l1m, EV_RESET_IND, arg); + break; + case (HW_DEACTIVATE | CONFIRM): + FsmEvent(&st->l1.l1m, EV_DEACT_CNF, arg); + break; + case (HW_DEACTIVATE | INDICATION): + FsmEvent(&st->l1.l1m, EV_DEACT_IND, arg); + break; + case (HW_POWERUP | CONFIRM): + FsmEvent(&st->l1.l1m, EV_POWER_UP, arg); + break; + case (HW_RSYNC | INDICATION): + FsmEvent(&st->l1.l1m, EV_RSYNC_IND, arg); + break; + case (HW_INFO2 | INDICATION): + FsmEvent(&st->l1.l1m, EV_INFO2_IND, arg); + break; + case (HW_INFO4_P8 | INDICATION): + case (HW_INFO4_P10 | INDICATION): + FsmEvent(&st->l1.l1m, EV_INFO4_IND, arg); + break; + default: + if (cs->debug) + debugl1(cs, "l1msg %04X unhandled", pr); + break; + } + st = st->next; + } +} + +void +l1_msg_b(struct PStack *st, int pr, void *arg) { + switch(pr) { + case (PH_ACTIVATE | REQUEST): + FsmEvent(&st->l1.l1m, EV_PH_ACTIVATE, NULL); break; - default: - if (cs->debug) { - sprintf(tmp, "dch_manl1 msg %04X unhandled", pr); - debugl1(cs, tmp); - } + case (PH_DEACTIVATE | REQUEST): + FsmEvent(&st->l1.l1m, EV_PH_DEACTIVATE, NULL); break; } } @@ -1369,7 +875,7 @@ { st->l1.hardware = cs; st->protocol = cs->protocol; - st->l1.l1m.fsm = &l1fsm; + st->l1.l1m.fsm = &l1fsm_d; st->l1.l1m.state = ST_L1_F3; st->l1.l1m.debug = cs->debug; st->l1.l1m.userdata = st; @@ -1379,7 +885,22 @@ setstack_tei(st); setstack_manager(st); st->l1.stlistp = &(cs->stlist); - st->ma.manl1 = dch_manl1; + st->l2.l2l1 = dch_l2l1; st->l1.Flags = 0; cs->setstack_d(st, cs); +} + +void +setstack_l1_B(struct PStack *st) +{ + struct IsdnCardState *cs = st->l1.hardware; + + st->l1.l1m.fsm = &l1fsm_b; + st->l1.l1m.state = ST_L1_NULL; + st->l1.l1m.debug = cs->debug; + st->l1.l1m.userdata = st; + st->l1.l1m.userint = 0; + st->l1.l1m.printdebug = l1m_debug; + st->l1.Flags = 0; + FsmInitTimer(&st->l1.l1m, &st->l1.timer); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isdnl1.h linux.pre11.3/drivers/isdn/hisax/isdnl1.h --- linux.vanilla/drivers/isdn/hisax/isdnl1.h Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/hisax/isdnl1.h Mon Jul 19 23:59:34 1999 @@ -1,6 +1,16 @@ -/* $Id: isdnl1.h,v 2.5 1998/02/02 13:36:58 keil Exp $ +/* $Id: isdnl1.h,v 2.8 1998/11/15 23:54:59 keil Exp $ * $Log: isdnl1.h,v $ + * Revision 2.8 1998/11/15 23:54:59 keil + * changes from 2.0 + * + * Revision 2.7 1998/09/30 22:21:55 keil + * cosmetics + * + * Revision 2.6 1998/05/25 12:58:06 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * * Revision 2.5 1998/02/02 13:36:58 keil * more debug * @@ -22,21 +32,6 @@ * */ - -#define L2FRAME_DEBUG - -/* DEBUG Level */ - -#define L1_DEB_WARN 0x01 -#define L1_DEB_INTSTAT 0x02 -#define L1_DEB_ISAC 0x04 -#define L1_DEB_ISAC_FIFO 0x08 -#define L1_DEB_HSCX 0x10 -#define L1_DEB_HSCX_FIFO 0x20 -#define L1_DEB_LAPD 0x40 -#define L1_DEB_IPAC 0x80 -#define L1_DEB_RECEIVE_FRAME 0x100 - #define D_RCVBUFREADY 0 #define D_XMTBUFREADY 1 #define D_L1STATECHANGE 2 @@ -49,11 +44,12 @@ #define B_RCVBUFREADY 0 #define B_XMTBUFREADY 1 -extern void debugl1(struct IsdnCardState *sp, char *msg); +extern void debugl1(struct IsdnCardState *cs, char *fmt, ...); extern void DChannel_proc_xmt(struct IsdnCardState *cs); extern void DChannel_proc_rcv(struct IsdnCardState *cs); - +extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg); +extern void l1_msg_b(struct PStack *st, int pr, void *arg); #ifdef L2FRAME_DEBUG -extern void Logl2Frame(struct IsdnCardState *sp, struct sk_buff *skb, char *buf, int dir); +extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir); #endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isdnl2.c linux.pre11.3/drivers/isdn/hisax/isdnl2.c --- linux.vanilla/drivers/isdn/hisax/isdnl2.c Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/hisax/isdnl2.c Mon Jul 19 23:59:34 1999 @@ -1,12 +1,45 @@ -/* $Id: isdnl2.c,v 2.7 1998/02/12 23:07:47 keil Exp $ +/* $Id: isdnl2.c,v 2.17 1999/07/01 08:11:50 keil Exp $ - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden * + * This file is (c) under GNU PUBLIC LICENSE + * For changes and modifications please read + * ../../../Documentation/isdn/HiSax.cert + * * Thanks to Jan den Ouden * Fritz Elfert * * $Log: isdnl2.c,v $ + * Revision 2.17 1999/07/01 08:11:50 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 2.16 1998/11/15 23:55:01 keil + * changes from 2.0 + * + * Revision 2.15 1998/08/13 23:36:42 keil + * HiSax 3.1 - don't work stable with current LinkLevel + * + * Revision 2.14 1998/06/19 15:19:18 keil + * fix LAPB tx_cnt for none I-frames + * + * Revision 2.13 1998/06/18 23:17:20 keil + * LAPB bugfix + * + * Revision 2.12 1998/05/25 14:10:12 keil + * HiSax 3.0 + * X.75 and leased are working again. + * + * Revision 2.11 1998/05/25 12:58:08 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * + * Revision 2.9 1998/04/10 10:35:30 paul + * fixed (silly?) warnings from egcs on Alpha. + * + * Revision 2.8 1998/03/07 22:57:04 tsbogend + * made HiSax working on Linux/Alpha + * * Revision 2.7 1998/02/12 23:07:47 keil * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * @@ -25,7 +58,7 @@ * Old stuff is still in the separate branch. * * Revision 2.2 1997/07/31 11:49:05 keil - * Eroor handling for no TEI assign + * Error handling for no TEI assign * * Revision 2.1 1997/07/27 21:34:38 keil * cosmetics @@ -41,9 +74,9 @@ #include "hisax.h" #include "isdnl2.h" -const char *l2_revision = "$Revision: 2.7 $"; +const char *l2_revision = "$Revision: 2.17 $"; -static void l2m_debug(struct FsmInst *fi, char *s); +static void l2m_debug(struct FsmInst *fi, char *fmt, ...); static struct Fsm l2fsm = @@ -76,7 +109,7 @@ enum { EV_L2_UI, - EV_L2_SABMX, + EV_L2_SABME, EV_L2_DISC, EV_L2_DM, EV_L2_UA, @@ -86,23 +119,25 @@ EV_L2_DL_DATA, EV_L2_ACK_PULL, EV_L2_DL_UNIT_DATA, - EV_L2_DL_ESTABLISH, - EV_L2_DL_RELEASE, + EV_L2_DL_ESTABLISH_REQ, + EV_L2_DL_RELEASE_REQ, EV_L2_MDL_ASSIGN, EV_L2_MDL_REMOVE, EV_L2_MDL_ERROR, - EV_L2_MDL_NOTEIPROC, EV_L1_DEACTIVATE, EV_L2_T200, EV_L2_T203, + EV_L2_SET_OWN_BUSY, + EV_L2_CLEAR_OWN_BUSY, + EV_L2_FRAME_ERROR, }; -#define L2_EVENT_COUNT (EV_L2_T203+1) +#define L2_EVENT_COUNT (EV_L2_FRAME_ERROR+1) static char *strL2Event[] = { "EV_L2_UI", - "EV_L2_SABMX", + "EV_L2_SABME", "EV_L2_DISC", "EV_L2_DM", "EV_L2_UA", @@ -112,15 +147,17 @@ "EV_L2_DL_DATA", "EV_L2_ACK_PULL", "EV_L2_DL_UNIT_DATA", - "EV_L2_DL_ESTABLISH", - "EV_L2_DL_RELEASE", + "EV_L2_DL_ESTABLISH_REQ", + "EV_L2_DL_RELEASE_REQ", "EV_L2_MDL_ASSIGN", "EV_L2_MDL_REMOVE", "EV_L2_MDL_ERROR", - "EV_L2_MDL_NOTEIPROC", "EV_L1_DEACTIVATE", "EV_L2_T200", "EV_L2_T203", + "EV_L2_SET_OWN_BUSY", + "EV_L2_CLEAR_OWN_BUSY", + "EV_L2_FRAME_ERROR", }; static int l2addrsize(struct Layer2 *l2); @@ -134,51 +171,46 @@ l2->windowar[i] = NULL; } -static void -ReleaseWin(struct Layer2 *l2) +static int +freewin1(struct Layer2 *l2) { int i, cnt = 0; for (i = 0; i < MAX_WINDOW; i++) { if (l2->windowar[i]) { cnt++; - dev_kfree_skb(l2->windowar[i]); + idev_kfree_skb(l2->windowar[i], FREE_WRITE); l2->windowar[i] = NULL; } } - if (cnt) - printk(KERN_WARNING "isdl2 freed %d skbuffs in release\n", cnt); + return cnt; } -inline int -cansend(struct PStack *st) +inline void +freewin(struct PStack *st) { - int p1; - - p1 = st->l2.vs - st->l2.va; - if (p1 < 0) - p1 += (test_bit(FLG_MOD128, &st->l2.flag) ? 128 : 8); - return ((p1 < st->l2.window) && !test_bit(FLG_PEER_BUSY, &st->l2.flag)); + freewin1(&st->l2); } static void -discard_i_queue(struct PStack *st) +ReleaseWin(struct Layer2 *l2) { - struct sk_buff *skb; + int cnt; - while ((skb = skb_dequeue(&st->l2.i_queue))) { - dev_kfree_skb(skb); - } + if((cnt = freewin1(l2))) + printk(KERN_WARNING "isdl2 freed %d skbuffs in release\n", cnt); } -static void -discard_ui_queue(struct PStack *st) +inline unsigned int +cansend(struct PStack *st) { - struct sk_buff *skb; + unsigned int p1; - while ((skb = skb_dequeue(&st->l2.ui_queue))) { - dev_kfree_skb(skb); - } + if(test_bit(FLG_MOD128, &st->l2.flag)) + p1 = (st->l2.vs - st->l2.va) % 128; + else + p1 = (st->l2.vs - st->l2.va) % 8; + return ((p1 < st->l2.window) && !test_bit(FLG_PEER_BUSY, &st->l2.flag)); } inline void @@ -224,103 +256,209 @@ } } -static void -enqueue_ui(struct PStack *st, - struct sk_buff *skb) -{ - st->l2.l2l1(st, PH_DATA_REQ, skb); -} - -static void +inline static void enqueue_super(struct PStack *st, struct sk_buff *skb) { - st->l2.l2l1(st, PH_DATA_REQ, skb); + if (test_bit(FLG_LAPB, &st->l2.flag)) + st->l1.bcs->tx_cnt += skb->len; + st->l2.l2l1(st, PH_DATA | REQUEST, skb); } +#define enqueue_ui(a, b) enqueue_super(a, b) + inline int -IsUI(u_char * data, int ext) +IsUI(u_char * data) { return ((data[0] & 0xef) == UI); } inline int -IsUA(u_char * data, int ext) +IsUA(u_char * data) { return ((data[0] & 0xef) == UA); } inline int -IsDM(u_char * data, int ext) +IsDM(u_char * data) { return ((data[0] & 0xef) == DM); } inline int -IsDISC(u_char * data, int ext) +IsDISC(u_char * data) { return ((data[0] & 0xef) == DISC); } inline int -IsRR(u_char * data, int ext) +IsRR(u_char * data, struct PStack *st) { - if (ext) + if (test_bit(FLG_MOD128, &st->l2.flag)) return (data[0] == RR); else return ((data[0] & 0xf) == 1); } inline int -IsSABMX(u_char * data, int ext) +IsSFrame(u_char * data, struct PStack *st) +{ + register u_char d = *data; + + if (!test_bit(FLG_MOD128, &st->l2.flag)) + d &= 0xf; + return(((d & 0xf3) == 1) && ((d & 0x0c) != 0x0c)); +} + +inline int +IsSABME(u_char * data, struct PStack *st) { u_char d = data[0] & ~0x10; - return (ext ? d == SABME : d == SABM); + return (test_bit(FLG_MOD128, &st->l2.flag) ? d == SABME : d == SABM); } inline int -IsREJ(u_char * data, int ext) +IsREJ(u_char * data, struct PStack *st) { - return (ext ? data[0] == REJ : (data[0] & 0xf) == REJ); + return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == REJ : (data[0] & 0xf) == REJ); } inline int -IsFRMR(u_char * data, int ext) +IsFRMR(u_char * data) { return ((data[0] & 0xef) == FRMR); } inline int -IsRNR(u_char * data, int ext) +IsRNR(u_char * data, struct PStack *st) { - return (ext ? data[0] == RNR : (data[0] & 0xf) == RNR); + return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == RNR : (data[0] & 0xf) == RNR); } -static int -legalnr(struct PStack *st, int nr) +int +iframe_error(struct PStack *st, struct sk_buff *skb) { - struct Layer2 *l2 = &st->l2; - int lnr, lvs; + int i = l2addrsize(&st->l2) + (test_bit(FLG_MOD128, &st->l2.flag) ? 1 : 0); + int rsp = *skb->data & 0x2; + + if (test_bit(FLG_ORIG, &st->l2.flag)) + rsp = !rsp; + + if (rsp) + return 'L'; + + + if (skb->len <= i) + return 'N'; + + if ((skb->len - i) > st->l2.maxlen) + return 'O'; + + + return 0; +} + +int +super_error(struct PStack *st, struct sk_buff *skb) +{ + if (skb->len != l2addrsize(&st->l2) + + (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1)) + return 'N'; + + return 0; +} + +int +unnum_error(struct PStack *st, struct sk_buff *skb, int wantrsp) +{ + int rsp = (*skb->data & 0x2) >> 1; + if (test_bit(FLG_ORIG, &st->l2.flag)) + rsp = !rsp; + + if (rsp != wantrsp) + return 'L'; + + if (skb->len != l2addrsize(&st->l2) + 1) + return 'N'; + + return 0; +} + +int +UI_error(struct PStack *st, struct sk_buff *skb) +{ + int rsp = *skb->data & 0x2; + if (test_bit(FLG_ORIG, &st->l2.flag)) + rsp = !rsp; + + if (rsp) + return 'L'; + + if (skb->len > st->l2.maxlen + l2addrsize(&st->l2) + 1) + return 'O'; - lvs = (l2->vs >= l2->va) ? l2->vs : - (l2->vs + (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8)); - lnr = (nr >= l2->va) ? nr : (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8); - return (lnr <= lvs); + return 0; +} + +int +FRMR_error(struct PStack *st, struct sk_buff *skb) +{ + int headers = l2addrsize(&st->l2) + 1; + u_char *datap = skb->data + headers; + int rsp = *skb->data & 0x2; + + if (test_bit(FLG_ORIG, &st->l2.flag)) + rsp = !rsp; + + if (!rsp) + return 'L'; + + if (test_bit(FLG_MOD128, &st->l2.flag)) { + if (skb->len < headers + 5) + return 'N'; + else + l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x %2x %2x", + datap[0], datap[1], datap[2], + datap[3], datap[4]); + } else { + if (skb->len < headers + 3) + return 'N'; + else + l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x", + datap[0], datap[1], datap[2]); + } + + return 0; +} + +static unsigned int +legalnr(struct PStack *st, unsigned int nr) +{ + struct Layer2 *l2 = &st->l2; + + if(test_bit(FLG_MOD128, &l2->flag)) + return ((nr - l2->va) % 128) <= ((l2->vs - l2->va) % 128); + else + return ((nr - l2->va) % 8) <= ((l2->vs - l2->va) % 8); } static void -setva(struct PStack *st, int nr) +setva(struct PStack *st, unsigned int nr) { struct Layer2 *l2 = &st->l2; int len; while (l2->va != nr) { - l2->va = (l2->va + 1) % (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8); + (l2->va)++; + if(test_bit(FLG_MOD128, &l2->flag)) + l2->va %= 128; + else + l2->va %= 8; len = l2->windowar[l2->sow]->len; if (PACKET_NOACK == l2->windowar[l2->sow]->pkt_type) len = -1; - dev_kfree_skb(l2->windowar[l2->sow]); + idev_kfree_skb(l2->windowar[l2->sow], FREE_WRITE); l2->windowar[l2->sow] = NULL; l2->sow = (l2->sow + 1) % l2->window; if (st->lli.l2writewakeup && (len >=0)) @@ -341,6 +479,7 @@ printk(KERN_WARNING "isdl2 can't alloc sbbuff for send_uframe\n"); return; } + SET_SKB_FREE(skb); memcpy(skb_put(skb, i), tmp, i); enqueue_super(st, skb); } @@ -354,7 +493,7 @@ inline void FreeSkb(struct sk_buff *skb) { - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); } @@ -368,6 +507,48 @@ return (PF); } +inline void +start_t200(struct PStack *st, int i) +{ + FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, i); + test_and_set_bit(FLG_T200_RUN, &st->l2.flag); +} + +inline void +restart_t200(struct PStack *st, int i) +{ + FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, i); + test_and_set_bit(FLG_T200_RUN, &st->l2.flag); +} + +inline void +stop_t200(struct PStack *st, int i) +{ + if(test_and_clear_bit(FLG_T200_RUN, &st->l2.flag)) + FsmDelTimer(&st->l2.t200, i); +} + +inline void +st5_dl_release_l2l3(struct PStack *st) +{ + int pr; + + if(test_and_clear_bit(FLG_PEND_REL, &st->l2.flag)) + pr = DL_RELEASE | CONFIRM; + else + pr = DL_RELEASE | INDICATION; + + st->l2.l2l3(st, pr, NULL); +} + +inline void +lapb_dl_release_l2l3(struct PStack *st, int f) +{ + if (test_bit(FLG_LAPB, &st->l2.flag)) + st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); + st->l2.l2l3(st, DL_RELEASE | f, NULL); +} + static void establishlink(struct FsmInst *fi) { @@ -379,49 +560,91 @@ cmd = (test_bit(FLG_MOD128, &st->l2.flag) ? SABME : SABM) | 0x10; send_uframe(st, cmd, CMD); FsmDelTimer(&st->l2.t203, 1); - FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 1); - test_and_set_bit(FLG_T200_RUN, &st->l2.flag); + restart_t200(st, 1); + test_and_clear_bit(FLG_PEND_REL, &st->l2.flag); + freewin(st); FsmChangeState(fi, ST_L2_5); } static void -l2_mdl_error(struct FsmInst *fi, int event, void *arg) +l2_mdl_error_ua(struct FsmInst *fi, int event, void *arg) { struct sk_buff *skb = arg; struct PStack *st = fi->userdata; - switch (event) { - case EV_L2_UA: - if (get_PollFlagFree(st, skb)) - st->ma.layer(st, MDL_ERROR_IND, (void *) 'C'); - else - st->ma.layer(st, MDL_ERROR_IND, (void *) 'D'); - break; - case EV_L2_DM: - if (get_PollFlagFree(st, skb)) - st->ma.layer(st, MDL_ERROR_IND, (void *) 'B'); - else { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'E'); - establishlink(fi); - test_and_clear_bit(FLG_L3_INIT, &st->l2.flag); - } - break; + if (get_PollFlagFree(st, skb)) + st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'C'); + else + st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'D'); +} + +static void +l2_mdl_error_dm(struct FsmInst *fi, int event, void *arg) +{ + struct sk_buff *skb = arg; + struct PStack *st = fi->userdata; + + if (get_PollFlagFree(st, skb)) + st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B'); + else { + st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E'); + establishlink(fi); + test_and_clear_bit(FLG_L3_INIT, &st->l2.flag); } } static void -l2_dl_establish(struct FsmInst *fi, int event, void *arg) +l2_st8_mdl_error_dm(struct FsmInst *fi, int event, void *arg) { + struct sk_buff *skb = arg; struct PStack *st = fi->userdata; - int state = fi->state; + if (get_PollFlagFree(st, skb)) + st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B'); + else { + st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E'); + } + establishlink(fi); + test_and_clear_bit(FLG_L3_INIT, &st->l2.flag); +} + +static void +l2_go_st3(struct FsmInst *fi, int event, void *arg) +{ FsmChangeState(fi, ST_L2_3); - if (state == ST_L2_1) - st->l2.l2tei(st, MDL_ASSIGN_IND, NULL); } static void -l2_send_ui(struct PStack *st) +l2_mdl_assign(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + FsmChangeState(fi, ST_L2_3); + st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL); +} + +static void +l2_queue_ui_assign(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + struct sk_buff *skb = arg; + + skb_queue_tail(&st->l2.ui_queue, skb); + FsmChangeState(fi, ST_L2_2); + st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL); +} + +static void +l2_queue_ui(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + struct sk_buff *skb = arg; + + skb_queue_tail(&st->l2.ui_queue, skb); +} + +static void +tx_ui(struct PStack *st) { struct sk_buff *skb; u_char header[MAX_HEADER_LEN]; @@ -436,18 +659,13 @@ } static void -l2_put_ui(struct FsmInst *fi, int event, void *arg) +l2_send_ui(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; struct sk_buff *skb = arg; skb_queue_tail(&st->l2.ui_queue, skb); - if (fi->state == ST_L2_1) { - FsmChangeState(fi, ST_L2_2); - st->l2.l2tei(st, MDL_ASSIGN_IND, NULL); - } - if (fi->state > ST_L2_3) - l2_send_ui(st); + tx_ui(st); } static void @@ -457,11 +675,12 @@ struct sk_buff *skb = arg; skb_pull(skb, l2headersize(&st->l2, 1)); - if (skb->len > st->l2.maxlen) { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'O'); - FreeSkb(skb); - } else - st->l2.l2l3(st, DL_UNIT_DATA, skb); + st->l2.l2l3(st, DL_UNIT_DATA | INDICATION, skb); +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * in states 1-3 for broadcast + */ + + } static void @@ -469,245 +688,243 @@ { struct PStack *st = fi->userdata; - if (fi->state != ST_L2_4) - discard_i_queue(st); - if (fi->state != ST_L2_5) - establishlink(fi); + establishlink(fi); test_and_set_bit(FLG_L3_INIT, &st->l2.flag); } static void -l2_dl_release(struct FsmInst *fi, int event, void *arg) +l2_discard_i_setl3(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; - if (fi->state == ST_L2_4) { - st->l2.l2man(st, DL_RELEASE, NULL); - return; - } else if (fi->state == ST_L2_5) { - test_and_set_bit(FLG_PEND_REL, &st->l2.flag); - return; - } - discard_i_queue(st); + discard_queue(&st->l2.i_queue); + test_and_set_bit(FLG_L3_INIT, &st->l2.flag); + test_and_clear_bit(FLG_PEND_REL, &st->l2.flag); +} + +static void +l2_l3_reestablish(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + discard_queue(&st->l2.i_queue); + establishlink(fi); + test_and_set_bit(FLG_L3_INIT, &st->l2.flag); +} + +static void +l2_release(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL); +} + +static void +l2_pend_rel(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + test_and_set_bit(FLG_PEND_REL, &st->l2.flag); +} + +static void +l2_disconnect(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + discard_queue(&st->l2.i_queue); + freewin(st); FsmChangeState(fi, ST_L2_6); st->l2.rc = 0; send_uframe(st, DISC | 0x10, CMD); FsmDelTimer(&st->l2.t203, 1); - FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 2); - test_and_set_bit(FLG_T200_RUN, &st->l2.flag); + restart_t200(st, 2); } static void -l2_got_SABMX(struct FsmInst *fi, int event, void *arg) +l2_start_multi(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; struct sk_buff *skb = arg; - int est = 1, state, rsp; - u_char PollFlag; + + send_uframe(st, UA | get_PollFlagFree(st, skb), RSP); + + clear_exception(&st->l2); + st->l2.vs = 0; + st->l2.va = 0; + st->l2.vr = 0; + st->l2.sow = 0; + FsmChangeState(fi, ST_L2_7); + FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3); + + st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL); +} + +static void +l2_send_UA(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + struct sk_buff *skb = arg; + + send_uframe(st, UA | get_PollFlagFree(st, skb), RSP); +} + +static void +l2_send_DM(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + struct sk_buff *skb = arg; + + send_uframe(st, DM | get_PollFlagFree(st, skb), RSP); +} + +static void +l2_restart_multi(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + struct sk_buff *skb = arg; + int est = 0, state; state = fi->state; - rsp = *skb->data & 0x2; - if (test_bit(FLG_ORIG, &st->l2.flag)) - rsp = !rsp; - if (rsp) { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'L'); - FreeSkb(skb); - if ((state == ST_L2_7) || (state == ST_L2_8)) - establishlink(fi); - return; - } - if (skb->len != (l2addrsize(&st->l2) + 1)) { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'N'); - FreeSkb(skb); - if ((state == ST_L2_7) || (state == ST_L2_8)) - establishlink(fi); - return; - } - PollFlag = get_PollFlagFree(st, skb); - if (ST_L2_6 == state) { - send_uframe(st, DM | PollFlag, RSP); - return; - } else - send_uframe(st, UA | PollFlag, RSP); - if (ST_L2_5 == state) - return; - if (ST_L2_4 != state) { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'F'); - if (st->l2.vs != st->l2.va) { - discard_i_queue(st); - est = 1; - } else - est = 0; + + send_uframe(st, UA | get_PollFlagFree(st, skb), RSP); + + st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'F'); + + if (st->l2.vs != st->l2.va) { + discard_queue(&st->l2.i_queue); + est = 1; } + clear_exception(&st->l2); st->l2.vs = 0; st->l2.va = 0; st->l2.vr = 0; st->l2.sow = 0; FsmChangeState(fi, ST_L2_7); - if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag)) - FsmDelTimer(&st->l2.t200, 2); - FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3); + stop_t200(st, 3); + FsmRestartTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3); if (est) - st->l2.l2man(st, DL_ESTABLISH, NULL); + st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL); - if (ST_L2_8 == state) + if ((ST_L2_7==state) || (ST_L2_8 == state)) if (skb_queue_len(&st->l2.i_queue) && cansend(st)) - st->l2.l2l1(st, PH_PULL_REQ, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); } static void -l2_got_disconn(struct FsmInst *fi, int event, void *arg) +l2_stop_multi(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; struct sk_buff *skb = arg; - u_char PollFlag, cmd = UA; - int state, rel = 1, cst = 1, rsp; - state = fi->state; - rsp = *skb->data & 0x2; - if (test_bit(FLG_ORIG, &st->l2.flag)) - rsp = !rsp; + FsmChangeState(fi, ST_L2_4); + FsmDelTimer(&st->l2.t203, 3); + stop_t200(st, 4); - if (rsp) { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'L'); - FreeSkb(skb); - if ((state == ST_L2_7) || (state == ST_L2_8)) - establishlink(fi); + send_uframe(st, UA | get_PollFlagFree(st, skb), RSP); + + discard_queue(&st->l2.i_queue); + freewin(st); + lapb_dl_release_l2l3(st, INDICATION); +} + +static void +l2_connected(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + struct sk_buff *skb = arg; + int pr=-1; + + if (!get_PollFlag(st, skb)) { + l2_mdl_error_ua(fi, event, arg); return; - } - if (skb->len != (l2addrsize(&st->l2) + 1)) { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'N'); - FreeSkb(skb); - if ((state == ST_L2_7) || (state == ST_L2_8)) - establishlink(fi); + } + FreeSkb(skb); + + if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag)) + l2_disconnect(fi, event, arg); + + if (test_and_clear_bit(FLG_L3_INIT, &st->l2.flag)) { + pr = DL_ESTABLISH | CONFIRM; + } else if (st->l2.vs != st->l2.va) { + discard_queue(&st->l2.i_queue); + pr = DL_ESTABLISH | INDICATION; + } + + stop_t200(st, 5); + + st->l2.vr = 0; + st->l2.vs = 0; + st->l2.va = 0; + st->l2.sow = 0; + FsmChangeState(fi, ST_L2_7); + FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 4); + + if (pr != -1) + st->l2.l2l3(st, pr, NULL); + + if (skb_queue_len(&st->l2.i_queue) && cansend(st)) + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); +} + +static void +l2_released(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + struct sk_buff *skb = arg; + + if (!get_PollFlag(st, skb)) { + l2_mdl_error_ua(fi, event, arg); return; } - PollFlag = get_PollFlagFree(st, skb); - if ((state == ST_L2_4) || (state == ST_L2_5)) { - rel = 0; - cst = 0; - cmd = DM; - } else if (state == ST_L2_6) { - rel = 0; - cst = 0; - } - if (cst) { - FsmChangeState(fi, ST_L2_4); - FsmDelTimer(&st->l2.t203, 3); - if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag)) - FsmDelTimer(&st->l2.t200, 2); - } - send_uframe(st, cmd | PollFlag, RSP); - if (rel) - st->l2.l2man(st, DL_RELEASE, NULL); -} + FreeSkb(skb); + stop_t200(st, 6); + lapb_dl_release_l2l3(st, CONFIRM); + FsmChangeState(fi, ST_L2_4); +} static void -l2_got_ua(struct FsmInst *fi, int event, void *arg) +l2_reestablish(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; struct sk_buff *skb = arg; - u_char PollFlag, est = 1; - int state,rsp; - state = fi->state; - rsp = *skb->data & 0x2; - if (test_bit(FLG_ORIG, &st->l2.flag)) - rsp = !rsp; - - if (!rsp) { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'L'); - FreeSkb(skb); - if ((state == ST_L2_7) || (state == ST_L2_8)) - establishlink(fi); - return; - } - if (skb->len != (l2addrsize(&st->l2) + 1)) { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'N'); - FreeSkb(skb); - if ((fi->state == ST_L2_7) || (fi->state == ST_L2_8)) - establishlink(fi); - return; - } - PollFlag = get_PollFlag(st, skb); - if (!PollFlag) { - l2_mdl_error(fi, event, arg); - return; + if (!get_PollFlagFree(st, skb)) { + establishlink(fi); + test_and_set_bit(FLG_L3_INIT, &st->l2.flag); } - FreeSkb(skb); +} - if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag)) - FsmDelTimer(&st->l2.t200, 2); - if (fi->state == ST_L2_5) { - if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag)) { - discard_i_queue(st); - st->l2.rc = 0; - send_uframe(st, DISC | 0x10, CMD); - FsmChangeState(fi, ST_L2_6); - FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 4); - test_and_set_bit(FLG_T200_RUN, &st->l2.flag); - } else { - if (!test_and_clear_bit(FLG_L3_INIT, &st->l2.flag)) { - if (st->l2.vs != st->l2.va) - discard_i_queue(st); - else - est = 0; - } - st->l2.vs = 0; - st->l2.va = 0; - st->l2.vr = 0; - st->l2.sow = 0; - FsmChangeState(fi, ST_L2_7); - FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 4); - if (est) - st->l2.l2man(st, DL_ESTABLISH, NULL); - } - } else { /* ST_L2_6 */ - st->l2.l2man(st, DL_RELEASE, NULL); +static void +l2_st5_dm_release(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + struct sk_buff *skb = arg; + + if (get_PollFlagFree(st, skb)) { + stop_t200(st, 7); + if (!test_bit(FLG_L3_INIT, &st->l2.flag)) + discard_queue(&st->l2.i_queue); + if (test_bit(FLG_LAPB, &st->l2.flag)) + st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); + st5_dl_release_l2l3(st); FsmChangeState(fi, ST_L2_4); } } static void -l2_got_dm(struct FsmInst *fi, int event, void *arg) +l2_st6_dm_release(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; struct sk_buff *skb = arg; - u_char PollFlag; - int state,rsp; - state = fi->state; - rsp = *skb->data & 0x2; - if (test_bit(FLG_ORIG, &st->l2.flag)) - rsp = !rsp; - - if (!rsp) { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'L'); - FreeSkb(skb); - if ((state == ST_L2_7) || (state == ST_L2_8)) - establishlink(fi); - return; - } - if (skb->len != (l2addrsize(&st->l2) + 1)) { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'N'); - FreeSkb(skb); - if ((fi->state == ST_L2_7) || (fi->state == ST_L2_8)) - establishlink(fi); - return; - } - PollFlag = get_PollFlagFree(st, skb); - if (!PollFlag) { - establishlink(fi); - test_and_clear_bit(FLG_L3_INIT, &st->l2.flag); - } else { - if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag)) - FsmDelTimer(&st->l2.t200, 2); - if (fi->state == ST_L2_5 && !test_bit(FLG_L3_INIT, &st->l2.flag)) - discard_i_queue(st); - st->l2.l2man(st, DL_RELEASE, NULL); + if (get_PollFlagFree(st, skb)) { + stop_t200(st, 8); + lapb_dl_release_l2l3(st, CONFIRM); FsmChangeState(fi, ST_L2_4); } } @@ -731,6 +948,7 @@ printk(KERN_WARNING "isdl2 can't alloc sbbuff for enquiry_cr\n"); return; } + SET_SKB_FREE(skb); memcpy(skb_put(skb, i), tmp, i); enqueue_super(st, skb); } @@ -753,8 +971,7 @@ else enquiry_cr(st, RR, CMD, 1); test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag); - FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 12); - test_and_set_bit(FLG_T200_RUN, &st->l2.flag); + start_t200(st, 9); } @@ -763,42 +980,44 @@ { struct PStack *st = fi->userdata; - st->ma.layer(st, MDL_ERROR_IND, (void *) 'J'); + st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'J'); establishlink(fi); + test_and_clear_bit(FLG_L3_INIT, &st->l2.flag); } static void -invoke_retransmission(struct PStack *st, int nr) +invoke_retransmission(struct PStack *st, unsigned int nr) { struct Layer2 *l2 = &st->l2; - int p1; - long flags; + unsigned int p1; if (l2->vs != nr) { - save_flags(flags); - cli(); while (l2->vs != nr) { - l2->vs = l2->vs - 1; - if (l2->vs < 0) - l2->vs += (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8); - p1 = l2->vs - l2->va; - if (p1 < 0) - p1 += (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8); + (l2->vs)--; + if(test_bit(FLG_MOD128, &l2->flag)) { + l2->vs %= 128; + p1 = (l2->vs - l2->va) % 128; + } else { + l2->vs %= 8; + p1 = (l2->vs - l2->va) % 8; + } p1 = (p1 + l2->sow) % l2->window; + if (test_bit(FLG_LAPB, &l2->flag)) + st->l1.bcs->tx_cnt += l2->windowar[p1]->len + l2headersize(l2, 0); skb_queue_head(&l2->i_queue, l2->windowar[p1]); l2->windowar[p1] = NULL; } - restore_flags(flags); - st->l2.l2l1(st, PH_PULL_REQ, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); } } static void -l2_got_st7_super(struct FsmInst *fi, int event, void *arg) +l2_st7_got_super(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; struct sk_buff *skb = arg; - int PollFlag, nr, rsp, typ = RR; + int PollFlag, rsp, typ = RR; + unsigned int nr; struct Layer2 *l2 = &st->l2; rsp = *skb->data & 0x2; @@ -806,70 +1025,77 @@ rsp = !rsp; skb_pull(skb, l2addrsize(l2)); - if (IsRNR(skb->data, test_bit(FLG_MOD128, &l2->flag))) { + if (IsRNR(skb->data, st)) { test_and_set_bit(FLG_PEER_BUSY, &l2->flag); typ = RNR; } else test_and_clear_bit(FLG_PEER_BUSY, &l2->flag); - if (IsREJ(skb->data, test_bit(FLG_MOD128, &l2->flag))) + if (IsREJ(skb->data, st)) typ = REJ; + if (test_bit(FLG_MOD128, &l2->flag)) { - if (skb->len == 2) { - PollFlag = (skb->data[1] & 0x1) == 0x1; - nr = skb->data[1] >> 1; - } else { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'N'); - FreeSkb(skb); - establishlink(fi); - return; - } + PollFlag = (skb->data[1] & 0x1) == 0x1; + nr = skb->data[1] >> 1; } else { - if (skb->len == 1) { - PollFlag = (skb->data[0] & 0x10); - nr = (skb->data[0] >> 5) & 0x7; - } else { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'N'); - FreeSkb(skb); - establishlink(fi); - return; - } + PollFlag = (skb->data[0] & 0x10); + nr = (skb->data[0] >> 5) & 0x7; } FreeSkb(skb); - if ((!rsp) && PollFlag) - enquiry_response(st); - if (rsp && PollFlag) - st->ma.layer(st, MDL_ERROR_IND, (void *) 'A'); + if (PollFlag) { + if (rsp) + st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'A'); + else + enquiry_response(st); + } if (legalnr(st, nr)) { if (typ == REJ) { setva(st, nr); invoke_retransmission(st, nr); - if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag)) - FsmDelTimer(&st->l2.t200, 9); + stop_t200(st, 10); if (FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 6)) l2m_debug(&st->l2.l2m, "Restart T203 ST7 REJ"); } else if ((nr == l2->vs) && (typ == RR)) { setva(st, nr); - if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag)) - FsmDelTimer(&st->l2.t200, 9); + stop_t200(st, 11); FsmRestartTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 7); } else if ((l2->va != nr) || (typ == RNR)) { setva(st, nr); - FsmDelTimer(&st->l2.t203, 9); - FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 6); - test_and_set_bit(FLG_T200_RUN, &st->l2.flag); + if(typ != RR) FsmDelTimer(&st->l2.t203, 9); + restart_t200(st, 12); } if (skb_queue_len(&st->l2.i_queue) && (typ == RR)) - st->l2.l2l1(st, PH_PULL_REQ, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); } else nrerrorrecovery(fi); +} - if ((fi->userint & LC_FLUSH_WAIT) && rsp && !(skb_queue_len(&st->l2.i_queue))) { - fi->userint &= ~LC_FLUSH_WAIT; - st->l2.l2man(st, DL_FLUSH, NULL); - } +static void +l2_feed_i_if_reest(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + struct sk_buff *skb = arg; + + if (test_bit(FLG_LAPB, &st->l2.flag)) + st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0); + if (!test_bit(FLG_L3_INIT, &st->l2.flag)) + skb_queue_tail(&st->l2.i_queue, skb); + else + FreeSkb(skb); +} + +static void +l2_feed_i_pull(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + struct sk_buff *skb = arg; + + if (test_bit(FLG_LAPB, &st->l2.flag)) + st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0); + skb_queue_tail(&st->l2.i_queue, skb); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); } static void @@ -880,10 +1106,7 @@ if (test_bit(FLG_LAPB, &st->l2.flag)) st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0); - if (!((fi->state == ST_L2_5) && test_bit(FLG_L3_INIT, &st->l2.flag))) - skb_queue_tail(&st->l2.i_queue, skb); - if (fi->state == ST_L2_7) - st->l2.l2l1(st, PH_PULL_REQ, NULL); + skb_queue_tail(&st->l2.i_queue, skb); } static void @@ -891,73 +1114,37 @@ { struct PStack *st = fi->userdata; struct sk_buff *skb = arg; - struct IsdnCardState *sp = st->l1.hardware; struct Layer2 *l2 = &(st->l2); - int PollFlag, ns, nr, i, hs, rsp; - char str[64]; - - rsp = *skb->data & 0x2; - if (test_bit(FLG_ORIG, &l2->flag)) - rsp = !rsp; + int PollFlag, ns, i; + unsigned int nr; - if (rsp) { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'L'); - FreeSkb(skb); - establishlink(fi); - return; - } i = l2addrsize(l2); if (test_bit(FLG_MOD128, &l2->flag)) { - if (skb->len <= (i + 1)) { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'N'); - FreeSkb(skb); - establishlink(fi); - return; - } else if ((skb->len - i - 1) > l2->maxlen) { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'O'); - FreeSkb(skb); - establishlink(fi); - return; - } PollFlag = ((skb->data[i + 1] & 0x1) == 0x1); ns = skb->data[i] >> 1; nr = (skb->data[i + 1] >> 1) & 0x7f; } else { - if (skb->len <= i) { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'N'); - FreeSkb(skb); - establishlink(fi); - return; - } else if ((skb->len - i) > l2->maxlen) { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'O'); - FreeSkb(skb); - establishlink(fi); - return; - } PollFlag = (skb->data[i] & 0x10); ns = (skb->data[i] >> 1) & 0x7; nr = (skb->data[i] >> 5) & 0x7; } if (test_bit(FLG_OWN_BUSY, &l2->flag)) { FreeSkb(skb); - enquiry_response(st); + if(PollFlag) enquiry_response(st); } else if (l2->vr == ns) { - l2->vr = (l2->vr + 1) % (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8); + (l2->vr)++; + if(test_bit(FLG_MOD128, &l2->flag)) + l2->vr %= 128; + else + l2->vr %= 8; test_and_clear_bit(FLG_REJEXC, &l2->flag); - if (test_bit(FLG_LAPD, &l2->flag)) - if (sp->dlogflag) { - hs = l2headersize(l2, 0); - LogFrame(st->l1.hardware, skb->data, skb->len); - sprintf(str, "Q.931 frame network->user tei %d", st->l2.tei); - dlogframe(st->l1.hardware, skb->data + hs, - skb->len - hs, str); - } + if (PollFlag) enquiry_response(st); else test_and_set_bit(FLG_ACK_PEND, &l2->flag); skb_pull(skb, l2headersize(l2, 0)); - st->l2.l2l3(st, DL_DATA, skb); + st->l2.l2l3(st, DL_DATA | INDICATION, skb); } else { /* n(s)!=v(r) */ FreeSkb(skb); @@ -971,26 +1158,22 @@ } if (legalnr(st, nr)) { - setva(st, nr); if (!test_bit(FLG_PEER_BUSY, &st->l2.flag) && (fi->state == ST_L2_7)) { if (nr == st->l2.vs) { - if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag)) - FsmDelTimer(&st->l2.t200, 10); + stop_t200(st, 13); FsmRestartTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 7); - } else if (nr != st->l2.va) { - FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, - NULL, 8); - test_and_set_bit(FLG_T200_RUN, &st->l2.flag); - } + } else if (nr != st->l2.va) + restart_t200(st, 14); } + setva(st, nr); } else { nrerrorrecovery(fi); return; } if (skb_queue_len(&st->l2.i_queue) && (fi->state == ST_L2_7)) - st->l2.l2l1(st, PH_PULL_REQ, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); if (test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag)) enquiry_cr(st, RR, RSP, 0); } @@ -1000,7 +1183,7 @@ { struct PStack *st = fi->userdata; - st->l2.tei = (int) arg; + st->l2.tei = (long) arg; if (fi->state == ST_L2_3) { establishlink(fi); @@ -1008,13 +1191,7 @@ } else FsmChangeState(fi, ST_L2_4); if (skb_queue_len(&st->l2.ui_queue)) - l2_send_ui(st); -} - -static void -l2_no_tei(struct FsmInst *fi, int event, void *arg) -{ - FsmChangeState(fi, ST_L2_4); + tx_ui(st); } static void @@ -1028,9 +1205,11 @@ } else if (st->l2.rc == st->l2.N200) { FsmChangeState(fi, ST_L2_4); test_and_clear_bit(FLG_T200_RUN, &st->l2.flag); - discard_i_queue(st); - st->ma.layer(st, MDL_ERROR_IND, (void *) 'G'); - st->l2.l2man(st, DL_RELEASE, NULL); + discard_queue(&st->l2.i_queue); + st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'G'); + if (test_bit(FLG_LAPB, &st->l2.flag)) + st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); + st5_dl_release_l2l3(st); } else { st->l2.rc++; FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9); @@ -1049,8 +1228,9 @@ FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9); } else if (st->l2.rc == st->l2.N200) { FsmChangeState(fi, ST_L2_4); - st->ma.layer(st, MDL_ERROR_IND, (void *) 'H'); - st->l2.l2man(st, DL_RELEASE, NULL); + test_and_clear_bit(FLG_T200_RUN, &st->l2.flag); + st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'H'); + lapb_dl_release_l2l3(st, CONFIRM); } else { st->l2.rc++; FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, @@ -1060,7 +1240,7 @@ } static void -l2_st78_tout_200(struct FsmInst *fi, int event, void *arg) +l2_st7_tout_200(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; @@ -1070,12 +1250,28 @@ return; } test_and_clear_bit(FLG_T200_RUN, &st->l2.flag); - if (fi->state == ST_L2_7) { - st->l2.rc = 0; - FsmChangeState(fi, ST_L2_8); + st->l2.rc = 0; + FsmChangeState(fi, ST_L2_8); + + transmit_enquiry(st); + st->l2.rc++; +} + +static void +l2_st8_tout_200(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + if (test_bit(FLG_LAPD, &st->l2.flag) && + test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) { + FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9); + return; } + test_and_clear_bit(FLG_T200_RUN, &st->l2.flag); if (st->l2.rc == st->l2.N200) { + st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'I'); establishlink(fi); + test_and_clear_bit(FLG_L3_INIT, &st->l2.flag); } else { transmit_enquiry(st); st->l2.rc++; @@ -1104,7 +1300,9 @@ struct sk_buff *skb, *oskb; struct Layer2 *l2 = &st->l2; u_char header[MAX_HEADER_LEN]; - int p1, i; + int i; + int unsigned p1; + long flags; if (!cansend(st)) return; @@ -1113,14 +1311,17 @@ if (!skb) return; - p1 = l2->vs - l2->va; - if (p1 < 0) - p1 += test_bit(FLG_MOD128, &l2->flag) ? 128 : 8; + save_flags(flags); + cli(); + if(test_bit(FLG_MOD128, &l2->flag)) + p1 = (l2->vs - l2->va) % 128; + else + p1 = (l2->vs - l2->va) % 8; p1 = (p1 + l2->sow) % l2->window; if (l2->windowar[p1]) { printk(KERN_WARNING "isdnl2 try overwrite ack queue entry %d\n", p1); - dev_kfree_skb(l2->windowar[p1]); + idev_kfree_skb(l2->windowar[p1], FREE_WRITE); } l2->windowar[p1] = skb_clone(skb, GFP_ATOMIC); @@ -1134,6 +1335,8 @@ header[i++] = (l2->vr << 5) | (l2->vs << 1); l2->vs = (l2->vs + 1) % 8; } + restore_flags(flags); + p1 = skb->data - skb->head; if (p1 >= i) memcpy(skb_push(skb, i), header, i); @@ -1142,89 +1345,74 @@ "isdl2 pull_iqueue skb header(%d/%d) too short\n", i, p1); oskb = skb; skb = alloc_skb(oskb->len + i, GFP_ATOMIC); + SET_SKB_FREE(skb); memcpy(skb_put(skb, i), header, i); memcpy(skb_put(skb, oskb->len), oskb->data, oskb->len); FreeSkb(oskb); } - st->l2.l2l1(st, PH_PULL_IND, skb); + st->l2.l2l1(st, PH_PULL | INDICATION, skb); test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag); if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) { FsmDelTimer(&st->l2.t203, 13); FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 11); } if (skb_queue_len(&l2->i_queue) && cansend(st)) - st->l2.l2l1(st, PH_PULL_REQ, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); } static void -l2_got_st8_super(struct FsmInst *fi, int event, void *arg) +l2_st8_got_super(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; struct sk_buff *skb = arg; - int PollFlag, nr, rsp, rnr = 0; + int PollFlag, rsp, rnr = 0; + unsigned int nr; struct Layer2 *l2 = &st->l2; rsp = *skb->data & 0x2; if (test_bit(FLG_ORIG, &l2->flag)) rsp = !rsp; + skb_pull(skb, l2addrsize(l2)); - if (IsRNR(skb->data, test_bit(FLG_MOD128, &l2->flag))) { + if (IsRNR(skb->data, st)) { test_and_set_bit(FLG_PEER_BUSY, &l2->flag); rnr = 1; } else test_and_clear_bit(FLG_PEER_BUSY, &l2->flag); + if (test_bit(FLG_MOD128, &l2->flag)) { - if (skb->len == 2) { - PollFlag = (skb->data[1] & 0x1) == 0x1; - nr = skb->data[1] >> 1; - } else { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'N'); - FreeSkb(skb); - establishlink(fi); - return; - } + PollFlag = (skb->data[1] & 0x1) == 0x1; + nr = skb->data[1] >> 1; } else { - if (skb->len == 1) { - PollFlag = (skb->data[0] & 0x10); - nr = (skb->data[0] >> 5) & 0x7; - } else { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'N'); - FreeSkb(skb); - establishlink(fi); - return; - } + PollFlag = (skb->data[0] & 0x10); + nr = (skb->data[0] >> 5) & 0x7; } FreeSkb(skb); if (rsp && PollFlag) { if (legalnr(st, nr)) { - setva(st, nr); - if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag)) - FsmDelTimer(&st->l2.t200, 7); - FsmDelTimer(&l2->t203, 8); if (rnr) { - FsmRestartTimer(&l2->t200, l2->T200, - EV_L2_T200, NULL, 14); - test_and_set_bit(FLG_T200_RUN, &st->l2.flag); - } else + restart_t200(st, 15); + } else { + stop_t200(st, 16); FsmAddTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 5); + setva(st, nr); + } invoke_retransmission(st, nr); FsmChangeState(fi, ST_L2_7); if (skb_queue_len(&l2->i_queue) && cansend(st)) - st->l2.l2l1(st, PH_PULL_REQ, NULL); - else if (fi->userint & LC_FLUSH_WAIT) { - fi->userint &= ~LC_FLUSH_WAIT; - st->l2.l2man(st, DL_FLUSH, NULL); - } - } + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); + } else + nrerrorrecovery(fi); } else { if (!rsp && PollFlag) enquiry_response(st); if (legalnr(st, nr)) { setva(st, nr); - } + } else + nrerrorrecovery(fi); } } @@ -1233,30 +1421,12 @@ { struct PStack *st = fi->userdata; struct sk_buff *skb = arg; - char tmp[64]; skb_pull(skb, l2addrsize(&st->l2) + 1); - if (test_bit(FLG_MOD128, &st->l2.flag)) { - if (skb->len < 5) - st->ma.layer(st, MDL_ERROR_IND, (void *) 'N'); - else { - sprintf(tmp, "FRMR information %2x %2x %2x %2x %2x", - skb->data[0], skb->data[1], skb->data[2], - skb->data[3], skb->data[4]); - l2m_debug(&st->l2.l2m, tmp); - } - } else { - if (skb->len < 3) - st->ma.layer(st, MDL_ERROR_IND, (void *) 'N'); - else { - sprintf(tmp, "FRMR information %2x %2x %2x", - skb->data[0], skb->data[1], skb->data[2]); - l2m_debug(&st->l2.l2m, tmp); - } - } + if (!(skb->data[0] & 1) || ((skb->data[0] & 3) == 1) || /* I or S */ - (IsUA(skb->data, 0) && (fi->state == ST_L2_7))) { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'K'); + (IsUA(skb->data) && (fi->state == ST_L2_7))) { + st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'K'); establishlink(fi); test_and_clear_bit(FLG_L3_INIT, &st->l2.flag); } @@ -1264,103 +1434,206 @@ } static void +l2_st24_tei_remove(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + discard_queue(&st->l2.ui_queue); + st->l2.tei = -1; + FsmChangeState(fi, ST_L2_1); +} + +static void +l2_st3_tei_remove(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + discard_queue(&st->l2.ui_queue); + st->l2.tei = -1; + st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); + FsmChangeState(fi, ST_L2_1); +} + +static void +l2_st5_tei_remove(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + discard_queue(&st->l2.i_queue); + discard_queue(&st->l2.ui_queue); + freewin(st); + st->l2.tei = -1; + stop_t200(st, 17); + st5_dl_release_l2l3(st); + FsmChangeState(fi, ST_L2_1); +} + +static void +l2_st6_tei_remove(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + discard_queue(&st->l2.ui_queue); + st->l2.tei = -1; + stop_t200(st, 18); + st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL); + FsmChangeState(fi, ST_L2_1); +} + +static void l2_tei_remove(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; - discard_i_queue(st); - discard_ui_queue(st); + discard_queue(&st->l2.i_queue); + discard_queue(&st->l2.ui_queue); + freewin(st); st->l2.tei = -1; - if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag)) - FsmDelTimer(&st->l2.t200, 18); + stop_t200(st, 17); FsmDelTimer(&st->l2.t203, 19); - if (fi->state != ST_L2_4) - st->l2.l2man(st, DL_RELEASE, NULL); + st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); FsmChangeState(fi, ST_L2_1); } static void -l2_persistant_da(struct FsmInst *fi, int event, void *arg) +l2_discard_i(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; - discard_i_queue(st); - discard_ui_queue(st); - if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag)) - FsmDelTimer(&st->l2.t200, 18); + discard_queue(&st->l2.i_queue); +} + +static void +l2_st5_persistant_da(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + discard_queue(&st->l2.i_queue); + discard_queue(&st->l2.ui_queue); + freewin(st); + stop_t200(st, 19); + st5_dl_release_l2l3(st); + FsmChangeState(fi, ST_L2_4); +} + +static void +l2_st6_persistant_da(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + discard_queue(&st->l2.ui_queue); + stop_t200(st, 20); + st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL); + FsmChangeState(fi, ST_L2_4); +} + +static void +l2_persistant_da(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + discard_queue(&st->l2.i_queue); + discard_queue(&st->l2.ui_queue); + freewin(st); + stop_t200(st, 19); FsmDelTimer(&st->l2.t203, 19); - test_and_clear_bit(FLG_PEND_REL, &st->l2.flag); - clear_exception(&st->l2); - switch (fi->state) { - case ST_L2_3: - st->l2.l2man(st, DL_RELEASE, NULL); - case ST_L2_2: - FsmChangeState(fi, ST_L2_1); - break; - case ST_L2_5: - case ST_L2_6: - case ST_L2_7: - case ST_L2_8: - st->l2.l2man(st, DL_RELEASE, NULL); - FsmChangeState(fi, ST_L2_4); - break; + st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); + FsmChangeState(fi, ST_L2_4); +} + +static void +l2_set_own_busy(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + if(!test_and_set_bit(FLG_OWN_BUSY, &st->l2.flag)) { + enquiry_cr(st, RNR, RSP, 0); + test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag); + } +} + +static void +l2_clear_own_busy(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + if(!test_and_clear_bit(FLG_OWN_BUSY, &st->l2.flag)) { + enquiry_cr(st, RR, RSP, 0); + test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag); } } +static void +l2_frame_error(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + st->ma.layer(st, MDL_ERROR | INDICATION, arg); +} + +static void +l2_frame_error_reest(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + st->ma.layer(st, MDL_ERROR | INDICATION, arg); + establishlink(fi); + test_and_clear_bit(FLG_L3_INIT, &st->l2.flag); +} + static struct FsmNode L2FnList[] HISAX_INITDATA = { - {ST_L2_1, EV_L2_MDL_NOTEIPROC, l2_no_tei}, - {ST_L2_1, EV_L2_DL_ESTABLISH, l2_dl_establish}, - {ST_L2_2, EV_L2_DL_ESTABLISH, l2_dl_establish}, - {ST_L2_4, EV_L2_DL_ESTABLISH, l2_establish}, - {ST_L2_5, EV_L2_DL_ESTABLISH, l2_establish}, - {ST_L2_7, EV_L2_DL_ESTABLISH, l2_establish}, - {ST_L2_8, EV_L2_DL_ESTABLISH, l2_establish}, - {ST_L2_4, EV_L2_DL_RELEASE, l2_dl_release}, - {ST_L2_5, EV_L2_DL_RELEASE, l2_dl_release}, - {ST_L2_7, EV_L2_DL_RELEASE, l2_dl_release}, - {ST_L2_8, EV_L2_DL_RELEASE, l2_dl_release}, - {ST_L2_5, EV_L2_DL_DATA, l2_feed_iqueue}, - {ST_L2_7, EV_L2_DL_DATA, l2_feed_iqueue}, + {ST_L2_1, EV_L2_DL_ESTABLISH_REQ, l2_mdl_assign}, + {ST_L2_2, EV_L2_DL_ESTABLISH_REQ, l2_go_st3}, + {ST_L2_4, EV_L2_DL_ESTABLISH_REQ, l2_establish}, + {ST_L2_5, EV_L2_DL_ESTABLISH_REQ, l2_discard_i_setl3}, + {ST_L2_7, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish}, + {ST_L2_8, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish}, + {ST_L2_4, EV_L2_DL_RELEASE_REQ, l2_release}, + {ST_L2_5, EV_L2_DL_RELEASE_REQ, l2_pend_rel}, + {ST_L2_7, EV_L2_DL_RELEASE_REQ, l2_disconnect}, + {ST_L2_8, EV_L2_DL_RELEASE_REQ, l2_disconnect}, + {ST_L2_5, EV_L2_DL_DATA, l2_feed_i_if_reest}, + {ST_L2_7, EV_L2_DL_DATA, l2_feed_i_pull}, {ST_L2_8, EV_L2_DL_DATA, l2_feed_iqueue}, - {ST_L2_1, EV_L2_DL_UNIT_DATA, l2_put_ui}, - {ST_L2_2, EV_L2_DL_UNIT_DATA, l2_put_ui}, - {ST_L2_3, EV_L2_DL_UNIT_DATA, l2_put_ui}, - {ST_L2_4, EV_L2_DL_UNIT_DATA, l2_put_ui}, - {ST_L2_5, EV_L2_DL_UNIT_DATA, l2_put_ui}, - {ST_L2_6, EV_L2_DL_UNIT_DATA, l2_put_ui}, - {ST_L2_7, EV_L2_DL_UNIT_DATA, l2_put_ui}, - {ST_L2_8, EV_L2_DL_UNIT_DATA, l2_put_ui}, + {ST_L2_1, EV_L2_DL_UNIT_DATA, l2_queue_ui_assign}, + {ST_L2_2, EV_L2_DL_UNIT_DATA, l2_queue_ui}, + {ST_L2_3, EV_L2_DL_UNIT_DATA, l2_queue_ui}, + {ST_L2_4, EV_L2_DL_UNIT_DATA, l2_send_ui}, + {ST_L2_5, EV_L2_DL_UNIT_DATA, l2_send_ui}, + {ST_L2_6, EV_L2_DL_UNIT_DATA, l2_send_ui}, + {ST_L2_7, EV_L2_DL_UNIT_DATA, l2_send_ui}, + {ST_L2_8, EV_L2_DL_UNIT_DATA, l2_send_ui}, {ST_L2_1, EV_L2_MDL_ASSIGN, l2_got_tei}, {ST_L2_2, EV_L2_MDL_ASSIGN, l2_got_tei}, {ST_L2_3, EV_L2_MDL_ASSIGN, l2_got_tei}, - {ST_L2_2, EV_L2_MDL_ERROR, l2_tei_remove}, - {ST_L2_3, EV_L2_MDL_ERROR, l2_tei_remove}, - {ST_L2_4, EV_L2_MDL_REMOVE, l2_tei_remove}, - {ST_L2_5, EV_L2_MDL_REMOVE, l2_tei_remove}, - {ST_L2_6, EV_L2_MDL_REMOVE, l2_tei_remove}, + {ST_L2_2, EV_L2_MDL_ERROR, l2_st24_tei_remove}, + {ST_L2_3, EV_L2_MDL_ERROR, l2_st3_tei_remove}, + {ST_L2_4, EV_L2_MDL_REMOVE, l2_st24_tei_remove}, + {ST_L2_5, EV_L2_MDL_REMOVE, l2_st5_tei_remove}, + {ST_L2_6, EV_L2_MDL_REMOVE, l2_st6_tei_remove}, {ST_L2_7, EV_L2_MDL_REMOVE, l2_tei_remove}, {ST_L2_8, EV_L2_MDL_REMOVE, l2_tei_remove}, - {ST_L2_4, EV_L2_SABMX, l2_got_SABMX}, - {ST_L2_5, EV_L2_SABMX, l2_got_SABMX}, - {ST_L2_6, EV_L2_SABMX, l2_got_SABMX}, - {ST_L2_7, EV_L2_SABMX, l2_got_SABMX}, - {ST_L2_8, EV_L2_SABMX, l2_got_SABMX}, - {ST_L2_4, EV_L2_DISC, l2_got_disconn}, - {ST_L2_5, EV_L2_DISC, l2_got_disconn}, - {ST_L2_6, EV_L2_DISC, l2_got_disconn}, - {ST_L2_7, EV_L2_DISC, l2_got_disconn}, - {ST_L2_8, EV_L2_DISC, l2_got_disconn}, - {ST_L2_4, EV_L2_UA, l2_mdl_error}, - {ST_L2_5, EV_L2_UA, l2_got_ua}, - {ST_L2_6, EV_L2_UA, l2_got_ua}, - {ST_L2_7, EV_L2_UA, l2_mdl_error}, - {ST_L2_8, EV_L2_UA, l2_mdl_error}, - {ST_L2_4, EV_L2_DM, l2_got_dm}, - {ST_L2_5, EV_L2_DM, l2_got_dm}, - {ST_L2_6, EV_L2_DM, l2_got_dm}, - {ST_L2_7, EV_L2_DM, l2_mdl_error}, - {ST_L2_8, EV_L2_DM, l2_mdl_error}, + {ST_L2_4, EV_L2_SABME, l2_start_multi}, + {ST_L2_5, EV_L2_SABME, l2_send_UA}, + {ST_L2_6, EV_L2_SABME, l2_send_DM}, + {ST_L2_7, EV_L2_SABME, l2_restart_multi}, + {ST_L2_8, EV_L2_SABME, l2_restart_multi}, + {ST_L2_4, EV_L2_DISC, l2_send_DM}, + {ST_L2_5, EV_L2_DISC, l2_send_DM}, + {ST_L2_6, EV_L2_DISC, l2_send_UA}, + {ST_L2_7, EV_L2_DISC, l2_stop_multi}, + {ST_L2_8, EV_L2_DISC, l2_stop_multi}, + {ST_L2_4, EV_L2_UA, l2_mdl_error_ua}, + {ST_L2_5, EV_L2_UA, l2_connected}, + {ST_L2_6, EV_L2_UA, l2_released}, + {ST_L2_7, EV_L2_UA, l2_mdl_error_ua}, + {ST_L2_8, EV_L2_UA, l2_mdl_error_ua}, + {ST_L2_4, EV_L2_DM, l2_reestablish}, + {ST_L2_5, EV_L2_DM, l2_st5_dm_release}, + {ST_L2_6, EV_L2_DM, l2_st6_dm_release}, + {ST_L2_7, EV_L2_DM, l2_mdl_error_dm}, + {ST_L2_8, EV_L2_DM, l2_st8_mdl_error_dm}, {ST_L2_1, EV_L2_UI, l2_got_ui}, {ST_L2_2, EV_L2_UI, l2_got_ui}, {ST_L2_3, EV_L2_UI, l2_got_ui}, @@ -1371,21 +1644,30 @@ {ST_L2_8, EV_L2_UI, l2_got_ui}, {ST_L2_7, EV_L2_FRMR, l2_got_FRMR}, {ST_L2_8, EV_L2_FRMR, l2_got_FRMR}, - {ST_L2_7, EV_L2_SUPER, l2_got_st7_super}, - {ST_L2_8, EV_L2_SUPER, l2_got_st8_super}, + {ST_L2_7, EV_L2_SUPER, l2_st7_got_super}, + {ST_L2_8, EV_L2_SUPER, l2_st8_got_super}, {ST_L2_7, EV_L2_I, l2_got_iframe}, {ST_L2_8, EV_L2_I, l2_got_iframe}, {ST_L2_5, EV_L2_T200, l2_st5_tout_200}, {ST_L2_6, EV_L2_T200, l2_st6_tout_200}, - {ST_L2_7, EV_L2_T200, l2_st78_tout_200}, - {ST_L2_8, EV_L2_T200, l2_st78_tout_200}, + {ST_L2_7, EV_L2_T200, l2_st7_tout_200}, + {ST_L2_8, EV_L2_T200, l2_st8_tout_200}, {ST_L2_7, EV_L2_T203, l2_st7_tout_203}, {ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue}, - {ST_L2_2, EV_L1_DEACTIVATE, l2_persistant_da}, - {ST_L2_3, EV_L1_DEACTIVATE, l2_persistant_da}, - {ST_L2_4, EV_L1_DEACTIVATE, l2_persistant_da}, - {ST_L2_5, EV_L1_DEACTIVATE, l2_persistant_da}, - {ST_L2_6, EV_L1_DEACTIVATE, l2_persistant_da}, + {ST_L2_7, EV_L2_SET_OWN_BUSY, l2_set_own_busy}, + {ST_L2_8, EV_L2_SET_OWN_BUSY, l2_set_own_busy}, + {ST_L2_7, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy}, + {ST_L2_8, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy}, + {ST_L2_4, EV_L2_FRAME_ERROR, l2_frame_error}, + {ST_L2_5, EV_L2_FRAME_ERROR, l2_frame_error}, + {ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error}, + {ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest}, + {ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest}, + {ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove}, + {ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove}, + {ST_L2_4, EV_L1_DEACTIVATE, l2_discard_i}, + {ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistant_da}, + {ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistant_da}, {ST_L2_7, EV_L1_DEACTIVATE, l2_persistant_da}, {ST_L2_8, EV_L1_DEACTIVATE, l2_persistant_da}, }; @@ -1398,52 +1680,79 @@ struct sk_buff *skb = arg; u_char *datap; int ret = 1, len; + int c = 0; switch (pr) { - case (PH_DATA_IND): + case (PH_DATA | INDICATION): datap = skb->data; len = l2addrsize(&st->l2); if (skb->len > len) datap += len; else { - st->ma.layer(st, MDL_ERROR_IND, (void *) 'N'); + FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'N'); FreeSkb(skb); return; } - if (!(*datap & 1)) /* I-Frame */ - ret = FsmEvent(&st->l2.l2m, EV_L2_I, skb); - else if ((*datap & 3) == 1) /* S-Frame */ - ret = FsmEvent(&st->l2.l2m, EV_L2_SUPER, skb); - else if (IsUI(datap, test_bit(FLG_MOD128, &st->l2.flag))) - ret = FsmEvent(&st->l2.l2m, EV_L2_UI, skb); - else if (IsSABMX(datap, test_bit(FLG_MOD128, &st->l2.flag))) - ret = FsmEvent(&st->l2.l2m, EV_L2_SABMX, skb); - else if (IsUA(datap, test_bit(FLG_MOD128, &st->l2.flag))) - ret = FsmEvent(&st->l2.l2m, EV_L2_UA, skb); - else if (IsDISC(datap, test_bit(FLG_MOD128, &st->l2.flag))) - ret = FsmEvent(&st->l2.l2m, EV_L2_DISC, skb); - else if (IsDM(datap, test_bit(FLG_MOD128, &st->l2.flag))) - ret = FsmEvent(&st->l2.l2m, EV_L2_DM, skb); - else if (IsFRMR(datap, test_bit(FLG_MOD128, &st->l2.flag))) - ret = FsmEvent(&st->l2.l2m, EV_L2_FRMR, skb); - else { - ret = 0; - st->ma.layer(st, MDL_ERROR_IND, (void *) 'L'); + if (!(*datap & 1)) { /* I-Frame */ + if(!(c = iframe_error(st, skb))) + ret = FsmEvent(&st->l2.l2m, EV_L2_I, skb); + } else if (IsSFrame(datap, st)) { /* S-Frame */ + if(!(c = super_error(st, skb))) + ret = FsmEvent(&st->l2.l2m, EV_L2_SUPER, skb); + } else if (IsUI(datap)) { + if(!(c = UI_error(st, skb))) + ret = FsmEvent(&st->l2.l2m, EV_L2_UI, skb); + } else if (IsSABME(datap, st)) { + if(!(c = unnum_error(st, skb, CMD))) + ret = FsmEvent(&st->l2.l2m, EV_L2_SABME, skb); + } else if (IsUA(datap)) { + if(!(c = unnum_error(st, skb, RSP))) + ret = FsmEvent(&st->l2.l2m, EV_L2_UA, skb); + } else if (IsDISC(datap)) { + if(!(c = unnum_error(st, skb, CMD))) + ret = FsmEvent(&st->l2.l2m, EV_L2_DISC, skb); + } else if (IsDM(datap)) { + if(!(c = unnum_error(st, skb, RSP))) + ret = FsmEvent(&st->l2.l2m, EV_L2_DM, skb); + } else if (IsFRMR(datap)) { + if(!(c = FRMR_error(st,skb))) + ret = FsmEvent(&st->l2.l2m, EV_L2_FRMR, skb); + } else { + FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'L'); FreeSkb(skb); + ret = 0; } - if (ret) { + if(c) { FreeSkb(skb); + FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) c); + ret = 0; } + if (ret) + FreeSkb(skb); break; - case (PH_PULL_CNF): + case (PH_PULL | CONFIRM): FsmEvent(&st->l2.l2m, EV_L2_ACK_PULL, arg); break; - case (PH_PAUSE_IND): + case (PH_PAUSE | INDICATION): test_and_set_bit(FLG_DCHAN_BUSY, &st->l2.flag); break; - case (PH_PAUSE_CNF): + case (PH_PAUSE | CONFIRM): test_and_clear_bit(FLG_DCHAN_BUSY, &st->l2.flag); break; + case (PH_ACTIVATE | CONFIRM): + case (PH_ACTIVATE | INDICATION): + test_and_set_bit(FLG_L1_ACTIV, &st->l2.flag); + if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag)) + FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH_REQ, arg); + break; + case (PH_DEACTIVATE | INDICATION): + case (PH_DEACTIVATE | CONFIRM): + test_and_clear_bit(FLG_L1_ACTIV, &st->l2.flag); + FsmEvent(&st->l2.l2m, EV_L1_DEACTIVATE, arg); + break; + default: + l2m_debug(&st->l2.l2m, "l2 unknown pr %04x", pr); + break; } } @@ -1451,45 +1760,43 @@ isdnl2_l3l2(struct PStack *st, int pr, void *arg) { switch (pr) { - case (DL_DATA): + case (DL_DATA | REQUEST): if (FsmEvent(&st->l2.l2m, EV_L2_DL_DATA, arg)) { - dev_kfree_skb((struct sk_buff *) arg); + idev_kfree_skb((struct sk_buff *) arg, FREE_READ); } break; - case (DL_UNIT_DATA): + case (DL_UNIT_DATA | REQUEST): if (FsmEvent(&st->l2.l2m, EV_L2_DL_UNIT_DATA, arg)) { - dev_kfree_skb((struct sk_buff *) arg); + idev_kfree_skb((struct sk_buff *) arg, FREE_READ); } break; - } -} - -static void -isdnl2_manl2(struct PStack *st, int pr, void *arg) -{ - switch (pr) { - case (DL_ESTABLISH): - FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH, arg); - break; - case (DL_RELEASE): - FsmEvent(&st->l2.l2m, EV_L2_DL_RELEASE, arg); - break; - case (MDL_NOTEIPROC): - FsmEvent(&st->l2.l2m, EV_L2_MDL_NOTEIPROC, NULL); - break; - case (DL_FLUSH): - (&st->l2.l2m)->userint |= LC_FLUSH_WAIT; + case (DL_ESTABLISH | REQUEST): + if (test_bit(FLG_L1_ACTIV, &st->l2.flag)) { + if (test_bit(FLG_LAPD, &st->l2.flag) || + test_bit(FLG_ORIG, &st->l2.flag)) { + FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH_REQ, arg); + } + } else { + if (test_bit(FLG_LAPD, &st->l2.flag) || + test_bit(FLG_ORIG, &st->l2.flag)) { + test_and_set_bit(FLG_ESTAB_PEND, &st->l2.flag); + } + st->l2.l2l1(st, PH_ACTIVATE, NULL); + } break; - case (PH_DEACTIVATE_IND): - FsmEvent(&st->l2.l2m, EV_L1_DEACTIVATE, arg); + case (DL_RELEASE | REQUEST): + if (test_bit(FLG_LAPB, &st->l2.flag)) { + st->l2.l2l1(st, PH_DEACTIVATE, NULL); + } + FsmEvent(&st->l2.l2m, EV_L2_DL_RELEASE_REQ, arg); break; - case (MDL_ASSIGN_REQ): + case (MDL_ASSIGN | REQUEST): FsmEvent(&st->l2.l2m, EV_L2_MDL_ASSIGN, arg); break; - case (MDL_REMOVE_REQ): + case (MDL_REMOVE | REQUEST): FsmEvent(&st->l2.l2m, EV_L2_MDL_REMOVE, arg); break; - case (MDL_ERROR_REQ): + case (MDL_ERROR | RESPONSE): FsmEvent(&st->l2.l2m, EV_L2_MDL_ERROR, arg); break; } @@ -1498,22 +1805,22 @@ void releasestack_isdnl2(struct PStack *st) { - FsmDelTimer(&st->l2.t200, 15); + FsmDelTimer(&st->l2.t200, 21); FsmDelTimer(&st->l2.t203, 16); - discard_i_queue(st); - discard_ui_queue(st); + discard_queue(&st->l2.i_queue); + discard_queue(&st->l2.ui_queue); ReleaseWin(&st->l2); } static void -l2m_debug(struct FsmInst *fi, char *s) +l2m_debug(struct FsmInst *fi, char *fmt, ...) { + va_list args; struct PStack *st = fi->userdata; - char tm[32], str[256]; - jiftime(tm, jiffies); - sprintf(str, "%s %s %s\n", tm, st->l2.debug_id, s); - HiSax_putstatus(st->l1.hardware, str); + va_start(args, fmt); + VHiSax_putstatus(st->l1.hardware, st->l2.debug_id, fmt, args); + va_end(args); } void @@ -1521,7 +1828,6 @@ { st->l1.l1l2 = isdnl2_l1l2; st->l3.l3l2 = isdnl2_l3l2; - st->ma.manl2 = isdnl2_manl2; skb_queue_head_init(&st->l2.i_queue); skb_queue_head_init(&st->l2.ui_queue); @@ -1529,6 +1835,9 @@ st->l2.debug = 0; st->l2.l2m.fsm = &l2fsm; + if (test_bit(FLG_LAPB, &st->l2.flag)) + st->l2.l2m.state = ST_L2_4; + else st->l2.l2m.state = ST_L2_1; st->l2.l2m.debug = 0; st->l2.l2m.userdata = st; @@ -1540,9 +1849,27 @@ FsmInitTimer(&st->l2.l2m, &st->l2.t203); } +static void +transl2_l3l2(struct PStack *st, int pr, void *arg) +{ + switch (pr) { + case (DL_DATA | REQUEST): + case (DL_UNIT_DATA | REQUEST): + st->l2.l2l1(st, PH_DATA | REQUEST, arg); + break; + case (DL_ESTABLISH | REQUEST): + st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL); + break; + case (DL_RELEASE | REQUEST): + st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); + break; + } +} + void setstack_transl2(struct PStack *st) { + st->l3.l3l2 = transl2_l3l2; } void diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isdnl3.c linux.pre11.3/drivers/isdn/hisax/isdnl3.c --- linux.vanilla/drivers/isdn/hisax/isdnl3.c Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/hisax/isdnl3.c Mon Jul 19 23:59:34 1999 @@ -1,12 +1,30 @@ -/* $Id: isdnl3.c,v 2.5 1998/02/12 23:07:52 keil Exp $ +/* $Id: isdnl3.c,v 2.9 1999/07/01 08:11:53 keil Exp $ - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden * + * This file is (c) under GNU PUBLIC LICENSE + * For changes and modifications please read + * ../../../Documentation/isdn/HiSax.cert + * * Thanks to Jan den Ouden * Fritz Elfert * * $Log: isdnl3.c,v $ + * Revision 2.9 1999/07/01 08:11:53 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 2.8 1998/11/15 23:55:04 keil + * changes from 2.0 + * + * Revision 2.7 1998/05/25 14:10:15 keil + * HiSax 3.0 + * X.75 and leased are working again. + * + * Revision 2.6 1998/05/25 12:58:11 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * * Revision 2.5 1998/02/12 23:07:52 keil * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * @@ -47,7 +65,64 @@ #include "isdnl3.h" #include -const char *l3_revision = "$Revision: 2.5 $"; +const char *l3_revision = "$Revision: 2.9 $"; + +static +struct Fsm l3fsm = +{NULL, 0, 0, NULL, NULL}; + +enum { + ST_L3_LC_REL, + ST_L3_LC_ESTAB_WAIT, + ST_L3_LC_REL_DELAY, + ST_L3_LC_REL_WAIT, + ST_L3_LC_ESTAB, +}; + +#define L3_STATE_COUNT (ST_L3_LC_ESTAB+1) + +static char *strL3State[] = +{ + "ST_L3_LC_REL", + "ST_L3_LC_ESTAB_WAIT", + "ST_L3_LC_REL_DELAY", + "ST_L3_LC_REL_WAIT", + "ST_L3_LC_ESTAB", +}; + +enum { + EV_ESTABLISH_REQ, + EV_ESTABLISH_IND, + EV_ESTABLISH_CNF, + EV_RELEASE_REQ, + EV_RELEASE_CNF, + EV_RELEASE_IND, + EV_TIMEOUT, +}; + +#define L3_EVENT_COUNT (EV_TIMEOUT+1) + +static char *strL3Event[] = +{ + "EV_ESTABLISH_REQ", + "EV_ESTABLISH_IND", + "EV_ESTABLISH_CNF", + "EV_RELEASE_REQ", + "EV_RELEASE_CNF", + "EV_RELEASE_IND", + "EV_TIMEOUT", +}; + +static void +l3m_debug(struct FsmInst *fi, char *fmt, ...) +{ + va_list args; + struct PStack *st = fi->userdata; + + va_start(args, fmt); + VHiSax_putstatus(st->l1.hardware, st->l3.debug_id, fmt, args); + va_end(args); +} u_char * findie(u_char * p, int size, u_char ie, int wanted_set) @@ -74,7 +149,14 @@ else { if (codeset == wanted_set) { if (*p == ie) - return (p); + { /* improved length check (Werner Cornelius) */ + if ((pend - p) < 2) + return(NULL); + if (*(p+1) > (pend - (p+2))) + return(NULL); + return (p); + } + if (*p > ie) return (NULL); } @@ -90,15 +172,15 @@ int getcallref(u_char * p) { - int l, m = 1, cr = 0; + int l, cr = 0; + p++; /* prot discr */ + if (*p & 0xfe) /* wrong callref BRI only 1 octet*/ + return(-2); l = 0xf & *p++; /* callref length */ if (!l) /* dummy CallRef */ return(-1); - while (l--) { - cr += m * (*p++); - m *= 8; - } + cr = *p++; return (cr); } @@ -115,25 +197,12 @@ } void -l3_debug(struct PStack *st, char *s) -{ - char str[256], tm[32]; - - jiftime(tm, jiffies); - sprintf(str, "%s l3 %s\n", tm, s); - HiSax_putstatus(st->l1.hardware, str); -} - -void newl3state(struct l3_process *pc, int state) { - char tmp[80]; - - if (pc->debug & L3_DEB_STATE) { - sprintf(tmp, "newstate cr %d %d --> %d", pc->callref, - pc->state, state); - l3_debug(pc->st, tmp); - } + if (pc->debug & L3_DEB_STATE) + l3_debug(pc->st, "newstate cr %d %d --> %d", + pc->callref & 0x7F, + pc->state, state); pc->state = state; } @@ -188,6 +257,7 @@ printk(KERN_WARNING "HiSax: No skb for D-channel\n"); return (NULL); } + SET_SKB_FREE(skb); skb_reserve(skb, MAX_HEADER_LEN); return (skb); } @@ -197,12 +267,19 @@ { struct sk_buff *skb = arg; - HiSax_putstatus(st->l1.hardware, "L3 no D protocol\n"); + HiSax_putstatus(st->l1.hardware, "L3", "no D protocol"); if (skb) { - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); } } +static int +no_l3_proto_spec(struct PStack *st, isdn_ctrl *ic) +{ + printk(KERN_WARNING "HiSax: no specific protocol handler for proto %lu\n",ic->arg & 0xFF); + return(-1); +} + #ifdef CONFIG_HISAX_EURO extern void setstack_dss1(struct PStack *st); #endif @@ -246,7 +323,7 @@ np->next = p; } p->next = NULL; - p->debug = L3_DEB_WARN; + p->debug = st->l3.debug; p->callref = cr; p->state = 0; p->chan = NULL; @@ -269,24 +346,47 @@ StopAllL3Timer(p); if (pp) pp->next = np->next; - else - p->st->l3.proc = np->next; + else if (!(p->st->l3.proc = np->next) && + !test_bit(FLG_PTP, &p->st->l2.flag)) + FsmEvent(&p->st->l3.l3m, EV_RELEASE_REQ, NULL); kfree(p); return; } pp = np; np = np->next; } - printk(KERN_ERR "HiSax internal L3 error CR not in list\n"); + printk(KERN_ERR "HiSax internal L3 error CR(%d) not in list\n", p->callref); + l3_debug(p->st, "HiSax internal L3 error CR(%d) not in list", p->callref); }; +static void +l3ml3p(struct PStack *st, int pr) +{ + struct l3_process *p = st->l3.proc; + + while (p) { + st->l3.l3ml3(st, pr, p); + p = p->next; + } +} + void -setstack_isdnl3(struct PStack *st, struct Channel *chanp) +setstack_l3dc(struct PStack *st, struct Channel *chanp) { char tmp[64]; st->l3.proc = NULL; st->l3.global = NULL; + skb_queue_head_init(&st->l3.squeue); + st->l3.l3m.fsm = &l3fsm; + st->l3.l3m.state = ST_L3_LC_REL; + st->l3.l3m.debug = 1; + st->l3.l3m.userdata = st; + st->l3.l3m.userint = 0; + st->l3.l3m.printdebug = l3m_debug; + FsmInitTimer(&st->l3.l3m, &st->l3.l3m_timer); + strcpy(st->l3.debug_id, "L3DC "); + st->lli.l4l3_proto = no_l3_proto_spec; #ifdef CONFIG_HISAX_EURO if (st->protocol == ISDN_PTYPE_EURO) { @@ -306,10 +406,12 @@ if (st->protocol == ISDN_PTYPE_LEASED) { st->lli.l4l3 = no_l3_proto; st->l2.l2l3 = no_l3_proto; + st->l3.l3ml3 = no_l3_proto; printk(KERN_INFO "HiSax: Leased line mode\n"); } else { st->lli.l4l3 = no_l3_proto; st->l2.l2l3 = no_l3_proto; + st->l3.l3ml3 = no_l3_proto; sprintf(tmp, "protocol %s not supported", (st->protocol == ISDN_PTYPE_1TR6) ? "1tr6" : (st->protocol == ISDN_PTYPE_EURO) ? "euro" : @@ -321,6 +423,11 @@ } void +isdnl3_trans(struct PStack *st, int pr, void *arg) { + st->l3.l3l2(st, pr, arg); +} + +void releasestack_isdnl3(struct PStack *st) { while (st->l3.proc) @@ -330,4 +437,174 @@ kfree(st->l3.global); st->l3.global = NULL; } + FsmDelTimer(&st->l3.l3m_timer, 54); + discard_queue(&st->l3.squeue); +} + +void +setstack_l3bc(struct PStack *st, struct Channel *chanp) +{ + + st->l3.proc = NULL; + st->l3.global = NULL; + skb_queue_head_init(&st->l3.squeue); + st->l3.l3m.fsm = &l3fsm; + st->l3.l3m.state = ST_L3_LC_REL; + st->l3.l3m.debug = 1; + st->l3.l3m.userdata = st; + st->l3.l3m.userint = 0; + st->l3.l3m.printdebug = l3m_debug; + strcpy(st->l3.debug_id, "L3BC "); + st->lli.l4l3 = isdnl3_trans; +} + +#define DREL_TIMER_VALUE 40000 + +static void +lc_activate(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + FsmChangeState(fi, ST_L3_LC_ESTAB_WAIT); + st->l3.l3l2(st, DL_ESTABLISH | REQUEST, NULL); +} + +static void +lc_connect(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + struct sk_buff *skb = arg; + + FsmChangeState(fi, ST_L3_LC_ESTAB); + while ((skb = skb_dequeue(&st->l3.squeue))) { + st->l3.l3l2(st, DL_DATA | REQUEST, skb); + } + l3ml3p(st, DL_ESTABLISH | INDICATION); +} + +static void +lc_connected(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + struct sk_buff *skb = arg; + + FsmDelTimer(&st->l3.l3m_timer, 51); + FsmChangeState(fi, ST_L3_LC_ESTAB); + while ((skb = skb_dequeue(&st->l3.squeue))) { + st->l3.l3l2(st, DL_DATA | REQUEST, skb); + } + l3ml3p(st, DL_ESTABLISH | CONFIRM); +} + +static void +lc_start_delay(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + FsmChangeState(fi, ST_L3_LC_REL_DELAY); + FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50); +} + +static void +lc_release_req(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + FsmChangeState(fi, ST_L3_LC_REL_WAIT); + st->l3.l3l2(st, DL_RELEASE | REQUEST, NULL); +} + +static void +lc_release_ind(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + FsmDelTimer(&st->l3.l3m_timer, 52); + FsmChangeState(fi, ST_L3_LC_REL); + discard_queue(&st->l3.squeue); + l3ml3p(st, DL_RELEASE | INDICATION); +} + +static void +lc_release_cnf(struct FsmInst *fi, int event, void *arg) +{ + struct PStack *st = fi->userdata; + + FsmChangeState(fi, ST_L3_LC_REL); + discard_queue(&st->l3.squeue); + l3ml3p(st, DL_RELEASE | CONFIRM); +} + + +/* *INDENT-OFF* */ +static struct FsmNode L3FnList[] HISAX_INITDATA = +{ + {ST_L3_LC_REL, EV_ESTABLISH_REQ, lc_activate}, + {ST_L3_LC_REL, EV_ESTABLISH_IND, lc_connect}, + {ST_L3_LC_REL, EV_ESTABLISH_CNF, lc_connect}, + {ST_L3_LC_ESTAB_WAIT, EV_ESTABLISH_CNF, lc_connected}, + {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_REQ, lc_start_delay}, + {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_IND, lc_release_ind}, + {ST_L3_LC_ESTAB, EV_RELEASE_IND, lc_release_ind}, + {ST_L3_LC_ESTAB, EV_RELEASE_REQ, lc_start_delay}, + {ST_L3_LC_REL_DELAY, EV_RELEASE_IND, lc_release_ind}, + {ST_L3_LC_REL_DELAY, EV_ESTABLISH_REQ, lc_connected}, + {ST_L3_LC_REL_DELAY, EV_TIMEOUT, lc_release_req}, + {ST_L3_LC_REL_WAIT, EV_RELEASE_CNF, lc_release_cnf}, + {ST_L3_LC_REL_WAIT, EV_ESTABLISH_REQ, lc_activate}, +}; +/* *INDENT-ON* */ + +#define L3_FN_COUNT (sizeof(L3FnList)/sizeof(struct FsmNode)) + +void +l3_msg(struct PStack *st, int pr, void *arg) +{ + + switch (pr) { + case (DL_DATA | REQUEST): + if (st->l3.l3m.state == ST_L3_LC_ESTAB) { + st->l3.l3l2(st, pr, arg); + } else { + struct sk_buff *skb = arg; + + skb_queue_head(&st->l3.squeue, skb); + FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL); + } + break; + case (DL_ESTABLISH | REQUEST): + FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL); + break; + case (DL_ESTABLISH | CONFIRM): + FsmEvent(&st->l3.l3m, EV_ESTABLISH_CNF, NULL); + break; + case (DL_ESTABLISH | INDICATION): + FsmEvent(&st->l3.l3m, EV_ESTABLISH_IND, NULL); + break; + case (DL_RELEASE | INDICATION): + FsmEvent(&st->l3.l3m, EV_RELEASE_IND, NULL); + break; + case (DL_RELEASE | CONFIRM): + FsmEvent(&st->l3.l3m, EV_RELEASE_CNF, NULL); + break; + case (DL_RELEASE | REQUEST): + FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL); + break; + } +} + +HISAX_INITFUNC(void +Isdnl3New(void)) +{ + l3fsm.state_count = L3_STATE_COUNT; + l3fsm.event_count = L3_EVENT_COUNT; + l3fsm.strEvent = strL3Event; + l3fsm.strState = strL3State; + FsmNew(&l3fsm, L3FnList, L3_FN_COUNT); +} + +void +Isdnl3Free(void) +{ + FsmFree(&l3fsm); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isdnl3.h linux.pre11.3/drivers/isdn/hisax/isdnl3.h --- linux.vanilla/drivers/isdn/hisax/isdnl3.h Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/hisax/isdnl3.h Mon Jul 19 23:59:34 1999 @@ -1,6 +1,20 @@ -/* $Id: isdnl3.h,v 2.0 1997/07/27 21:15:42 keil Exp $ +/* $Id: isdnl3.h,v 2.4 1999/07/01 08:11:54 keil Exp $ * $Log: isdnl3.h,v $ + * Revision 2.4 1999/07/01 08:11:54 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 2.3 1998/11/15 23:55:06 keil + * changes from 2.0 + * + * Revision 2.2 1998/05/25 14:10:17 keil + * HiSax 3.0 + * X.75 and leased are working again. + * + * Revision 2.1 1998/05/25 12:58:13 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * * Revision 2.0 1997/07/27 21:15:42 keil * New Callref based layer3 * @@ -22,20 +36,23 @@ #define SBIT(state) (1<l1.hardware, "l3 ", fmt, ## args) + extern void newl3state(struct l3_process *pc, int state); extern void L3InitTimer(struct l3_process *pc, struct L3Timer *t); extern void L3DelTimer(struct L3Timer *t); @@ -45,3 +62,4 @@ extern struct l3_process *new_l3_process(struct PStack *st, int cr); extern void release_l3_process(struct l3_process *p); extern struct l3_process *getl3proc(struct PStack *st, int cr); +extern void l3_msg(struct PStack *st, int pr, void *arg); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isurf.c linux.pre11.3/drivers/isdn/hisax/isurf.c --- linux.vanilla/drivers/isdn/hisax/isurf.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/isurf.c Mon Jul 19 23:59:34 1999 @@ -0,0 +1,252 @@ +/* $Id: isurf.c,v 1.3 1999/07/12 21:05:18 keil Exp $ + + * isurf.c low level stuff for Siemens I-Surf/I-Talk cards + * + * Author Karsten Keil (keil@isdn4linux.de) + * + * $Log: isurf.c,v $ + * Revision 1.3 1999/07/12 21:05:18 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 1.2 1999/07/01 08:07:56 keil + * Initial version + * + * + * + */ + +#define __NO_VERSION__ +#include +#include "hisax.h" +#include "isac.h" +#include "isar.h" +#include "isdnl1.h" + +extern const char *CardType[]; + +static const char *ISurf_revision = "$Revision: 1.3 $"; + +#define byteout(addr,val) outb(val,addr) +#define bytein(addr) inb(addr) + +#define ISURF_ISAR_RESET 1 +#define ISURF_ISAC_RESET 2 +#define ISURF_ISAR_EA 4 +#define ISURF_ARCOFI_RESET 8 +#define ISURF_RESET (ISURF_ISAR_RESET | ISURF_ISAC_RESET | ISURF_ARCOFI_RESET) + +#define ISURF_ISAR_OFFSET 0 +#define ISURF_ISAC_OFFSET 0x100 + +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) +{ + return (readb(cs->hw.isurf.isac + offset)); +} + +static void +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) +{ + writeb(value, cs->hw.isurf.isac + offset); mb(); +} + +static void +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + register int i; + for (i = 0; i < size; i++) + data[i] = readb(cs->hw.isurf.isac); +} + +static void +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + register int i; + for (i = 0; i < size; i++){ + writeb(data[i], cs->hw.isurf.isac);mb(); + } +} + +/* ISAR access routines + * mode = 0 access with IRQ on + * mode = 1 access with IRQ off + * mode = 2 access with IRQ off and using last offset + */ + +static u_char +ReadISAR(struct IsdnCardState *cs, int mode, u_char offset) +{ + return(readb(cs->hw.isurf.isar + offset)); +} + +static void +WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value) +{ + writeb(value, cs->hw.isurf.isar + offset);mb(); +} + +static void +isurf_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val; + int cnt = 5; + + if (!cs) { + printk(KERN_WARNING "ISurf: Spurious interrupt!\n"); + return; + } + + val = readb(cs->hw.isurf.isar + ISAR_IRQBIT); + Start_ISAR: + if (val & ISAR_IRQSTA) + isar_int_main(cs); + val = readb(cs->hw.isurf.isac + ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + val = readb(cs->hw.isurf.isar + ISAR_IRQBIT); + if ((val & ISAR_IRQSTA) && --cnt) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "ISAR IntStat after IntRoutine"); + goto Start_ISAR; + } + val = readb(cs->hw.isurf.isac + ISAC_ISTA); + if (val && --cnt) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + if (!cnt) + printk(KERN_WARNING "ISurf IRQ LOOP\n"); + + writeb(0, cs->hw.isurf.isar + ISAR_IRQBIT); mb(); + writeb(0xFF, cs->hw.isurf.isac + ISAC_MASK);mb(); + writeb(0, cs->hw.isurf.isac + ISAC_MASK);mb(); + writeb(ISAR_IRQMSK, cs->hw.isurf.isar + ISAR_IRQBIT); mb(); +} + +void +release_io_isurf(struct IsdnCardState *cs) +{ + release_region(cs->hw.isurf.reset, 1); +} + +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(); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10*HZ)/1000); + byteout(cs->hw.isurf.reset, ISURF_ISAR_EA); /* Reset Off */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10*HZ)/1000); + restore_flags(flags); +} + +static int +ISurf_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + switch (mt) { + case CARD_RESET: + reset_isurf(cs, ISURF_RESET); + return(0); + case CARD_RELEASE: + release_io_isurf(cs); + return(0); + case CARD_INIT: + clear_pending_isac_ints(cs); + writeb(0, cs->hw.isurf.isar+ISAR_IRQBIT);mb(); + initisac(cs); + initisar(cs); + /* Reenable ISAC IRQ */ + cs->writeisac(cs, ISAC_MASK, 0); + /* RESET Receiver and Transmitter */ + cs->writeisac(cs, ISAC_CMDR, 0x41); + return(0); + case CARD_TEST: + return(0); + case CARD_LOAD_FIRM: + if (isar_load_firmware(cs, arg)) + return(1); + ll_run(cs); + reset_isurf(cs, ISURF_ISAR_EA | ISURF_ISAC_RESET | + ISURF_ARCOFI_RESET); + initisac(cs); + cs->writeisac(cs, ISAC_MASK, 0); + cs->writeisac(cs, ISAC_CMDR, 0x41); + return(0); + } + return(0); +} + +__initfunc(int +setup_isurf(struct IsdnCard *card)) +{ + int ver; + struct IsdnCardState *cs = card->cs; + char tmp[64]; + + strcpy(tmp, ISurf_revision); + printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp)); + + if (cs->typ != ISDN_CTYPE_ISURF) + return(0); + if (card->para[1] && card->para[2]) { + cs->hw.isurf.reset = card->para[1]; + cs->hw.isurf.isar = card->para[2] + ISURF_ISAR_OFFSET; + cs->hw.isurf.isac = card->para[2] + ISURF_ISAC_OFFSET; + cs->irq = card->para[0]; + } else { + printk(KERN_WARNING "HiSax: %s port/mem not set\n", + CardType[card->typ]); + return (0); + } + if (check_region(cs->hw.isurf.reset, 1)) { + printk(KERN_WARNING + "HiSax: %s config port %x already in use\n", + CardType[card->typ], + cs->hw.isurf.reset); + return (0); + } else { + request_region(cs->hw.isurf.reset, 1, "isurf isdn"); + } + + printk(KERN_INFO + "ISurf: defined at 0x%x 0x%x IRQ %d\n", + cs->hw.isurf.reset, + cs->hw.isurf.isar, + cs->irq); + + cs->cardmsg = &ISurf_card_msg; + cs->irq_func = &isurf_interrupt; + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r; + cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r; + reset_isurf(cs, ISURF_RESET); + test_and_set_bit(HW_ISAR, &cs->HW_Flags); + ISACVersion(cs, "ISurf:"); + cs->BC_Read_Reg = &ReadISAR; + cs->BC_Write_Reg = &WriteISAR; + cs->BC_Send_Data = &isar_fill_fifo; + ver = ISARVersion(cs, "ISurf:"); + if (ver < 0) { + printk(KERN_WARNING + "ISurf: wrong ISAR version (ret = %d)\n", ver); + release_io_isurf(cs); + return (0); + } + return (1); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/ix1_micro.c linux.pre11.3/drivers/isdn/hisax/ix1_micro.c --- linux.vanilla/drivers/isdn/hisax/ix1_micro.c Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/hisax/ix1_micro.c Mon Jul 19 23:59:34 1999 @@ -1,4 +1,4 @@ -/* $Id: ix1_micro.c,v 2.6 1998/02/11 17:28:09 keil Exp $ +/* $Id: ix1_micro.c,v 2.8 1999/07/12 21:05:19 keil Exp $ * ix1_micro.c low level stuff for ITK ix1-micro Rev.2 isdn cards * derived from the original file teles3.c from Karsten Keil @@ -11,6 +11,13 @@ * Beat Doebeli * * $Log: ix1_micro.c,v $ + * Revision 2.8 1999/07/12 21:05:19 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 2.7 1998/04/15 16:44:31 keil + * new init code + * * Revision 2.6 1998/02/11 17:28:09 keil * Niccy PnP/PCI support * @@ -81,7 +88,7 @@ #include "isdnl1.h" extern const char *CardType[]; -const char *ix1_revision = "$Revision: 2.6 $"; +const char *ix1_revision = "$Revision: 2.8 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -196,7 +203,7 @@ ix1micro_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u_char val, stat = 0; + u_char val; if (!cs) { printk(KERN_WARNING "IX1: Spurious interrupt!\n"); @@ -204,16 +211,12 @@ } val = readreg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_ISTA + 0x40); Start_HSCX: - if (val) { + if (val) hscx_int_main(cs, val); - stat |= 1; - } val = readreg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_ISTA); Start_ISAC: - if (val) { + if (val) isac_interrupt(cs, val); - stat |= 2; - } val = readreg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_ISTA + 0x40); if (val) { if (cs->debug & L1_DEB_HSCX) @@ -226,16 +229,12 @@ debugl1(cs, "ISAC IntStat after IntRoutine"); goto Start_ISAC; } - if (stat & 1) { - writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0xFF); - writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0xFF); - writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0); - writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0); - } - if (stat & 2) { - writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0xFF); - writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0); - } + writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0); + writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0); + writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0); } void @@ -273,14 +272,8 @@ case CARD_RELEASE: release_io_ix1micro(cs); return(0); - case CARD_SETIRQ: - return(request_irq(cs->irq, &ix1micro_interrupt, - I4L_IRQ_FLAG, "HiSax", cs)); case CARD_INIT: - clear_pending_isac_ints(cs); - clear_pending_hscx_ints(cs); - initisac(cs); - inithscx(cs); + inithscxisac(cs, 3); return(0); case CARD_TEST: return(0); @@ -331,6 +324,7 @@ cs->BC_Write_Reg = &WriteHSCX; cs->BC_Send_Data = &hscx_fill_fifo; cs->cardmsg = &ix1_card_msg; + cs->irq_func = &ix1micro_interrupt; ISACVersion(cs, "ix1-Micro:"); if (HscxVersion(cs, "ix1-Micro:")) { printk(KERN_WARNING diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/jade.c linux.pre11.3/drivers/isdn/hisax/jade.c --- linux.vanilla/drivers/isdn/hisax/jade.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/jade.c Mon Jul 19 23:59:34 1999 @@ -0,0 +1,326 @@ +/* $Id: jade.c,v 1.2 1999/07/01 08:07:57 keil Exp $ + * + * jade.c JADE stuff (derived from original hscx.c) + * + * Author Roland Klabunde (R.Klabunde@Berkom.de) + * + * $Log: jade.c,v $ + * Revision 1.2 1999/07/01 08:07:57 keil + * Initial version + * + * + */ + + +#define __NO_VERSION__ +#include "hisax.h" +#include "hscx.h" +#include "jade.h" +#include "isdnl1.h" +#include + + +HISAX_INITFUNC(int +JadeVersion(struct IsdnCardState *cs, char *s)) +{ + int ver,i; + int to = 50; + cs->BC_Write_Reg(cs, -1, 0x50, 0x19); + i=0; + while (to) { + udelay(1); + ver = cs->BC_Read_Reg(cs, -1, 0x60); + to--; + if (ver) + break; + if (!to) { + printk(KERN_INFO "%s JADE version not obtainable\n", s); + return (0); + } + } + /* Wait for the JADE */ + udelay(10); + /* Read version */ + ver = cs->BC_Read_Reg(cs, -1, 0x60); + printk(KERN_INFO "%s JADE version: %d\n", s, ver); + return (1); +} + +/* Write to indirect accessible jade register set */ +static void +jade_write_indirect(struct IsdnCardState *cs, u_char reg, u_char value) +{ + int to = 50; + long flags; + u_char ret; + save_flags(flags); + cli(); + /* Write the data */ + cs->BC_Write_Reg(cs, -1, COMM_JADE+1, value); + /* Say JADE we wanna write indirect reg 'reg' */ + cs->BC_Write_Reg(cs, -1, COMM_JADE, reg); + to = 50; + /* Wait for RDY goes high */ + while (to) { + udelay(1); + ret = cs->BC_Read_Reg(cs, -1, COMM_JADE); + to--; + if (ret & 1) + /* Got acknowledge */ + break; + if (!to) { + restore_flags(flags); + printk(KERN_INFO "Can not see ready bit from JADE DSP (reg=0x%X, value=0x%X)\n", reg, value); + return; + } + } + restore_flags(flags); +} + + + +void +modejade(struct BCState *bcs, int mode, int bc) +{ + struct IsdnCardState *cs = bcs->cs; + int jade = bcs->hw.hscx.hscx; + + if (cs->debug & L1_DEB_HSCX) { + char tmp[40]; + sprintf(tmp, "jade %c mode %d ichan %d", + 'A' + jade, mode, bc); + debugl1(cs, tmp); + } + bcs->mode = mode; + bcs->channel = bc; + + cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (mode == L1_MODE_TRANS ? jadeMODE_TMO:0x00)); + cs->BC_Write_Reg(cs, jade, jade_HDLC_CCR0, (jadeCCR0_PU|jadeCCR0_ITF)); + cs->BC_Write_Reg(cs, jade, jade_HDLC_CCR1, 0x00); + + jade_write_indirect(cs, jade_HDLC1SERRXPATH, 0x08); + jade_write_indirect(cs, jade_HDLC2SERRXPATH, 0x08); + jade_write_indirect(cs, jade_HDLC1SERTXPATH, 0x00); + jade_write_indirect(cs, jade_HDLC2SERTXPATH, 0x00); + + cs->BC_Write_Reg(cs, jade, jade_HDLC_XCCR, 0x07); + cs->BC_Write_Reg(cs, jade, jade_HDLC_RCCR, 0x07); + + if (bc == 0) { + cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAX, 0x00); + cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAR, 0x00); + } else { + cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAX, 0x04); + cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAR, 0x04); + } + switch (mode) { + case (L1_MODE_NULL): + cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, jadeMODE_TMO); + break; + case (L1_MODE_TRANS): + cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (jadeMODE_TMO|jadeMODE_RAC|jadeMODE_XAC)); + break; + case (L1_MODE_HDLC): + cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (jadeMODE_RAC|jadeMODE_XAC)); + break; + } + if (mode) { + cs->BC_Write_Reg(cs, jade, jade_HDLC_RCMD, (jadeRCMD_RRES|jadeRCMD_RMC)); + cs->BC_Write_Reg(cs, jade, jade_HDLC_XCMD, jadeXCMD_XRES); + /* Unmask ints */ + cs->BC_Write_Reg(cs, jade, jade_HDLC_IMR, 0xF8); + } + else + /* Mask ints */ + cs->BC_Write_Reg(cs, jade, jade_HDLC_IMR, 0x00); +} + +void +jade_sched_event(struct BCState *bcs, int event) +{ + bcs->event |= 1 << event; + queue_task(&bcs->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +static void +jade_l2l1(struct PStack *st, int pr, void *arg) +{ + struct sk_buff *skb = arg; + long flags; + + switch (pr) { + case (PH_DATA | REQUEST): + save_flags(flags); + cli(); + if (st->l1.bcs->tx_skb) { + skb_queue_tail(&st->l1.bcs->squeue, skb); + restore_flags(flags); + } else { + st->l1.bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + st->l1.bcs->hw.hscx.count = 0; + restore_flags(flags); + st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); + } + break; + case (PH_PULL | INDICATION): + if (st->l1.bcs->tx_skb) { + printk(KERN_WARNING "jade_l2l1: this shouldn't happen\n"); + break; + } + test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + st->l1.bcs->tx_skb = skb; + st->l1.bcs->hw.hscx.count = 0; + st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); + break; + case (PH_PULL | REQUEST): + if (!st->l1.bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + break; + case (PH_ACTIVATE | REQUEST): + test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + modejade(st->l1.bcs, st->l1.mode, st->l1.bc); + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | REQUEST): + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | CONFIRM): + test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + modejade(st->l1.bcs, 0, st->l1.bc); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); + break; + } +} + +void +close_jadestate(struct BCState *bcs) +{ + modejade(bcs, 0, bcs->channel); + if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { + if (bcs->hw.hscx.rcvbuf) { + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + } + if (bcs->blog) { + kfree(bcs->blog); + bcs->blog = NULL; + } + discard_queue(&bcs->rqueue); + discard_queue(&bcs->squeue); + if (bcs->tx_skb) { + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + } + } +} + +static int +open_jadestate(struct IsdnCardState *cs, struct BCState *bcs) +{ + if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { + if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for hscx.rcvbuf\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + return (1); + } + if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for bcs->blog\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + return (2); + } + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + } + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->event = 0; + bcs->hw.hscx.rcvidx = 0; + bcs->tx_cnt = 0; + return (0); +} + + +int +setstack_jade(struct PStack *st, struct BCState *bcs) +{ + bcs->channel = st->l1.bc; + if (open_jadestate(st->l1.hardware, bcs)) + return (-1); + st->l1.bcs = bcs; + st->l2.l2l1 = jade_l2l1; + setstack_manager(st); + bcs->st = st; + setstack_l1_B(st); + return (0); +} + +HISAX_INITFUNC(void +clear_pending_jade_ints(struct IsdnCardState *cs)) +{ + int val; + char tmp[64]; + + cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0x00); + cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0x00); + + val = cs->BC_Read_Reg(cs, 1, jade_HDLC_ISR); + sprintf(tmp, "jade B ISTA %x", val); + debugl1(cs, tmp); + val = cs->BC_Read_Reg(cs, 0, jade_HDLC_ISR); + sprintf(tmp, "jade A ISTA %x", val); + debugl1(cs, tmp); + val = cs->BC_Read_Reg(cs, 1, jade_HDLC_STAR); + sprintf(tmp, "jade B STAR %x", val); + debugl1(cs, tmp); + val = cs->BC_Read_Reg(cs, 0, jade_HDLC_STAR); + sprintf(tmp, "jade A STAR %x", val); + debugl1(cs, tmp); + /* Unmask ints */ + cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0xF8); + cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0xF8); +} + +HISAX_INITFUNC(void +initjade(struct IsdnCardState *cs)) +{ + cs->bcs[0].BC_SetStack = setstack_jade; + cs->bcs[1].BC_SetStack = setstack_jade; + cs->bcs[0].BC_Close = close_jadestate; + cs->bcs[1].BC_Close = close_jadestate; + cs->bcs[0].hw.hscx.hscx = 0; + cs->bcs[1].hw.hscx.hscx = 1; + + /* Stop DSP audio tx/rx */ + jade_write_indirect(cs, 0x11, 0x0f); + jade_write_indirect(cs, 0x17, 0x2f); + + /* Transparent Mode, RxTx inactive, No Test, No RFS/TFS */ + cs->BC_Write_Reg(cs, 0, jade_HDLC_MODE, jadeMODE_TMO); + cs->BC_Write_Reg(cs, 1, jade_HDLC_MODE, jadeMODE_TMO); + /* Power down, 1-Idle, RxTx least significant bit first */ + cs->BC_Write_Reg(cs, 0, jade_HDLC_CCR0, 0x00); + cs->BC_Write_Reg(cs, 1, jade_HDLC_CCR0, 0x00); + /* Mask all interrupts */ + cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0x00); + cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0x00); + /* Setup host access to hdlc controller */ + jade_write_indirect(cs, jade_HDLCCNTRACCESS, (jadeINDIRECT_HAH1|jadeINDIRECT_HAH2)); + /* Unmask HDLC int (don´t forget DSP int later on)*/ + cs->BC_Write_Reg(cs, -1,jade_INT, (jadeINT_HDLC1|jadeINT_HDLC2)); + + /* once again TRANSPARENT */ + modejade(cs->bcs, 0, 0); + modejade(cs->bcs + 1, 0, 0); +} + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/jade.h linux.pre11.3/drivers/isdn/hisax/jade.h --- linux.vanilla/drivers/isdn/hisax/jade.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/jade.h Mon Jul 19 23:59:34 1999 @@ -0,0 +1,137 @@ +/* $Id: jade.h,v 1.2 1999/07/01 08:07:58 keil Exp $ + * jade.h JADE specific defines + * + * Author Roland Klabunde (R.Klabunde@Berkom.de) + * + * + * $Log: jade.h,v $ + * Revision 1.2 1999/07/01 08:07:58 keil + * Initial version + * + * + */ + +/* All Registers original Siemens Spec */ +#ifndef __JADE_H__ +#define __JADE_H__ + +/* Special registers for access to indirect accessible JADE regs */ +#define DIRECT_IO_JADE 0x0000 /* Jade direct io access area */ +#define COMM_JADE 0x0040 /* Jade communication area */ + +/********************************************************************/ +/* JADE-HDLC registers */ +/********************************************************************/ +#define jade_HDLC_RFIFO 0x00 /* R */ +#define jade_HDLC_XFIFO 0x00 /* W */ + +#define jade_HDLC_STAR 0x20 /* R */ + #define jadeSTAR_XDOV 0x80 + #define jadeSTAR_XFW 0x40 /* Does not work*/ + #define jadeSTAR_XCEC 0x20 + #define jadeSTAR_RCEC 0x10 + #define jadeSTAR_BSY 0x08 + #define jadeSTAR_RNA 0x04 + #define jadeSTAR_STR 0x02 + #define jadeSTAR_STX 0x01 + +#define jade_HDLC_XCMD 0x20 /* W */ + #define jadeXCMD_XF 0x80 + #define jadeXCMD_XME 0x40 + #define jadeXCMD_XRES 0x20 + #define jadeXCMD_STX 0x01 + +#define jade_HDLC_RSTA 0x21 /* R */ + #define jadeRSTA_VFR 0x80 + #define jadeRSTA_RDO 0x40 + #define jadeRSTA_CRC 0x20 + #define jadeRSTA_RAB 0x10 + #define jadeRSTA_MASK 0xF0 + +#define jade_HDLC_MODE 0x22 /* RW*/ + #define jadeMODE_TMO 0x80 + #define jadeMODE_RAC 0x40 + #define jadeMODE_XAC 0x20 + #define jadeMODE_TLP 0x10 + #define jadeMODE_ERFS 0x02 + #define jadeMODE_ETFS 0x01 + +#define jade_HDLC_RBCH 0x24 /* R */ + +#define jade_HDLC_RBCL 0x25 /* R */ +#define jade_HDLC_RCMD 0x25 /* W */ + #define jadeRCMD_RMC 0x80 + #define jadeRCMD_RRES 0x40 + #define jadeRCMD_RMD 0x20 + #define jadeRCMD_STR 0x02 + +#define jade_HDLC_CCR0 0x26 /* RW*/ + #define jadeCCR0_PU 0x80 + #define jadeCCR0_ITF 0x40 + #define jadeCCR0_C32 0x20 + #define jadeCCR0_CRL 0x10 + #define jadeCCR0_RCRC 0x08 + #define jadeCCR0_XCRC 0x04 + #define jadeCCR0_RMSB 0x02 + #define jadeCCR0_XMSB 0x01 + +#define jade_HDLC_CCR1 0x27 /* RW*/ + #define jadeCCR1_RCS0 0x80 + #define jadeCCR1_RCONT 0x40 + #define jadeCCR1_RFDIS 0x20 + #define jadeCCR1_XCS0 0x10 + #define jadeCCR1_XCONT 0x08 + #define jadeCCR1_XFDIS 0x04 + +#define jade_HDLC_TSAR 0x28 /* RW*/ +#define jade_HDLC_TSAX 0x29 /* RW*/ +#define jade_HDLC_RCCR 0x2A /* RW*/ +#define jade_HDLC_XCCR 0x2B /* RW*/ + +#define jade_HDLC_ISR 0x2C /* R */ +#define jade_HDLC_IMR 0x2C /* W */ + #define jadeISR_RME 0x80 + #define jadeISR_RPF 0x40 + #define jadeISR_RFO 0x20 + #define jadeISR_XPR 0x10 + #define jadeISR_XDU 0x08 + #define jadeISR_ALLS 0x04 + +#define jade_INT 0x75 + #define jadeINT_HDLC1 0x02 + #define jadeINT_HDLC2 0x01 + #define jadeINT_DSP 0x04 +#define jade_INTR 0x70 + +/********************************************************************/ +/* Indirect accessible JADE registers of common interest */ +/********************************************************************/ +#define jade_CHIPVERSIONNR 0x00 /* Does not work*/ + +#define jade_HDLCCNTRACCESS 0x10 + #define jadeINDIRECT_HAH1 0x02 + #define jadeINDIRECT_HAH2 0x01 + +#define jade_HDLC1SERRXPATH 0x1D +#define jade_HDLC1SERTXPATH 0x1E +#define jade_HDLC2SERRXPATH 0x1F +#define jade_HDLC2SERTXPATH 0x20 + #define jadeINDIRECT_SLIN1 0x10 + #define jadeINDIRECT_SLIN0 0x08 + #define jadeINDIRECT_LMOD1 0x04 + #define jadeINDIRECT_LMOD0 0x02 + #define jadeINDIRECT_HHR 0x01 + #define jadeINDIRECT_HHX 0x01 + +#define jade_RXAUDIOCH1CFG 0x11 +#define jade_RXAUDIOCH2CFG 0x14 +#define jade_TXAUDIOCH1CFG 0x17 +#define jade_TXAUDIOCH2CFG 0x1A + +extern int JadeVersion(struct IsdnCardState *cs, char *s); +extern void jade_sched_event(struct BCState *bcs, int event); +extern void modejade(struct BCState *bcs, int mode, int bc); +extern void clear_pending_jade_ints(struct IsdnCardState *cs); +extern void initjade(struct IsdnCardState *cs); + +#endif /* __JADE_H__ */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/jade_irq.c linux.pre11.3/drivers/isdn/hisax/jade_irq.c --- linux.vanilla/drivers/isdn/hisax/jade_irq.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/jade_irq.c Mon Jul 19 23:59:34 1999 @@ -0,0 +1,247 @@ +/* $Id: jade_irq.c,v 1.2 1999/07/01 08:07:59 keil Exp $ + * + * jade_irq.c Low level JADE IRQ stuff (derived from original hscx_irq.c) + * + * Author Roland Klabunde (R.Klabunde@Berkom.de) + * + * $Log: jade_irq.c,v $ + * Revision 1.2 1999/07/01 08:07:59 keil + * Initial version + * + * + */ + +static inline void +waitforCEC(struct IsdnCardState *cs, int jade, int reg) +{ + int to = 50; + int mask = (reg == jade_HDLC_XCMD ? jadeSTAR_XCEC : jadeSTAR_RCEC); + while ((READJADE(cs, jade, jade_HDLC_STAR) & mask) && to) { + udelay(1); + to--; + } + if (!to) + printk(KERN_WARNING "HiSax: waitforCEC (jade) timeout\n"); +} + + +static inline void +waitforXFW(struct IsdnCardState *cs, int jade) +{ + /* Does not work on older jade versions, don't care */ +} + +static inline void +WriteJADECMDR(struct IsdnCardState *cs, int jade, int reg, u_char data) +{ + long flags; + + save_flags(flags); + cli(); + waitforCEC(cs, jade, reg); + WRITEJADE(cs, jade, reg, data); + restore_flags(flags); +} + + + +static void +jade_empty_fifo(struct BCState *bcs, int count) +{ + u_char *ptr; + struct IsdnCardState *cs = bcs->cs; + long flags; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "jade_empty_fifo"); + + if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "jade_empty_fifo: incoming packet too large"); + WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC); + bcs->hw.hscx.rcvidx = 0; + return; + } + ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; + bcs->hw.hscx.rcvidx += count; + save_flags(flags); + cli(); + READJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count); + WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC); + restore_flags(flags); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "jade_empty_fifo %c cnt %d", + bcs->hw.hscx.hscx ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } +} + +static void +jade_fill_fifo(struct BCState *bcs) +{ + struct IsdnCardState *cs = bcs->cs; + int more, count; + int fifo_size = 32; + u_char *ptr; + long flags; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "jade_fill_fifo"); + + if (!bcs->tx_skb) + return; + if (bcs->tx_skb->len <= 0) + return; + + more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; + if (bcs->tx_skb->len > fifo_size) { + more = !0; + count = fifo_size; + } else + count = bcs->tx_skb->len; + + waitforXFW(cs, bcs->hw.hscx.hscx); + save_flags(flags); + cli(); + ptr = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.hscx.count += count; + WRITEJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count); + WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME)); + restore_flags(flags); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "jade_fill_fifo %c cnt %d", + bcs->hw.hscx.hscx ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } +} + + +static inline void +jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade) +{ + u_char r; + struct BCState *bcs = cs->bcs + jade; + struct sk_buff *skb; + int fifo_size = 32; + int count; + int i_jade = (int) jade; /* To satisfy the compiler */ + + if (!test_bit(BC_FLG_INIT, &bcs->Flag)) + return; + + if (val & 0x80) { /* RME */ + r = READJADE(cs, i_jade, jade_HDLC_RSTA); + if ((r & 0xf0) != 0xa0) { + if (!(r & 0x80)) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "JADE %s invalid frame", (jade ? "B":"A")); + if ((r & 0x40) && bcs->mode) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "JADE %c RDO mode=%d", 'A'+jade, bcs->mode); + if (!(r & 0x20)) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "JADE %c CRC error", 'A'+jade); + WriteJADECMDR(cs, jade, jade_HDLC_RCMD, jadeRCMD_RMC); + } else { + count = READJADE(cs, i_jade, jade_HDLC_RBCL) & 0x1F; + if (count == 0) + count = fifo_size; + jade_empty_fifo(bcs, count); + if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { + if (cs->debug & L1_DEB_HSCX_FIFO) + debugl1(cs, "HX Frame %d", count); + if (!(skb = dev_alloc_skb(count))) + printk(KERN_WARNING "JADE %s receive out of memory\n", (jade ? "B":"A")); + else { + SET_SKB_FREE(skb); + memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); + skb_queue_tail(&bcs->rqueue, skb); + } + } + } + bcs->hw.hscx.rcvidx = 0; + jade_sched_event(bcs, B_RCVBUFREADY); + } + if (val & 0x40) { /* RPF */ + jade_empty_fifo(bcs, fifo_size); + if (bcs->mode == L1_MODE_TRANS) { + /* receive audio data */ + if (!(skb = dev_alloc_skb(fifo_size))) + printk(KERN_WARNING "HiSax: receive out of memory\n"); + else { + SET_SKB_FREE(skb); + memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); + skb_queue_tail(&bcs->rqueue, skb); + } + bcs->hw.hscx.rcvidx = 0; + jade_sched_event(bcs, B_RCVBUFREADY); + } + } + if (val & 0x10) { /* XPR */ + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + jade_fill_fifo(bcs); + return; + } else { + if (bcs->st->lli.l1writewakeup && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) + bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count); + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + bcs->hw.hscx.count = 0; + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.hscx.count = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + jade_fill_fifo(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + jade_sched_event(bcs, B_XMTBUFREADY); + } + } +} + +static inline void +jade_int_main(struct IsdnCardState *cs, u_char val, int jade) +{ + struct BCState *bcs; + bcs = cs->bcs + jade; + + if (val & jadeISR_RFO) { + /* handled with RDO */ + val &= ~jadeISR_RFO; + } + if (val & jadeISR_XDU) { + /* relevant in HDLC mode only */ + /* don't reset XPR here */ + if (bcs->mode == 1) + jade_fill_fifo(bcs); + else { + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.hscx.count); + bcs->tx_cnt += bcs->hw.hscx.count; + bcs->hw.hscx.count = 0; + } + WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, jadeXCMD_XRES); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "JADE %c EXIR %x Lost TX", 'A'+jade, val); + } + } + if (val & (jadeISR_RME|jadeISR_RPF|jadeISR_XPR)) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "JADE %c interrupt %x", 'A'+jade, val); + jade_interrupt(cs, val, jade); + } +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/l3_1tr6.c linux.pre11.3/drivers/isdn/hisax/l3_1tr6.c --- linux.vanilla/drivers/isdn/hisax/l3_1tr6.c Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/hisax/l3_1tr6.c Mon Jul 19 23:59:34 1999 @@ -1,11 +1,32 @@ -/* $Id: l3_1tr6.c,v 2.4 1998/02/12 23:07:57 keil Exp $ +/* $Id: l3_1tr6.c,v 2.9 1999/07/01 08:11:55 keil Exp $ * German 1TR6 D-channel protocol * - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) + * + * This file is (c) under GNU PUBLIC LICENSE + * For changes and modifications please read + * ../../../Documentation/isdn/HiSax.cert * * * $Log: l3_1tr6.c,v $ + * Revision 2.9 1999/07/01 08:11:55 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 2.8 1998/11/15 23:55:08 keil + * changes from 2.0 + * + * Revision 2.7 1998/08/13 23:36:45 keil + * HiSax 3.1 - don't work stable with current LinkLevel + * + * Revision 2.6 1998/05/25 14:10:18 keil + * HiSax 3.0 + * X.75 and leased are working again. + * + * Revision 2.5 1998/05/25 12:58:14 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * * Revision 2.4 1998/02/12 23:07:57 keil * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * @@ -38,7 +59,7 @@ #include extern char *HiSax_getrev(const char *revision); -const char *l3_1tr6_revision = "$Revision: 2.4 $"; +const char *l3_1tr6_revision = "$Revision: 2.9 $"; #define MsgHead(ptr, cref, mty, dis) \ *ptr++ = dis; \ @@ -56,66 +77,34 @@ return; p = skb_put(skb, 4); MsgHead(p, pc->callref, mt, pd); - pc->st->l3.l3l2(pc->st, DL_DATA, skb); + l3_msg(pc->st, DL_DATA | REQUEST, skb); } -static int -l31tr6_check_messagetype_validity(int mt, int pd) { -/* verify if a message type exists */ - - if (pd == PROTO_DIS_N0) - switch(mt) { - case MT_N0_REG_IND: - case MT_N0_CANC_IND: - case MT_N0_FAC_STA: - case MT_N0_STA_ACK: - case MT_N0_STA_REJ: - case MT_N0_FAC_INF: - case MT_N0_INF_ACK: - case MT_N0_INF_REJ: - case MT_N0_CLOSE: - case MT_N0_CLO_ACK: - return(1); - default: - return(0); - } - else if (pd == PROTO_DIS_N1) - switch(mt) { - case MT_N1_ESC: - case MT_N1_ALERT: - case MT_N1_CALL_SENT: - case MT_N1_CONN: - case MT_N1_CONN_ACK: - case MT_N1_SETUP: - case MT_N1_SETUP_ACK: - case MT_N1_RES: - case MT_N1_RES_ACK: - case MT_N1_RES_REJ: - case MT_N1_SUSP: - case MT_N1_SUSP_ACK: - case MT_N1_SUSP_REJ: - case MT_N1_USER_INFO: - case MT_N1_DET: - case MT_N1_DISC: - case MT_N1_REL: - case MT_N1_REL_ACK: - case MT_N1_CANC_ACK: - case MT_N1_CANC_REJ: - case MT_N1_CON_CON: - case MT_N1_FAC: - case MT_N1_FAC_ACK: - case MT_N1_FAC_CAN: - case MT_N1_FAC_REG: - case MT_N1_FAC_REJ: - case MT_N1_INFO: - case MT_N1_REG_ACK: - case MT_N1_REG_REJ: - case MT_N1_STAT: - return (1); - default: - return(0); - } - return(0); +static void +l3_1tr6_release_req(struct l3_process *pc, u_char pr, void *arg) +{ + StopAllL3Timer(pc); + newl3state(pc, 19); + l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1); + L3AddTimer(&pc->timer, T308, CC_T308_1); +} + +static void +l3_1tr6_invalid(struct l3_process *pc, u_char pr, void *arg) +{ + struct sk_buff *skb = arg; + + idev_kfree_skb(skb, FREE_READ); + l3_1tr6_release_req(pc, 0, NULL); +} + +static void +l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb) +{ + idev_kfree_skb(skb, FREE_READ); + if (pc->st->l3.debug & L3_DEB_WARN) + l3_debug(pc->st, msg); + l3_1tr6_release_req(pc, 0, NULL); } static void @@ -204,7 +193,7 @@ L3DelTimer(&pc->timer); L3AddTimer(&pc->timer, T303, CC_T303); newl3state(pc, 1); - pc->st->l3.l3l2(pc->st, DL_DATA, skb); + l3_msg(pc->st, DL_DATA | REQUEST, skb); } static void @@ -220,17 +209,29 @@ /* Channel Identification */ p = skb->data; if ((p = findie(p, skb->len, WE0_chanID, 0))) { - pc->para.bchannel = p[2] & 0x3; - bcfound++; - } else if (pc->st->l3.debug & L3_DEB_WARN) - l3_debug(pc->st, "setup without bchannel"); + if (p[1] != 1) { + l3_1tr6_error(pc, "setup wrong chanID len", skb); + return; + } + if ((p[2] & 0xf4) != 0x80) { + l3_1tr6_error(pc, "setup wrong WE0_chanID", skb); + return; + } + if ((pc->para.bchannel = p[2] & 0x3)) + bcfound++; + } else { + l3_1tr6_error(pc, "missing setup chanID", skb); + return; + } p = skb->data; if ((p = findie(p, skb->len, WE6_serviceInd, 6))) { pc->para.setup.si1 = p[2]; pc->para.setup.si2 = p[3]; - } else if (pc->st->l3.debug & L3_DEB_WARN) - l3_debug(pc->st, "setup without service indicator"); + } else { + l3_1tr6_error(pc, "missing setup SI", skb); + return; + } p = skb->data; if ((p = findie(p, skb->len, WE0_destAddr, 0))) @@ -250,7 +251,7 @@ if ((FAC_SPV == p[3]) || (FAC_Activate == p[3])) pc->para.spv = 1; } - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); /* Signal all services, linklevel takes care of Service-Indicator */ if (bcfound) { @@ -261,7 +262,7 @@ l3_debug(pc->st, tmp); } newl3state(pc, 6); - pc->st->l3.l3l4(pc, CC_SETUP_IND, NULL); + pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc); } else release_l3_process(pc); } @@ -276,12 +277,22 @@ p = skb->data; newl3state(pc, 2); if ((p = findie(p, skb->len, WE0_chanID, 0))) { + if (p[1] != 1) { + l3_1tr6_error(pc, "setup_ack wrong chanID len", skb); + return; + } + if ((p[2] & 0xf4) != 0x80) { + l3_1tr6_error(pc, "setup_ack wrong WE0_chanID", skb); + return; + } pc->para.bchannel = p[2] & 0x3; - } else if (pc->st->l3.debug & L3_DEB_WARN) - l3_debug(pc->st, "setup answer without bchannel"); - dev_kfree_skb(skb); + } else { + l3_1tr6_error(pc, "missing setup_ack WE0_chanID", skb); + return; + } + idev_kfree_skb(skb, FREE_READ); L3AddTimer(&pc->timer, T304, CC_T304); - pc->st->l3.l3l4(pc, CC_MORE_INFO, NULL); + pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc); } static void @@ -293,13 +304,27 @@ L3DelTimer(&pc->timer); p = skb->data; if ((p = findie(p, skb->len, WE0_chanID, 0))) { + if (p[1] != 1) { + l3_1tr6_error(pc, "call sent wrong chanID len", skb); + return; + } + if ((p[2] & 0xf4) != 0x80) { + l3_1tr6_error(pc, "call sent wrong WE0_chanID", skb); + return; + } + if ((pc->state == 2) && (pc->para.bchannel != (p[2] & 0x3))) { + l3_1tr6_error(pc, "call sent wrong chanID value", skb); + return; + } pc->para.bchannel = p[2] & 0x3; - } else if (pc->st->l3.debug & L3_DEB_WARN) - l3_debug(pc->st, "setup answer without bchannel"); - dev_kfree_skb(skb); + } else { + l3_1tr6_error(pc, "missing call sent WE0_chanID", skb); + return; + } + idev_kfree_skb(skb, FREE_READ); L3AddTimer(&pc->timer, T310, CC_T310); newl3state(pc, 3); - pc->st->l3.l3l4(pc, CC_PROCEEDING_IND, NULL); + pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc); } static void @@ -307,10 +332,10 @@ { struct sk_buff *skb = arg; - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); L3DelTimer(&pc->timer); /* T304 */ newl3state(pc, 4); - pc->st->l3.l3l4(pc, CC_ALERTING_IND, NULL); + pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc); } static void @@ -330,7 +355,7 @@ } if (tmpcharge > pc->para.chargeinfo) { pc->para.chargeinfo = tmpcharge; - pc->st->l3.l3l4(pc, CC_INFO_CHARGE, NULL); + pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc); } if (pc->st->l3.debug & L3_DEB_CHARGE) { sprintf(tmp, "charging info %d", pc->para.chargeinfo); @@ -338,7 +363,7 @@ } } else if (pc->st->l3.debug & L3_DEB_CHARGE) l3_debug(pc->st, "charging info not found"); - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); } @@ -347,7 +372,7 @@ { struct sk_buff *skb = arg; - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); } static void @@ -356,10 +381,14 @@ struct sk_buff *skb = arg; L3DelTimer(&pc->timer); /* T310 */ + if (!findie(skb->data, skb->len, WE6_date, 6)) { + l3_1tr6_error(pc, "missing connect date", skb); + return; + } newl3state(pc, 10); - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); pc->para.chargeinfo = 0; - pc->st->l3.l3l4(pc, CC_SETUP_CNF, NULL); + pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc); } static void @@ -380,13 +409,16 @@ pc->para.cause = 0; pc->para.loc = 0; } - } else - pc->para.cause = -1; - dev_kfree_skb(skb); + } else { + pc->para.cause = NO_CAUSE; + l3_1tr6_error(pc, "missing REL cause", skb); + return; + } + idev_kfree_skb(skb, FREE_READ); StopAllL3Timer(pc); newl3state(pc, 0); l3_1TR6_message(pc, MT_N1_REL_ACK, PROTO_DIS_N1); - pc->st->l3.l3l4(pc, CC_RELEASE_IND, NULL); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); release_l3_process(pc); } @@ -395,11 +427,11 @@ { struct sk_buff *skb = arg; - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); StopAllL3Timer(pc); newl3state(pc, 0); - pc->para.cause = -1; - pc->st->l3.l3l4(pc, CC_RELEASE_CNF, NULL); + pc->para.cause = NO_CAUSE; + pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc); release_l3_process(pc); } @@ -421,7 +453,7 @@ } if (tmpcharge > pc->para.chargeinfo) { pc->para.chargeinfo = tmpcharge; - pc->st->l3.l3l4(pc, CC_INFO_CHARGE, NULL); + pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc); } if (pc->st->l3.debug & L3_DEB_CHARGE) { sprintf(tmp, "charging info %d", pc->para.chargeinfo); @@ -446,11 +478,15 @@ } else { if (pc->st->l3.debug & L3_DEB_WARN) l3_debug(pc->st, "cause not found"); - pc->para.cause = -1; + pc->para.cause = NO_CAUSE; } - dev_kfree_skb(skb); + if (!findie(skb->data, skb->len, WE6_date, 6)) { + l3_1tr6_error(pc, "missing connack date", skb); + return; + } + idev_kfree_skb(skb, FREE_READ); newl3state(pc, 12); - pc->st->l3.l3l4(pc, CC_DISCONNECT_IND, NULL); + pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc); } @@ -459,11 +495,15 @@ { struct sk_buff *skb = arg; - dev_kfree_skb(skb); + if (!findie(skb->data, skb->len, WE6_date, 6)) { + l3_1tr6_error(pc, "missing connack date", skb); + return; + } + idev_kfree_skb(skb, FREE_READ); newl3state(pc, 10); pc->para.chargeinfo = 0; L3DelTimer(&pc->timer); - pc->st->l3.l3l4(pc, CC_SETUP_COMPLETE_IND, NULL); + pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc); } static void @@ -502,7 +542,7 @@ if (!(skb = l3_alloc_skb(l))) return; memcpy(skb_put(skb, l), tmp, l); - pc->st->l3.l3l2(pc->st, DL_DATA, skb); + l3_msg(pc->st, DL_DATA | REQUEST, skb); L3DelTimer(&pc->timer); L3AddTimer(&pc->timer, T313, CC_T313); } @@ -530,6 +570,9 @@ case 0x10: clen = 0; break; + case 0x11: + cause = CAUSE_UserBusy; + break; case 0x15: cause = CAUSE_CallRejected; break; @@ -545,20 +588,11 @@ if (!(skb = l3_alloc_skb(l))) return; memcpy(skb_put(skb, l), tmp, l); - pc->st->l3.l3l2(pc->st, DL_DATA, skb); + l3_msg(pc->st, DL_DATA | REQUEST, skb); L3AddTimer(&pc->timer, T305, CC_T305); } static void -l3_1tr6_release_req(struct l3_process *pc, u_char pr, void *arg) -{ - StopAllL3Timer(pc); - newl3state(pc, 19); - l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1); - L3AddTimer(&pc->timer, T308, CC_T308_1); -} - -static void l3_1tr6_t303(struct l3_process *pc, u_char pr, void *arg) { if (pc->N303 > 0) { @@ -567,8 +601,8 @@ l3_1tr6_setup_req(pc, pr, arg); } else { L3DelTimer(&pc->timer); - pc->st->l3.l3l4(pc, CC_NOSETUP_RSP_ERR, NULL); - release_l3_process(pc); + pc->para.cause = 0; + l3_1tr6_disconnect_req(pc, 0, NULL); } } @@ -578,7 +612,7 @@ L3DelTimer(&pc->timer); pc->para.cause = 0xE6; l3_1tr6_disconnect_req(pc, pr, NULL); - pc->st->l3.l3l4(pc, CC_SETUP_ERR, NULL); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void @@ -592,7 +626,7 @@ u_char clen = 1; L3DelTimer(&pc->timer); - if (pc->para.cause > 0) + if (pc->para.cause != NO_CAUSE) cause = pc->para.cause; /* Map DSS1 causes */ switch (cause & 0x7f) { @@ -613,7 +647,7 @@ if (!(skb = l3_alloc_skb(l))) return; memcpy(skb_put(skb, l), tmp, l); - pc->st->l3.l3l2(pc->st, DL_DATA, skb); + l3_msg(pc->st, DL_DATA | REQUEST, skb); L3AddTimer(&pc->timer, T308, CC_T308_1); } @@ -623,7 +657,7 @@ L3DelTimer(&pc->timer); pc->para.cause = 0xE6; l3_1tr6_disconnect_req(pc, pr, NULL); - pc->st->l3.l3l4(pc, CC_SETUP_ERR, NULL); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void @@ -632,7 +666,7 @@ L3DelTimer(&pc->timer); pc->para.cause = 0xE6; l3_1tr6_disconnect_req(pc, pr, NULL); - pc->st->l3.l3l4(pc, CC_CONNECT_ERR, NULL); + pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc); } static void @@ -648,29 +682,45 @@ l3_1tr6_t308_2(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); - pc->st->l3.l3l4(pc, CC_RELEASE_ERR, NULL); + pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc); release_l3_process(pc); } + +static void +l3_1tr6_dl_reset(struct l3_process *pc, u_char pr, void *arg) +{ + pc->para.cause = CAUSE_LocalProcErr; + l3_1tr6_disconnect_req(pc, pr, NULL); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); +} + +static void +l3_1tr6_dl_release(struct l3_process *pc, u_char pr, void *arg) +{ + newl3state(pc, 0); + pc->para.cause = 0x1b; /* Destination out of order */ + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); + release_l3_process(pc); +} + /* *INDENT-OFF* */ static struct stateentry downstl[] = { {SBIT(0), - CC_SETUP_REQ, l3_1tr6_setup_req}, + CC_SETUP | REQUEST, l3_1tr6_setup_req}, {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) | SBIT(10), - CC_DISCONNECT_REQ, l3_1tr6_disconnect_req}, + CC_DISCONNECT | REQUEST, l3_1tr6_disconnect_req}, {SBIT(12), - CC_RELEASE_REQ, l3_1tr6_release_req}, - {ALL_STATES, - CC_DLRL, l3_1tr6_reset}, + CC_RELEASE | REQUEST, l3_1tr6_release_req}, {SBIT(6), - CC_IGNORE, l3_1tr6_reset}, + CC_IGNORE | REQUEST, l3_1tr6_reset}, {SBIT(6), - CC_REJECT_REQ, l3_1tr6_disconnect_req}, + CC_REJECT | REQUEST, l3_1tr6_disconnect_req}, {SBIT(6), - CC_ALERTING_REQ, l3_1tr6_alert_req}, + CC_ALERTING | REQUEST, l3_1tr6_alert_req}, {SBIT(6) | SBIT(7), - CC_SETUP_RSP, l3_1tr6_setup_rsp}, + CC_SETUP | RESPONSE, l3_1tr6_setup_rsp}, {SBIT(1), CC_T303, l3_1tr6_t303}, {SBIT(2), @@ -687,12 +737,14 @@ CC_T308_2, l3_1tr6_t308_2}, }; -static int downstl_len = sizeof(downstl) / -sizeof(struct stateentry); +#define DOWNSTL_LEN \ + (sizeof(downstl) / sizeof(struct stateentry)) static struct stateentry datastln1[] = { {SBIT(0), + MT_N1_INVALID, l3_1tr6_invalid}, + {SBIT(0), MT_N1_SETUP, l3_1tr6_setup}, {SBIT(1), MT_N1_SETUP_ACK, l3_1tr6_setup_ack}, @@ -711,18 +763,31 @@ {SBIT(10), MT_N1_INFO, l3_1tr6_info}, {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | - SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19), + SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17), MT_N1_REL, l3_1tr6_rel}, {SBIT(19), + MT_N1_REL, l3_1tr6_rel_ack}, + {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | + SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17), + MT_N1_REL_ACK, l3_1tr6_invalid}, + {SBIT(19), MT_N1_REL_ACK, l3_1tr6_rel_ack} }; -/* *INDENT-ON* */ - +#define DATASTLN1_LEN \ + (sizeof(datastln1) / sizeof(struct stateentry)) - -static int datastln1_len = sizeof(datastln1) / -sizeof(struct stateentry); +static struct stateentry manstatelist[] = +{ + {SBIT(2), + DL_ESTABLISH | INDICATION, l3_1tr6_dl_reset}, + {ALL_STATES, + DL_RELEASE | INDICATION, l3_1tr6_dl_release}, +}; + +#define MANSLLEN \ + (sizeof(manstatelist) / sizeof(struct stateentry)) +/* *INDENT-ON* */ static void up1tr6(struct PStack *st, int pr, void *arg) @@ -732,22 +797,34 @@ struct sk_buff *skb = arg; char tmp[80]; + switch (pr) { + case (DL_DATA | INDICATION): + case (DL_UNIT_DATA | INDICATION): + break; + case (DL_ESTABLISH | CONFIRM): + case (DL_ESTABLISH | INDICATION): + case (DL_RELEASE | INDICATION): + case (DL_RELEASE | CONFIRM): + l3_msg(st, pr, arg); + return; + break; + } if (skb->len < 4) { if (st->l3.debug & L3_DEB_PROTERR) { sprintf(tmp, "up1tr6 len only %d", skb->len); l3_debug(st, tmp); } - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); return; } if ((skb->data[0] & 0xfe) != PROTO_DIS_N0) { if (st->l3.debug & L3_DEB_PROTERR) { sprintf(tmp, "up1tr6%sunexpected discriminator %x message len %d", - (pr == DL_DATA) ? " " : "(broadcast) ", + (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", skb->data[0], skb->len); l3_debug(st, tmp); } - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); return; } if (skb->data[1] != 1) { @@ -755,43 +832,62 @@ sprintf(tmp, "up1tr6 CR len not 1"); l3_debug(st, tmp); } - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); return; } cr = skb->data[2]; mt = skb->data[3]; if (skb->data[0] == PROTO_DIS_N0) { - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); if (st->l3.debug & L3_DEB_STATE) { sprintf(tmp, "up1tr6%s N0 mt %x unhandled", - (pr == DL_DATA) ? " " : "(broadcast) ", mt); + (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", mt); l3_debug(st, tmp); } } else if (skb->data[0] == PROTO_DIS_N1) { if (!(proc = getl3proc(st, cr))) { - if ((mt == MT_N1_SETUP) && (cr < 128)) { + if (mt == MT_N1_SETUP) { + if (cr < 128) { + if (!(proc = new_l3_process(st, cr))) { + if (st->l3.debug & L3_DEB_PROTERR) { + sprintf(tmp, "up1tr6 no roc mem"); + l3_debug(st, tmp); + } + idev_kfree_skb(skb, FREE_READ); + return; + } + } else { + idev_kfree_skb(skb, FREE_READ); + return; + } + } else if ((mt == MT_N1_REL) || (mt == MT_N1_REL_ACK) || + (mt == MT_N1_CANC_ACK) || (mt == MT_N1_CANC_REJ) || + (mt == MT_N1_REG_ACK) || (mt == MT_N1_REG_REJ) || + (mt == MT_N1_SUSP_ACK) || (mt == MT_N1_RES_REJ) || + (mt == MT_N1_INFO)) { + idev_kfree_skb(skb, FREE_READ); + return; + } else { if (!(proc = new_l3_process(st, cr))) { if (st->l3.debug & L3_DEB_PROTERR) { sprintf(tmp, "up1tr6 no roc mem"); l3_debug(st, tmp); } - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); return; } - } else { - dev_kfree_skb(skb); - return; + mt = MT_N1_INVALID; } } - for (i = 0; i < datastln1_len; i++) + for (i = 0; i < DATASTLN1_LEN; i++) if ((mt == datastln1[i].primitive) && ((1 << proc->state) & datastln1[i].state)) break; - if (i == datastln1_len) { - dev_kfree_skb(skb); + if (i == DATASTLN1_LEN) { + idev_kfree_skb(skb, FREE_READ); if (st->l3.debug & L3_DEB_STATE) { sprintf(tmp, "up1tr6%sstate %d mt %x unhandled", - (pr == DL_DATA) ? " " : "(broadcast) ", + (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", proc->state, mt); l3_debug(st, tmp); } @@ -799,7 +895,7 @@ } else { if (st->l3.debug & L3_DEB_STATE) { sprintf(tmp, "up1tr6%sstate %d mt %x", - (pr == DL_DATA) ? " " : "(broadcast) ", + (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", proc->state, mt); l3_debug(st, tmp); } @@ -816,7 +912,10 @@ struct Channel *chan; char tmp[80]; - if (CC_SETUP_REQ == pr) { + if ((DL_ESTABLISH | REQUEST)== pr) { + l3_msg(st, pr, NULL); + return; + } else if ((CC_SETUP | REQUEST) == pr) { chan = arg; cr = newcallref(); cr |= 0x80; @@ -832,11 +931,11 @@ proc = arg; } - for (i = 0; i < downstl_len; i++) + for (i = 0; i < DOWNSTL_LEN; i++) if ((pr == downstl[i].primitive) && ((1 << proc->state) & downstl[i].state)) break; - if (i == downstl_len) { + if (i == DOWNSTL_LEN) { if (st->l3.debug & L3_DEB_STATE) { sprintf(tmp, "down1tr6 state %d prim %d unhandled", proc->state, pr); @@ -852,6 +951,34 @@ } } +static void +man1tr6(struct PStack *st, int pr, void *arg) +{ + int i; + struct l3_process *proc = arg; + + if (!proc) { + printk(KERN_ERR "HiSax man1tr6 without proc pr=%04x\n", pr); + return; + } + for (i = 0; i < MANSLLEN; i++) + if ((pr == manstatelist[i].primitive) && + ((1 << proc->state) & manstatelist[i].state)) + break; + if (i == MANSLLEN) { + if (st->l3.debug & L3_DEB_STATE) { + l3_debug(st, "cr %d man1tr6 state %d prim %d unhandled", + proc->callref & 0x7f, proc->state, pr); + } + } else { + if (st->l3.debug & L3_DEB_STATE) { + l3_debug(st, "cr %d man1tr6 state %d prim %d", + proc->callref & 0x7f, proc->state, pr); + } + manstatelist[i].rout(proc, pr, arg); + } +} + void setstack_1tr6(struct PStack *st) { @@ -859,6 +986,7 @@ st->lli.l4l3 = down1tr6; st->l2.l2l3 = up1tr6; + st->l3.l3ml3 = man1tr6; st->l3.N303 = 0; strcpy(tmp, l3_1tr6_revision); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/l3_1tr6.h linux.pre11.3/drivers/isdn/hisax/l3_1tr6.h --- linux.vanilla/drivers/isdn/hisax/l3_1tr6.h Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/hisax/l3_1tr6.h Mon Jul 19 23:59:34 1999 @@ -1,8 +1,11 @@ -/* $Id: l3_1tr6.h,v 2.0 1997/07/27 21:15:47 keil Exp $ +/* $Id: l3_1tr6.h,v 2.1 1998/08/13 23:36:48 keil Exp $ * * German 1TR6 D-channel protocol defines * * $Log: l3_1tr6.h,v $ + * Revision 2.1 1998/08/13 23:36:48 keil + * HiSax 3.1 - don't work stable with current LinkLevel + * * Revision 2.0 1997/07/27 21:15:47 keil * New Callref based layer3 * @@ -64,6 +67,7 @@ #define MT_N1_REG_ACK 0x6C #define MT_N1_REG_REJ 0x6F #define MT_N1_STAT 0x63 +#define MT_N1_INVALID 0 /* * W Elemente diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/l3dss1.c linux.pre11.3/drivers/isdn/hisax/l3dss1.c --- linux.vanilla/drivers/isdn/hisax/l3dss1.c Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/hisax/l3dss1.c Mon Jul 19 23:59:34 1999 @@ -1,14 +1,42 @@ -/* $Id: l3dss1.c,v 2.7 1998/02/12 23:08:01 keil Exp $ +/* $Id: l3dss1.c,v 2.14 1999/07/09 08:30:08 keil Exp $ * EURO/DSS1 D-channel protocol * - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden * + * This file is (c) under GNU PUBLIC LICENSE + * For changes and modifications please read + * ../../../Documentation/isdn/HiSax.cert + * * Thanks to Jan den Ouden * Fritz Elfert * * $Log: l3dss1.c,v $ + * Revision 2.14 1999/07/09 08:30:08 keil + * cosmetics + * + * Revision 2.13 1999/07/01 08:11:58 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 2.12 1998/11/15 23:55:10 keil + * changes from 2.0 + * + * Revision 2.11 1998/08/13 23:36:51 keil + * HiSax 3.1 - don't work stable with current LinkLevel + * + * Revision 2.10 1998/05/25 14:10:20 keil + * HiSax 3.0 + * X.75 and leased are working again. + * + * Revision 2.9 1998/05/25 12:58:17 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * + * Revision 2.8 1998/03/19 13:18:47 keil + * Start of a CAPI like interface for supplementary Service + * first service: SUSPEND + * * Revision 2.7 1998/02/12 23:08:01 keil * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * @@ -50,119 +78,349 @@ #include extern char *HiSax_getrev(const char *revision); -const char *dss1_revision = "$Revision: 2.7 $"; +const char *dss1_revision = "$Revision: 2.14 $"; #define EXT_BEARER_CAPS 1 #define MsgHead(ptr, cref, mty) \ *ptr++ = 0x8; \ - *ptr++ = 0x1; \ - *ptr++ = cref^0x80; \ + if (cref == -1) { \ + *ptr++ = 0x0; \ + } else { \ + *ptr++ = 0x1; \ + *ptr++ = cref^0x80; \ + } \ *ptr++ = mty -#ifdef HISAX_DE_AOC +/**********************************************/ +/* get a new invoke id for remote operations. */ +/* Only a return value != 0 is valid */ +/**********************************************/ +static unsigned char new_invoke_id(struct PStack *p) +{ + unsigned char retval; + int flags,i; + + i = 32; /* maximum search depth */ + + save_flags(flags); + cli(); + + retval = p->prot.dss1.last_invoke_id + 1; /* try new id */ + while ((i) && (p->prot.dss1.invoke_used[retval >> 3] == 0xFF)) { + p->prot.dss1.last_invoke_id = (retval & 0xF8) + 8; + i--; + } + if (i) { + while (p->prot.dss1.invoke_used[retval >> 3] & (1 << (retval & 7))) + retval++; + } else + retval = 0; + p->prot.dss1.last_invoke_id = retval; + p->prot.dss1.invoke_used[retval >> 3] |= (1 << (retval & 7)); + restore_flags(flags); + + return(retval); +} /* new_invoke_id */ + +/*************************/ +/* free a used invoke id */ +/*************************/ +static void free_invoke_id(struct PStack *p, unsigned char id) +{ int flags; + + if (!id) return; /* 0 = invalid value */ + + save_flags(flags); + cli(); + p->prot.dss1.invoke_used[id >> 3] &= ~(1 << (id & 7)); + restore_flags(flags); +} /* free_invoke_id */ + + +/**********************************************************/ +/* create a new l3 process and fill in dss1 specific data */ +/**********************************************************/ +static struct l3_process +*dss1_new_l3_process(struct PStack *st, int cr) +{ struct l3_process *proc; + + if (!(proc = new_l3_process(st, cr))) + return(NULL); + + proc->prot.dss1.invoke_id = 0; + proc->prot.dss1.remote_operation = 0; + proc->prot.dss1.uus1_data[0] = '\0'; + + return(proc); +} /* dss1_new_l3_process */ + +/************************************************/ +/* free a l3 process and all dss1 specific data */ +/************************************************/ +static void +dss1_release_l3_process(struct l3_process *p) +{ + free_invoke_id(p->st,p->prot.dss1.invoke_id); + release_l3_process(p); +} /* dss1_release_l3_process */ + +/********************************************************/ +/* search a process with invoke id id and dummy callref */ +/********************************************************/ +static struct l3_process * +l3dss1_search_dummy_proc(struct PStack *st, int id) +{ struct l3_process *pc = st->l3.proc; /* start of processes */ + + if (!id) return(NULL); + + while (pc) + { if ((pc->callref == -1) && (pc->prot.dss1.invoke_id == id)) + return(pc); + pc = pc->next; + } + return(NULL); +} /* l3dss1_search_dummy_proc */ + +/*******************************************************************/ +/* called when a facility message with a dummy callref is received */ +/* and a return result is delivered. id specifies the invoke id. */ +/*******************************************************************/ +static void +l3dss1_dummy_return_result(struct PStack *st, int id, u_char *p, u_char nlen) +{ isdn_ctrl ic; + struct IsdnCardState *cs; + struct l3_process *pc = NULL; + + if ((pc = l3dss1_search_dummy_proc(st, id))) + { L3DelTimer(&pc->timer); /* remove timer */ + + cs = pc->st->l1.hardware; + ic.driver = cs->myid; + ic.command = ISDN_STAT_PROT; + ic.arg = DSS1_STAT_INVOKE_RES; + ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id; + ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id; + ic.parm.dss1_io.proc = pc->prot.dss1.proc; + ic.parm.dss1_io.timeout= 0; + ic.parm.dss1_io.datalen = nlen; + ic.parm.dss1_io.data = p; + free_invoke_id(pc->st, pc->prot.dss1.invoke_id); + pc->prot.dss1.invoke_id = 0; /* reset id */ + + cs->iif.statcallb(&ic); + dss1_release_l3_process(pc); + } + else + l3_debug(st, "dummy return result id=0x%x result len=%d",id,nlen); +} /* l3dss1_dummy_return_result */ + +/*******************************************************************/ +/* called when a facility message with a dummy callref is received */ +/* and a return error is delivered. id specifies the invoke id. */ +/*******************************************************************/ +static void +l3dss1_dummy_error_return(struct PStack *st, int id, ulong error) +{ isdn_ctrl ic; + struct IsdnCardState *cs; + struct l3_process *pc = NULL; + + if ((pc = l3dss1_search_dummy_proc(st, id))) + { L3DelTimer(&pc->timer); /* remove timer */ + + cs = pc->st->l1.hardware; + ic.driver = cs->myid; + ic.command = ISDN_STAT_PROT; + ic.arg = DSS1_STAT_INVOKE_ERR; + ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id; + ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id; + ic.parm.dss1_io.proc = pc->prot.dss1.proc; + ic.parm.dss1_io.timeout= error; + ic.parm.dss1_io.datalen = 0; + ic.parm.dss1_io.data = NULL; + free_invoke_id(pc->st, pc->prot.dss1.invoke_id); + pc->prot.dss1.invoke_id = 0; /* reset id */ + + cs->iif.statcallb(&ic); + dss1_release_l3_process(pc); + } + else + l3_debug(st, "dummy return error id=0x%x error=0x%lx",id,error); +} /* l3dss1_error_return */ + +/*******************************************************************/ +/* called when a facility message with a dummy callref is received */ +/* and a invoke is delivered. id specifies the invoke id. */ +/*******************************************************************/ +static void +l3dss1_dummy_invoke(struct PStack *st, int cr, int id, + int ident, u_char *p, u_char nlen) +{ isdn_ctrl ic; + struct IsdnCardState *cs; + + l3_debug(st, "dummy invoke %s id=0x%x ident=0x%x datalen=%d", + (cr == -1) ? "local" : "broadcast",id,ident,nlen); + if (cr >= -1) return; /* ignore local data */ + + cs = st->l1.hardware; + ic.driver = cs->myid; + ic.command = ISDN_STAT_PROT; + ic.arg = DSS1_STAT_INVOKE_BRD; + ic.parm.dss1_io.hl_id = id; + ic.parm.dss1_io.ll_id = 0; + ic.parm.dss1_io.proc = ident; + ic.parm.dss1_io.timeout= 0; + ic.parm.dss1_io.datalen = nlen; + ic.parm.dss1_io.data = p; + + cs->iif.statcallb(&ic); +} /* l3dss1_dummy_invoke */ + static void -l3dss1_parse_facility(struct l3_process *pc, u_char *p) +l3dss1_parse_facility(struct PStack *st, struct l3_process *pc, + int cr, u_char * p) { int qd_len = 0; - char tmp[32]; + unsigned char nlen = 0, ilen, cp_tag; + int ident, id; + ulong err_ret; + + if (pc) + st = pc->st; /* valid Stack */ + else + if ((!st) || (cr >= 0)) return; /* neither pc nor st specified */ p++; qd_len = *p++; if (qd_len == 0) { - l3_debug(pc->st, "qd_len == 0"); + l3_debug(st, "qd_len == 0"); return; } - if((*p & 0x1F) != 0x11) { /* Service discriminator, supplementary service */ - l3_debug(pc->st, "supplementary service != 0x11"); + if ((*p & 0x1F) != 0x11) { /* Service discriminator, supplementary service */ + l3_debug(st, "supplementary service != 0x11"); return; } - while(qd_len > 0 && !(*p & 0x80)) { /* extension ? */ - p++; qd_len--; - } - if(qd_len < 2) { - l3_debug(pc->st, "qd_len < 2"); - return; + while (qd_len > 0 && !(*p & 0x80)) { /* extension ? */ + p++; + qd_len--; } - p++; qd_len--; - if((*p & 0xE0) != 0xA0) { /* class and form */ - l3_debug(pc->st, "class and form != 0xA0"); + if (qd_len < 2) { + l3_debug(st, "qd_len < 2"); return; } - switch(*p & 0x1F) { /* component tag */ - case 1: /* invoke */ - { - unsigned char nlen, ilen; - int ident; - - p++; qd_len--; - if(qd_len < 1) { - l3_debug(pc->st, "qd_len < 1"); - break; - } - if(*p & 0x80) { /* length format */ - l3_debug(pc->st, "*p & 0x80 length format"); - break; - } - nlen = *p++; qd_len--; - if(qd_len < nlen) { - l3_debug(pc->st, "qd_len < nlen"); - return; - } - qd_len -= nlen; - - if(nlen < 2) { - l3_debug(pc->st, "nlen < 2"); - return; - } - if(*p != 0x02) { /* invoke identifier tag */ - l3_debug(pc->st, "invoke identifier tag !=0x02"); - return; - } - p++; nlen--; - if(*p & 0x80) { /* length format */ - l3_debug(pc->st, "*p & 0x80 length format 2"); - break; - } - ilen = *p++; nlen--; - if(ilen > nlen || ilen == 0) { - l3_debug(pc->st, "ilen > nlen || ilen == 0"); - return; - } - nlen -= ilen; - ident = 0; - while(ilen > 0) { - ident = (ident << 8) | (*p++ & 0xFF); /* invoke identifier */ - ilen--; - } - - if(nlen < 2) { - l3_debug(pc->st, "nlen < 2 22"); - return; - } - if(*p != 0x02) { /* operation value */ - l3_debug(pc->st, "operation value !=0x02"); - return; - } - p++; nlen--; - ilen = *p++; nlen--; - if(ilen > nlen || ilen == 0) { - l3_debug(pc->st, "ilen > nlen || ilen == 0 22"); - return; - } - nlen -= ilen; - ident = 0; - while(ilen > 0) { - ident = (ident << 8) | (*p++ & 0xFF); - ilen--; - } - - #define FOO1(s,a,b) \ + p++; + qd_len--; + if ((*p & 0xE0) != 0xA0) { /* class and form */ + l3_debug(st, "class and form != 0xA0"); + return; + } + + cp_tag = *p & 0x1F; /* remember tag value */ + + p++; + qd_len--; + if (qd_len < 1) + { l3_debug(st, "qd_len < 1"); + return; + } + if (*p & 0x80) + { /* length format indefinite or limited */ + nlen = *p++ & 0x7F; /* number of len bytes or indefinite */ + if ((qd_len-- < ((!nlen) ? 3 : (1 + nlen))) || + (nlen > 1)) + { l3_debug(st, "length format error or not implemented"); + return; + } + if (nlen == 1) + { nlen = *p++; /* complete length */ + qd_len--; + } + else + { qd_len -= 2; /* trailing null bytes */ + if ((*(p+qd_len)) || (*(p+qd_len+1))) + { l3_debug(st,"length format indefinite error"); + return; + } + nlen = qd_len; + } + } + else + { nlen = *p++; + qd_len--; + } + if (qd_len < nlen) + { l3_debug(st, "qd_len < nlen"); + return; + } + qd_len -= nlen; + + if (nlen < 2) + { l3_debug(st, "nlen < 2"); + return; + } + if (*p != 0x02) + { /* invoke identifier tag */ + l3_debug(st, "invoke identifier tag !=0x02"); + return; + } + p++; + nlen--; + if (*p & 0x80) + { /* length format */ + l3_debug(st, "invoke id length format 2"); + return; + } + ilen = *p++; + nlen--; + if (ilen > nlen || ilen == 0) + { l3_debug(st, "ilen > nlen || ilen == 0"); + return; + } + nlen -= ilen; + id = 0; + while (ilen > 0) + { id = (id << 8) | (*p++ & 0xFF); /* invoke identifier */ + ilen--; + } + + switch (cp_tag) { /* component tag */ + case 1: /* invoke */ + if (nlen < 2) { + l3_debug(st, "nlen < 2 22"); + return; + } + if (*p != 0x02) { /* operation value */ + l3_debug(st, "operation value !=0x02"); + return; + } + p++; + nlen--; + ilen = *p++; + nlen--; + if (ilen > nlen || ilen == 0) { + l3_debug(st, "ilen > nlen || ilen == 0 22"); + return; + } + nlen -= ilen; + ident = 0; + while (ilen > 0) { + ident = (ident << 8) | (*p++ & 0xFF); + ilen--; + } + + if (!pc) + { l3dss1_dummy_invoke(st, cr, id, ident, p, nlen); + return; + } +#if HISAX_DE_AOC + { + +#define FOO1(s,a,b) \ while(nlen > 1) { \ int ilen = p[1]; \ if(nlen < ilen+2) { \ - l3_debug(pc->st, "FOO1 nlen < ilen+2"); \ + l3_debug(st, "FOO1 nlen < ilen+2"); \ return; \ } \ nlen -= ilen+2; \ @@ -174,305 +432,824 @@ p += ilen+2; \ } \ } - - switch(ident) { - default: - break; - case 0x22: /* during */ - FOO1("1A",0x30,FOO1("1C",0xA1,FOO1("1D",0x30,FOO1("1E",0x02,({ - ident = 0; - while(ilen > 0) { - ident = (ident<<8) | *p++; - ilen--; - } - if (ident > pc->para.chargeinfo) { - pc->para.chargeinfo = ident; - pc->st->l3.l3l4(pc, CC_INFO_CHARGE, NULL); - } - if (pc->st->l3.debug & L3_DEB_CHARGE) { - if (*(p+2) == 0) { - sprintf(tmp, "charging info during %d", pc->para.chargeinfo); - l3_debug(pc->st, tmp); - } - else { - sprintf(tmp, "charging info final %d", pc->para.chargeinfo); - l3_debug(pc->st, tmp); - } - } - }))))) - break; - case 0x24: /* final */ - FOO1("2A",0x30,FOO1("2B",0x30,FOO1("2C",0xA1,FOO1("2D",0x30,FOO1("2E",0x02,({ - ident = 0; - while(ilen > 0) { - ident = (ident<<8) | *p++; - ilen--; - } - if (ident > pc->para.chargeinfo) { - pc->para.chargeinfo = ident; - pc->st->l3.l3l4(pc, CC_INFO_CHARGE, NULL); - } - if (pc->st->l3.debug & L3_DEB_CHARGE) { - sprintf(tmp, "charging info final %d", pc->para.chargeinfo); - l3_debug(pc->st, tmp); - } - })))))) - break; - } - #undef FOO1 - + + switch (ident) { + case 0x22: /* during */ + FOO1("1A", 0x30, FOO1("1C", 0xA1, FOO1("1D", 0x30, FOO1("1E", 0x02, ( { + ident = 0; + nlen = (nlen)?nlen:0; /* Make gcc happy */ + while (ilen > 0) { + ident = (ident << 8) | *p++; + ilen--; + } + if (ident > pc->para.chargeinfo) { + pc->para.chargeinfo = ident; + st->l3.l3l4(st, CC_CHARGE | INDICATION, pc); + } + if (st->l3.debug & L3_DEB_CHARGE) { + if (*(p + 2) == 0) { + l3_debug(st, "charging info during %d", pc->para.chargeinfo); + } + else { + l3_debug(st, "charging info final %d", pc->para.chargeinfo); + } + } + } + ))))) + break; + case 0x24: /* final */ + FOO1("2A", 0x30, FOO1("2B", 0x30, FOO1("2C", 0xA1, FOO1("2D", 0x30, FOO1("2E", 0x02, ( { + ident = 0; + nlen = (nlen)?nlen:0; /* Make gcc happy */ + while (ilen > 0) { + ident = (ident << 8) | *p++; + ilen--; + } + if (ident > pc->para.chargeinfo) { + pc->para.chargeinfo = ident; + st->l3.l3l4(st, CC_CHARGE | INDICATION, pc); + } + if (st->l3.debug & L3_DEB_CHARGE) { + l3_debug(st, "charging info final %d", pc->para.chargeinfo); + } + } + )))))) + break; + default: + l3_debug(st, "invoke break invalid ident %02x",ident); + break; + } +#undef FOO1 + + } +#else not HISAX_DE_AOC + l3_debug(st, "invoke break"); +#endif not HISAX_DE_AOC + break; + case 2: /* return result */ + /* if no process available handle separately */ + if (!pc) + { if (cr == -1) + l3dss1_dummy_return_result(st, id, p, nlen); + return; + } + if ((pc->prot.dss1.invoke_id) && (pc->prot.dss1.invoke_id == id)) + { /* Diversion successfull */ + free_invoke_id(st,pc->prot.dss1.invoke_id); + pc->prot.dss1.remote_result = 0; /* success */ + pc->prot.dss1.invoke_id = 0; + pc->redir_result = pc->prot.dss1.remote_result; + st->l3.l3l4(st, CC_REDIR | INDICATION, pc); } /* Diversion successfull */ + else + l3_debug(st,"return error unknown identifier"); + break; + case 3: /* return error */ + err_ret = 0; + if (nlen < 2) + { l3_debug(st, "return error nlen < 2"); + return; + } + if (*p != 0x02) + { /* result tag */ + l3_debug(st, "invoke error tag !=0x02"); + return; + } + p++; + nlen--; + if (*p > 4) + { /* length format */ + l3_debug(st, "invoke return errlen > 4 "); + return; + } + ilen = *p++; + nlen--; + if (ilen > nlen || ilen == 0) + { l3_debug(st, "error return ilen > nlen || ilen == 0"); + return; + } + nlen -= ilen; + while (ilen > 0) + { err_ret = (err_ret << 8) | (*p++ & 0xFF); /* error value */ + ilen--; + } + /* if no process available handle separately */ + if (!pc) + { if (cr == -1) + l3dss1_dummy_error_return(st, id, err_ret); + return; + } + if ((pc->prot.dss1.invoke_id) && (pc->prot.dss1.invoke_id == id)) + { /* Deflection error */ + free_invoke_id(st,pc->prot.dss1.invoke_id); + pc->prot.dss1.remote_result = err_ret; /* result */ + pc->prot.dss1.invoke_id = 0; + pc->redir_result = pc->prot.dss1.remote_result; + st->l3.l3l4(st, CC_REDIR | INDICATION, pc); + } /* Deflection error */ + else + l3_debug(st,"return result unknown identifier"); + break; + default: + l3_debug(st, "facility default break tag=0x%02x",cp_tag); + break; + } +} + +static void +l3dss1_message(struct l3_process *pc, u_char mt) +{ + struct sk_buff *skb; + u_char *p; + + if (!(skb = l3_alloc_skb(4))) + return; + p = skb_put(skb, 4); + MsgHead(p, pc->callref, mt); + l3_msg(pc->st, DL_DATA | REQUEST, skb); +} + +static void +l3dss1_message_cause(struct l3_process *pc, u_char mt, u_char cause) +{ + struct sk_buff *skb; + u_char tmp[16]; + u_char *p = tmp; + int l; + + MsgHead(p, pc->callref, mt); + *p++ = IE_CAUSE; + *p++ = 0x2; + *p++ = 0x80; + *p++ = cause | 0x80; + + l = p - tmp; + if (!(skb = l3_alloc_skb(l))) + return; + memcpy(skb_put(skb, l), tmp, l); + l3_msg(pc->st, DL_DATA | REQUEST, skb); +} + +static void +l3dss1_status_send(struct l3_process *pc, u_char pr, void *arg) +{ + u_char tmp[16]; + u_char *p = tmp; + int l; + struct sk_buff *skb; + + MsgHead(p, pc->callref, MT_STATUS); + + *p++ = IE_CAUSE; + *p++ = 0x2; + *p++ = 0x80; + *p++ = pc->para.cause | 0x80; + + *p++ = IE_CALL_STATE; + *p++ = 0x1; + *p++ = pc->state & 0x3f; + + l = p - tmp; + if (!(skb = l3_alloc_skb(l))) + return; + memcpy(skb_put(skb, l), tmp, l); + l3_msg(pc->st, DL_DATA | REQUEST, skb); +} + +static void +l3dss1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg) +{ + /* This routine is called if here was no SETUP made (checks in dss1up and in + * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code + * MT_STATUS_ENQUIRE in the NULL state is handled too + */ + u_char tmp[16]; + u_char *p = tmp; + int l; + struct sk_buff *skb; + + switch (pc->para.cause) { + case 81: /* invalid callreference */ + case 88: /* incomp destination */ + case 96: /* mandory IE missing */ + case 100: /* invalid IE contents */ + case 101: /* incompatible Callstate */ + MsgHead(p, pc->callref, MT_RELEASE_COMPLETE); + *p++ = IE_CAUSE; + *p++ = 0x2; + *p++ = 0x80; + *p++ = pc->para.cause | 0x80; + break; + default: + printk(KERN_ERR "HiSax l3dss1_msg_without_setup wrong cause %d\n", + pc->para.cause); + return; + } + l = p - tmp; + if (!(skb = l3_alloc_skb(l))) + return; + memcpy(skb_put(skb, l), tmp, l); + l3_msg(pc->st, DL_DATA | REQUEST, skb); + dss1_release_l3_process(pc); +} + +static int ie_ALERTING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1, + IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_HLC, IE_USER_USER, -1}; +static int ie_CALL_PROCEEDING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1, + IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_HLC, -1}; +static int ie_CONNECT[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1, + IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_DATE, IE_CONNECT_PN, + IE_CONNECT_SUB, IE_LLC, IE_HLC, IE_USER_USER, -1}; +static int ie_CONNECT_ACKNOWLEDGE[] = {IE_CHANNEL_ID, IE_DISPLAY, -1}; +static int ie_DISCONNECT[] = {IE_CAUSE | IE_MANDATORY, IE_FACILITY, + IE_PROGRESS, IE_DISPLAY, IE_USER_USER, -1}; +/* not used + * static int ie_INFORMATION[] = {IE_COMPLETE, IE_DISPLAY, IE_KEYPAD, + * IE_CALLED_PN, -1}; + */ +static int ie_NOTIFY[] = {IE_BEARER, IE_NOTIFY | IE_MANDATORY, IE_DISPLAY, -1}; +static int ie_PROGRESS[] = {IE_BEARER, IE_CAUSE, IE_FACILITY, IE_PROGRESS | + IE_MANDATORY, IE_DISPLAY, IE_HLC, IE_USER_USER, -1}; +static int ie_RELEASE[] = {IE_CAUSE | IE_MANDATORY_1, IE_FACILITY, IE_DISPLAY, IE_USER_USER, -1}; +/* a RELEASE_COMPLETE with errors don't require special actions +static int ie_RELEASE_COMPLETE[] = {IE_CAUSE | IE_MANDATORY_1, IE_DISPLAY, IE_USER_USER, -1}; +*/ +static int ie_RESUME_ACKNOWLEDGE[] = {IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY, + IE_DISPLAY, -1}; +static int ie_RESUME_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1}; +static int ie_SETUP[] = {IE_COMPLETE, IE_BEARER | IE_MANDATORY, + IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY, IE_PROGRESS, + IE_NET_FAC, IE_DISPLAY, IE_KEYPAD, IE_CALLING_PN, + IE_CALLING_SUB, IE_CALLED_PN, IE_CALLED_SUB, IE_LLC, IE_USER_USER, -1}; +static int ie_SETUP_ACKNOWLEDGE[] = {IE_CHANNEL_ID | IE_MANDATORY, IE_FACILITY, + IE_PROGRESS, IE_DISPLAY, -1}; +static int ie_STATUS[] = {IE_CAUSE | IE_MANDATORY, IE_CALL_STATE | + IE_MANDATORY, IE_DISPLAY, -1}; +static int ie_STATUS_ENQUIRY[] = {IE_DISPLAY, -1}; +static int ie_SUSPEND_ACKNOWLEDGE[] = {IE_DISPLAY, IE_FACILITY, -1}; +static int ie_SUSPEND_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1}; +/* not used + * static int ie_CONGESTION_CONTROL[] = {IE_CONGESTION | IE_MANDATORY, + * IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1}; + * static int ie_USER_INFORMATION[] = {IE_MORE_DATA, IE_USER_USER | IE_MANDATORY, -1}; + * static int ie_RESTART[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_RESTART_IND | + * IE_MANDATORY, -1}; + */ +static int ie_FACILITY[] = {IE_FACILITY | IE_MANDATORY, IE_DISPLAY, -1}; +static int comp_required[] = {1,2,3,5,6,7,9,10,11,14,15,-1}; +static int l3_valid_states[] = {0,1,2,3,4,6,7,8,9,10,11,12,15,17,19,25,-1}; + +struct ie_len { + int ie; + int len; +}; + +static +struct ie_len max_ie_len[] = { + {IE_SEGMENT, 4}, + {IE_BEARER, 12}, + {IE_CAUSE, 32}, + {IE_CALL_ID, 10}, + {IE_CALL_STATE, 3}, + {IE_CHANNEL_ID, 34}, + {IE_FACILITY, 255}, + {IE_PROGRESS, 4}, + {IE_NET_FAC, 255}, + {IE_NOTIFY, 3}, + {IE_DISPLAY, 82}, + {IE_DATE, 8}, + {IE_KEYPAD, 34}, + {IE_SIGNAL, 3}, + {IE_INFORATE, 6}, + {IE_E2E_TDELAY, 11}, + {IE_TDELAY_SEL, 5}, + {IE_PACK_BINPARA, 3}, + {IE_PACK_WINSIZE, 4}, + {IE_PACK_SIZE, 4}, + {IE_CUG, 7}, + {IE_REV_CHARGE, 3}, + {IE_CALLING_PN, 24}, + {IE_CALLING_SUB, 23}, + {IE_CALLED_PN, 24}, + {IE_CALLED_SUB, 23}, + {IE_REDIR_NR, 255}, + {IE_TRANS_SEL, 255}, + {IE_RESTART_IND, 3}, + {IE_LLC, 18}, + {IE_HLC, 5}, + {IE_USER_USER, 131}, + {-1,0}, +}; + +static int +getmax_ie_len(u_char ie) { + int i = 0; + while (max_ie_len[i].ie != -1) { + if (max_ie_len[i].ie == ie) + return(max_ie_len[i].len); + i++; + } + return(255); +} + +static int +ie_in_set(struct l3_process *pc, u_char ie, int *checklist) { + int ret = 1; + + while (*checklist != -1) { +#if 0 + if (pc->debug & L3_DEB_CHECK) + l3_debug(pc->st, "ie_in_set ie(%x) cl(%x)", + ie, *checklist); +#endif + if ((*checklist & 0xff) == ie) { + if (ie & 0x80) + return(-ret); + else + return(ret); + } + ret++; + checklist++; + } + return(0); +} + +static int +check_infoelements(struct l3_process *pc, struct sk_buff *skb, int *checklist) +{ + int *cl = checklist; + u_char mt; + u_char *p, ie; + int l, newpos, oldpos; + int err_seq = 0, err_len = 0, err_compr = 0, err_ureg = 0; + + p = skb->data; + /* skip cr */ + p++; + l = (*p++) & 0xf; + p += l; + mt = *p++; + oldpos = 0; +/* shift codeset procedure not implemented in the moment */ + while ((p - skb->data) < skb->len) { + if ((newpos = ie_in_set(pc, *p, cl))) { + if (newpos > 0) { + if (newpos < oldpos) + err_seq++; + else + oldpos = newpos; + } + } else { + if (ie_in_set(pc, *p, comp_required)) + err_compr++; + else + err_ureg++; } - break; - case 2: /* return result */ - l3_debug(pc->st, "return result break"); - break; - case 3: /* return error */ - l3_debug(pc->st, "return error break"); - break; - default: - l3_debug(pc->st, "default break"); - break; - } -} -#endif - -static int -l3dss1_check_messagetype_validity(int mt) { -/* verify if a message type exists */ - switch(mt) { + ie = *p++; + if (newpos >= 0) { + l = *p++; + p += l; + l += 2; + } else + l = 1; + if (l > getmax_ie_len(ie)) + err_len++; + } + if (err_compr | err_ureg | err_len | err_seq) { + if (pc->debug & L3_DEB_CHECK) + l3_debug(pc->st, "check_infoelements mt %x %d/%d/%d/%d", + mt, err_compr, err_ureg, err_len, err_seq); + if (err_compr) + return(ERR_IE_COMPREHENSION); + if (err_ureg) + return(ERR_IE_UNRECOGNIZED); + if (err_len) + return(ERR_IE_LENGTH); + if (err_seq) + return(ERR_IE_SEQUENCE); + } + return(0); +} + +/* verify if a message type exists and contain no IE error */ +static int +l3dss1_check_messagetype_validity(struct l3_process *pc, int mt, void *arg) +{ + switch (mt) { case MT_ALERTING: case MT_CALL_PROCEEDING: case MT_CONNECT: case MT_CONNECT_ACKNOWLEDGE: + case MT_DISCONNECT: + case MT_INFORMATION: + case MT_FACILITY: + case MT_NOTIFY: case MT_PROGRESS: + case MT_RELEASE: + case MT_RELEASE_COMPLETE: case MT_SETUP: case MT_SETUP_ACKNOWLEDGE: - case MT_RESUME: case MT_RESUME_ACKNOWLEDGE: case MT_RESUME_REJECT: - case MT_SUSPEND: case MT_SUSPEND_ACKNOWLEDGE: case MT_SUSPEND_REJECT: case MT_USER_INFORMATION: - case MT_DISCONNECT: - case MT_RELEASE: - case MT_RELEASE_COMPLETE: case MT_RESTART: case MT_RESTART_ACKNOWLEDGE: - case MT_SEGMENT: case MT_CONGESTION_CONTROL: - case MT_INFORMATION: - case MT_FACILITY: - case MT_NOTIFY: case MT_STATUS: case MT_STATUS_ENQUIRY: + if (pc->debug & L3_DEB_CHECK) + l3_debug(pc->st, "l3dss1_check_messagetype_validity mt(%x) OK", mt); + break; + case MT_RESUME: /* RESUME only in user->net */ + case MT_SUSPEND: /* SUSPEND only in user->net */ + default: + if (pc->debug & (L3_DEB_CHECK | L3_DEB_WARN)) + l3_debug(pc->st, "l3dss1_check_messagetype_validity mt(%x) fail", mt); + pc->para.cause = 97; + l3dss1_status_send(pc, 0, NULL); return(1); + } + return(0); +} + +static void +l3dss1_std_ie_err(struct l3_process *pc, int ret) { + + if (pc->debug & L3_DEB_CHECK) + l3_debug(pc->st, "check_infoelements ret %d", ret); + switch(ret) { + case 0: + break; + case ERR_IE_COMPREHENSION: + pc->para.cause = 96; + l3dss1_status_send(pc, 0, NULL); + break; + case ERR_IE_UNRECOGNIZED: + pc->para.cause = 99; + l3dss1_status_send(pc, 0, NULL); + break; + case ERR_IE_LENGTH: + pc->para.cause = 100; + l3dss1_status_send(pc, 0, NULL); + break; + case ERR_IE_SEQUENCE: default: - return(0); + break; } +} + +static int +l3dss1_get_channel_id(struct l3_process *pc, struct sk_buff *skb) { + u_char *p; + + p = skb->data; + if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) { + p++; + if (*p != 1) { /* len for BRI = 1 */ + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "wrong chid len %d", *p); + return (-2); + } + p++; + if (*p & 0x60) { /* only base rate interface */ + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "wrong chid %x", *p); + return (-3); + } + return(*p & 0x3); + } else + return(-1); +} + +static int +l3dss1_get_cause(struct l3_process *pc, struct sk_buff *skb) { + u_char l, i=0; + u_char *p; + + p = skb->data; + pc->para.cause = 31; + pc->para.loc = 0; + if ((p = findie(p, skb->len, IE_CAUSE, 0))) { + p++; + l = *p++; + if (l>30) + return(1); + if (l) { + pc->para.loc = *p++; + l--; + } else { + return(2); + } + if (l && !(pc->para.loc & 0x80)) { + l--; + p++; /* skip recommendation */ + } + if (l) { + pc->para.cause = *p++; + l--; + if (!(pc->para.cause & 0x80)) + return(3); + } else + return(4); + while (l && (i<6)) { + pc->para.diag[i++] = *p++; + l--; + } + } else + return(-1); return(0); } static void -l3dss1_message(struct l3_process *pc, u_char mt) +l3dss1_msg_with_uus(struct l3_process *pc, u_char cmd) { struct sk_buff *skb; - u_char *p; + u_char tmp[16+40]; + u_char *p = tmp; + int l; - if (!(skb = l3_alloc_skb(4))) + MsgHead(p, pc->callref, cmd); + + if (pc->prot.dss1.uus1_data[0]) + { *p++ = IE_USER_USER; /* UUS info element */ + *p++ = strlen(pc->prot.dss1.uus1_data) + 1; + *p++ = 0x04; /* IA5 chars */ + strcpy(p,pc->prot.dss1.uus1_data); + p += strlen(pc->prot.dss1.uus1_data); + pc->prot.dss1.uus1_data[0] = '\0'; + } + + l = p - tmp; + if (!(skb = l3_alloc_skb(l))) return; - p = skb_put(skb, 4); - MsgHead(p, pc->callref, mt); - pc->st->l3.l3l2(pc->st, DL_DATA, skb); -} + memcpy(skb_put(skb, l), tmp, l); + l3_msg(pc->st, DL_DATA | REQUEST, skb); +} /* l3dss1_msg_with_uus */ static void l3dss1_release_req(struct l3_process *pc, u_char pr, void *arg) { StopAllL3Timer(pc); newl3state(pc, 19); - l3dss1_message(pc, MT_RELEASE); + if (!pc->prot.dss1.uus1_data[0]) + l3dss1_message(pc, MT_RELEASE); + else + l3dss1_msg_with_uus(pc, MT_RELEASE); L3AddTimer(&pc->timer, T308, CC_T308_1); } -static void -l3dss1_release_cmpl(struct l3_process *pc, u_char pr, void *arg) -{ - u_char *p; - struct sk_buff *skb = arg; - int cause = -1; +static void +l3dss1_release_cmpl(struct l3_process *pc, u_char pr, void *arg) +{ + struct sk_buff *skb = arg; + int ret; + + if ((ret = l3dss1_get_cause(pc, skb))>0) { + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "RELCMPL get_cause ret(%d)",ret); + } else if (ret < 0) + pc->para.cause = NO_CAUSE; + StopAllL3Timer(pc); + newl3state(pc, 0); + pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc); + dss1_release_l3_process(pc); +} + +#if EXT_BEARER_CAPS + +u_char * +EncodeASyncParams(u_char * p, u_char si2) +{ // 7c 06 88 90 21 42 00 bb + + p[0] = p[1] = 0; + p[2] = 0x80; + if (si2 & 32) // 7 data bits + + p[2] += 16; + else // 8 data bits + + p[2] += 24; + + if (si2 & 16) // 2 stop bits + + p[2] += 96; + else // 1 stop bit + + p[2] = 32; + + if (si2 & 8) // even parity + + p[2] += 2; + else // no parity + + p[2] += 3; + + switch (si2 & 0x07) { + case 0: + p[0] = 66; // 1200 bit/s + + break; + case 1: + p[0] = 88; // 1200/75 bit/s + + break; + case 2: + p[0] = 87; // 75/1200 bit/s + + break; + case 3: + p[0] = 67; // 2400 bit/s + + break; + case 4: + p[0] = 69; // 4800 bit/s + + break; + case 5: + p[0] = 72; // 9600 bit/s + + break; + case 6: + p[0] = 73; // 14400 bit/s + + break; + case 7: + p[0] = 75; // 19200 bit/s + + break; + } + return p + 3; +} + +u_char +EncodeSyncParams(u_char si2, u_char ai) +{ + + switch (si2) { + case 0: + return ai + 2; // 1200 bit/s + + case 1: + return ai + 24; // 1200/75 bit/s + + case 2: + return ai + 23; // 75/1200 bit/s + + case 3: + return ai + 3; // 2400 bit/s + + case 4: + return ai + 5; // 4800 bit/s + + case 5: + return ai + 8; // 9600 bit/s + + case 6: + return ai + 9; // 14400 bit/s + + case 7: + return ai + 11; // 19200 bit/s + + case 8: + return ai + 14; // 48000 bit/s + + case 9: + return ai + 15; // 56000 bit/s + + case 15: + return ai + 40; // negotiate bit/s + + default: + break; + } + return ai; +} + + +static u_char +DecodeASyncParams(u_char si2, u_char * p) +{ + u_char info; + + switch (p[5]) { + case 66: // 1200 bit/s + + break; // si2 don't change + + case 88: // 1200/75 bit/s + + si2 += 1; + break; + case 87: // 75/1200 bit/s + + si2 += 2; + break; + case 67: // 2400 bit/s + + si2 += 3; + break; + case 69: // 4800 bit/s + + si2 += 4; + break; + case 72: // 9600 bit/s + + si2 += 5; + break; + case 73: // 14400 bit/s + + si2 += 6; + break; + case 75: // 19200 bit/s + + si2 += 7; + break; + } + + info = p[7] & 0x7f; + if ((info & 16) && (!(info & 8))) // 7 data bits + + si2 += 32; // else 8 data bits + + if ((info & 96) == 96) // 2 stop bits + + si2 += 16; // else 1 stop bit + + if ((info & 2) && (!(info & 1))) // even parity + + si2 += 8; // else no parity + + return si2; +} + + +static u_char +DecodeSyncParams(u_char si2, u_char info) +{ + info &= 0x7f; + switch (info) { + case 40: // bit/s negotiation failed ai := 165 not 175! + + return si2 + 15; + case 15: // 56000 bit/s failed, ai := 0 not 169 ! + + return si2 + 9; + case 14: // 48000 bit/s + + return si2 + 8; + case 11: // 19200 bit/s + + return si2 + 7; + case 9: // 14400 bit/s + + return si2 + 6; + case 8: // 9600 bit/s + + return si2 + 5; + case 5: // 4800 bit/s + + return si2 + 4; + case 3: // 2400 bit/s + + return si2 + 3; + case 23: // 75/1200 bit/s + + return si2 + 2; + case 24: // 1200/75 bit/s + + return si2 + 1; + default: // 1200 bit/s - p = skb->data; - pc->para.loc = 0; - if ((p = findie(p, skb->len, IE_CAUSE, 0))) { - p++; - if (*p++ == 2) - pc->para.loc = *p++; - cause = *p & 0x7f; + return si2; } - dev_kfree_skb(skb); - StopAllL3Timer(pc); - pc->para.cause = cause; - newl3state(pc, 0); - pc->st->l3.l3l4(pc, CC_RELEASE_CNF, NULL); - release_l3_process(pc); } -#ifdef EXT_BEARER_CAPS +static u_char +DecodeSI2(struct sk_buff *skb) +{ + u_char *p; //, *pend=skb->data + skb->len; -u_char *EncodeASyncParams(u_char *p, u_char si2) -{ // 7c 06 88 90 21 42 00 bb + if ((p = findie(skb->data, skb->len, 0x7c, 0))) { + switch (p[4] & 0x0f) { + case 0x01: + if (p[1] == 0x04) // sync. Bitratenadaption - p[0] = p[1] = 0; p[2] = 0x80; - if (si2 & 32) // 7 data bits - p[2] += 16; - else // 8 data bits - p[2] +=24; - - if (si2 & 16) // 2 stop bits - p[2] += 96; - else // 1 stop bit - p[2] = 32; - - if (si2 & 8) // even parity - p[2] += 2; - else // no parity - p[2] += 3; - - switch (si2 & 0x07) - { - case 0: p[0] = 66; // 1200 bit/s - break; - case 1: p[0] = 88; // 1200/75 bit/s - break; - case 2: p[0] = 87; // 75/1200 bit/s - break; - case 3: p[0] = 67; // 2400 bit/s - break; - case 4: p[0] = 69; // 4800 bit/s - break; - case 5: p[0] = 72; // 9600 bit/s - break; - case 6: p[0] = 73; // 14400 bit/s - break; - case 7: p[0] = 75; // 19200 bit/s - break; - } - return p+3; -} - -u_char EncodeSyncParams(u_char si2, u_char ai) -{ - - switch (si2) - { - case 0: return ai + 2; // 1200 bit/s - case 1: return ai + 24; // 1200/75 bit/s - case 2: return ai + 23; // 75/1200 bit/s - case 3: return ai + 3; // 2400 bit/s - case 4: return ai + 5; // 4800 bit/s - case 5: return ai + 8; // 9600 bit/s - case 6: return ai + 9; // 14400 bit/s - case 7: return ai + 11; // 19200 bit/s - case 8: return ai + 14; // 48000 bit/s - case 9: return ai + 15; // 56000 bit/s - case 15: return ai + 40; // negotiate bit/s - default: break; - } - return ai; -} - - -static u_char DecodeASyncParams(u_char si2, u_char *p) -{ u_char info; - - switch (p[5]) - { - case 66: // 1200 bit/s - break; // si2 bleibt gleich - case 88: // 1200/75 bit/s - si2 += 1; - break; - case 87: // 75/1200 bit/s - si2 += 2; - break; - case 67: // 2400 bit/s - si2 += 3; - break; - case 69: // 4800 bit/s - si2 += 4; - break; - case 72: // 9600 bit/s - si2 += 5; - break; - case 73: // 14400 bit/s - si2 += 6; - break; - case 75: // 19200 bit/s - si2 += 7; - break; - } - - info = p[7] & 0x7f; - if ((info & 16) && (!(info & 8))) // 7 data bits - si2 += 32; // else 8 data bits - if ((info & 96) == 96) // 2 stop bits - si2 += 16; // else 1 stop bit - if ((info & 2) && (!(info & 1))) // even parity - si2 += 8; // else no parity - - return si2; -} - - -static u_char DecodeSyncParams(u_char si2, u_char info) -{ - info &= 0x7f; - switch (info) - { - case 40: // bit/s aushandeln --- hat nicht geklappt, ai wird 165 statt 175! - return si2 + 15; - case 15: // 56000 bit/s --- hat nicht geklappt, ai wird 0 statt 169 ! - return si2 + 9; - case 14: // 48000 bit/s - return si2 + 8; - case 11: // 19200 bit/s - return si2 + 7; - case 9: // 14400 bit/s - return si2 + 6; - case 8: // 9600 bit/s - return si2 + 5; - case 5: // 4800 bit/s - return si2 + 4; - case 3: // 2400 bit/s - return si2 + 3; - case 23: // 75/1200 bit/s - return si2 + 2; - case 24: // 1200/75 bit/s - return si2 + 1; - default: // 1200 bit/s - return si2; - } -} - -static u_char DecodeSI2(struct sk_buff *skb) -{ u_char *p; //, *pend=skb->data + skb->len; - - if ((p = findie(skb->data, skb->len, 0x7c, 0))) - { - switch (p[4] & 0x0f) - { - case 0x01: if (p[1] == 0x04) // sync. Bitratenadaption - return DecodeSyncParams(160, p[5]); // V.110/X.30 - else if (p[1] == 0x06) // async. Bitratenadaption - return DecodeASyncParams(192, p); // V.110/X.30 - break; - case 0x08: // if (p[5] == 0x02) // sync. Bitratenadaption - return DecodeSyncParams(176, p[5]); // V.120 - break; - } - } - return 0; + return DecodeSyncParams(160, p[5]); // V.110/X.30 + + else if (p[1] == 0x06) // async. Bitratenadaption + + return DecodeASyncParams(192, p); // V.110/X.30 + + break; + case 0x08: // if (p[5] == 0x02) // sync. Bitratenadaption + + return DecodeSyncParams(176, p[5]); // V.120 + + break; + } + } + return 0; } #endif @@ -486,6 +1263,7 @@ u_char tmp[128]; u_char *p = tmp; u_char channel = 0; + u_char send_keypad; u_char screen = 0x80; u_char *teln; u_char *msn; @@ -495,13 +1273,17 @@ MsgHead(p, pc->callref, MT_SETUP); + teln = pc->para.setup.phone; + send_keypad = (strchr(teln,'*') || strchr(teln,'#')) ? 1 : 0; /* * Set Bearer Capability, Map info from 1TR6-convention to EDSS1 */ -#ifdef HISAX_EURO_SENDCOMPLETE - *p++ = 0xa1; /* complete indicator */ +#if HISAX_EURO_SENDCOMPLETE + if (!send_keypad) + *p++ = 0xa1; /* complete indicator */ #endif - switch (pc->para.setup.si1) { + if (!send_keypad) + switch (pc->para.setup.si1) { case 1: /* Telephony */ *p++ = 0x4; /* BC-IE-code */ *p++ = 0x3; /* Length */ @@ -517,12 +1299,26 @@ *p++ = 0x88; /* Coding Std. CCITT, unrestr. dig. Inform. */ *p++ = 0x90; /* Circuit-Mode 64kbps */ break; - } + } + else { *p++ = 0x4; /* assumptions for bearer services with keypad */ + *p++ = 0x3; + *p++ = 0x80; + *p++ = 0x90; + *p++ = 0xa3; + *p++ = 0x18; /* no specific channel */ + *p++ = 0x01; + *p++ = 0x83; + *p++ = 0x2C; /* IE keypad */ + *p++ = strlen(teln); + while (*teln) + *p++ = (*teln++) & 0x7F; + } + + /* * What about info2? Mapping to High-Layer-Compatibility? */ - teln = pc->para.setup.phone; - if (*teln) { + if ((*teln) && (!send_keypad)) { /* parse number for special things */ if (!isdigit(*teln)) { switch (0x5f & *teln) { @@ -542,7 +1338,8 @@ case 'D': screen = 0x80; break; - default: + + default: if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "Wrong MSN Code"); break; @@ -558,11 +1355,11 @@ msn = pc->para.setup.eazmsn; sub = NULL; sp = msn; - while (*sp) { + while (*sp) { if ('.' == *sp) { sub = sp; *sp = 0; - } else + } else sp++; } if (*msn) { @@ -579,56 +1376,81 @@ } if (sub) { *sub++ = '.'; - *p++ = 0x6d; /* Calling party subaddress */ - *p++ = strlen(sub) + 2; + *p++ = 0x6d; /* Calling party subaddress */ + *p++ = strlen(sub) + 2; *p++ = 0x80; /* NSAP coded */ *p++ = 0x50; /* local IDI format */ - while (*sub) + while (*sub) *p++ = *sub++ & 0x7f; } sub = NULL; sp = teln; - while (*sp) { + while (*sp) { if ('.' == *sp) { sub = sp; *sp = 0; - } else + } else sp++; } - *p++ = 0x70; - *p++ = strlen(teln) + 1; - /* Classify as AnyPref. */ - *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */ - while (*teln) - *p++ = *teln++ & 0x7f; - - if (sub) { - *sub++ = '.'; - *p++ = 0x71; /* Called party subaddress */ - *p++ = strlen(sub) + 2; - *p++ = 0x80; /* NSAP coded */ - *p++ = 0x50; /* local IDI format */ - while (*sub) - *p++ = *sub++ & 0x7f; - } - -#ifdef EXT_BEARER_CAPS - if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175)) - { // sync. Bitratenadaption, V.110/X.30 - *p++ = 0x7c; *p++ = 0x04; *p++ = 0x88; *p++ = 0x90; *p++ = 0x21; - *p++ = EncodeSyncParams(pc->para.setup.si2 - 160, 0x80); - } - else if ((pc->para.setup.si2 >= 176) && (pc->para.setup.si2 <= 191)) - { // sync. Bitratenadaption, V.120 - *p++ = 0x7c; *p++ = 0x05; *p++ = 0x88; *p++ = 0x90; *p++ = 0x28; - *p++ = EncodeSyncParams(pc->para.setup.si2 - 176, 0); - *p++ = 0x82; - } - else if (pc->para.setup.si2 >= 192) - { // async. Bitratenadaption, V.110/X.30 - *p++ = 0x7c; *p++ = 0x06; *p++ = 0x88; *p++ = 0x90; *p++ = 0x21; - p = EncodeASyncParams(p, pc->para.setup.si2 - 192); + + if (!send_keypad) { + *p++ = 0x70; + *p++ = strlen(teln) + 1; + /* Classify as AnyPref. */ + *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */ + while (*teln) + *p++ = *teln++ & 0x7f; + + if (sub) { + *sub++ = '.'; + *p++ = 0x71; /* Called party subaddress */ + *p++ = strlen(sub) + 2; + *p++ = 0x80; /* NSAP coded */ + *p++ = 0x50; /* local IDI format */ + while (*sub) + *p++ = *sub++ & 0x7f; + } } +#if EXT_BEARER_CAPS + if (send_keypad) { /* special handling independant of si2 */ + *p++ = 0x7c; + *p++ = 0x03; + *p++ = 0x80; + *p++ = 0x90; + *p++ = 0xa3; + } else if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175)) { // sync. Bitratenadaption, V.110/X.30 + + *p++ = 0x7c; + *p++ = 0x04; + *p++ = 0x88; + *p++ = 0x90; + *p++ = 0x21; + *p++ = EncodeSyncParams(pc->para.setup.si2 - 160, 0x80); + } else if ((pc->para.setup.si2 >= 176) && (pc->para.setup.si2 <= 191)) { // sync. Bitratenadaption, V.120 + + *p++ = 0x7c; + *p++ = 0x05; + *p++ = 0x88; + *p++ = 0x90; + *p++ = 0x28; + *p++ = EncodeSyncParams(pc->para.setup.si2 - 176, 0); + *p++ = 0x82; + } else if (pc->para.setup.si2 >= 192) { // async. Bitratenadaption, V.110/X.30 + + *p++ = 0x7c; + *p++ = 0x06; + *p++ = 0x88; + *p++ = 0x90; + *p++ = 0x21; + p = EncodeASyncParams(p, pc->para.setup.si2 - 192); +#if HISAX_SEND_STD_LLC_IE + } else { + *p++ = 0x7c; + *p++ = 0x02; + *p++ = 0x88; + *p++ = 0x90; +#endif + } #endif l = p - tmp; if (!(skb = l3_alloc_skb(l))) @@ -637,227 +1459,276 @@ L3DelTimer(&pc->timer); L3AddTimer(&pc->timer, T303, CC_T303); newl3state(pc, 1); - pc->st->l3.l3l2(pc->st, DL_DATA, skb); + l3_msg(pc->st, DL_DATA | REQUEST, skb); } static void l3dss1_call_proc(struct l3_process *pc, u_char pr, void *arg) { - u_char *p; struct sk_buff *skb = arg; + int id, ret; + if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) { + if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) { + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "setup answer with wrong chid %x", id); + pc->para.cause = 100; + l3dss1_status_send(pc, pr, NULL); + return; + } + pc->para.bchannel = id; + } else if (1 == pc->state) { + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "setup answer without chid (ret %d)", id); + pc->para.cause = 96; + l3dss1_status_send(pc, pr, NULL); + return; + } + /* Now we are on none mandatory IEs */ + ret = check_infoelements(pc, skb, ie_CALL_PROCEEDING); + if (ERR_IE_COMPREHENSION == ret) { + l3dss1_std_ie_err(pc, ret); + return; + } L3DelTimer(&pc->timer); - p = skb->data; - if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) { - pc->para.bchannel = p[2] & 0x3; - if ((!pc->para.bchannel) && (pc->debug & L3_DEB_WARN)) - l3_debug(pc->st, "setup answer without bchannel"); - } else if (pc->debug & L3_DEB_WARN) - l3_debug(pc->st, "setup answer without bchannel"); - dev_kfree_skb(skb); newl3state(pc, 3); L3AddTimer(&pc->timer, T310, CC_T310); - pc->st->l3.l3l4(pc, CC_PROCEEDING_IND, NULL); + if (ret) /* STATUS for none mandatory IE errors after actions are taken */ + l3dss1_std_ie_err(pc, ret); + pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc); } static void l3dss1_setup_ack(struct l3_process *pc, u_char pr, void *arg) { - u_char *p; struct sk_buff *skb = arg; + int id, ret; + if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) { + if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) { + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "setup answer with wrong chid %x", id); + pc->para.cause = 100; + l3dss1_status_send(pc, pr, NULL); + return; + } + pc->para.bchannel = id; + } else { + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "setup answer without chid (ret %d)", id); + pc->para.cause = 96; + l3dss1_status_send(pc, pr, NULL); + return; + } + /* Now we are on none mandatory IEs */ + ret = check_infoelements(pc, skb, ie_SETUP_ACKNOWLEDGE); + if (ERR_IE_COMPREHENSION == ret) { + l3dss1_std_ie_err(pc, ret); + return; + } L3DelTimer(&pc->timer); - p = skb->data; - if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) { - pc->para.bchannel = p[2] & 0x3; - if ((!pc->para.bchannel) && (pc->debug & L3_DEB_WARN)) - l3_debug(pc->st, "setup answer without bchannel"); - } else if (pc->debug & L3_DEB_WARN) - l3_debug(pc->st, "setup answer without bchannel"); - dev_kfree_skb(skb); newl3state(pc, 2); L3AddTimer(&pc->timer, T304, CC_T304); - pc->st->l3.l3l4(pc, CC_MORE_INFO, NULL); + if (ret) /* STATUS for none mandatory IE errors after actions are taken */ + l3dss1_std_ie_err(pc, ret); + pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc); } static void l3dss1_disconnect(struct l3_process *pc, u_char pr, void *arg) { - u_char *p; struct sk_buff *skb = arg; - int cause = -1; + u_char *p; + int ret; + u_char cause = 0; StopAllL3Timer(pc); - p = skb->data; - pc->para.loc = 0; - if ((p = findie(p, skb->len, IE_CAUSE, 0))) { - p++; - if (*p++ == 2) - pc->para.loc = *p++; - cause = *p & 0x7f; - } - dev_kfree_skb(skb); + if ((ret = l3dss1_get_cause(pc, skb))) { + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "DISC get_cause ret(%d)", ret); + if (ret < 0) + cause = 96; + else if (ret > 0) + cause = 100; + } + if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) + l3dss1_parse_facility(pc->st, pc, pc->callref, p); + ret = check_infoelements(pc, skb, ie_DISCONNECT); + if (ERR_IE_COMPREHENSION == ret) + cause = 96; + else if ((!cause) && (ERR_IE_UNRECOGNIZED == ret)) + cause = 99; + ret = pc->state; newl3state(pc, 12); - pc->para.cause = cause; - pc->st->l3.l3l4(pc, CC_DISCONNECT_IND, NULL); + if (cause) + newl3state(pc, 19); + if (11 != ret) + pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc); + else if (!cause) + l3dss1_release_req(pc, pr, NULL); + if (cause) { + l3dss1_message_cause(pc, MT_RELEASE, cause); + L3AddTimer(&pc->timer, T308, CC_T308_1); + } } static void l3dss1_connect(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; + int ret; - dev_kfree_skb(skb); + ret = check_infoelements(pc, skb, ie_CONNECT); + if (ERR_IE_COMPREHENSION == ret) { + l3dss1_std_ie_err(pc, ret); + return; + } L3DelTimer(&pc->timer); /* T310 */ newl3state(pc, 10); pc->para.chargeinfo = 0; - pc->st->l3.l3l4(pc, CC_SETUP_CNF, NULL); + /* here should inserted COLP handling KKe */ + if (ret) + l3dss1_std_ie_err(pc, ret); + pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc); } static void l3dss1_alerting(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; + int ret; - dev_kfree_skb(skb); + ret = check_infoelements(pc, skb, ie_ALERTING); + if (ERR_IE_COMPREHENSION == ret) { + l3dss1_std_ie_err(pc, ret); + return; + } L3DelTimer(&pc->timer); /* T304 */ newl3state(pc, 4); - pc->st->l3.l3l4(pc, CC_ALERTING_IND, NULL); -} - -static void -l3dss1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg) -{ - /* This routine is called if here was no SETUP made (checks in dss1up and in - * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code - * It is called after it is veryfied that Layer2 is up. - * The cause value is allready in pc->para.cause - * MT_STATUS_ENQUIRE in the NULL state is handled too - */ - u_char tmp[16]; - u_char *p=tmp; - int l; - struct sk_buff *skb; - - switch (pc->para.cause) { - case 81: /* 0x51 invalid callreference */ - case 96: /* 0x60 mandory IE missing */ - case 101: /* 0x65 incompatible Callstate */ - MsgHead(p, pc->callref, MT_RELEASE_COMPLETE); - *p++ = IE_CAUSE; - *p++ = 0x2; - *p++ = 0x80; - *p++ = pc->para.cause | 0x80; - break; - default: - printk(KERN_ERR "HiSax internal error l3dss1_msg_without_setup\n"); - return; - } - l = p - tmp; - if (!(skb = l3_alloc_skb(l))) - return; - memcpy(skb_put(skb, l), tmp, l); - pc->st->l3.l3l2(pc->st, DL_DATA, skb); - release_l3_process(pc); + if (ret) + l3dss1_std_ie_err(pc, ret); + pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc); } static void l3dss1_setup(struct l3_process *pc, u_char pr, void *arg) { - u_char *p, *ptmp[8]; - int i; + u_char *p; int bcfound = 0; char tmp[80]; struct sk_buff *skb = arg; - - /* ETS 300-104 1.3.4 and 1.3.5 - * we need to detect unknown inform. element from 0 to 7 - */ - p = skb->data; - for(i = 0; i < 8; i++) - ptmp[i] = skb->data; - if (findie(ptmp[1], skb->len, 0x01, 0) - || findie(ptmp[2], skb->len, 0x02, 0) - || findie(ptmp[3], skb->len, 0x03, 0) - || findie(ptmp[5], skb->len, 0x05, 0) - || findie(ptmp[6], skb->len, 0x06, 0) - || findie(ptmp[7], skb->len, 0x07, 0)) { - /* if ie is < 8 and not 0 nor 4, send RELEASE_COMPLETE - * cause 0x60 - */ - pc->para.cause = 0x60; - dev_kfree_skb(skb); - if (pc->state == 0) - pc->st->l3.l3l4(pc, CC_ESTABLISH, NULL); - else - l3dss1_msg_without_setup(pc, pr, NULL); - return; - } - - /* - * Channel Identification - */ - p = skb->data; - if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) { - pc->para.bchannel = p[2] & 0x3; - if (pc->para.bchannel) - bcfound++; - else if (pc->debug & L3_DEB_WARN) - l3_debug(pc->st, "setup without bchannel"); - } else if (pc->debug & L3_DEB_WARN) - l3_debug(pc->st, "setup without bchannel"); + int id; + int err = 0; /* - * Bearer Capabilities + * Bearer Capabilities */ p = skb->data; + /* only the first occurence 'll be detected ! */ if ((p = findie(p, skb->len, 0x04, 0))) { - pc->para.setup.si2 = 0; - switch (p[2] & 0x1f) { - case 0x00: - /* Speech */ - case 0x10: - /* 3.1 Khz audio */ - pc->para.setup.si1 = 1; - break; - case 0x08: - /* Unrestricted digital information */ - pc->para.setup.si1 = 7; + if ((p[1] < 2) || (p[1] > 11)) + err = 1; + else { + pc->para.setup.si2 = 0; + switch (p[2] & 0x7f) { + case 0x00: /* Speech */ + case 0x10: /* 3.1 Khz audio */ + pc->para.setup.si1 = 1; + break; + case 0x08: /* Unrestricted digital information */ + pc->para.setup.si1 = 7; /* JIM, 05.11.97 I wanna set service indicator 2 */ -#ifdef EXT_BEARER_CAPS - pc->para.setup.si2 = DecodeSI2(skb); - printk(KERN_DEBUG "HiSax: SI=%d, AI=%d\n", - pc->para.setup.si1, pc->para.setup.si2); +#if EXT_BEARER_CAPS + pc->para.setup.si2 = DecodeSI2(skb); + if (pc->debug & L3_DEB_SI) + l3_debug(pc->st, "SI=%d, AI=%d", + pc->para.setup.si1, + pc->para.setup.si2); #endif - break; - case 0x09: - /* Restricted digital information */ - pc->para.setup.si1 = 2; - break; - case 0x11: - /* Unrestr. digital information with tones/announcements */ - pc->para.setup.si1 = 3; - break; - case 0x18: - /* Video */ - pc->para.setup.si1 = 4; - break; - default: - pc->para.setup.si1 = 0; + break; + case 0x09: /* Restricted digital information */ + pc->para.setup.si1 = 2; + break; + case 0x11: + /* Unrestr. digital information with + * tones/announcements ( or 7 kHz audio + */ + pc->para.setup.si1 = 3; + break; + case 0x18: /* Video */ + pc->para.setup.si1 = 4; + break; + default: + err = 2; + break; + } + switch (p[3] & 0x7f) { + case 0x40: /* packed mode */ + break; + case 0x10: /* 64 kbit */ + case 0x11: /* 2*64 kbit */ + case 0x13: /* 384 kbit */ + case 0x15: /* 1536 kbit */ + case 0x17: /* 1920 kbit */ + pc->para.moderate = p[3] & 0x7f; + break; + default: + err = 3; + break; + } + } + if (err) { + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "setup with wrong bearer(l=%d:%x,%x)", + p[1], p[2], p[3]); + pc->para.cause = 100; + l3dss1_msg_without_setup(pc, pr, NULL); + return; } } else { if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup without bearer capabilities"); /* ETS 300-104 1.3.3 */ - pc->para.cause = 0x60; - dev_kfree_skb(skb); - if (pc->state == 0) - pc->st->l3.l3l4(pc, CC_ESTABLISH, NULL); - else - l3dss1_msg_without_setup(pc, pr, NULL); + pc->para.cause = 96; + l3dss1_msg_without_setup(pc, pr, NULL); return; } - + /* + * Channel Identification + */ + if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) { + if ((pc->para.bchannel = id)) { + if ((3 == id) && (0x10 == pc->para.moderate)) { + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "setup with wrong chid %x", + id); + pc->para.cause = 100; + l3dss1_msg_without_setup(pc, pr, NULL); + return; + } + bcfound++; + } else + { if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "setup without bchannel, call waiting"); + bcfound++; + } + } else { + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "setup with wrong chid ret %d", id); + pc->para.cause = 96; + l3dss1_msg_without_setup(pc, pr, NULL); + return; + } + /* Now we are on none mandatory IEs */ +#if 1 +/* !!!!!! this check seems to be a problem ? info bugfix to Karsten */ + err = check_infoelements(pc, skb, ie_SETUP); + if (ERR_IE_COMPREHENSION == err) { + pc->para.cause = 96; + l3dss1_msg_without_setup(pc, pr, NULL); + return; + } +#endif p = skb->data; if ((p = findie(p, skb->len, 0x70, 0))) iecpy(pc->para.setup.eazmsn, p, 1); @@ -867,8 +1738,8 @@ p = skb->data; if ((p = findie(p, skb->len, 0x71, 0))) { /* Called party subaddress */ - if ((p[1]>=2) && (p[2]==0x80) && (p[3]==0x50)) { - tmp[0]='.'; + if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) { + tmp[0] = '.'; iecpy(&tmp[1], p, 2); strcat(pc->para.setup.eazmsn, tmp); } else if (pc->debug & L3_DEB_WARN) @@ -892,65 +1763,54 @@ p = skb->data; if ((p = findie(p, skb->len, 0x6d, 0))) { /* Calling party subaddress */ - if ((p[1]>=2) && (p[2]==0x80) && (p[3]==0x50)) { - tmp[0]='.'; + if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) { + tmp[0] = '.'; iecpy(&tmp[1], p, 2); strcat(pc->para.setup.phone, tmp); } else if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "wrong calling subaddress"); } - dev_kfree_skb(skb); - +#if 0 if (bcfound) { if ((pc->para.setup.si1 != 7) && (pc->debug & L3_DEB_WARN)) { - sprintf(tmp, "non-digital call: %s -> %s", - pc->para.setup.phone, pc->para.setup.eazmsn); - l3_debug(pc->st, tmp); + l3_debug(pc->st, "non-digital call: %s -> %s", + pc->para.setup.phone, pc->para.setup.eazmsn); + } + if ((pc->para.setup.si1 != 7) && + test_bit(FLG_PTP, &pc->st->l2.flag)) { + pc->para.cause = 88; /* incompatible destination */ + l3dss1_msg_without_setup(pc, pr, NULL); + return; } newl3state(pc, 6); - pc->st->l3.l3l4(pc, CC_SETUP_IND, NULL); + pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc); } else - release_l3_process(pc); + dss1_release_l3_process(pc); +#else + newl3state(pc, 6); + if (err) /* STATUS for none mandatory IE errors after actions are taken */ + l3dss1_std_ie_err(pc, err); + pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc); +#endif } static void l3dss1_reset(struct l3_process *pc, u_char pr, void *arg) { - release_l3_process(pc); -} - -static void -l3dss1_setup_rsp(struct l3_process *pc, u_char pr, - void *arg) -{ - newl3state(pc, 8); - l3dss1_message(pc, MT_CONNECT); - L3DelTimer(&pc->timer); - L3AddTimer(&pc->timer, T313, CC_T313); -} - -static void -l3dss1_connect_ack(struct l3_process *pc, u_char pr, void *arg) -{ - struct sk_buff *skb = arg; - - dev_kfree_skb(skb); - newl3state(pc, 10); - L3DelTimer(&pc->timer); - pc->st->l3.l3l4(pc, CC_SETUP_COMPLETE_IND, NULL); + dss1_release_l3_process(pc); } static void l3dss1_disconnect_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u_char tmp[16]; + u_char tmp[16+40]; u_char *p = tmp; int l; - u_char cause = 0x10; + u_char cause = 16; - if (pc->para.cause > 0) + if (pc->para.cause != NO_CAUSE) cause = pc->para.cause; StopAllL3Timer(pc); @@ -962,25 +1822,68 @@ *p++ = 0x80; *p++ = cause | 0x80; + if (pc->prot.dss1.uus1_data[0]) + { *p++ = IE_USER_USER; /* UUS info element */ + *p++ = strlen(pc->prot.dss1.uus1_data) + 1; + *p++ = 0x04; /* IA5 chars */ + strcpy(p,pc->prot.dss1.uus1_data); + p += strlen(pc->prot.dss1.uus1_data); + pc->prot.dss1.uus1_data[0] = '\0'; + } + l = p - tmp; if (!(skb = l3_alloc_skb(l))) return; memcpy(skb_put(skb, l), tmp, l); newl3state(pc, 11); - pc->st->l3.l3l2(pc->st, DL_DATA, skb); + l3_msg(pc->st, DL_DATA | REQUEST, skb); L3AddTimer(&pc->timer, T305, CC_T305); } static void +l3dss1_setup_rsp(struct l3_process *pc, u_char pr, + void *arg) +{ + if (!pc->para.bchannel) + { if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "D-chan connect for waiting call"); + l3dss1_disconnect_req(pc, pr, arg); + return; + } + newl3state(pc, 8); + l3dss1_message(pc, MT_CONNECT); + L3DelTimer(&pc->timer); + L3AddTimer(&pc->timer, T313, CC_T313); +} + +static void +l3dss1_connect_ack(struct l3_process *pc, u_char pr, void *arg) +{ + struct sk_buff *skb = arg; + int ret; + + ret = check_infoelements(pc, skb, ie_CONNECT_ACKNOWLEDGE); + if (ERR_IE_COMPREHENSION == ret) { + l3dss1_std_ie_err(pc, ret); + return; + } + newl3state(pc, 10); + L3DelTimer(&pc->timer); + if (ret) + l3dss1_std_ie_err(pc, ret); + pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc); +} + +static void l3dss1_reject_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; u_char tmp[16]; u_char *p = tmp; int l; - u_char cause = 0x95; + u_char cause = 21; - if (pc->para.cause > 0) + if (pc->para.cause != NO_CAUSE) cause = pc->para.cause; MsgHead(p, pc->callref, MT_RELEASE_COMPLETE); @@ -988,47 +1891,50 @@ *p++ = IE_CAUSE; *p++ = 0x2; *p++ = 0x80; - *p++ = cause; + *p++ = cause | 0x80; l = p - tmp; if (!(skb = l3_alloc_skb(l))) return; memcpy(skb_put(skb, l), tmp, l); - pc->st->l3.l3l2(pc->st, DL_DATA, skb); - pc->st->l3.l3l4(pc, CC_RELEASE_IND, NULL); + l3_msg(pc->st, DL_DATA | REQUEST, skb); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); - release_l3_process(pc); + dss1_release_l3_process(pc); } static void l3dss1_release(struct l3_process *pc, u_char pr, void *arg) { - u_char *p; struct sk_buff *skb = arg; - int cause = -1; + u_char *p; + int ret, cause=0; - p = skb->data; - if ((p = findie(p, skb->len, IE_CAUSE, 0))) { - p++; - if (*p++ == 2) - pc->para.loc = *p++; - cause = *p & 0x7f; - } - p = skb->data; - if ((p = findie(p, skb->len, IE_FACILITY, 0))) { -#ifdef HISAX_DE_AOC - l3dss1_parse_facility(pc,p); -#else - p = NULL; -#endif - } - dev_kfree_skb(skb); StopAllL3Timer(pc); - pc->para.cause = cause; - l3dss1_message(pc, MT_RELEASE_COMPLETE); - pc->st->l3.l3l4(pc, CC_RELEASE_IND, NULL); + if ((ret = l3dss1_get_cause(pc, skb))>0) { + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "REL get_cause ret(%d)", ret); + } else if (ret<0) + pc->para.cause = NO_CAUSE; + if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) { + l3dss1_parse_facility(pc->st, pc, pc->callref, p); + } + if ((ret<0) && (pc->state != 11)) + cause = 96; + else if (ret>0) + cause = 100; + ret = check_infoelements(pc, skb, ie_RELEASE); + if (ERR_IE_COMPREHENSION == ret) + cause = 96; + else if ((ERR_IE_UNRECOGNIZED == ret) && (!cause)) + cause = 99; + if (cause) + l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, cause); + else + l3dss1_message(pc, MT_RELEASE_COMPLETE); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); - release_l3_process(pc); + dss1_release_l3_process(pc); } static void @@ -1036,66 +1942,350 @@ void *arg) { newl3state(pc, 7); - l3dss1_message(pc, MT_ALERTING); + if (!pc->prot.dss1.uus1_data[0]) + l3dss1_message(pc, MT_ALERTING); + else + l3dss1_msg_with_uus(pc, MT_ALERTING); +} + +static void +l3dss1_proceed_req(struct l3_process *pc, u_char pr, + void *arg) +{ + newl3state(pc, 9); + l3dss1_message(pc, MT_CALL_PROCEEDING); + pc->st->l3.l3l4(pc->st, CC_PROCEED_SEND | INDICATION, pc); +} + +/********************************************/ +/* deliver a incoming display message to HL */ +/********************************************/ +static void +l3dss1_deliver_display(struct l3_process *pc, int pr, u_char *infp) +{ u_char len; + isdn_ctrl ic; + struct IsdnCardState *cs; + char *p; + + if (*infp++ != IE_DISPLAY) return; + if ((len = *infp++) > 80) return; /* total length <= 82 */ + if (!pc->chan) return; + + p = ic.parm.display; + while (len--) + *p++ = *infp++; + *p = '\0'; + ic.command = ISDN_STAT_DISPLAY; + cs = pc->st->l1.hardware; + ic.driver = cs->myid; + ic.arg = pc->chan->chan; + cs->iif.statcallb(&ic); +} /* l3dss1_deliver_display */ + + +static void +l3dss1_progress(struct l3_process *pc, u_char pr, void *arg) +{ + struct sk_buff *skb = arg; + int err = 0; + u_char *p; + + if ((p = findie(skb->data, skb->len, IE_PROGRESS, 0))) { + if (p[1] != 4) { + err = 1; + pc->para.cause = 100; + } else if (p[2] & 0x60) { + switch (p[2]) { + case 0x80: + case 0x81: + case 0x82: + case 0x84: + case 0x85: + case 0x87: + case 0x8a: + switch (p[3]) { + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x88: + break; + default: + err = 2; + pc->para.cause = 100; + break; + } + break; + default: + err = 3; + pc->para.cause = 100; + break; + } + } + } else { + pc->para.cause = 96; + err = 4; + } + if (err) { + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "progress error %d", err); + l3dss1_status_send(pc, pr, NULL); + return; + } + /* Now we are on none mandatory IEs */ + err = check_infoelements(pc, skb, ie_PROGRESS); + if (err) + l3dss1_std_ie_err(pc, err); + if (ERR_IE_COMPREHENSION != err) + pc->st->l3.l3l4(pc->st, CC_PROGRESS | INDICATION, pc); +} + +static void +l3dss1_notify(struct l3_process *pc, u_char pr, void *arg) +{ + struct sk_buff *skb = arg; + int err = 0; + u_char *p; + + if ((p = findie(skb->data, skb->len, IE_NOTIFY, 0))) { + if (p[1] != 1) { + err = 1; + pc->para.cause = 100; + } else { + switch (p[2]) { + case 0x80: + case 0x81: + case 0x82: + break; + default: + pc->para.cause = 100; + err = 2; + break; + } + } + } else { + pc->para.cause = 96; + err = 3; + } + if (err) { + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "notify error %d", err); + l3dss1_status_send(pc, pr, NULL); + return; + } + /* Now we are on none mandatory IEs */ + err = check_infoelements(pc, skb, ie_NOTIFY); + if (err) + l3dss1_std_ie_err(pc, err); + if (ERR_IE_COMPREHENSION != err) + pc->st->l3.l3l4(pc->st, CC_NOTIFY | INDICATION, pc); } static void l3dss1_status_enq(struct l3_process *pc, u_char pr, void *arg) { - u_char tmp[16]; - u_char *p = tmp; - int l; + int ret; struct sk_buff *skb = arg; - dev_kfree_skb(skb); - - MsgHead(p, pc->callref, MT_STATUS); - - *p++ = IE_CAUSE; - *p++ = 0x2; - *p++ = 0x80; - *p++ = 0x9E; /* answer status enquire */ + ret = check_infoelements(pc, skb, ie_STATUS_ENQUIRY); + l3dss1_std_ie_err(pc, ret); - *p++ = 0x14; /* CallState */ - *p++ = 0x1; - *p++ = pc->state & 0x3f; + idev_kfree_skb(skb, FREE_READ); - l = p - tmp; - if (!(skb = l3_alloc_skb(l))) - return; - memcpy(skb_put(skb, l), tmp, l); - pc->st->l3.l3l2(pc->st, DL_DATA, skb); + l3dss1_status_send(pc, 0x1E, NULL); /* answer status enquire */ } -static void -l3dss1_status_req(struct l3_process *pc, u_char pr, void *arg) +/******************************/ +/* handle deflection requests */ +/******************************/ +static void l3dss1_redir_req(struct l3_process *pc, u_char pr, void *arg) { - /* ETS 300-104 7.4.1, 8.4.1, 10.3.1, 11.4.1, 12.4.1, 13.4.1, 14.4.1... - if setup has been made and a non expected message type is received, we must send MT_STATUS cause 0x62 */ - u_char tmp[16]; + struct sk_buff *skb; + u_char tmp[128]; u_char *p = tmp; - int l; - struct sk_buff *skb = arg; + u_char *subp; + u_char len_phone = 0; + u_char len_sub = 0; + int l; + + + strcpy(pc->prot.dss1.uus1_data,pc->chan->setup.eazmsn); /* copy uus element if available */ + if (!pc->chan->setup.phone[0]) + { pc->para.cause = -1; + l3dss1_disconnect_req(pc,pr,arg); /* disconnect immediately */ + return; + } /* only uus */ + + if (pc->prot.dss1.invoke_id) + free_invoke_id(pc->st,pc->prot.dss1.invoke_id); + + if (!(pc->prot.dss1.invoke_id = new_invoke_id(pc->st))) + return; + + MsgHead(p, pc->callref, MT_FACILITY); + + for (subp = pc->chan->setup.phone; (*subp) && (*subp != '.'); subp++) len_phone++; /* len of phone number */ + if (*subp++ == '.') len_sub = strlen(subp) + 2; /* length including info subadress element */ + + *p++ = 0x1c; /* Facility info element */ + *p++ = len_phone + len_sub + 2 + 2 + 8 + 3 + 3; /* length of element */ + *p++ = 0x91; /* remote operations protocol */ + *p++ = 0xa1; /* invoke component */ + + *p++ = len_phone + len_sub + 2 + 2 + 8 + 3; /* length of data */ + *p++ = 0x02; /* invoke id tag, integer */ + *p++ = 0x01; /* length */ + *p++ = pc->prot.dss1.invoke_id; /* invoke id */ + *p++ = 0x02; /* operation value tag, integer */ + *p++ = 0x01; /* length */ + *p++ = 0x0D; /* Call Deflect */ + + *p++ = 0x30; /* sequence phone number */ + *p++ = len_phone + 2 + 2 + 3 + len_sub; /* length */ + + *p++ = 0x30; /* Deflected to UserNumber */ + *p++ = len_phone+2+len_sub; /* length */ + *p++ = 0x80; /* NumberDigits */ + *p++ = len_phone; /* length */ + for (l = 0; l < len_phone; l++) + *p++ = pc->chan->setup.phone[l]; + + if (len_sub) + { *p++ = 0x04; /* called party subadress */ + *p++ = len_sub - 2; + while (*subp) *p++ = *subp++; + } - dev_kfree_skb(skb); + *p++ = 0x01; /* screening identifier */ + *p++ = 0x01; + *p++ = pc->chan->setup.screen; - MsgHead(p, pc->callref, MT_STATUS); + l = p - tmp; + if (!(skb = l3_alloc_skb(l))) return; + memcpy(skb_put(skb, l), tmp, l); - *p++ = IE_CAUSE; - *p++ = 0x2; - *p++ = 0x80; - *p++ = 0x62 | 0x80; /* status sending */ + l3_msg(pc->st, DL_DATA | REQUEST, skb); +} /* l3dss1_redir_req */ - *p++ = 0x14; /* CallState */ - *p++ = 0x1; - *p++ = pc->state & 0x3f; +/********************************************/ +/* handle deflection request in early state */ +/********************************************/ +static void l3dss1_redir_req_early(struct l3_process *pc, u_char pr, void *arg) +{ + l3dss1_proceed_req(pc,pr,arg); + l3dss1_redir_req(pc,pr,arg); +} /* l3dss1_redir_req_early */ + +/***********************************************/ +/* handle special commands for this protocol. */ +/* Examples are call independant services like */ +/* remote operations with dummy callref. */ +/***********************************************/ +static int l3dss1_cmd_global(struct PStack *st, isdn_ctrl *ic) +{ u_char id; + u_char temp[265]; + u_char *p = temp; + int i, l, proc_len; + struct sk_buff *skb; + struct l3_process *pc = NULL; + + switch (ic->arg) + { case DSS1_CMD_INVOKE: + if (ic->parm.dss1_io.datalen < 0) return(-2); /* invalid parameter */ + + for (proc_len = 1, i = ic->parm.dss1_io.proc >> 8; i; i++) + i = i >> 8; /* add one byte */ + l = ic->parm.dss1_io.datalen + proc_len + 8; /* length excluding ie header */ + if (l > 255) + return(-2); /* too long */ + + if (!(id = new_invoke_id(st))) + return(0); /* first get a invoke id -> return if no available */ + + i = -1; + MsgHead(p, i, MT_FACILITY); /* build message head */ + *p++ = 0x1C; /* Facility IE */ + *p++ = l; /* length of ie */ + *p++ = 0x91; /* remote operations */ + *p++ = 0xA1; /* invoke */ + *p++ = l - 3; /* length of invoke */ + *p++ = 0x02; /* invoke id tag */ + *p++ = 0x01; /* length is 1 */ + *p++ = id; /* invoke id */ + *p++ = 0x02; /* operation */ + *p++ = proc_len; /* length of operation */ + + for (i = proc_len; i; i--) + *p++ = (ic->parm.dss1_io.proc >> (i-1)) & 0xFF; + memcpy(p, ic->parm.dss1_io.data, ic->parm.dss1_io.datalen); /* copy data */ + l = (p - temp) + ic->parm.dss1_io.datalen; /* total length */ + + if (ic->parm.dss1_io.timeout > 0) + if (!(pc = dss1_new_l3_process(st, -1))) + { free_invoke_id(st, id); + return(-2); + } + pc->prot.dss1.ll_id = ic->parm.dss1_io.ll_id; /* remember id */ + pc->prot.dss1.proc = ic->parm.dss1_io.proc; /* and procedure */ + + if (!(skb = l3_alloc_skb(l))) + { free_invoke_id(st, id); + if (pc) dss1_release_l3_process(pc); + return(-2); + } + memcpy(skb_put(skb, l), temp, l); + + if (pc) + { pc->prot.dss1.invoke_id = id; /* remember id */ + L3AddTimer(&pc->timer, ic->parm.dss1_io.timeout, CC_TDSS1_IO | REQUEST); + } + + l3_msg(st, DL_DATA | REQUEST, skb); + ic->parm.dss1_io.hl_id = id; /* return id */ + return(0); + + case DSS1_CMD_INVOKE_ABORT: + if ((pc = l3dss1_search_dummy_proc(st, ic->parm.dss1_io.hl_id))) + { L3DelTimer(&pc->timer); /* remove timer */ + dss1_release_l3_process(pc); + return(0); + } + else + { l3_debug(st, "l3dss1_cmd_global abort unknown id"); + return(-2); + } + break; + + default: + l3_debug(st, "l3dss1_cmd_global unknown cmd 0x%lx", ic->arg); + return(-1); + } /* switch ic-> arg */ + return(-1); +} /* l3dss1_cmd_global */ + +static void +l3dss1_io_timer(struct l3_process *pc) +{ isdn_ctrl ic; + struct IsdnCardState *cs = pc->st->l1.hardware; + + L3DelTimer(&pc->timer); /* remove timer */ + + ic.driver = cs->myid; + ic.command = ISDN_STAT_PROT; + ic.arg = DSS1_STAT_INVOKE_ERR; + ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id; + ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id; + ic.parm.dss1_io.proc = pc->prot.dss1.proc; + ic.parm.dss1_io.timeout= -1; + ic.parm.dss1_io.datalen = 0; + ic.parm.dss1_io.data = NULL; + free_invoke_id(pc->st, pc->prot.dss1.invoke_id); + pc->prot.dss1.invoke_id = 0; /* reset id */ - l = p - tmp; - if (!(skb = l3_alloc_skb(l))) - return; - memcpy(skb_put(skb, l), tmp, l); - pc->st->l3.l3l2(pc->st, DL_DATA, skb); -} + cs->iif.statcallb(&ic); + + dss1_release_l3_process(pc); +} /* l3dss1_io_timer */ static void l3dss1_release_ind(struct l3_process *pc, u_char pr, void *arg) @@ -1107,22 +2297,27 @@ if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) { p++; - if (1== *p++) + if (1 == *p++) callState = *p; } - if(callState == 0) { + if (callState == 0) { /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1 * set down layer 3 without sending any message */ - pc->st->l3.l3l4(pc, CC_RELEASE_IND, NULL); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); - release_l3_process(pc); + dss1_release_l3_process(pc); } else { - pc->st->l3.l3l4(pc, CC_IGNORE, NULL); + pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc); } } static void +l3dss1_dummy(struct l3_process *pc, u_char pr, void *arg) +{ +} + +static void l3dss1_t303(struct l3_process *pc, u_char pr, void *arg) { if (pc->N303 > 0) { @@ -1131,8 +2326,8 @@ l3dss1_setup_req(pc, pr, arg); } else { L3DelTimer(&pc->timer); - pc->st->l3.l3l4(pc, CC_NOSETUP_RSP_ERR, NULL); - release_l3_process(pc); + pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc); + dss1_release_l3_process(pc); } } @@ -1140,9 +2335,9 @@ l3dss1_t304(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); - pc->para.cause = 0xE6; + pc->para.cause = 102; l3dss1_disconnect_req(pc, pr, NULL); - pc->st->l3.l3l4(pc, CC_SETUP_ERR, NULL); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } @@ -1153,25 +2348,25 @@ u_char *p = tmp; int l; struct sk_buff *skb; - u_char cause = 0x90; + u_char cause = 16; L3DelTimer(&pc->timer); - if (pc->para.cause > 0) - cause = pc->para.cause | 0x80; + if (pc->para.cause != NO_CAUSE) + cause = pc->para.cause; MsgHead(p, pc->callref, MT_RELEASE); *p++ = IE_CAUSE; *p++ = 0x2; *p++ = 0x80; - *p++ = cause; + *p++ = cause | 0x80; l = p - tmp; if (!(skb = l3_alloc_skb(l))) return; memcpy(skb_put(skb, l), tmp, l); newl3state(pc, 19); - pc->st->l3.l3l2(pc->st, DL_DATA, skb); + l3_msg(pc->st, DL_DATA | REQUEST, skb); L3AddTimer(&pc->timer, T308, CC_T308_1); } @@ -1179,18 +2374,18 @@ l3dss1_t310(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); - pc->para.cause = 0xE6; + pc->para.cause = 102; l3dss1_disconnect_req(pc, pr, NULL); - pc->st->l3.l3l4(pc, CC_SETUP_ERR, NULL); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void l3dss1_t313(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); - pc->para.cause = 0xE6; + pc->para.cause = 102; l3dss1_disconnect_req(pc, pr, NULL); - pc->st->l3.l3l4(pc, CC_CONNECT_ERR, NULL); + pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc); } static void @@ -1206,118 +2401,315 @@ l3dss1_t308_2(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); - pc->st->l3.l3l4(pc, CC_RELEASE_ERR, NULL); - release_l3_process(pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc); + dss1_release_l3_process(pc); +} + +static void +l3dss1_t318(struct l3_process *pc, u_char pr, void *arg) +{ + L3DelTimer(&pc->timer); + pc->para.cause = 102; /* Timer expiry */ + pc->para.loc = 0; /* local */ + pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc); + newl3state(pc, 19); + l3dss1_message(pc, MT_RELEASE); + L3AddTimer(&pc->timer, T308, CC_T308_1); +} + +static void +l3dss1_t319(struct l3_process *pc, u_char pr, void *arg) +{ + L3DelTimer(&pc->timer); + pc->para.cause = 102; /* Timer expiry */ + pc->para.loc = 0; /* local */ + pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc); + newl3state(pc, 10); } static void l3dss1_restart(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); - pc->st->l3.l3l4(pc, CC_DLRL, NULL); - release_l3_process(pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); + dss1_release_l3_process(pc); } static void l3dss1_status(struct l3_process *pc, u_char pr, void *arg) { u_char *p; - char tmp[64], *t; - int l; struct sk_buff *skb = arg; - int cause, callState; - - cause = callState = -1; - p = skb->data; - t = tmp; - if ((p = findie(p, skb->len, IE_CAUSE, 0))) { + int ret; + u_char cause = 0, callState = 0; + + if ((ret = l3dss1_get_cause(pc, skb))) { + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "STATUS get_cause ret(%d)",ret); + if (ret < 0) + cause = 96; + else if (ret > 0) + cause = 100; + } + if ((p = findie(skb->data, skb->len, IE_CALL_STATE, 0))) { p++; - l = *p++; - t += sprintf(t,"Status CR %x Cause:", pc->callref); - while (l--) { - cause = *p; - t += sprintf(t," %2x",*p++); - } + if (1 == *p++) { + callState = *p; + if (!ie_in_set(pc, *p, l3_valid_states)) + cause = 100; + } else + cause = 100; } else - sprintf(t,"Status CR %x no Cause", pc->callref); - l3_debug(pc->st, tmp); - p = skb->data; - t = tmp; - t += sprintf(t,"Status state %x ", pc->state); - if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) { - p++; - if (1== *p++) { - callState = *p; - t += sprintf(t,"peer state %x" , *p); - } + cause = 96; + if (!cause) { /* no error before */ + ret = check_infoelements(pc, skb, ie_STATUS); + if (ERR_IE_COMPREHENSION == ret) + cause = 96; + else if (ERR_IE_UNRECOGNIZED == ret) + cause = 99; + } + if (cause) { + u_char tmp; + + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "STATUS error(%d/%d)",ret,cause); + tmp = pc->para.cause; + pc->para.cause = cause; + l3dss1_status_send(pc, 0, NULL); + if (cause == 99) + pc->para.cause = tmp; else - t += sprintf(t,"peer state len error"); - } else - sprintf(t,"no peer state"); - l3_debug(pc->st, tmp); - if(((cause & 0x7f) == 0x6f) && (callState == 0)) { - /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... - * if received MT_STATUS with cause == 0x6f and call + return; + } + cause = pc->para.cause; + if (((cause & 0x7f) == 111) && (callState == 0)) { + /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... + * if received MT_STATUS with cause == 111 and call * state == 0, then we must set down layer 3 */ - l3dss1_release_ind(pc, pr, arg); - } else - dev_kfree_skb(skb); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); + newl3state(pc, 0); + dss1_release_l3_process(pc); + } } static void l3dss1_facility(struct l3_process *pc, u_char pr, void *arg) { - u_char *p; struct sk_buff *skb = arg; + int ret; + + ret = check_infoelements(pc, skb, ie_FACILITY); + l3dss1_std_ie_err(pc, ret); + { + u_char *p; + if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) + l3dss1_parse_facility(pc->st, pc, pc->callref, p); + } +} - p = skb->data; - if ((p = findie(p, skb->len, IE_FACILITY, 0))) { -#ifdef HISAX_DE_AOC - l3dss1_parse_facility(pc,p); -#else - p = NULL; -#endif +static void +l3dss1_suspend_req(struct l3_process *pc, u_char pr, void *arg) +{ + struct sk_buff *skb; + u_char tmp[32]; + u_char *p = tmp; + u_char i, l; + u_char *msg = pc->chan->setup.phone; + + MsgHead(p, pc->callref, MT_SUSPEND); + + *p++ = IE_CALL_ID; + l = *msg++; + if (l && (l <= 10)) { /* Max length 10 octets */ + *p++ = l; + for (i = 0; i < l; i++) + *p++ = *msg++; + } else { + l3_debug(pc->st, "SUS wrong CALL_ID len %d", l); + return; } + l = p - tmp; + if (!(skb = l3_alloc_skb(l))) + return; + memcpy(skb_put(skb, l), tmp, l); + l3_msg(pc->st, DL_DATA | REQUEST, skb); + newl3state(pc, 15); + L3AddTimer(&pc->timer, T319, CC_T319); } +static void +l3dss1_suspend_ack(struct l3_process *pc, u_char pr, void *arg) +{ + struct sk_buff *skb = arg; + int ret; + + L3DelTimer(&pc->timer); + newl3state(pc, 0); + pc->para.cause = NO_CAUSE; + pc->st->l3.l3l4(pc->st, CC_SUSPEND | CONFIRM, pc); + /* We don't handle suspend_ack for IE errors now */ + if ((ret = check_infoelements(pc, skb, ie_SUSPEND_ACKNOWLEDGE))) + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "SUSPACK check ie(%d)",ret); + dss1_release_l3_process(pc); +} + +static void +l3dss1_suspend_rej(struct l3_process *pc, u_char pr, void *arg) +{ + struct sk_buff *skb = arg; + int ret; + + if ((ret = l3dss1_get_cause(pc, skb))) { + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "SUSP_REJ get_cause ret(%d)",ret); + if (ret < 0) + pc->para.cause = 96; + else + pc->para.cause = 100; + l3dss1_status_send(pc, pr, NULL); + return; + } + ret = check_infoelements(pc, skb, ie_SUSPEND_REJECT); + if (ERR_IE_COMPREHENSION == ret) { + l3dss1_std_ie_err(pc, ret); + return; + } + L3DelTimer(&pc->timer); + pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc); + newl3state(pc, 10); + if (ret) /* STATUS for none mandatory IE errors after actions are taken */ + l3dss1_std_ie_err(pc, ret); +} + +static void +l3dss1_resume_req(struct l3_process *pc, u_char pr, void *arg) +{ + struct sk_buff *skb; + u_char tmp[32]; + u_char *p = tmp; + u_char i, l; + u_char *msg = pc->para.setup.phone; + + MsgHead(p, pc->callref, MT_RESUME); + + *p++ = IE_CALL_ID; + l = *msg++; + if (l && (l <= 10)) { /* Max length 10 octets */ + *p++ = l; + for (i = 0; i < l; i++) + *p++ = *msg++; + } else { + l3_debug(pc->st, "RES wrong CALL_ID len %d", l); + return; + } + l = p - tmp; + if (!(skb = l3_alloc_skb(l))) + return; + memcpy(skb_put(skb, l), tmp, l); + l3_msg(pc->st, DL_DATA | REQUEST, skb); + newl3state(pc, 17); + L3AddTimer(&pc->timer, T319, CC_T319); +} + +static void +l3dss1_resume_ack(struct l3_process *pc, u_char pr, void *arg) +{ + struct sk_buff *skb = arg; + int id, ret; + + if ((id = l3dss1_get_channel_id(pc, skb)) > 0) { + if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) { + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "resume ack with wrong chid %x", id); + pc->para.cause = 100; + l3dss1_status_send(pc, pr, NULL); + return; + } + pc->para.bchannel = id; + } else if (1 == pc->state) { + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "resume ack without chid (ret %d)", id); + pc->para.cause = 96; + l3dss1_status_send(pc, pr, NULL); + return; + } + ret = check_infoelements(pc, skb, ie_RESUME_ACKNOWLEDGE); + if (ERR_IE_COMPREHENSION == ret) { + l3dss1_std_ie_err(pc, ret); + return; + } + L3DelTimer(&pc->timer); + pc->st->l3.l3l4(pc->st, CC_RESUME | CONFIRM, pc); + newl3state(pc, 10); + if (ret) /* STATUS for none mandatory IE errors after actions are taken */ + l3dss1_std_ie_err(pc, ret); +} + +static void +l3dss1_resume_rej(struct l3_process *pc, u_char pr, void *arg) +{ + struct sk_buff *skb = arg; + int ret; + + if ((ret = l3dss1_get_cause(pc, skb))) { + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "RES_REJ get_cause ret(%d)",ret); + if (ret < 0) + pc->para.cause = 96; + else + pc->para.cause = 100; + l3dss1_status_send(pc, pr, NULL); + return; + } + ret = check_infoelements(pc, skb, ie_RESUME_REJECT); + if (ERR_IE_COMPREHENSION == ret) { + l3dss1_std_ie_err(pc, ret); + return; + } + L3DelTimer(&pc->timer); + pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc); + newl3state(pc, 0); + if (ret) /* STATUS for none mandatory IE errors after actions are taken */ + l3dss1_std_ie_err(pc, ret); + dss1_release_l3_process(pc); +} - static void l3dss1_global_restart(struct l3_process *pc, u_char pr, void *arg) { u_char tmp[32]; u_char *p; - u_char ri, chan=0; + u_char ri, ch = 0, chan = 0; int l; struct sk_buff *skb = arg; struct l3_process *up; - + newl3state(pc, 2); L3DelTimer(&pc->timer); p = skb->data; if ((p = findie(p, skb->len, IE_RESTART_IND, 0))) { - ri = p[2]; - sprintf(tmp, "Restart %x", ri); + ri = p[2]; + l3_debug(pc->st, "Restart %x", ri); } else { - sprintf(tmp, "Restart without restart IE"); + l3_debug(pc->st, "Restart without restart IE"); ri = 0x86; } - l3_debug(pc->st, tmp); p = skb->data; if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) { chan = p[2] & 3; - sprintf(tmp, "Restart for channel %d", chan); - l3_debug(pc->st, tmp); + ch = p[2]; + if (pc->st->l3.debug) + l3_debug(pc->st, "Restart for channel %d", chan); } - dev_kfree_skb(skb); newl3state(pc, 2); up = pc->st->l3.proc; while (up) { - if ((ri & 7)==7) - up->st->lli.l4l3(up->st, CC_RESTART, up); + if ((ri & 7) == 7) + up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up); else if (up->para.bchannel == chan) - up->st->lli.l4l3(up->st, CC_RESTART, up); + up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up); up = up->next; } p = tmp; @@ -1325,9 +2717,9 @@ if (chan) { *p++ = IE_CHANNEL_ID; *p++ = 1; - *p++ = chan | 0x80; + *p++ = ch | 0x80; } - *p++ = 0x79; /* RESTART Ind */ + *p++ = 0x79; /* RESTART Ind */ *p++ = 1; *p++ = ri; l = p - tmp; @@ -1335,32 +2727,75 @@ return; memcpy(skb_put(skb, l), tmp, l); newl3state(pc, 0); - pc->st->l3.l3l2(pc->st, DL_DATA, skb); + l3_msg(pc->st, DL_DATA | REQUEST, skb); +} + +static void +l3dss1_dl_reset(struct l3_process *pc, u_char pr, void *arg) +{ + pc->para.cause = 0x29; /* Temporary failure */ + l3dss1_disconnect_req(pc, pr, NULL); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); +} + +static void +l3dss1_dl_release(struct l3_process *pc, u_char pr, void *arg) +{ + newl3state(pc, 0); + pc->para.cause = 0x1b; /* Destination out of order */ + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); + release_l3_process(pc); +} + +static void +l3dss1_dl_reestablish(struct l3_process *pc, u_char pr, void *arg) +{ + L3DelTimer(&pc->timer); + L3AddTimer(&pc->timer, T309, CC_T309); + l3_msg(pc->st, DL_ESTABLISH | REQUEST, NULL); +} + +static void +l3dss1_dl_reest_status(struct l3_process *pc, u_char pr, void *arg) +{ + L3DelTimer(&pc->timer); + + l3dss1_status_send(pc, 0x1F, NULL); /* normal, unspecified */ } /* *INDENT-OFF* */ static struct stateentry downstatelist[] = { {SBIT(0), - CC_ESTABLISH, l3dss1_msg_without_setup}, + CC_SETUP | REQUEST, l3dss1_setup_req}, {SBIT(0), - CC_SETUP_REQ, l3dss1_setup_req}, - {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) | SBIT(10), - CC_DISCONNECT_REQ, l3dss1_disconnect_req}, + CC_RESUME | REQUEST, l3dss1_resume_req}, + {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10), + CC_DISCONNECT | REQUEST, l3dss1_disconnect_req}, {SBIT(12), - CC_RELEASE_REQ, l3dss1_release_req}, + CC_RELEASE | REQUEST, l3dss1_release_req}, {ALL_STATES, - CC_DLRL, l3dss1_reset}, - {ALL_STATES, - CC_RESTART, l3dss1_restart}, + CC_RESTART | REQUEST, l3dss1_restart}, {SBIT(6), - CC_IGNORE, l3dss1_reset}, + CC_IGNORE | REQUEST, l3dss1_reset}, {SBIT(6), - CC_REJECT_REQ, l3dss1_reject_req}, + CC_REJECT | REQUEST, l3dss1_reject_req}, {SBIT(6), - CC_ALERTING_REQ, l3dss1_alert_req}, - {SBIT(6) | SBIT(7), - CC_SETUP_RSP, l3dss1_setup_rsp}, + CC_PROCEED_SEND | REQUEST, l3dss1_proceed_req}, + {SBIT(6) | SBIT(9), + CC_ALERTING | REQUEST, l3dss1_alert_req}, + {SBIT(6) | SBIT(7) | SBIT(9), + CC_SETUP | RESPONSE, l3dss1_setup_rsp}, + {SBIT(10), + CC_SUSPEND | REQUEST, l3dss1_suspend_req}, + {SBIT(6), + CC_PROCEED_SEND | REQUEST, l3dss1_proceed_req}, + {SBIT(7) | SBIT(9), + CC_REDIR | REQUEST, l3dss1_redir_req}, + {SBIT(6), + CC_REDIR | REQUEST, l3dss1_redir_req_early}, + {SBIT(9) | SBIT(25), + CC_DISCONNECT | REQUEST, l3dss1_disconnect_req}, {SBIT(1), CC_T303, l3dss1_t303}, {SBIT(2), @@ -1371,14 +2806,20 @@ CC_T313, l3dss1_t313}, {SBIT(11), CC_T305, l3dss1_t305}, + {SBIT(15), + CC_T319, l3dss1_t319}, + {SBIT(17), + CC_T318, l3dss1_t318}, {SBIT(19), CC_T308_1, l3dss1_t308_1}, {SBIT(19), CC_T308_2, l3dss1_t308_2}, + {SBIT(10), + CC_T309, l3dss1_dl_release}, }; -static int downsllen = sizeof(downstatelist) / -sizeof(struct stateentry); +#define DOWNSLLEN \ + (sizeof(downstatelist) / sizeof(struct stateentry)) static struct stateentry datastatelist[] = { @@ -1394,90 +2835,109 @@ MT_SETUP, l3dss1_setup}, {SBIT(1) | SBIT(2), MT_CALL_PROCEEDING, l3dss1_call_proc}, - {SBIT(3) | SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19), - MT_CALL_PROCEEDING, l3dss1_status_req}, {SBIT(1), MT_SETUP_ACKNOWLEDGE, l3dss1_setup_ack}, - {SBIT(2) | SBIT(3) | SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19), - MT_SETUP_ACKNOWLEDGE, l3dss1_status_req}, - {SBIT(1) | SBIT(2) | SBIT(3), + {SBIT(2) | SBIT(3), MT_ALERTING, l3dss1_alerting}, - {SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19), - MT_ALERTING, l3dss1_status_req}, + {SBIT(2) | SBIT(3), + MT_PROGRESS, l3dss1_progress}, + {SBIT(10) | SBIT(11) | SBIT(15), + MT_NOTIFY, l3dss1_notify}, {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19), MT_RELEASE_COMPLETE, l3dss1_release_cmpl}, - {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) | - SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) /*| SBIT(19)*/, + {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) /* | SBIT(17) | SBIT(19)*/, MT_RELEASE, l3dss1_release}, {SBIT(19), MT_RELEASE, l3dss1_release_ind}, - {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10), + {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(15), MT_DISCONNECT, l3dss1_disconnect}, - {SBIT(11), - MT_DISCONNECT, l3dss1_release_req}, +// {SBIT(11), +// MT_DISCONNECT, l3dss1_release_req}, + {SBIT(19), + MT_DISCONNECT, l3dss1_dummy}, {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4), MT_CONNECT, l3dss1_connect}, - {SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19), - MT_CONNECT, l3dss1_status_req}, - {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(11) | SBIT(19), - MT_CONNECT_ACKNOWLEDGE, l3dss1_status_req}, {SBIT(8), MT_CONNECT_ACKNOWLEDGE, l3dss1_connect_ack}, - {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19), - MT_INVALID, l3dss1_status_req}, + {SBIT(15), + MT_SUSPEND_ACKNOWLEDGE, l3dss1_suspend_ack}, + {SBIT(15), + MT_SUSPEND_REJECT, l3dss1_suspend_rej}, + {SBIT(17), + MT_RESUME_ACKNOWLEDGE, l3dss1_resume_ack}, + {SBIT(17), + MT_RESUME_REJECT, l3dss1_resume_rej}, }; -static int datasllen = sizeof(datastatelist) / sizeof(struct stateentry); +#define DATASLLEN \ + (sizeof(datastatelist) / sizeof(struct stateentry)) static struct stateentry globalmes_list[] = { {ALL_STATES, - MT_STATUS, l3dss1_status}, + MT_STATUS, l3dss1_status}, {SBIT(0), MT_RESTART, l3dss1_global_restart}, /* {SBIT(1), - MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack}, + MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack}, */ }; -static int globalm_len = sizeof(globalmes_list) / sizeof(struct stateentry); +#define GLOBALM_LEN \ + (sizeof(globalmes_list) / sizeof(struct stateentry)) -#if 0 -static struct stateentry globalcmd_list[] = +static struct stateentry manstatelist[] = { - {ALL_STATES, - CC_STATUS, l3dss1_status_req}, - {SBIT(0), - CC_RESTART, l3dss1_restart_req}, + {SBIT(2), + DL_ESTABLISH | INDICATION, l3dss1_dl_reset}, + {SBIT(10), + DL_ESTABLISH | CONFIRM, l3dss1_dl_reest_status}, + {SBIT(10), + DL_RELEASE | INDICATION, l3dss1_dl_reestablish}, + {ALL_STATES, + DL_RELEASE | INDICATION, l3dss1_dl_release}, }; -static int globalc_len = sizeof(globalcmd_list) / sizeof(struct stateentry); -#endif +#define MANSLLEN \ + (sizeof(manstatelist) / sizeof(struct stateentry)) /* *INDENT-ON* */ + static void global_handler(struct PStack *st, int mt, struct sk_buff *skb) { + u_char tmp[16]; + u_char *p = tmp; + int l; int i; - char tmp[64]; struct l3_process *proc = st->l3.global; - - for (i = 0; i < globalm_len; i++) + + proc->callref = skb->data[2]; /* cr flag */ + for (i = 0; i < GLOBALM_LEN; i++) if ((mt == globalmes_list[i].primitive) && ((1 << proc->state) & globalmes_list[i].state)) break; - if (i == globalm_len) { - dev_kfree_skb(skb); + if (i == GLOBALM_LEN) { if (st->l3.debug & L3_DEB_STATE) { - sprintf(tmp, "dss1 global state %d mt %x unhandled", + l3_debug(st, "dss1 global state %d mt %x unhandled", proc->state, mt); - l3_debug(st, tmp); } - return; + MsgHead(p, proc->callref, MT_STATUS); + *p++ = IE_CAUSE; + *p++ = 0x2; + *p++ = 0x80; + *p++ = 81 |0x80; /* invalid cr */ + *p++ = 0x14; /* CallState */ + *p++ = 0x1; + *p++ = proc->state & 0x3f; + l = p - tmp; + if (!(skb = l3_alloc_skb(l))) + return; + memcpy(skb_put(skb, l), tmp, l); + l3_msg(proc->st, DL_DATA | REQUEST, skb); } else { if (st->l3.debug & L3_DEB_STATE) { - sprintf(tmp, "dss1 global %d mt %x", + l3_debug(st, "dss1 global %d mt %x", proc->state, mt); - l3_debug(st, tmp); } globalmes_list[i].rout(proc, mt, skb); } @@ -1488,124 +2948,166 @@ { int i, mt, cr, cause, callState; char *ptr; + u_char *p; struct sk_buff *skb = arg; struct l3_process *proc; - char tmp[80]; + + switch (pr) { + case (DL_DATA | INDICATION): + case (DL_UNIT_DATA | INDICATION): + break; + case (DL_ESTABLISH | CONFIRM): + case (DL_ESTABLISH | INDICATION): + case (DL_RELEASE | INDICATION): + case (DL_RELEASE | CONFIRM): + l3_msg(st, pr, arg); + return; + break; + default: + printk(KERN_ERR "HiSax dss1up unknown pr=%04x\n", pr); + return; + } + if (skb->len < 3) { + l3_debug(st, "dss1up frame too short(%d)", skb->len); + idev_kfree_skb(skb, FREE_READ); + return; + } if (skb->data[0] != PROTO_DIS_EURO) { if (st->l3.debug & L3_DEB_PROTERR) { - sprintf(tmp, "dss1up%sunexpected discriminator %x message len %d", - (pr == DL_DATA) ? " " : "(broadcast) ", - skb->data[0], skb->len); - l3_debug(st, tmp); + l3_debug(st, "dss1up%sunexpected discriminator %x message len %d", + (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", + skb->data[0], skb->len); } - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); return; } cr = getcallref(skb->data); + if (skb->len < ((skb->data[1] & 0x0f) + 3)) { + l3_debug(st, "dss1up frame too short(%d)", skb->len); + idev_kfree_skb(skb, FREE_READ); + return; + } mt = skb->data[skb->data[1] + 2]; - if (!cr) { /* Global CallRef */ + if (st->l3.debug & L3_DEB_STATE) + l3_debug(st, "dss1up cr %d", cr); + if (cr == -2) { /* wrong Callref */ + if (st->l3.debug & L3_DEB_WARN) + l3_debug(st, "dss1up wrong Callref"); + idev_kfree_skb(skb, FREE_READ); + return; + } else if (cr == -1) { /* Dummy Callref */ + if (mt == MT_FACILITY) + if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) { + l3dss1_parse_facility(st, NULL, + (pr == (DL_DATA | INDICATION)) ? -1 : -2, p); + idev_kfree_skb(skb, FREE_READ); + return; + } + if (st->l3.debug & L3_DEB_WARN) + l3_debug(st, "dss1up dummy Callref (no facility msg or ie)"); + idev_kfree_skb(skb, FREE_READ); + return; + } else if ((((skb->data[1] & 0x0f) == 1) && (0==(cr & 0x7f))) || + (((skb->data[1] & 0x0f) == 2) && (0==(cr & 0x7fff)))) { /* Global CallRef */ + if (st->l3.debug & L3_DEB_STATE) + l3_debug(st, "dss1up Global CallRef"); global_handler(st, mt, skb); - return; - } else if (cr == -1) { /* Dummy Callref */ - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); return; } else if (!(proc = getl3proc(st, cr))) { /* No transaction process exist, that means no call with * this callreference is active */ if (mt == MT_SETUP) { - /* Setup creates a new transaction process */ - if (!(proc = new_l3_process(st, cr))) { + /* Setup creates a new transaction process */ + if (!(proc = dss1_new_l3_process(st, cr))) { /* May be to answer with RELEASE_COMPLETE and * CAUSE 0x2f "Resource unavailable", but this * need a new_l3_process too ... arghh */ - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); return; } } else if (mt == MT_STATUS) { cause = 0; - if((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) { - ptr++; - if (*ptr++ == 2) - ptr++; - cause = *ptr & 0x7f; + if ((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) { + ptr++; + if (*ptr++ == 2) + ptr++; + cause = *ptr & 0x7f; } callState = 0; - if((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) { + if ((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) { ptr++; if (*ptr++ == 2) ptr++; callState = *ptr; } - if (callState == 0) { - /* ETS 300-104 part 2.4.1 - * if setup has not been made and a message type - * MT_STATUS is received with call state == 0, - * we must send nothing - */ - dev_kfree_skb(skb); - return; - } else { + /* ETS 300-104 part 2.4.1 + * if setup has not been made and a message type + * MT_STATUS is received with call state == 0, + * we must send nothing + */ + if (callState != 0) { /* ETS 300-104 part 2.4.2 - * if setup has not been made and a message type + * if setup has not been made and a message type * MT_STATUS is received with call state != 0, * we must send MT_RELEASE_COMPLETE cause 101 */ - dev_kfree_skb(skb); - if ((proc = new_l3_process(st, cr))) { - proc->para.cause = 0x65; /* 101 */ - proc->st->l3.l3l4(proc, CC_ESTABLISH, NULL); + if ((proc = dss1_new_l3_process(st, cr))) { + proc->para.cause = 101; + l3dss1_msg_without_setup(proc, 0, NULL); } - return; } - } else if (mt == MT_RELEASE_COMPLETE){ - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); + return; + } else if (mt == MT_RELEASE_COMPLETE) { + idev_kfree_skb(skb, FREE_READ); return; } else { /* ETS 300-104 part 2 - * if setup has not been made and a message type + * if setup has not been made and a message type * (except MT_SETUP and RELEASE_COMPLETE) is received, * we must send MT_RELEASE_COMPLETE cause 81 */ - dev_kfree_skb(skb); - if ((proc = new_l3_process(st, cr))) { - proc->para.cause = 0x51; /* 81 */ - proc->st->l3.l3l4(proc, CC_ESTABLISH, NULL); + idev_kfree_skb(skb, FREE_READ); + if ((proc = dss1_new_l3_process(st, cr))) { + proc->para.cause = 81; + l3dss1_msg_without_setup(proc, 0, NULL); } return; } - } else if (!l3dss1_check_messagetype_validity(mt)) { - /* ETS 300-104 7.4.2, 8.4.2, 10.3.2, 11.4.2, 12.4.2, 13.4.2, - * 14.4.2... - * if setup has been made and invalid message type is received, - * we must send MT_STATUS cause 0x62 - */ - mt = MT_INVALID; /* sorry, not clean, but do the right thing ;-) */ } - - for (i = 0; i < datasllen; i++) + if (l3dss1_check_messagetype_validity(proc, mt, skb)) { + idev_kfree_skb(skb, FREE_READ); + return; + } + if ((p = findie(skb->data, skb->len, IE_DISPLAY, 0)) != NULL) + l3dss1_deliver_display(proc, pr, p); /* Display IE included */ + for (i = 0; i < DATASLLEN; i++) if ((mt == datastatelist[i].primitive) && ((1 << proc->state) & datastatelist[i].state)) break; - if (i == datasllen) { - dev_kfree_skb(skb); + if (i == DATASLLEN) { if (st->l3.debug & L3_DEB_STATE) { - sprintf(tmp, "dss1up%sstate %d mt %x unhandled", - (pr == DL_DATA) ? " " : "(broadcast) ", + l3_debug(st, "dss1up%sstate %d mt %#x unhandled", + (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", proc->state, mt); - l3_debug(st, tmp); } - return; + if ((MT_RELEASE_COMPLETE != mt) && (MT_RELEASE != mt)) { + proc->para.cause = 101; + l3dss1_status_send(proc, pr, skb); + } } else { if (st->l3.debug & L3_DEB_STATE) { - sprintf(tmp, "dss1up%sstate %d mt %x", - (pr == DL_DATA) ? " " : "(broadcast) ", + l3_debug(st, "dss1up%sstate %d mt %x", + (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", proc->state, mt); - l3_debug(st, tmp); } datastatelist[i].rout(proc, pr, skb); } + idev_kfree_skb(skb, FREE_READ); + return; } static void @@ -1614,13 +3116,15 @@ int i, cr; struct l3_process *proc; struct Channel *chan; - char tmp[80]; - if (CC_SETUP_REQ == pr) { + if ((DL_ESTABLISH | REQUEST) == pr) { + l3_msg(st, pr, NULL); + return; + } else if (((CC_SETUP | REQUEST) == pr) || ((CC_RESUME | REQUEST) == pr)) { chan = arg; cr = newcallref(); cr |= 0x80; - if ((proc = new_l3_process(st, cr))) { + if ((proc = dss1_new_l3_process(st, cr))) { proc->chan = chan; chan->proc = proc; proc->para.setup = chan->setup; @@ -1630,37 +3134,78 @@ proc = arg; } if (!proc) { - printk(KERN_ERR "HiSax internal error dss1down without proc\n"); + printk(KERN_ERR "HiSax dss1down without proc pr=%04x\n", pr); return; } - for (i = 0; i < downsllen; i++) + + if ( pr == (CC_TDSS1_IO | REQUEST)) { + l3dss1_io_timer(proc); /* timer expires */ + return; + } + + for (i = 0; i < DOWNSLLEN; i++) if ((pr == downstatelist[i].primitive) && ((1 << proc->state) & downstatelist[i].state)) break; - if (i == downsllen) { + if (i == DOWNSLLEN) { if (st->l3.debug & L3_DEB_STATE) { - sprintf(tmp, "dss1down state %d prim %d unhandled", + l3_debug(st, "dss1down state %d prim %#x unhandled", proc->state, pr); - l3_debug(st, tmp); } } else { if (st->l3.debug & L3_DEB_STATE) { - sprintf(tmp, "dss1down state %d prim %d", + l3_debug(st, "dss1down state %d prim %#x", proc->state, pr); - l3_debug(st, tmp); } downstatelist[i].rout(proc, pr, arg); } } +static void +dss1man(struct PStack *st, int pr, void *arg) +{ + int i; + struct l3_process *proc = arg; + + if (!proc) { + printk(KERN_ERR "HiSax dss1man without proc pr=%04x\n", pr); + return; + } + for (i = 0; i < MANSLLEN; i++) + if ((pr == manstatelist[i].primitive) && + ((1 << proc->state) & manstatelist[i].state)) + break; + if (i == MANSLLEN) { + if (st->l3.debug & L3_DEB_STATE) { + l3_debug(st, "cr %d dss1man state %d prim %#x unhandled", + proc->callref & 0x7f, proc->state, pr); + } + } else { + if (st->l3.debug & L3_DEB_STATE) { + l3_debug(st, "cr %d dss1man state %d prim %#x", + proc->callref & 0x7f, proc->state, pr); + } + manstatelist[i].rout(proc, pr, arg); + } +} + void setstack_dss1(struct PStack *st) { char tmp[64]; + int i; st->lli.l4l3 = dss1down; + st->lli.l4l3_proto = l3dss1_cmd_global; st->l2.l2l3 = dss1up; + st->l3.l3ml3 = dss1man; st->l3.N303 = 1; + st->prot.dss1.last_invoke_id = 0; + st->prot.dss1.invoke_used[0] = 1; /* Bit 0 must always be set to 1 */ + i = 1; + while (i < 32) + st->prot.dss1.invoke_used[i++] = 0; + if (!(st->l3.global = kmalloc(sizeof(struct l3_process), GFP_ATOMIC))) { printk(KERN_ERR "HiSax can't get memory for dss1 global CR\n"); } else { @@ -1670,8 +3215,15 @@ st->l3.global->debug = L3_DEB_WARN; st->l3.global->st = st; st->l3.global->N303 = 1; + st->l3.global->prot.dss1.invoke_id = 0; + L3InitTimer(st->l3.global, &st->l3.global->timer); } strcpy(tmp, dss1_revision); printk(KERN_INFO "HiSax: DSS1 Rev. %s\n", HiSax_getrev(tmp)); } + + + + + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/l3dss1.h linux.pre11.3/drivers/isdn/hisax/l3dss1.h --- linux.vanilla/drivers/isdn/hisax/l3dss1.h Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/hisax/l3dss1.h Mon Jul 19 23:59:34 1999 @@ -1,8 +1,15 @@ -/* $Id: l3dss1.h,v 1.5 1998/02/02 13:34:30 keil Exp $ +/* $Id: l3dss1.h,v 1.7 1999/07/01 08:12:02 keil Exp $ * * DSS1 (Euro) D-channel protocol defines * * $Log: l3dss1.h,v $ + * Revision 1.7 1999/07/01 08:12:02 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 1.6 1998/03/19 13:18:50 keil + * Start of a CAPI like interface for supplementary Service + * first service: SUSPEND + * * Revision 1.5 1998/02/02 13:34:30 keil * Support australian Microlink net and german AOCD * @@ -21,10 +28,14 @@ * * */ + +#ifndef l3dss1_process + #define T303 4000 #define T304 30000 #define T305 30000 #define T308 4000 +#define T309 40000 #define T310 30000 #define T313 4000 #define T318 4000 @@ -34,38 +45,99 @@ * Message-Types */ -#define MT_ALERTING 0x01 -#define MT_CALL_PROCEEDING 0x02 -#define MT_CONNECT 0x07 -#define MT_CONNECT_ACKNOWLEDGE 0x0f -#define MT_PROGRESS 0x03 -#define MT_SETUP 0x05 -#define MT_SETUP_ACKNOWLEDGE 0x0d -#define MT_RESUME 0x26 -#define MT_RESUME_ACKNOWLEDGE 0x2e -#define MT_RESUME_REJECT 0x22 -#define MT_SUSPEND 0x25 -#define MT_SUSPEND_ACKNOWLEDGE 0x2d -#define MT_SUSPEND_REJECT 0x21 -#define MT_USER_INFORMATION 0x20 -#define MT_DISCONNECT 0x45 -#define MT_RELEASE 0x4d -#define MT_RELEASE_COMPLETE 0x5a -#define MT_RESTART 0x46 -#define MT_RESTART_ACKNOWLEDGE 0x4e -#define MT_SEGMENT 0x60 -#define MT_CONGESTION_CONTROL 0x79 -#define MT_INFORMATION 0x7b -#define MT_FACILITY 0x62 -#define MT_NOTIFY 0x6e -#define MT_STATUS 0x7d -#define MT_STATUS_ENQUIRY 0x75 - -#define MT_INVALID 0xff - -#define IE_CAUSE 0x08 -#define IE_BEARER 0x04 -#define IE_FACILITY 0x1c -#define IE_CALL_STATE 0x14 -#define IE_CHANNEL_ID 0x18 -#define IE_RESTART_IND 0x79 +#define MT_ALERTING 0x01 +#define MT_CALL_PROCEEDING 0x02 +#define MT_CONNECT 0x07 +#define MT_CONNECT_ACKNOWLEDGE 0x0f +#define MT_PROGRESS 0x03 +#define MT_SETUP 0x05 +#define MT_SETUP_ACKNOWLEDGE 0x0d +#define MT_RESUME 0x26 +#define MT_RESUME_ACKNOWLEDGE 0x2e +#define MT_RESUME_REJECT 0x22 +#define MT_SUSPEND 0x25 +#define MT_SUSPEND_ACKNOWLEDGE 0x2d +#define MT_SUSPEND_REJECT 0x21 +#define MT_USER_INFORMATION 0x20 +#define MT_DISCONNECT 0x45 +#define MT_RELEASE 0x4d +#define MT_RELEASE_COMPLETE 0x5a +#define MT_RESTART 0x46 +#define MT_RESTART_ACKNOWLEDGE 0x4e +#define MT_SEGMENT 0x60 +#define MT_CONGESTION_CONTROL 0x79 +#define MT_INFORMATION 0x7b +#define MT_FACILITY 0x62 +#define MT_NOTIFY 0x6e +#define MT_STATUS 0x7d +#define MT_STATUS_ENQUIRY 0x75 + +#define IE_SEGMENT 0x00 +#define IE_BEARER 0x04 +#define IE_CAUSE 0x08 +#define IE_CALL_ID 0x10 +#define IE_CALL_STATE 0x14 +#define IE_CHANNEL_ID 0x18 +#define IE_FACILITY 0x1c +#define IE_PROGRESS 0x1e +#define IE_NET_FAC 0x20 +#define IE_NOTIFY 0x27 +#define IE_DISPLAY 0x28 +#define IE_DATE 0x29 +#define IE_KEYPAD 0x2c +#define IE_SIGNAL 0x34 +#define IE_INFORATE 0x40 +#define IE_E2E_TDELAY 0x42 +#define IE_TDELAY_SEL 0x43 +#define IE_PACK_BINPARA 0x44 +#define IE_PACK_WINSIZE 0x45 +#define IE_PACK_SIZE 0x46 +#define IE_CUG 0x47 +#define IE_REV_CHARGE 0x4a +#define IE_CONNECT_PN 0x4c +#define IE_CONNECT_SUB 0x4d +#define IE_CALLING_PN 0x6c +#define IE_CALLING_SUB 0x6d +#define IE_CALLED_PN 0x70 +#define IE_CALLED_SUB 0x71 +#define IE_REDIR_NR 0x74 +#define IE_TRANS_SEL 0x78 +#define IE_RESTART_IND 0x79 +#define IE_LLC 0x7c +#define IE_HLC 0x7d +#define IE_USER_USER 0x7e +#define IE_ESCAPE 0x7f +#define IE_SHIFT 0x90 +#define IE_MORE_DATA 0xa0 +#define IE_COMPLETE 0xa1 +#define IE_CONGESTION 0xb0 +#define IE_REPEAT 0xd0 + +#define IE_MANDATORY 0x0100 +/* mandatory not in every case */ +#define IE_MANDATORY_1 0x0200 + +#define ERR_IE_COMPREHENSION 1 +#define ERR_IE_UNRECOGNIZED -1 +#define ERR_IE_LENGTH -2 +#define ERR_IE_SEQUENCE -3 + +#else /* only l3dss1_process */ + +/* l3dss1 specific data in l3 process */ +typedef struct + { unsigned char invoke_id; /* used invoke id in remote ops, 0 = not active */ + ulong ll_id; /* remebered ll id */ + u_char remote_operation; /* handled remote operation, 0 = not active */ + int proc; /* rememered procedure */ + ulong remote_result; /* result of remote operation for statcallb */ + char uus1_data[35]; /* data send during alerting or disconnect */ + } dss1_proc_priv; + +/* l3dss1 specific data in protocol stack */ +typedef struct + { unsigned char last_invoke_id; /* last used value for invoking */ + unsigned char invoke_used[32]; /* 256 bits for 256 values */ + } dss1_stk_priv; + +#endif /* only l3dss1_process */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/lmgr.c linux.pre11.3/drivers/isdn/hisax/lmgr.c --- linux.vanilla/drivers/isdn/hisax/lmgr.c Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/hisax/lmgr.c Mon Jul 19 23:59:34 1999 @@ -1,11 +1,24 @@ -/* $Id: lmgr.c,v 1.2 1997/10/29 19:09:34 keil Exp $ +/* $Id: lmgr.c,v 1.6 1999/07/01 08:12:04 keil Exp $ - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) * * * Layermanagement module * * $Log: lmgr.c,v $ + * Revision 1.6 1999/07/01 08:12:04 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 1.5 1998/11/15 23:55:12 keil + * changes from 2.0 + * + * Revision 1.4 1998/05/25 12:58:19 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * + * Revision 1.3 1998/03/07 22:57:06 tsbogend + * made HiSax working on Linux/Alpha + * * Revision 1.2 1997/10/29 19:09:34 keil * new L1 * @@ -26,7 +39,7 @@ case 'D': case 'G': case 'H': - st->l2.l2tei(st, MDL_ERROR_REQ, NULL); + st->l2.l2tei(st, MDL_ERROR | REQUEST, NULL); break; } } @@ -34,17 +47,15 @@ static void hisax_manager(struct PStack *st, int pr, void *arg) { - char tm[32], str[256]; - int Code; + long Code; switch (pr) { - case MDL_ERROR_IND: - Code = (int) arg; - jiftime(tm, jiffies); - sprintf(str, "%s manager: MDL_ERROR %c %s\n", tm, - Code, test_bit(FLG_LAPD, &st->l2.flag) ? + case (MDL_ERROR | INDICATION): + Code = (long) arg; + HiSax_putstatus(st->l1.hardware, "manager: MDL_ERROR", + " %c %s", (char)Code, + test_bit(FLG_LAPD, &st->l2.flag) ? "D-channel" : "B-channel"); - HiSax_putstatus(st->l1.hardware, str); if (test_bit(FLG_LAPD, &st->l2.flag)) error_handling_dchan(st, Code); break; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/md5sums.asc linux.pre11.3/drivers/isdn/hisax/md5sums.asc --- linux.vanilla/drivers/isdn/hisax/md5sums.asc Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/md5sums.asc Mon Jul 19 23:59:34 1999 @@ -0,0 +1,29 @@ +-----BEGIN PGP SIGNED MESSAGE----- + +# This are valid md5sums for certificated HiSax driver. +# The certification is valid only if the md5sums of all files match. +# The certification is valid only for ELSA QuickStep cards in the moment. +# Read ../../../Documentation/isdn/HiSax.cert for more informations. +# +7b86f7c9709d1a96f2591b76db297116 isac.c +773fb8b13e20ef92c0bc991fea23c673 isdnl1.c +f2ef2bc94883f818d0beb184688786bc isdnl2.c +c7b9992f966c645e0eea548b0d3655a0 isdnl3.c +df3c2d2bc312af0689ed97a1fe7ad2df tei.c +94facb2403188ddfb6b83a890a5e7fa0 callc.c +f3ec2a634f06074d16167aaba02b6dc1 cert.c +e69680e894417b00949473ce38259e2a l3dss1.c +04082bae9726b7c34adb008d3752ac73 l3_1tr6.c +6705bf924beeb147d80dc91fa0aa25ee elsa.c +# end of md5sums + +-----BEGIN PGP SIGNATURE----- +Version: 2.6.3i +Charset: noconv + +iQCVAwUBN3FBezpxHvX/mS9tAQGs9wQAk4pSCWvx5CMheSRedQ7nTtIoVQKPiAEx +6/0DWE5hu5IsSOG4ZbLG/ISdad4OOZjWfMpeeIwsHVGVSspGvo9lpIMOS9EqEvr8 +I+kCrPQwKaEN675U2m0ofsELAPOyH2JICjKdbW+iipWI+6oqGta7aw/tbgDqykVr +vz2L4uxmgUY= +=r0Yz +-----END PGP SIGNATURE----- diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/mic.c linux.pre11.3/drivers/isdn/hisax/mic.c --- linux.vanilla/drivers/isdn/hisax/mic.c Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/hisax/mic.c Mon Jul 19 23:59:34 1999 @@ -1,4 +1,4 @@ -/* $Id: mic.c,v 1.6 1998/02/17 15:39:57 keil Exp $ +/* $Id: mic.c,v 1.8 1999/07/12 21:05:20 keil Exp $ * mic.c low level stuff for mic cards * @@ -8,6 +8,13 @@ * * * $Log: mic.c,v $ + * Revision 1.8 1999/07/12 21:05:20 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 1.7 1998/04/15 16:44:32 keil + * new init code + * * Revision 1.6 1998/02/17 15:39:57 keil * fix reset problem * @@ -37,7 +44,7 @@ extern const char *CardType[]; -const char *mic_revision = "$Revision: 1.6 $"; +const char *mic_revision = "$Revision: 1.8 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -155,7 +162,7 @@ mic_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u_char val, stat = 0; + u_char val; if (!cs) { printk(KERN_WARNING "mic: Spurious interrupt!\n"); @@ -163,16 +170,12 @@ } val = readreg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_ISTA + 0x40); Start_HSCX: - if (val) { + if (val) hscx_int_main(cs, val); - stat |= 1; - } val = readreg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_ISTA); Start_ISAC: - if (val) { + if (val) isac_interrupt(cs, val); - stat |= 2; - } val = readreg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_ISTA + 0x40); if (val) { if (cs->debug & L1_DEB_HSCX) @@ -185,16 +188,12 @@ debugl1(cs, "ISAC IntStat after IntRoutine"); goto Start_ISAC; } - if (stat & 1) { - writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0xFF); - writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0xFF); - writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0x0); - writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0x0); - } - if (stat & 2) { - writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0xFF); - writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0x0); - } + writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0x0); + writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0x0); + writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0x0); } void @@ -215,15 +214,9 @@ case CARD_RELEASE: release_io_mic(cs); return(0); - case CARD_SETIRQ: - return(request_irq(cs->irq, &mic_interrupt, - I4L_IRQ_FLAG, "HiSax", cs)); case CARD_INIT: inithscx(cs); /* /RTSA := ISAC RST */ - clear_pending_isac_ints(cs); - clear_pending_hscx_ints(cs); - initisac(cs); - inithscx(cs); + inithscxisac(cs, 3); return(0); case CARD_TEST: return(0); @@ -273,6 +266,7 @@ cs->BC_Write_Reg = &WriteHSCX; cs->BC_Send_Data = &hscx_fill_fifo; cs->cardmsg = &mic_card_msg; + cs->irq_func = &mic_interrupt; ISACVersion(cs, "mic:"); if (HscxVersion(cs, "mic:")) { printk(KERN_WARNING diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/netjet.c linux.pre11.3/drivers/isdn/hisax/netjet.c --- linux.vanilla/drivers/isdn/hisax/netjet.c Sun Nov 8 15:10:15 1998 +++ linux.pre11.3/drivers/isdn/hisax/netjet.c Mon Jul 19 23:59:34 1999 @@ -1,13 +1,37 @@ -/* $Id: netjet.c,v 1.3 1998/02/12 23:08:05 keil Exp $ +/* $Id: netjet.c,v 1.10 1999/07/12 21:05:22 keil Exp $ * netjet.c low level stuff for Traverse Technologie NETJet ISDN cards * - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) * * Thanks to Traverse Technologie Australia for documents and informations * * * $Log: netjet.c,v $ + * Revision 1.10 1999/07/12 21:05:22 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 1.9 1999/07/01 08:12:05 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 1.8 1998/11/15 23:55:14 keil + * changes from 2.0 + * + * Revision 1.7 1998/09/30 22:24:48 keil + * Fix missing line in setstack* + * + * Revision 1.6 1998/08/13 23:36:54 keil + * HiSax 3.1 - don't work stable with current LinkLevel + * + * Revision 1.5 1998/05/25 12:58:21 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * + * Revision 1.4 1998/04/15 16:42:35 keil + * new init code + * new PCI init (2.1.94) + * * Revision 1.3 1998/02/12 23:08:05 keil * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * @@ -25,15 +49,23 @@ #include "hscx.h" #include "isdnl1.h" #include +#ifndef COMPAT_HAS_NEW_PCI #include +#endif #include -#define fcstab ppp_crc16_table #include -extern __u16 ppp_crc16_table[256]; /* from ppp code */ + +#ifndef bus_to_virt +#define bus_to_virt (u_int *) +#endif + +#ifndef virt_to_bus +#define virt_to_bus (u_int) +#endif extern const char *CardType[]; -const char *NETjet_revision = "$Revision: 1.3 $"; +const char *NETjet_revision = "$Revision: 1.10 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -62,6 +94,12 @@ #define NETJET_ISAC_OFF 0xc0 #define NETJET_ISACIRQ 0x10 +#define NETJET_IRQM0_READ 0x0c +#define NETJET_IRQM0_READ_1 0x04 +#define NETJET_IRQM0_READ_2 0x08 +#define NETJET_IRQM0_WRITE 0x03 +#define NETJET_IRQM0_WRITE_1 0x01 +#define NETJET_IRQM0_WRITE_2 0x02 #define NETJET_DMA_SIZE 512 @@ -115,6 +153,42 @@ insb(cs->hw.njet.isac, data, size); } +__u16 fcstab[256] = +{ + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + static void WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size) { @@ -146,25 +220,20 @@ mode_tiger(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; - char tmp[64]; - if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "Tiger mode %d bchan %d/%d", + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "Tiger mode %d bchan %d/%d", mode, bc, bcs->channel); - debugl1(cs, tmp); - } bcs->mode = mode; bcs->channel = bc; switch (mode) { case (L1_MODE_NULL): fill_mem(bcs, bcs->hw.tiger.send, NETJET_DMA_SIZE, bc, 0xff); - if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "Tiger stat rec %d/%d send %d", + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "Tiger stat rec %d/%d send %d", bcs->hw.tiger.r_tot, bcs->hw.tiger.r_err, bcs->hw.tiger.s_tot); - debugl1(cs, tmp); - } if ((cs->bcs[0].mode == L1_MODE_NULL) && (cs->bcs[1].mode == L1_MODE_NULL)) { cs->hw.njet.dmactrl = 0; @@ -197,16 +266,14 @@ test_and_set_bit(BC_FLG_EMPTY, &bcs->Flag); break; } - if (cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "tiger: set %x %x %x %x/%x pulse=%d", + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "tiger: set %x %x %x %x/%x pulse=%d", bytein(cs->hw.njet.base + NETJET_DMACTRL), bytein(cs->hw.njet.base + NETJET_IRQMASK0), bytein(cs->hw.njet.base + NETJET_IRQSTAT0), inl(cs->hw.njet.base + NETJET_DMA_READ_ADR), inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR), bytein(cs->hw.njet.base + NETJET_PULSE_CNT)); - debugl1(cs, tmp); - } } static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off) @@ -266,7 +333,7 @@ val >>= 1;\ } -static void make_raw_data(struct BCState *bcs) { +static int make_raw_data(struct BCState *bcs) { register u_int i,s_cnt=0; register u_char j; register u_char val; @@ -274,13 +341,15 @@ register u_char s_val = 0; register u_char bitcnt = 0; u_int fcs; - char tmp[64]; - + if (!bcs->tx_skb) { + debugl1(bcs->cs, "tiger make_raw: NULL skb"); + return(1); + } bcs->hw.tiger.sendbuf[s_cnt++] = HDLC_FLAG_VALUE; fcs = PPP_INITFCS; - for (i=0; ihw.tiger.tx_skb->len; i++) { - val = bcs->hw.tiger.tx_skb->data[i]; + for (i=0; itx_skb->len; i++) { + val = bcs->tx_skb->data[i]; fcs = PPP_FCS (fcs, val); MAKE_RAW_BYTE; } @@ -303,11 +372,9 @@ } val >>= 1; } - if (bcs->cs->debug & L1_DEB_HSCX) { - sprintf(tmp,"tiger make_raw: in %d out %d.%d", - bcs->hw.tiger.tx_skb->len, s_cnt, bitcnt); - debugl1(bcs->cs,tmp); - } + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs,"tiger make_raw: in %ld out %d.%d", + bcs->tx_skb->len, s_cnt, bitcnt); if (bitcnt) { while (8>bitcnt++) { s_val >>= 1; @@ -316,8 +383,9 @@ bcs->hw.tiger.sendbuf[s_cnt++] = s_val; } bcs->hw.tiger.sendcnt = s_cnt; - bcs->tx_cnt -= bcs->hw.tiger.tx_skb->len; + bcs->tx_cnt -= bcs->tx_skb->len; bcs->hw.tiger.sp = bcs->hw.tiger.sendbuf; + return(0); } static void got_frame(struct BCState *bcs, int count) { @@ -326,6 +394,7 @@ if (!(skb = dev_alloc_skb(count))) printk(KERN_WARNING "TIGER: receive out of memory\n"); else { + SET_SKB_FREE(skb); memcpy(skb_put(skb, count), bcs->hw.tiger.rcvbuf, count); skb_queue_tail(&bcs->rqueue, skb); } @@ -349,7 +418,6 @@ register u_char r_val = bcs->hw.tiger.r_val; register u_int bitcnt = bcs->hw.tiger.r_bitcnt; u_int *p = buf; - char tmp[64]; for (i=0;ichannel ? ((*p>>8) & 0xff) : (*p & 0xff); @@ -370,11 +438,9 @@ } else { r_one=0; state= HDLC_FLAG_SEARCH; - if (bcs->cs->debug & L1_DEB_HSCX) { - sprintf(tmp,"tiger read_raw: zBit(%d,%d,%d) %x", + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs,"tiger read_raw: zBit(%d,%d,%d) %x", bcs->hw.tiger.r_tot,i,j,val); - debugl1(bcs->cs,tmp); - } } } else if (state == HDLC_FLAG_SEARCH) { if (val & 1) { @@ -387,11 +453,9 @@ bitcnt=0; r_val=0; state=HDLC_FLAG_FOUND; - if (bcs->cs->debug & L1_DEB_HSCX) { - sprintf(tmp,"tiger read_raw: flag(%d,%d,%d) %x", + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs,"tiger read_raw: flag(%d,%d,%d) %x", bcs->hw.tiger.r_tot,i,j,val); - debugl1(bcs->cs,tmp); - } } r_one=0; } @@ -425,12 +489,10 @@ bcs->hw.tiger.r_fcs = PPP_INITFCS; bcs->hw.tiger.rcvbuf[0] = r_val; bcs->hw.tiger.r_fcs = PPP_FCS (bcs->hw.tiger.r_fcs, r_val); - if (bcs->cs->debug & L1_DEB_HSCX) { - sprintf(tmp,"tiger read_raw: byte1(%d,%d,%d) rval %x val %x i %x", + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs,"tiger read_raw: byte1(%d,%d,%d) rval %x val %x i %x", bcs->hw.tiger.r_tot,i,j,r_val,val, bcs->cs->hw.njet.irqstat0); - debugl1(bcs->cs,tmp); - } } } else if (state == HDLC_FRAME_FOUND) { if (val & 1) { @@ -453,11 +515,9 @@ state=HDLC_FLAG_SEARCH; bcs->hw.tiger.r_err++; } else { - if (bcs->cs->debug & L1_DEB_HSCX) { - sprintf(tmp,"tiger frame end(%d,%d): fcs(%x) i %x", + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs,"tiger frame end(%d,%d): fcs(%x) i %x", i,j,bcs->hw.tiger.r_fcs, bcs->cs->hw.njet.irqstat0); - debugl1(bcs->cs, tmp); - } if (bcs->hw.tiger.r_fcs == PPP_GOODFCS) { got_frame(bcs, (bitcnt>>3)-3); } else @@ -509,7 +569,15 @@ u_int *p; int cnt = NETJET_DMA_SIZE/2; - if (cs->hw.njet.irqstat0 & 4) + if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_READ) { + debugl1(cs,"tiger warn read double dma %x/%x", + cs->hw.njet.irqstat0, cs->hw.njet.last_is0); + return; + } else { + cs->hw.njet.last_is0 &= ~NETJET_IRQM0_READ; + cs->hw.njet.last_is0 |= (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ); + } + if (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ_1) p = cs->bcs[0].hw.tiger.rec + NETJET_DMA_SIZE - 1; else p = cs->bcs[0].hw.tiger.rec + cnt - 1; @@ -517,32 +585,28 @@ read_raw(cs->bcs, p, cnt); if (cs->bcs[1].mode == L1_MODE_HDLC) read_raw(cs->bcs + 1, p, cnt); - cs->hw.njet.irqstat0 &= 0xf3; + cs->hw.njet.irqstat0 &= ~NETJET_IRQM0_READ; } static void write_raw(struct BCState *bcs, u_int *buf, int cnt); static void fill_dma(struct BCState *bcs) { - char tmp[64]; register u_int *p, *sp; register int cnt; - if (!bcs->hw.tiger.tx_skb) + if (!bcs->tx_skb) return; - if (bcs->cs->debug & L1_DEB_HSCX) { - sprintf(tmp,"tiger fill_dma1: c%d %4x", bcs->channel, + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs,"tiger fill_dma1: c%d %4x", bcs->channel, bcs->Flag); - debugl1(bcs->cs,tmp); - } if (test_and_set_bit(BC_FLG_BUSY, &bcs->Flag)) return; - make_raw_data(bcs); - if (bcs->cs->debug & L1_DEB_HSCX) { - sprintf(tmp,"tiger fill_dma2: c%d %4x", bcs->channel, + if (make_raw_data(bcs)) + return; + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs,"tiger fill_dma2: c%d %4x", bcs->channel, bcs->Flag); - debugl1(bcs->cs,tmp); - } if (test_and_clear_bit(BC_FLG_NOFRAME, &bcs->Flag)) { write_raw(bcs, bcs->hw.tiger.sendp, bcs->hw.tiger.free); } else if (test_and_clear_bit(BC_FLG_HALF, &bcs->Flag)) { @@ -582,17 +646,14 @@ } write_raw(bcs, p, cnt); } - if (bcs->cs->debug & L1_DEB_HSCX) { - sprintf(tmp,"tiger fill_dma3: c%d %4x", bcs->channel, + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs,"tiger fill_dma3: c%d %4x", bcs->channel, bcs->Flag); - debugl1(bcs->cs,tmp); - } } static void write_raw(struct BCState *bcs, u_int *buf, int cnt) { u_int mask, val, *p=buf; u_int i, s_cnt; - char tmp[64]; if (cnt <= 0) return; @@ -617,26 +678,23 @@ p = bcs->hw.tiger.send; } bcs->hw.tiger.s_tot += s_cnt; - if (bcs->cs->debug & L1_DEB_HSCX) { - sprintf(tmp,"tiger write_raw: c%d %x-%x %d/%d %d %x", bcs->channel, - (u_int)buf, (u_int)p, s_cnt, cnt, bcs->hw.tiger.sendcnt, - bcs->cs->hw.njet.irqstat0); - debugl1(bcs->cs,tmp); - } + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs,"tiger write_raw: c%d %x-%x %d/%d %d %x", bcs->channel, + (u_int)buf, (u_int)p, s_cnt, cnt, + bcs->hw.tiger.sendcnt, bcs->cs->hw.njet.irqstat0); if (bcs->cs->debug & L1_DEB_HSCX_FIFO) printframe(bcs->cs, bcs->hw.tiger.sp, s_cnt, "snd"); bcs->hw.tiger.sp += s_cnt; bcs->hw.tiger.sendp = p; if (!bcs->hw.tiger.sendcnt) { - if (!bcs->hw.tiger.tx_skb) { - sprintf(tmp,"tiger write_raw: NULL skb s_cnt %d", s_cnt); - debugl1(bcs->cs, tmp); + if (!bcs->tx_skb) { + debugl1(bcs->cs,"tiger write_raw: NULL skb s_cnt %d", s_cnt); } else { if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->hw.tiger.tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.tiger.tx_skb->len); - dev_kfree_skb(bcs->hw.tiger.tx_skb); - bcs->hw.tiger.tx_skb = NULL; + (PACKET_NOACK != bcs->tx_skb->pkt_type)) + bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len); + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + bcs->tx_skb = NULL; } test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); bcs->hw.tiger.free = cnt - s_cnt; @@ -646,7 +704,7 @@ test_and_clear_bit(BC_FLG_HALF, &bcs->Flag); test_and_set_bit(BC_FLG_NOFRAME, &bcs->Flag); } - if ((bcs->hw.tiger.tx_skb = skb_dequeue(&bcs->squeue))) { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { fill_dma(bcs); } else { mask ^= 0xffffffff; @@ -656,11 +714,9 @@ if (p>bcs->hw.tiger.s_end) p = bcs->hw.tiger.send; } - if (bcs->cs->debug & L1_DEB_HSCX) { - sprintf(tmp, "tiger write_raw: fill rest %d", + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs, "tiger write_raw: fill rest %d", cnt - s_cnt); - debugl1(bcs->cs,tmp); - } } bcs->event |= 1 << B_XMTBUFREADY; queue_task(&bcs->tqueue, &tq_immediate); @@ -671,24 +727,28 @@ test_and_set_bit(BC_FLG_HALF, &bcs->Flag); fill_mem(bcs, buf, cnt, bcs->channel, 0xff); bcs->hw.tiger.free += cnt; - if (bcs->cs->debug & L1_DEB_HSCX) { - sprintf(tmp,"tiger write_raw: fill half"); - debugl1(bcs->cs,tmp); - } + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs,"tiger write_raw: fill half"); } else if (test_and_clear_bit(BC_FLG_HALF, &bcs->Flag)) { test_and_set_bit(BC_FLG_EMPTY, &bcs->Flag); fill_mem(bcs, buf, cnt, bcs->channel, 0xff); - if (bcs->cs->debug & L1_DEB_HSCX) { - sprintf(tmp,"tiger write_raw: fill full"); - debugl1(bcs->cs,tmp); - } + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs,"tiger write_raw: fill full"); } } static void write_tiger(struct IsdnCardState *cs) { u_int *p, cnt = NETJET_DMA_SIZE/2; - if (cs->hw.njet.irqstat0 & 1) + if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_WRITE) { + debugl1(cs,"tiger warn write double dma %x/%x", + cs->hw.njet.irqstat0, cs->hw.njet.last_is0); + return; + } else { + cs->hw.njet.last_is0 &= ~NETJET_IRQM0_WRITE; + cs->hw.njet.last_is0 |= (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE); + } + if (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE_1) p = cs->bcs[0].hw.tiger.send + NETJET_DMA_SIZE - 1; else p = cs->bcs[0].hw.tiger.send + cnt - 1; @@ -696,7 +756,7 @@ write_raw(cs->bcs, p, cnt); if (cs->bcs[1].mode == L1_MODE_HDLC) write_raw(cs->bcs + 1, p, cnt); - cs->hw.njet.irqstat0 &= 0xfc; + cs->hw.njet.irqstat0 &= ~NETJET_IRQM0_WRITE; } static void @@ -706,45 +766,58 @@ long flags; switch (pr) { - case (PH_DATA_REQ): + case (PH_DATA | REQUEST): save_flags(flags); cli(); - if (st->l1.bcs->hw.tiger.tx_skb) { + if (st->l1.bcs->tx_skb) { skb_queue_tail(&st->l1.bcs->squeue, skb); restore_flags(flags); } else { - st->l1.bcs->hw.tiger.tx_skb = skb; + st->l1.bcs->tx_skb = skb; st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); restore_flags(flags); } break; - case (PH_PULL_IND): - if (st->l1.bcs->hw.tiger.tx_skb) { + case (PH_PULL | INDICATION): + if (st->l1.bcs->tx_skb) { printk(KERN_WARNING "tiger_l2l1: this shouldn't happen\n"); break; } save_flags(flags); cli(); - st->l1.bcs->hw.tiger.tx_skb = skb; + st->l1.bcs->tx_skb = skb; st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); restore_flags(flags); break; - case (PH_PULL_REQ): - if (!st->l1.bcs->hw.tiger.tx_skb) { + case (PH_PULL | REQUEST): + if (!st->l1.bcs->tx_skb) { test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - st->l1.l1l2(st, PH_PULL_CNF, NULL); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); } else test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; + case (PH_ACTIVATE | REQUEST): + test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + mode_tiger(st->l1.bcs, st->l1.mode, st->l1.bc); + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | REQUEST): + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | CONFIRM): + test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + mode_tiger(st->l1.bcs, 0, st->l1.bc); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); + break; } } + void close_tigerstate(struct BCState *bcs) { - struct sk_buff *skb; - - mode_tiger(bcs, 0, 0); + mode_tiger(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { if (bcs->hw.tiger.rcvbuf) { kfree(bcs->hw.tiger.rcvbuf); @@ -754,32 +827,26 @@ kfree(bcs->hw.tiger.sendbuf); bcs->hw.tiger.sendbuf = NULL; } - while ((skb = skb_dequeue(&bcs->rqueue))) { - dev_kfree_skb(skb); - } - while ((skb = skb_dequeue(&bcs->squeue))) { - dev_kfree_skb(skb); - } - if (bcs->hw.tiger.tx_skb) { - dev_kfree_skb(bcs->hw.tiger.tx_skb); - bcs->hw.tiger.tx_skb = NULL; + discard_queue(&bcs->rqueue); + discard_queue(&bcs->squeue); + if (bcs->tx_skb) { + idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } } } static int -open_tigerstate(struct IsdnCardState *cs, int bc) +open_tigerstate(struct IsdnCardState *cs, struct BCState *bcs) { - struct BCState *bcs = cs->bcs + bc; - if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { - if (!(bcs->hw.tiger.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_KERNEL))) { + if (!(bcs->hw.tiger.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { printk(KERN_WARNING "HiSax: No memory for tiger.rcvbuf\n"); return (1); } - if (!(bcs->hw.tiger.sendbuf = kmalloc(RAW_BUFMAX, GFP_KERNEL))) { + if (!(bcs->hw.tiger.sendbuf = kmalloc(RAW_BUFMAX, GFP_ATOMIC))) { printk(KERN_WARNING "HiSax: No memory for tiger.sendbuf\n"); return (1); @@ -787,7 +854,7 @@ skb_queue_head_init(&bcs->rqueue); skb_queue_head_init(&bcs->squeue); } - bcs->hw.tiger.tx_skb = NULL; + bcs->tx_skb = NULL; bcs->hw.tiger.sendcnt = 0; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); bcs->event = 0; @@ -795,34 +862,17 @@ return (0); } -static void -tiger_manl1(struct PStack *st, int pr, - void *arg) -{ - switch (pr) { - case (PH_ACTIVATE_REQ): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - mode_tiger(st->l1.bcs, st->l1.mode, st->l1.bc); - st->l1.l1man(st, PH_ACTIVATE_CNF, NULL); - break; - case (PH_DEACTIVATE_REQ): - if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) - mode_tiger(st->l1.bcs, 0, 0); - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - break; - } -} - int setstack_tiger(struct PStack *st, struct BCState *bcs) { - if (open_tigerstate(st->l1.hardware, bcs->channel)) + bcs->channel = st->l1.bc; + if (open_tigerstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; st->l2.l2l1 = tiger_l2l1; - st->ma.manl1 = tiger_manl1; setstack_manager(st); bcs->st = st; + setstack_l1_B(st); return (0); } @@ -830,8 +880,6 @@ __initfunc(void inittiger(struct IsdnCardState *cs)) { - char tmp[128]; - if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_SIZE * sizeof(unsigned int), GFP_KERNEL | GFP_DMA))) { printk(KERN_WARNING @@ -845,9 +893,8 @@ cs->bcs[1].hw.tiger.s_end = cs->bcs[0].hw.tiger.s_end; memset(cs->bcs[0].hw.tiger.send, 0xff, NETJET_DMA_SIZE * sizeof(unsigned int)); - sprintf(tmp, "tiger: send buf %x - %x", (u_int)cs->bcs[0].hw.tiger.send, + debugl1(cs, "tiger: send buf %x - %x", (u_int)cs->bcs[0].hw.tiger.send, (u_int)(cs->bcs[0].hw.tiger.send + NETJET_DMA_SIZE - 1)); - debugl1(cs, tmp); outl(virt_to_bus(cs->bcs[0].hw.tiger.send), cs->hw.njet.base + NETJET_DMA_READ_START); outl(virt_to_bus(cs->bcs[0].hw.tiger.s_irq), @@ -860,9 +907,8 @@ "HiSax: No memory for tiger.rec\n"); return; } - sprintf(tmp, "tiger: rec buf %x - %x", (u_int)cs->bcs[0].hw.tiger.rec, + debugl1(cs, "tiger: rec buf %x - %x", (u_int)cs->bcs[0].hw.tiger.rec, (u_int)(cs->bcs[0].hw.tiger.rec + NETJET_DMA_SIZE - 1)); - debugl1(cs, tmp); cs->bcs[1].hw.tiger.rec = cs->bcs[0].hw.tiger.rec; memset(cs->bcs[0].hw.tiger.rec, 0xff, NETJET_DMA_SIZE * sizeof(unsigned int)); outl(virt_to_bus(cs->bcs[0].hw.tiger.rec), @@ -871,11 +917,10 @@ cs->hw.njet.base + NETJET_DMA_WRITE_IRQ); outl(virt_to_bus(cs->bcs[0].hw.tiger.rec + NETJET_DMA_SIZE - 1), cs->hw.njet.base + NETJET_DMA_WRITE_END); - sprintf(tmp, "tiger: dmacfg %x/%x pulse=%d", + debugl1(cs, "tiger: dmacfg %x/%x pulse=%d", inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR), inl(cs->hw.njet.base + NETJET_DMA_READ_ADR), bytein(cs->hw.njet.base + NETJET_PULSE_CNT)); - debugl1(cs, tmp); cs->hw.njet.last_is0 = 0; cs->bcs[0].BC_SetStack = setstack_tiger; cs->bcs[1].BC_SetStack = setstack_tiger; @@ -906,8 +951,8 @@ netjet_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u_char val, sval, stat = 1; - char tmp[128]; + u_char val, sval; + long flags; if (!cs) { printk(KERN_WARNING "NETjet: Spurious interrupt!\n"); @@ -916,49 +961,49 @@ if (!((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT1)) & NETJET_ISACIRQ)) { val = ReadISAC(cs, ISAC_ISTA); - if (cs->debug & L1_DEB_ISAC) { - sprintf(tmp, "tiger: i1 %x %x", sval, val); - debugl1(cs, tmp); - } + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "tiger: i1 %x %x", sval, val); if (val) { isac_interrupt(cs, val); - stat |= 2; + WriteISAC(cs, ISAC_MASK, 0xFF); + WriteISAC(cs, ISAC_MASK, 0x0); } } - if ((cs->hw.njet.irqstat0 = bytein(cs->hw.njet.base + NETJET_IRQSTAT0))) { -/* sprintf(tmp, "tiger: ist0 %x %x %x %x/%x pulse=%d", + save_flags(flags); + cli(); + if ((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT0))) { + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + restore_flags(flags); + return; + } + cs->hw.njet.irqstat0 = sval; + restore_flags(flags); +/* debugl1(cs, "tiger: ist0 %x %x %x %x/%x pulse=%d", sval, bytein(cs->hw.njet.base + NETJET_DMACTRL), bytein(cs->hw.njet.base + NETJET_IRQMASK0), inl(cs->hw.njet.base + NETJET_DMA_READ_ADR), inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR), bytein(cs->hw.njet.base + NETJET_PULSE_CNT)); - debugl1(cs, tmp); */ - if (cs->hw.njet.last_is0 & cs->hw.njet.irqstat0 & 0xf) { - sprintf(tmp, "tiger: ist0 %x->%x irq lost", - cs->hw.njet.last_is0, cs->hw.njet.irqstat0); - debugl1(cs, tmp); - } - cs->hw.njet.last_is0 = cs->hw.njet.irqstat0; /* cs->hw.njet.irqmask0 = ((0x0f & cs->hw.njet.irqstat0) ^ 0x0f) | 0x30; */ byteout(cs->hw.njet.base + NETJET_IRQSTAT0, cs->hw.njet.irqstat0); /* byteout(cs->hw.njet.base + NETJET_IRQMASK0, cs->hw.njet.irqmask0); -*/ if (cs->hw.njet.irqstat0 & 0x0c) +*/ if (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) read_tiger(cs); - if (cs->hw.njet.irqstat0 & 0x03) + if (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE) write_tiger(cs); - } + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + restore_flags(flags); + /* if (!testcnt--) { cs->hw.njet.dmactrl = 0; byteout(cs->hw.njet.base + NETJET_DMACTRL, cs->hw.njet.dmactrl); byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0); } -*/ if (stat & 2) { - WriteISAC(cs, ISAC_MASK, 0xFF); - WriteISAC(cs, ISAC_MASK, 0x0); - } +*/ } static void @@ -1004,13 +1049,12 @@ case CARD_RELEASE: release_io_netjet(cs); return(0); - case CARD_SETIRQ: - return(request_irq(cs->irq, &netjet_interrupt, - I4L_IRQ_FLAG, "HiSax", cs)); case CARD_INIT: inittiger(cs); clear_pending_isac_ints(cs); initisac(cs); + /* Reenable all IRQ */ + cs->writeisac(cs, ISAC_MASK, 0); return(0); case CARD_TEST: return(0); @@ -1018,9 +1062,11 @@ return(0); } - - -static int pci_index __initdata = 0; +#ifdef COMPAT_HAS_NEW_PCI +static struct pci_dev *dev_netjet __initdata = NULL; +#else +static int pci_index __initdata = 0; +#endif __initfunc(int setup_netjet(struct IsdnCard *card)) @@ -1029,15 +1075,40 @@ struct IsdnCardState *cs = card->cs; char tmp[64]; #if CONFIG_PCI +#ifndef COMPAT_HAS_NEW_PCI u_char pci_bus, pci_device_fn, pci_irq; u_int pci_ioaddr, found; #endif - +#endif strcpy(tmp, NETjet_revision); printk(KERN_INFO "HiSax: Traverse Tech. NETjet driver Rev. %s\n", HiSax_getrev(tmp)); if (cs->typ != ISDN_CTYPE_NETJET) return(0); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); #if CONFIG_PCI +#ifdef COMPAT_HAS_NEW_PCI + if (!pci_present()) { + printk(KERN_ERR "Netjet: no PCI bus present\n"); + return(0); + } + if ((dev_netjet = pci_find_device(PCI_VENDOR_TRAVERSE_TECH, + PCI_NETJET_ID, dev_netjet))) { + cs->irq = dev_netjet->irq; + if (!cs->irq) { + printk(KERN_WARNING "NETjet: No IRQ for PCI card found\n"); + return(0); + } + cs->hw.njet.base = dev_netjet->base_address[0] + & PCI_BASE_ADDRESS_IO_MASK; + if (!cs->hw.njet.base) { + printk(KERN_WARNING "NETjet: No IO-Adr for PCI card found\n"); + return(0); + } + } else { + printk(KERN_WARNING "NETjet: No PCI card found\n"); + return(0); + } +#else found = 0; for (; pci_index < 0xff; pci_index++) { if (pcibios_find_device(PCI_VENDOR_TRAVERSE_TECH, @@ -1045,7 +1116,7 @@ == PCIBIOS_SUCCESSFUL) found = 1; else - break; + continue; /* get IRQ */ pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pci_irq); @@ -1060,6 +1131,7 @@ printk(KERN_WARNING "NETjet: No PCI card found\n"); return(0); } + pci_index++; if (!pci_irq) { printk(KERN_WARNING "NETjet: No IRQ for PCI card found\n"); return(0); @@ -1068,11 +1140,11 @@ printk(KERN_WARNING "NETjet: No IO-Adr for PCI card found\n"); return(0); } - pci_ioaddr &= ~3; /* remove io/mem flag */ - cs->hw.njet.base = pci_ioaddr; - cs->hw.njet.auxa = pci_ioaddr + NETJET_AUXDATA; - cs->hw.njet.isac = pci_ioaddr | NETJET_ISAC_OFF; + cs->hw.njet.base = pci_ioaddr & PCI_BASE_ADDRESS_IO_MASK; cs->irq = pci_irq; +#endif /* COMPAT_HAS_NEW_PCI */ + cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; + cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; bytecnt = 256; #else printk(KERN_WARNING "NETjet: NO_PCI_BIOS\n"); @@ -1101,6 +1173,8 @@ cs->BC_Write_Reg = &dummywr; cs->BC_Send_Data = &fill_dma; cs->cardmsg = &NETjet_card_msg; + cs->irq_func = &netjet_interrupt; + cs->irq_flags |= SA_SHIRQ; ISACVersion(cs, "NETjet:"); return (1); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/niccy.c linux.pre11.3/drivers/isdn/hisax/niccy.c --- linux.vanilla/drivers/isdn/hisax/niccy.c Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/hisax/niccy.c Mon Jul 19 23:59:34 1999 @@ -1,4 +1,4 @@ -/* $Id: niccy.c,v 1.2 1998/02/11 17:31:04 keil Exp $ +/* $Id: niccy.c,v 1.6 1999/07/12 21:05:23 keil Exp $ * niccy.c low level stuff for Dr. Neuhaus NICCY PnP and NICCY PCI and * compatible (SAGEM cybermodem) @@ -8,24 +8,38 @@ * Thanks to Dr. Neuhaus and SAGEM for informations * * $Log: niccy.c,v $ - * Revision 1.2 1998/02/11 17:31:04 keil - * new file + * Revision 1.6 1999/07/12 21:05:23 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 1.5 1999/07/01 08:12:07 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel * + * Revision 1.4 1998/04/16 19:16:48 keil + * need config.h * + * Revision 1.3 1998/04/15 16:42:59 keil + * new init code + * + * Revision 1.2 1998/02/11 17:31:04 keil + * new file * */ -#include + #define __NO_VERSION__ +#include #include "hisax.h" #include "isac.h" #include "hscx.h" #include "isdnl1.h" #include +#ifndef COMPAT_HAS_NEW_PCI #include +#endif extern const char *CardType[]; -const char *niccy_revision = "$Revision: 1.2 $"; +const char *niccy_revision = "$Revision: 1.6 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -44,6 +58,10 @@ /* PCI stuff */ #define PCI_VENDOR_DR_NEUHAUS 0x1267 #define PCI_NICCY_ID 0x1016 +#define PCI_IRQ_CTRL_REG 0x38 +#define PCI_IRQ_ENABLE 0x1f00 +#define PCI_IRQ_DISABLE 0xff0000 +#define PCI_IRQ_ASSERT 0x800000 static inline u_char readreg(unsigned int ale, unsigned int adr, u_char off) @@ -146,24 +164,27 @@ niccy_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u_char val, stat = 0; + u_char val; if (!cs) { printk(KERN_WARNING "Niccy: Spurious interrupt!\n"); return; } + if (cs->subtyp == NICCY_PCI) { + int ival; + ival = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); + if (!(ival & PCI_IRQ_ASSERT)) /* IRQ not for us (shared) */ + return; + outl(ival, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); + } val = readreg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_ISTA + 0x40); Start_HSCX: - if (val) { + if (val) hscx_int_main(cs, val); - stat |= 1; - } val = readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_ISTA); Start_ISAC: - if (val) { + if (val) isac_interrupt(cs, val); - stat |= 2; - } val = readreg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_ISTA + 0x40); if (val) { if (cs->debug & L1_DEB_HSCX) @@ -176,24 +197,26 @@ debugl1(cs, "ISAC IntStat after IntRoutine"); goto Start_ISAC; } - if (stat & 1) { - writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0xFF); - writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0xFF); - writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0); - writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0); - } - if (stat & 2) { - writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0xFF); - writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0); - } + writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0); + writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0); + writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0); } void release_io_niccy(struct IsdnCardState *cs) { - if (cs->subtyp == NICCY_PCI) + if (cs->subtyp == NICCY_PCI) { + int val; + + val = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); + val &= PCI_IRQ_DISABLE; + outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); + release_region(cs->hw.niccy.cfg_reg, 0x80); release_region(cs->hw.niccy.isac, 4); - else { + } else { release_region(cs->hw.niccy.isac, 2); release_region(cs->hw.niccy.isac_ale, 2); } @@ -202,7 +225,13 @@ static void niccy_reset(struct IsdnCardState *cs) { - // No reset procedure known + int val, nval; + + val = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); + nval = val | PCI_IRQ_ENABLE; + outl(nval, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); + + inithscxisac(cs, 3); } static int @@ -215,14 +244,8 @@ case CARD_RELEASE: release_io_niccy(cs); return(0); - case CARD_SETIRQ: - return(request_irq(cs->irq, &niccy_interrupt, - I4L_IRQ_FLAG, "HiSax", cs)); case CARD_INIT: - clear_pending_isac_ints(cs); - clear_pending_hscx_ints(cs); - initisac(cs); - inithscx(cs); + niccy_reset(cs); return(0); case CARD_TEST: return(0); @@ -230,7 +253,11 @@ return(0); } -static int pci_index __initdata = 0; +#ifdef COMPAT_HAS_NEW_PCI +static struct pci_dev *niccy_dev __initdata = NULL; +#else +static int pci_index __initdata = 0; +#endif __initfunc(int setup_niccy(struct IsdnCard *card)) @@ -272,8 +299,38 @@ request_region(cs->hw.niccy.isac_ale, 2, "niccy addr"); } else { #if CONFIG_PCI - u_char pci_bus, pci_device_fn, pci_irq; u_int pci_ioaddr; +#ifdef COMPAT_HAS_NEW_PCI + if (!pci_present()) { + printk(KERN_ERR "Niccy: no PCI bus present\n"); + return(0); + } + cs->subtyp = 0; + if ((niccy_dev = pci_find_device(PCI_VENDOR_DR_NEUHAUS, + PCI_NICCY_ID, niccy_dev))) { + /* get IRQ */ + if (!niccy_dev->irq) { + printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n"); + return(0); + } + cs->irq = niccy_dev->irq; + if (!niccy_dev->base_address[0]) { + printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n"); + return(0); + } + cs->hw.niccy.cfg_reg = niccy_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; + if (!niccy_dev->base_address[1]) { + printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n"); + return(0); + } + pci_ioaddr = niccy_dev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK; + cs->subtyp = NICCY_PCI; + } else { + printk(KERN_WARNING "Niccy: No PCI card found\n"); + return(0); + } +#else + u_char pci_bus, pci_device_fn, pci_irq; cs->subtyp = 0; for (; pci_index < 0xff; pci_index++) { @@ -282,17 +339,22 @@ == PCIBIOS_SUCCESSFUL) cs->subtyp = NICCY_PCI; else - break; + continue; /* get IRQ */ pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pci_irq); + /* get IO pci AMCC address */ + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_0, &pci_ioaddr); + if (!pci_ioaddr) { + printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n"); + return(0); + } + cs->hw.niccy.cfg_reg = pci_ioaddr & ~3 ; /* get IO address */ - /* if it won't work try the other PCI addresses - * PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_5 - */ pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_2, &pci_ioaddr); + PCI_BASE_ADDRESS_1, &pci_ioaddr); if (cs->subtyp) break; } @@ -300,21 +362,23 @@ printk(KERN_WARNING "Niccy: No PCI card found\n"); return(0); } + pci_index++; if (!pci_irq) { printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n"); return(0); } - if (!pci_ioaddr) { printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n"); return(0); } pci_ioaddr &= ~3; /* remove io/mem flag */ + cs->irq = pci_irq; +#endif /* COMPAT_HAS_NEW_PCI */ + cs->irq_flags |= SA_SHIRQ; cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA; cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR; cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA; cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR; - cs->irq = pci_irq; if (check_region((cs->hw.niccy.isac), 4)) { printk(KERN_WARNING "HiSax: %s data port %x-%x already in use\n", @@ -324,6 +388,17 @@ return (0); } else request_region(cs->hw.niccy.isac, 4, "niccy"); + if (check_region(cs->hw.niccy.cfg_reg, 0x80)) { + printk(KERN_WARNING + "HiSax: %s pci port %x-%x already in use\n", + CardType[card->typ], + cs->hw.niccy.cfg_reg, + cs->hw.niccy.cfg_reg + 0x80); + release_region(cs->hw.niccy.isac, 4); + return (0); + } else { + request_region(cs->hw.niccy.cfg_reg, 0x80, "niccy pci"); + } #else printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOS\n"); printk(KERN_WARNING "Niccy: unable to config NICCY PCI\n"); @@ -334,7 +409,6 @@ "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n", CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI", cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale); - niccy_reset(cs); cs->readisac = &ReadISAC; cs->writeisac = &WriteISAC; cs->readisacfifo = &ReadISACfifo; @@ -343,6 +417,7 @@ cs->BC_Write_Reg = &WriteHSCX; cs->BC_Send_Data = &hscx_fill_fifo; cs->cardmsg = &niccy_card_msg; + cs->irq_func = &niccy_interrupt; ISACVersion(cs, "Niccy:"); if (HscxVersion(cs, "Niccy:")) { printk(KERN_WARNING diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/q931.c linux.pre11.3/drivers/isdn/hisax/q931.c --- linux.vanilla/drivers/isdn/hisax/q931.c Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/hisax/q931.c Mon Jul 19 23:59:34 1999 @@ -1,4 +1,4 @@ -/* $Id: q931.c,v 1.6 1997/07/27 21:09:44 keil Exp $ +/* $Id: q931.c,v 1.7 1998/11/15 23:55:17 keil Exp $ * q931.c code to decode ITU Q.931 call control messages * @@ -14,6 +14,9 @@ * * * $Log: q931.c,v $ + * Revision 1.7 1998/11/15 23:55:17 keil + * changes from 2.0 + * * Revision 1.6 1997/07/27 21:09:44 keil * move functions to isdnl3.c * @@ -159,7 +162,7 @@ {MT_N0_CLO_ACK, "CLOse ACKnowledge"} }; -int mt_n0_len = (sizeof(mt_n0) / sizeof(struct MessageType)); +#define MT_N0_LEN (sizeof(mt_n0) / sizeof(struct MessageType)) static struct MessageType mt_n1[] = @@ -196,7 +199,7 @@ {MT_N1_STAT, "STATus"} }; -int mt_n1_len = (sizeof(mt_n1) / sizeof(struct MessageType)); +#define MT_N1_LEN (sizeof(mt_n1) / sizeof(struct MessageType)) static struct MessageType fac_1tr6[] = { @@ -220,9 +223,7 @@ {FAC_Rueckwechsel, "Rueckwechsel"}, {FAC_Umleitung, "Umleitung"} }; -int fac_1tr6_len = (sizeof(fac_1tr6) / sizeof(struct MessageType)); - - +#define FAC_1TR6_LEN (sizeof(fac_1tr6) / sizeof(struct MessageType)) static int prbits(char *dest, u_char b, int start, int len) @@ -925,7 +926,7 @@ {WE0_userInfo, "User Info", general} }; -static int we_0_len = (sizeof(we_0) / sizeof(struct InformationElement)); +#define WE_0_LEN (sizeof(we_0) / sizeof(struct InformationElement)) static struct InformationElement we_6[] = { @@ -937,7 +938,7 @@ {WE6_statusCalled, "Status Called", general}, {WE6_addTransAttr, "Additional Transmission Attributes", general} }; -static int we_6_len = (sizeof(we_6) / sizeof(struct InformationElement)); +#define WE_6_LEN (sizeof(we_6) / sizeof(struct InformationElement)) int QuickHex(char *txt, u_char * p, int cnt) @@ -964,39 +965,92 @@ } void -LogFrame(struct IsdnCardState *sp, u_char * buf, int size) +LogFrame(struct IsdnCardState *cs, u_char * buf, int size) { char *dp; if (size < 1) return; - dp = sp->dlogspace; - if (size < 4096 / 3 - 10) { - dp += sprintf(dp, "HEX:"); + dp = cs->dlog; + if (size < MAX_DLOG_SPACE / 3 - 10) { + *dp++ = 'H'; + *dp++ = 'E'; + *dp++ = 'X'; + *dp++ = ':'; dp += QuickHex(dp, buf, size); dp--; *dp++ = '\n'; *dp = 0; + HiSax_putstatus(cs, NULL, cs->dlog); } else - sprintf(dp, "LogFrame: warning Frame too big (%d)\n", - size); - HiSax_putstatus(sp, sp->dlogspace); + HiSax_putstatus(cs, "LogFrame: ", "warning Frame too big (%d)", size); } void -dlogframe(struct IsdnCardState *sp, u_char * buf, int size, char *comment) +dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir) { - u_char *bend = buf + size; + u_char *bend, *buf; char *dp; unsigned char pd, cr_l, cr, mt; - int i, cs = 0, cs_old = 0, cs_fest = 0; + unsigned char sapi, tei, ftyp; + int i, cset = 0, cs_old = 0, cs_fest = 0; + int size, finish = 0; - if (size < 1) + if (skb->len < 3) return; /* display header */ - dp = sp->dlogspace; - dp += sprintf(dp, "%s\n", comment); - + dp = cs->dlog; + dp += jiftime(dp, jiffies); + *dp++ = ' '; + sapi = skb->data[0] >> 2; + tei = skb->data[1] >> 1; + ftyp = skb->data[2]; + buf = skb->data; + dp += sprintf(dp, "frame %s ", dir ? "network->user" : "user->network"); + size = skb->len; + + if (tei == GROUP_TEI) { + if (sapi == CTRL_SAPI) { /* sapi 0 */ + if (ftyp == 3) { + dp += sprintf(dp, "broadcast\n"); + buf += 3; + size -= 3; + } else { + dp += sprintf(dp, "no UI broadcast\n"); + finish = 1; + } + } else if (sapi == TEI_SAPI) { + dp += sprintf(dp, "tei managment\n"); + finish = 1; + } else { + dp += sprintf(dp, "unknown sapi %d broadcast\n", sapi); + finish = 1; + } + } else { + if (sapi == CTRL_SAPI) { + if (!(ftyp & 1)) { /* IFrame */ + dp += sprintf(dp, "with tei %d\n", tei); + buf += 4; + size -= 4; + } else { + dp += sprintf(dp, "SFrame with tei %d\n", tei); + finish = 1; + } + } else { + dp += sprintf(dp, "unknown sapi %d tei %d\n", sapi, tei); + finish = 1; + } + } + bend = skb->data + skb->len; + if (buf >= bend) { + dp += sprintf(dp, "frame too short\n"); + finish = 1; + } + if (finish) { + *dp = 0; + HiSax_putstatus(cs, NULL, cs->dlog); + return; + } if ((0xfe & buf[0]) == PROTO_DIS_N0) { /* 1TR6 */ /* locate message type */ pd = *buf++; @@ -1007,11 +1061,11 @@ cr = 0; mt = *buf++; if (pd == PROTO_DIS_N0) { /* N0 */ - for (i = 0; i < mt_n0_len; i++) + for (i = 0; i < MT_N0_LEN; i++) if (mt_n0[i].nr == mt) break; /* display message type if it exists */ - if (i == mt_n0_len) + if (i == MT_N0_LEN) dp += sprintf(dp, "callref %d %s size %d unknown message type N0 %x!\n", cr & 0x7f, (cr & 0x80) ? "called" : "caller", size, mt); @@ -1020,11 +1074,11 @@ cr & 0x7f, (cr & 0x80) ? "called" : "caller", size, mt_n0[i].descr); } else { /* N1 */ - for (i = 0; i < mt_n1_len; i++) + for (i = 0; i < MT_N1_LEN; i++) if (mt_n1[i].nr == mt) break; /* display message type if it exists */ - if (i == mt_n1_len) + if (i == MT_N1_LEN) dp += sprintf(dp, "callref %d %s size %d unknown message type N1 %x!\n", cr & 0x7f, (cr & 0x80) ? "called" : "caller", size, mt); @@ -1041,8 +1095,8 @@ switch ((*buf >> 4) & 7) { case 1: dp += sprintf(dp, " Shift %x\n", *buf & 0xf); - cs_old = cs; - cs = *buf & 7; + cs_old = cset; + cset = *buf & 7; cs_fest = *buf & 8; break; case 3: @@ -1066,33 +1120,33 @@ continue; } /* No, locate it in the table */ - if (cs == 0) { - for (i = 0; i < we_0_len; i++) + if (cset == 0) { + for (i = 0; i < WE_0_LEN; i++) if (*buf == we_0[i].nr) break; /* When found, give appropriate msg */ - if (i != we_0_len) { + if (i != WE_0_LEN) { dp += sprintf(dp, " %s\n", we_0[i].descr); dp += we_0[i].f(dp, buf); } else - dp += sprintf(dp, " Codeset %d attribute %x attribute size %d\n", cs, *buf, buf[1]); - } else if (cs == 6) { - for (i = 0; i < we_6_len; i++) + dp += sprintf(dp, " Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]); + } else if (cset == 6) { + for (i = 0; i < WE_6_LEN; i++) if (*buf == we_6[i].nr) break; /* When found, give appropriate msg */ - if (i != we_6_len) { + if (i != WE_6_LEN) { dp += sprintf(dp, " %s\n", we_6[i].descr); dp += we_6[i].f(dp, buf); } else - dp += sprintf(dp, " Codeset %d attribute %x attribute size %d\n", cs, *buf, buf[1]); + dp += sprintf(dp, " Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]); } else - dp += sprintf(dp, " Unknown Codeset %d attribute %x attribute size %d\n", cs, *buf, buf[1]); + dp += sprintf(dp, " Unknown Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]); /* Skip to next element */ if (cs_fest == 8) { - cs = cs_old; + cset = cs_old; cs_old = 0; cs_fest = 0; } @@ -1170,6 +1224,6 @@ } else { dp += sprintf(dp, "Unknown protocol %x!", buf[0]); } - dp += sprintf(dp, "\n"); - HiSax_putstatus(sp, sp->dlogspace); + *dp = 0; + HiSax_putstatus(cs, NULL, cs->dlog); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/rawhdlc.c linux.pre11.3/drivers/isdn/hisax/rawhdlc.c --- linux.vanilla/drivers/isdn/hisax/rawhdlc.c Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/hisax/rawhdlc.c Mon Jul 19 23:59:34 1999 @@ -1,4 +1,4 @@ -/* $Id: rawhdlc.c,v 1.2 1998/02/09 10:53:51 keil Exp $ +/* $Id: rawhdlc.c,v 1.3 1998/06/17 19:51:21 he Exp $ * rawhdlc.c support routines for cards that don't support HDLC * diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/s0box.c linux.pre11.3/drivers/isdn/hisax/s0box.c --- linux.vanilla/drivers/isdn/hisax/s0box.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/s0box.c Mon Jul 19 23:59:34 1999 @@ -0,0 +1,267 @@ +/* $Id: s0box.c,v 2.2 1999/07/12 21:05:25 keil Exp $ + + * s0box.c low level stuff for Creatix S0BOX + * + * Author S0BOX specific stuff: Enrik Berkhan (enrik@starfleet.inka.de) + * + * + */ +#define __NO_VERSION__ +#include "hisax.h" +#include "isac.h" +#include "hscx.h" +#include "isdnl1.h" + +extern const char *CardType[]; +const char *s0box_revision = "$Revision: 2.2 $"; + +static inline void +writereg(unsigned int padr, signed int addr, u_char off, u_char val) { + unsigned long flags; + + save_flags(flags); + cli(); + outb_p(0x1c,padr+2); + outb_p(0x14,padr+2); + outb_p((addr+off)&0x7f,padr); + outb_p(0x16,padr+2); + outb_p(val,padr); + outb_p(0x17,padr+2); + outb_p(0x14,padr+2); + outb_p(0x1c,padr+2); + restore_flags(flags); +} + +static u_char nibtab[] = { 1, 9, 5, 0xd, 3, 0xb, 7, 0xf, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8, 4, 0xc, 2, 0xa, 6, 0xe } ; + +static inline u_char +readreg(unsigned int padr, signed int addr, u_char off) { + register u_char n1, n2; + unsigned long flags; + + save_flags(flags); + cli(); + outb_p(0x1c,padr+2); + outb_p(0x14,padr+2); + outb_p((addr+off)|0x80,padr); + outb_p(0x16,padr+2); + outb_p(0x17,padr+2); + n1 = (inb_p(padr+1) >> 3) & 0x17; + outb_p(0x16,padr+2); + n2 = (inb_p(padr+1) >> 3) & 0x17; + outb_p(0x14,padr+2); + outb_p(0x1c,padr+2); + restore_flags(flags); + return nibtab[n1] | (nibtab[n2] << 4); +} + +static inline void +read_fifo(unsigned int padr, signed int adr, u_char * data, int size) +{ + int i; + register u_char n1, n2; + + outb_p(0x1c, padr+2); + outb_p(0x14, padr+2); + outb_p(adr|0x80, padr); + outb_p(0x16, padr+2); + for (i=0; i> 3) & 0x17; + outb_p(0x16,padr+2); + n2 = (inb_p(padr+1) >> 3) & 0x17; + *(data++)=nibtab[n1] | (nibtab[n2] << 4); + } + outb_p(0x14,padr+2); + outb_p(0x1c,padr+2); + return; +} + +static inline void +write_fifo(unsigned int padr, signed int adr, u_char * data, int size) +{ + int i; + outb_p(0x1c, padr+2); + outb_p(0x14, padr+2); + outb_p(adr&0x7f, padr); + for (i=0; ihw.teles3.cfg_reg, cs->hw.teles3.isac, offset)); +} + +static void +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) +{ + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, offset, value); +} + +static void +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + read_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.isacfifo, data, size); +} + +static void +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + write_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.isacfifo, data, size); +} + +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) +{ + return (readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[hscx], offset)); +} + +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) +{ + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[hscx], offset, value); +} + +/* + * fast interrupt HSCX stuff goes here + */ + +#define READHSCX(cs, nr, reg) readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[nr], reg) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[nr], reg, data) +#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscxfifo[nr], ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscxfifo[nr], ptr, cnt) + +#include "hscx_irq.c" + +static void +s0box_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ +#define MAXCOUNT 5 + struct IsdnCardState *cs = dev_id; + u_char val; + int count = 0; + + if (!cs) { + printk(KERN_WARNING "Teles: Spurious interrupt!\n"); + return; + } + val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + count++; + val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA); + if (val && count < MAXCOUNT) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA); + if (val && count < MAXCOUNT) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + if (count >= MAXCOUNT) + printk(KERN_WARNING "S0Box: more than %d loops in s0box_interrupt\n", count); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0x0); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0x0); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0x0); +} + +void +release_io_s0box(struct IsdnCardState *cs) +{ + release_region(cs->hw.teles3.cfg_reg, 8); +} + +static int +S0Box_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + switch (mt) { + case CARD_RESET: + break; + case CARD_RELEASE: + release_io_s0box(cs); + break; + case CARD_INIT: + inithscxisac(cs, 3); + break; + case CARD_TEST: + break; + } + return(0); +} + +__initfunc(int +setup_s0box(struct IsdnCard *card)) +{ + struct IsdnCardState *cs = card->cs; + char tmp[64]; + + strcpy(tmp, s0box_revision); + printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_S0BOX) + return (0); + + cs->hw.teles3.cfg_reg = card->para[1]; + cs->hw.teles3.hscx[0] = -0x20; + cs->hw.teles3.hscx[1] = 0x0; + cs->hw.teles3.isac = 0x20; + cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e; + cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e; + cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e; + cs->irq = card->para[0]; + if (check_region(cs->hw.teles3.cfg_reg,8)) { + printk(KERN_WARNING + "HiSax: %s ports %x-%x already in use\n", + CardType[cs->typ], + cs->hw.teles3.cfg_reg, + cs->hw.teles3.cfg_reg + 7); + return 0; + } else + request_region(cs->hw.teles3.cfg_reg, 8, "S0Box parallel I/O"); + printk(KERN_INFO + "HiSax: %s config irq:%d isac:0x%x cfg:0x%x\n", + CardType[cs->typ], cs->irq, + cs->hw.teles3.isac, cs->hw.teles3.cfg_reg); + printk(KERN_INFO + "HiSax: hscx A:0x%x hscx B:0x%x\n", + cs->hw.teles3.hscx[0], cs->hw.teles3.hscx[1]); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &S0Box_card_msg; + cs->irq_func = &s0box_interrupt; + ISACVersion(cs, "S0Box:"); + if (HscxVersion(cs, "S0Box:")) { + printk(KERN_WARNING + "S0Box: wrong HSCX versions check IO address\n"); + release_io_s0box(cs); + return (0); + } + return (1); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/saphir.c linux.pre11.3/drivers/isdn/hisax/saphir.c --- linux.vanilla/drivers/isdn/hisax/saphir.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/saphir.c Mon Jul 19 23:59:34 1999 @@ -0,0 +1,326 @@ +/* $Id: saphir.c,v 1.3 1999/07/12 21:05:26 keil Exp $ + + * saphir.c low level stuff for HST Saphir 1 + * + * Author Karsten Keil (keil@isdn4linux.de) + * + * Thanks to HST High Soft Tech GmbH + * + * + * $Log: saphir.c,v $ + * Revision 1.3 1999/07/12 21:05:26 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 1.2 1999/07/01 08:07:55 keil + * Initial version + * + * + */ + + +#define __NO_VERSION__ +#include "hisax.h" +#include "isac.h" +#include "hscx.h" +#include "isdnl1.h" + +extern const char *CardType[]; +static char *saphir_rev = "$Revision: 1.3 $"; + +#define byteout(addr,val) outb(val,addr) +#define bytein(addr) inb(addr) + +#define ISAC_DATA 0 +#define HSCX_DATA 1 +#define ADDRESS_REG 2 +#define IRQ_REG 3 +#define SPARE_REG 4 +#define RESET_REG 5 + +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) +{ + register u_char ret; + long flags; + + save_flags(flags); + cli(); + byteout(ale, off); + ret = bytein(adr); + restore_flags(flags); + return (ret); +} + +static inline void +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) +{ + /* fifo read without cli because it's allready done */ + + byteout(ale, off); + insb(adr, data, size); +} + + +static inline void +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) +{ + long flags; + + save_flags(flags); + cli(); + byteout(ale, off); + byteout(adr, data); + restore_flags(flags); +} + +static inline void +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) +{ + /* fifo write without cli because it's allready done */ + byteout(ale, off); + outsb(adr, data, size); +} + +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) +{ + return (readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset)); +} + +static void +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) +{ + writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset, value); +} + +static void +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + readfifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size); +} + +static void +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + writefifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size); +} + +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) +{ + return (readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, + offset + (hscx ? 0x40 : 0))); +} + +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) +{ + writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, + offset + (hscx ? 0x40 : 0), value); +} + +#define READHSCX(cs, nr, reg) readreg(cs->hw.saphir.ale, \ + cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.saphir.ale, \ + cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0), data) + +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.saphir.ale, \ + cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.saphir.ale, \ + cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#include "hscx_irq.c" + +static void +saphir_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val; + + if (!cs) { + printk(KERN_WARNING "saphir: Spurious interrupt!\n"); + return; + } + val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40); + if (val) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA); + if (val) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + /* Watchdog */ + if (cs->hw.saphir.timer.function) { + del_timer(&cs->hw.saphir.timer); + cs->hw.saphir.timer.expires = jiffies + 1*HZ; + add_timer(&cs->hw.saphir.timer); + } else + printk(KERN_WARNING "saphir: Spurious timer!\n"); + writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0); + writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0); + writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0); +} + +static void +SaphirWatchDog(struct IsdnCardState *cs) +{ + /* 5 sec WatchDog, so read at least every 4 sec */ + cs->readisac(cs, ISAC_RBCH); + del_timer(&cs->hw.saphir.timer); + cs->hw.saphir.timer.expires = jiffies + 1*HZ; + add_timer(&cs->hw.saphir.timer); +} + +void +release_io_saphir(struct IsdnCardState *cs) +{ + long flags; + + save_flags(flags); + cli(); + byteout(cs->hw.saphir.cfg_reg + IRQ_REG, 0xff); + del_timer(&cs->hw.saphir.timer); + cs->hw.saphir.timer.function = NULL; + restore_flags(flags); + if (cs->hw.saphir.cfg_reg) + release_region(cs->hw.saphir.cfg_reg, 6); +} + +static int +saphir_reset(struct IsdnCardState *cs) +{ + long flags; + u_char irq_val; + + switch(cs->irq) { + case 5: irq_val = 0; + break; + case 3: irq_val = 1; + break; + case 11: + irq_val = 2; + break; + case 12: + irq_val = 3; + break; + case 15: + irq_val = 4; + break; + default: + printk(KERN_WARNING "HiSax: saphir wrong IRQ %d\n", + cs->irq); + 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); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((30*HZ)/1000); /* Timeout 30ms */ + byteout(cs->hw.saphir.cfg_reg + RESET_REG, 0); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((30*HZ)/1000); /* Timeout 30ms */ + restore_flags(flags); + byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val); + byteout(cs->hw.saphir.cfg_reg + SPARE_REG, 0x02); + return (0); +} + +static int +saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + switch (mt) { + case CARD_RESET: + saphir_reset(cs); + return(0); + case CARD_RELEASE: + release_io_saphir(cs); + return(0); + case CARD_INIT: + inithscxisac(cs, 3); + return(0); + case CARD_TEST: + return(0); + } + return(0); +} + + +__initfunc(int +setup_saphir(struct IsdnCard *card)) +{ + struct IsdnCardState *cs = card->cs; + char tmp[64]; + + strcpy(tmp, saphir_rev); + printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_HSTSAPHIR) + return (0); + + /* IO-Ports */ + cs->hw.saphir.cfg_reg = card->para[1]; + cs->hw.saphir.isac = card->para[1] + ISAC_DATA; + cs->hw.saphir.hscx = card->para[1] + HSCX_DATA; + cs->hw.saphir.ale = card->para[1] + ADDRESS_REG; + cs->irq = card->para[0]; + if (check_region((cs->hw.saphir.cfg_reg), 6)) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.saphir.cfg_reg, + cs->hw.saphir.cfg_reg + 5); + return (0); + } else + request_region(cs->hw.saphir.cfg_reg,6, "saphir"); + + printk(KERN_INFO + "HiSax: %s config irq:%d io:0x%X\n", + CardType[cs->typ], cs->irq, + cs->hw.saphir.cfg_reg); + + cs->hw.saphir.timer.function = (void *) SaphirWatchDog; + cs->hw.saphir.timer.data = (long) cs; + init_timer(&cs->hw.saphir.timer); + cs->hw.saphir.timer.expires = jiffies + 4*HZ; + add_timer(&cs->hw.saphir.timer); + if (saphir_reset(cs)) { + release_io_saphir(cs); + return (0); + } + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &saphir_card_msg; + cs->irq_func = &saphir_interrupt; + ISACVersion(cs, "saphir:"); + if (HscxVersion(cs, "saphir:")) { + printk(KERN_WARNING + "saphir: wrong HSCX versions check IO address\n"); + release_io_saphir(cs); + return (0); + } + return (1); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/sedlbauer.c linux.pre11.3/drivers/isdn/hisax/sedlbauer.c --- linux.vanilla/drivers/isdn/hisax/sedlbauer.c Sun Nov 8 15:10:15 1998 +++ linux.pre11.3/drivers/isdn/hisax/sedlbauer.c Mon Jul 19 23:59:34 1999 @@ -1,11 +1,14 @@ -/* $Id: sedlbauer.c,v 1.6 1998/02/09 18:46:06 keil Exp $ +/* $Id: sedlbauer.c,v 1.11 1999/07/12 21:05:27 keil Exp $ * sedlbauer.c low level stuff for Sedlbauer cards - * includes Support for the Sedlbauer Speed Star - * derived from the original file dynalink.c from Karsten Keil + * includes support for the Sedlbauer speed star (speed star II), + * support for the Sedlbauer speed fax+, + * support for the Sedlbauer ISDN-Controller PC/104 and + * support for the Sedlbauer speed pci + * derived from the original file asuscom.c from Karsten Keil * * Copyright (C) 1997,1998 Marcus Niemann (for the modifications to - * the original file dynalink.c) + * the original file asuscom.c) * * Author Marcus Niemann (niemann@www-bib.fh-bielefeld.de) * @@ -14,6 +17,22 @@ * Edgar Toernig * * $Log: sedlbauer.c,v $ + * Revision 1.11 1999/07/12 21:05:27 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 1.10 1999/07/01 08:12:09 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 1.9 1998/11/15 23:55:20 keil + * changes from 2.0 + * + * Revision 1.8 1998/08/13 23:34:51 keil + * starting speedfax+ (ISAR) support + * + * Revision 1.7 1998/04/15 16:44:33 keil + * new init code + * * Revision 1.6 1998/02/09 18:46:06 keil * Support for Sedlbauer PCMCIA (Marcus Niemann) * @@ -35,36 +54,94 @@ * */ +/* Supported cards: + * Card: Chip: Configuration: Comment: + * --------------------------------------------------------------------- + * Speed Card ISAC_HSCX DIP-SWITCH + * Speed Win ISAC_HSCX ISAPNP + * Speed Fax+ ISAC_ISAR ISAPNP #HDLC works# + * Speed Star ISAC_HSCX CARDMGR + * Speed Win2 IPAC ISAPNP + * ISDN PC/104 IPAC DIP-SWITCH + * Speed Star2 IPAC CARDMGR + * Speed PCI IPAC PNP + * + * Important: + * For the sedlbauer speed fax+ to work properly you have to download + * the firmware onto the card. + * For example: hisaxctrl 9 ISAR.BIN +*/ + +#define SEDLBAUER_PCI 1 + #define __NO_VERSION__ +#include #include "hisax.h" #include "isac.h" +#include "ipac.h" #include "hscx.h" +#include "isar.h" #include "isdnl1.h" +#include +#ifndef COMPAT_HAS_NEW_PCI +#include +#endif extern const char *CardType[]; -const char *Sedlbauer_revision = "$Revision: 1.6 $"; +const char *Sedlbauer_revision = "$Revision: 1.11 $"; const char *Sedlbauer_Types[] = -{"None", "Speed Card", "Speed Win", "Speed Star"}; + {"None", "speed card/win", "speed star", "speed fax+", + "speed win II / ISDN PC/104", "speed star II", "speed pci"}; + +#ifdef SEDLBAUER_PCI +#define PCI_VENDOR_SEDLBAUER 0xe159 +#define PCI_SPEEDPCI_ID 0x02 +#endif -#define SEDL_SPEED_CARD 1 -#define SEDL_SPEED_WIN 2 -#define SEDL_SPEED_STAR 3 +#define SEDL_SPEED_CARD_WIN 1 +#define SEDL_SPEED_STAR 2 +#define SEDL_SPEED_FAX 3 +#define SEDL_SPEED_WIN2_PC104 4 +#define SEDL_SPEED_STAR2 5 +#define SEDL_SPEED_PCI 6 + +#define SEDL_CHIP_TEST 0 +#define SEDL_CHIP_ISAC_HSCX 1 +#define SEDL_CHIP_ISAC_ISAR 2 +#define SEDL_CHIP_IPAC 3 + +#define SEDL_BUS_ISA 1 +#define SEDL_BUS_PCI 2 +#define SEDL_BUS_PCMCIA 3 #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -#define SEDL_RESET_ON 0 -#define SEDL_RESET_OFF 1 -#define SEDL_ISAC 2 -#define SEDL_HSCX 3 -#define SEDL_ADR 4 - -#define SEDL_PCMCIA_RESET 0 -#define SEDL_PCMCIA_ISAC 1 -#define SEDL_PCMCIA_HSCX 2 -#define SEDL_PCMCIA_ADR 4 +#define SEDL_HSCX_ISA_RESET_ON 0 +#define SEDL_HSCX_ISA_RESET_OFF 1 +#define SEDL_HSCX_ISA_ISAC 2 +#define SEDL_HSCX_ISA_HSCX 3 +#define SEDL_HSCX_ISA_ADR 4 + +#define SEDL_HSCX_PCMCIA_RESET 0 +#define SEDL_HSCX_PCMCIA_ISAC 1 +#define SEDL_HSCX_PCMCIA_HSCX 2 +#define SEDL_HSCX_PCMCIA_ADR 4 + +#define SEDL_ISAR_ISA_ISAC 4 +#define SEDL_ISAR_ISA_ISAR 6 +#define SEDL_ISAR_ISA_ADR 8 +#define SEDL_ISAR_ISA_ISAR_RESET_ON 10 +#define SEDL_ISAR_ISA_ISAR_RESET_OFF 12 + +#define SEDL_IPAC_ANY_ADR 0 +#define SEDL_IPAC_ANY_IPAC 2 + +#define SEDL_IPAC_PCI_BASE 0 +#define SEDL_IPAC_PCI_ADR 0xc0 +#define SEDL_IPAC_PCI_IPAC 0xc8 #define SEDL_RESET 0x3 /* same as DOS driver */ @@ -139,6 +216,29 @@ } static u_char +ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset) +{ + return (readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80));} + +static void +WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) +{ + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80, value); +} + +static void +ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) +{ + readfifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size); +} + +static void +WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) +{ + writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size); +} + +static u_char ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { return (readreg(cs->hw.sedl.adr, @@ -152,6 +252,34 @@ cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0), value); } +/* ISAR access routines + * mode = 0 access with IRQ on + * mode = 1 access with IRQ off + * mode = 2 access with IRQ off and using last offset + */ + +static u_char +ReadISAR(struct IsdnCardState *cs, int mode, u_char offset) +{ + if (mode == 0) + return (readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset)); + else if (mode == 1) + byteout(cs->hw.sedl.adr, offset); + return(bytein(cs->hw.sedl.hscx)); +} + +static void +WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value) +{ + if (mode == 0) + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset, value); + else { + if (mode == 1) + byteout(cs->hw.sedl.adr, offset); + byteout(cs->hw.sedl.hscx, value); + } +} + /* * fast interrupt HSCX stuff goes here */ @@ -173,14 +301,14 @@ sedlbauer_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u_char val, stat = 0; + u_char val; if (!cs) { printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n"); return; } - if ((cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) && (*cs->busy_flag == 1)) { + if ((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && (*cs->busy_flag == 1)) { /* The card tends to generate interrupts while being removed causing us to just crash the kernel. bad. */ printk(KERN_WARNING "Sedlbauer: card not available!\n"); @@ -189,16 +317,12 @@ val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40); Start_HSCX: - if (val) { + if (val) hscx_int_main(cs, val); - stat |= 1; - } val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA); Start_ISAC: - if (val) { + if (val) isac_interrupt(cs, val); - stat |= 2; - } val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40); if (val) { if (cs->debug & L1_DEB_HSCX) @@ -211,23 +335,109 @@ debugl1(cs, "ISAC IntStat after IntRoutine"); goto Start_ISAC; } - if (stat & 1) { - writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0xFF); - writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0xFF); - writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0x0); - writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0x0); - } - if (stat & 2) { - writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF); - writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0x0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0x0); +} + +static void +sedlbauer_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char ista, val, icnt = 5; + + if (!cs) { + printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n"); + return; + } + ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA); +Start_IPAC: + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); + if (ista & 0x0f) { + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) + hscx_int_main(cs, val); + } + if (ista & 0x20) { + val = 0xfe & readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA | 0x80); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); } + ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA); + if ((ista & 0x3f) && icnt) { + icnt--; + goto Start_IPAC; + } + if (!icnt) + printk(KERN_WARNING "Sedlbauer IRQ LOOP\n"); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xFF); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xC0); +} + +static void +sedlbauer_interrupt_isar(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val; + int cnt = 5; + + if (!cs) { + printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n"); + return; + } + + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT); + Start_ISAR: + if (val & ISAR_IRQSTA) + isar_int_main(cs); + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT); + if ((val & ISAR_IRQSTA) && --cnt) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "ISAR IntStat after IntRoutine"); + goto Start_ISAR; + } + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA); + if (val && --cnt) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + if (!cnt) + printk(KERN_WARNING "Sedlbauer IRQ LOOP\n"); + + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, 0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, ISAR_IRQMSK); } void release_io_sedlbauer(struct IsdnCardState *cs) { - int bytecnt = 8; + int bytecnt = (cs->subtyp == SEDL_SPEED_FAX) ? 16 : 8; + if (cs->hw.sedl.bus == SEDL_BUS_PCI) { + bytecnt = 256; + } if (cs->hw.sedl.cfg_reg) release_region(cs->hw.sedl.cfg_reg, bytecnt); } @@ -237,16 +447,36 @@ { long flags; - if (cs->typ != ISDN_CTYPE_SEDLBAUER_PCMCIA) { - byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */ - save_flags(flags); - sti(); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - restore_flags(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(); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10*HZ)/1000); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x0); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10*HZ)/1000); + 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 { + byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */ + save_flags(flags); + sti(); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10*HZ)/1000); + byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((10*HZ)/1000); + restore_flags(flags); + } } } @@ -260,95 +490,274 @@ case CARD_RELEASE: release_io_sedlbauer(cs); return(0); - case CARD_SETIRQ: - return(request_irq(cs->irq, &sedlbauer_interrupt, - I4L_IRQ_FLAG, "HiSax", cs)); case CARD_INIT: - clear_pending_isac_ints(cs); - clear_pending_hscx_ints(cs); - initisac(cs); - inithscx(cs); + if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { + clear_pending_isac_ints(cs); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, + ISAR_IRQBIT, 0); + initisac(cs); + initisar(cs); + /* Reenable all IRQ */ + cs->writeisac(cs, ISAC_MASK, 0); + /* RESET Receiver and Transmitter */ + cs->writeisac(cs, ISAC_CMDR, 0x41); + } else { + inithscxisac(cs, 3); + } return(0); case CARD_TEST: return(0); + case CARD_LOAD_FIRM: + if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { + if (isar_load_firmware(cs, arg)) + return(1); + else + ll_run(cs); + } + return(0); } return(0); } + +#ifdef SEDLBAUER_PCI +#ifdef COMPAT_HAS_NEW_PCI +static struct pci_dev *dev_sedl __initdata = NULL; +#else +static int pci_index __initdata = 0; +#endif +#endif + __initfunc(int setup_sedlbauer(struct IsdnCard *card)) { - int bytecnt; + int bytecnt, ver, val; struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, Sedlbauer_revision); printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ == ISDN_CTYPE_SEDLBAUER) { - cs->subtyp = SEDL_SPEED_CARD; + cs->subtyp = SEDL_SPEED_CARD_WIN; + cs->hw.sedl.bus = SEDL_BUS_ISA; + cs->hw.sedl.chip = SEDL_CHIP_TEST; } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) { cs->subtyp = SEDL_SPEED_STAR; + cs->hw.sedl.bus = SEDL_BUS_PCMCIA; + cs->hw.sedl.chip = SEDL_CHIP_TEST; + } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) { + cs->subtyp = SEDL_SPEED_FAX; + cs->hw.sedl.bus = SEDL_BUS_ISA; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; } else return (0); bytecnt = 8; - cs->hw.sedl.cfg_reg = card->para[1]; - cs->irq = card->para[0]; - if (cs->subtyp == SEDL_SPEED_STAR) { - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_HSCX; - cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_RESET; - cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_RESET; + if (card->para[1]) { + cs->hw.sedl.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { + bytecnt = 16; + } } else { - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX; - cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_RESET_ON; - cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_RESET_OFF; - } - - /* In case of the sedlbauer pcmcia card, this region is in use, +/* Probe for Sedlbauer speed pci */ +#if SEDLBAUER_PCI +#if CONFIG_PCI +#ifdef COMPAT_HAS_NEW_PCI + if (!pci_present()) { + printk(KERN_ERR "FritzPCI: no PCI bus present\n"); + return(0); + } + if ((dev_sedl = pci_find_device(PCI_VENDOR_SEDLBAUER, + PCI_SPEEDPCI_ID, dev_sedl))) { + cs->irq = dev_sedl->irq; + if (!cs->irq) { + printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n"); + return(0); + } + cs->hw.sedl.cfg_reg = dev_sedl->base_address[0] & + PCI_BASE_ADDRESS_IO_MASK; + } else { + printk(KERN_WARNING "Sedlbauer: No PCI card found\n"); + return(0); + } +#else + for (; pci_index < 255; pci_index++) { + unsigned char pci_bus, pci_device_fn; + unsigned int ioaddr; + unsigned char irq; + + if (pcibios_find_device (PCI_VENDOR_SEDLBAUER, + PCI_SPEEDPCI_ID, pci_index, + &pci_bus, &pci_device_fn) != 0) { + continue; + } + pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_INTERRUPT_LINE, &irq); + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_0, &ioaddr); + cs->irq = irq; + cs->hw.sedl.cfg_reg = ioaddr & PCI_BASE_ADDRESS_IO_MASK; + if (!cs->hw.sedl.cfg_reg) { + printk(KERN_WARNING "Sedlbauer: No IO-Adr for PCI card found\n"); + return(0); + } + break; + } + if (pci_index == 255) { + printk(KERN_WARNING "Sedlbauer: No PCI card found\n"); + return(0); + } + pci_index++; +#endif /* COMPAT_HAS_NEW_PCI */ + cs->irq_flags |= SA_SHIRQ; + cs->hw.sedl.bus = SEDL_BUS_PCI; + cs->hw.sedl.chip = SEDL_CHIP_IPAC; + cs->subtyp = SEDL_SPEED_PCI; + bytecnt = 256; + byteout(cs->hw.sedl.cfg_reg, 0xff); + byteout(cs->hw.sedl.cfg_reg, 0x00); + byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd); + byteout(cs->hw.sedl.cfg_reg+ 5, 0x02); +#else + printk(KERN_WARNING "Sedlbauer: NO_PCI_BIOS\n"); + return (0); +#endif /* CONFIG_PCI */ +#endif /* SEDLBAUER_PCI */ + } + + /* In case of the sedlbauer pcmcia card, this region is in use, reserved for us by the card manager. So we do not check it here, it would fail. */ - if (cs->typ != ISDN_CTYPE_SEDLBAUER_PCMCIA && - check_region((cs->hw.sedl.cfg_reg), bytecnt)) { + if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA && + check_region((cs->hw.sedl.cfg_reg), bytecnt)) { printk(KERN_WARNING - "HiSax: %s config port %x-%x already in use\n", - CardType[card->typ], - cs->hw.sedl.cfg_reg, - cs->hw.sedl.cfg_reg + bytecnt); - return (0); + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.sedl.cfg_reg, + cs->hw.sedl.cfg_reg + bytecnt); + return (0); } else { request_region(cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn"); } printk(KERN_INFO - "Sedlbauer: defined at 0x%x IRQ %d\n", + "Sedlbauer: defined at 0x%x-0x%x IRQ %d\n", cs->hw.sedl.cfg_reg, + cs->hw.sedl.cfg_reg + bytecnt, cs->irq); - printk(KERN_WARNING - "Sedlbauer %s uses ports 0x%x-0x%x\n", - Sedlbauer_Types[cs->subtyp], - cs->hw.sedl.cfg_reg, - cs->hw.sedl.cfg_reg + bytecnt); - printk(KERN_INFO "Sedlbauer: resetting card\n"); - reset_sedlbauer(cs); - cs->readisac = &ReadISAC; - cs->writeisac = &WriteISAC; - cs->readisacfifo = &ReadISACfifo; - cs->writeisacfifo = &WriteISACfifo; cs->BC_Read_Reg = &ReadHSCX; cs->BC_Write_Reg = &WriteHSCX; cs->BC_Send_Data = &hscx_fill_fifo; cs->cardmsg = &Sedl_card_msg; - ISACVersion(cs, "Sedlbauer:"); - if (HscxVersion(cs, "Sedlbauer:")) { - printk(KERN_WARNING - "Sedlbauer: wrong HSCX versions check IO address\n"); - release_io_sedlbauer(cs); - return (0); + +/* + * testing ISA and PCMCIA Cards for IPAC, default is ISAC + * do not test for PCI card, because ports are different + * and PCI card uses only IPAC (for the moment) + */ + if (cs->hw.sedl.bus != SEDL_BUS_PCI) { + val = readreg(cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR, + cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID); + if (val == 1) { + /* IPAC */ + cs->subtyp = SEDL_SPEED_WIN2_PC104; + if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) { + cs->subtyp = SEDL_SPEED_STAR2; + } + cs->hw.sedl.chip = SEDL_CHIP_IPAC; + } else { + /* ISAC_HSCX oder ISAC_ISAR */ + if (cs->hw.sedl.chip == SEDL_CHIP_TEST) { + cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX; + } + } + } + +/* + * hw.sedl.chip is now properly set + */ + printk(KERN_INFO "Sedlbauer: %s detected\n", + Sedlbauer_Types[cs->subtyp]); + + + if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) { + /* IPAC */ + if (cs->hw.sedl.bus == SEDL_BUS_PCI) { + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC; + } else { + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; + } + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + cs->readisac = &ReadISAC_IPAC; + cs->writeisac = &WriteISAC_IPAC; + cs->readisacfifo = &ReadISACfifo_IPAC; + cs->writeisacfifo = &WriteISACfifo_IPAC; + cs->irq_func = &sedlbauer_interrupt_ipac; + + val = readreg(cs->hw.sedl.adr,cs->hw.sedl.isac, IPAC_ID); + printk(KERN_INFO "Sedlbauer: IPAC version %x\n", val); + reset_sedlbauer(cs); + } else { + /* ISAC_HSCX oder ISAC_ISAR */ + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR; + cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_ON; + cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_OFF; + cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar; + cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar; + test_and_set_bit(HW_ISAR, &cs->HW_Flags); + cs->irq_func = &sedlbauer_interrupt_isar; + + ISACVersion(cs, "Sedlbauer:"); + + 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); + release_io_sedlbauer(cs); + return (0); + } + } else { + if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) { + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX; + cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; + cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; + } else { + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX; + cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON; + cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF; + } + cs->irq_func = &sedlbauer_interrupt; + ISACVersion(cs, "Sedlbauer:"); + + if (HscxVersion(cs, "Sedlbauer:")) { + printk(KERN_WARNING + "Sedlbauer: wrong HSCX versions check IO address\n"); + release_io_sedlbauer(cs); + return (0); + } + reset_sedlbauer(cs); + } } return (1); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/sportster.c linux.pre11.3/drivers/isdn/hisax/sportster.c --- linux.vanilla/drivers/isdn/hisax/sportster.c Sun Nov 8 15:10:15 1998 +++ linux.pre11.3/drivers/isdn/hisax/sportster.c Mon Jul 19 23:59:34 1999 @@ -1,4 +1,4 @@ -/* $Id: sportster.c,v 1.5 1998/02/02 13:29:46 keil Exp $ +/* $Id: sportster.c,v 1.9 1999/07/12 21:05:29 keil Exp $ * sportster.c low level stuff for USR Sportster internal TA * @@ -7,6 +7,19 @@ * Thanks to Christian "naddy" Weisgerber (3Com, US Robotics) for documentation * * $Log: sportster.c,v $ + * Revision 1.9 1999/07/12 21:05:29 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 1.8 1999/07/01 08:12:10 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 1.7 1998/11/15 23:55:22 keil + * changes from 2.0 + * + * Revision 1.6 1998/04/15 16:44:35 keil + * new init code + * * Revision 1.5 1998/02/02 13:29:46 keil * fast io * @@ -30,7 +43,7 @@ #include "isdnl1.h" extern const char *CardType[]; -const char *sportster_revision = "$Revision: 1.5 $"; +const char *sportster_revision = "$Revision: 1.9 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -165,11 +178,11 @@ save_flags(flags); sti(); current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); + schedule_timeout((10*HZ)/1000); cs->hw.spt.res_irq &= ~SPORTSTER_RESET; /* Reset Off */ byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); + schedule_timeout((10*HZ)/1000); restore_flags(flags); } @@ -183,16 +196,11 @@ case CARD_RELEASE: release_io_sportster(cs); return(0); - case CARD_SETIRQ: - return(request_irq(cs->irq, &sportster_interrupt, - I4L_IRQ_FLAG, "HiSax", cs)); case CARD_INIT: - clear_pending_isac_ints(cs); - clear_pending_hscx_ints(cs); - initisac(cs); - inithscx(cs); + inithscxisac(cs, 1); cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */ byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); + inithscxisac(cs, 2); return(0); case CARD_TEST: return(0); @@ -278,6 +286,7 @@ cs->BC_Write_Reg = &WriteHSCX; cs->BC_Send_Data = &hscx_fill_fifo; cs->cardmsg = &Sportster_card_msg; + cs->irq_func = &sportster_interrupt; ISACVersion(cs, "Sportster:"); if (HscxVersion(cs, "Sportster:")) { printk(KERN_WARNING diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/tei.c linux.pre11.3/drivers/isdn/hisax/tei.c --- linux.vanilla/drivers/isdn/hisax/tei.c Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/hisax/tei.c Mon Jul 19 23:59:34 1999 @@ -1,12 +1,37 @@ -/* $Id: tei.c,v 2.7 1998/02/12 23:08:11 keil Exp $ +/* $Id: tei.c,v 2.12 1999/07/01 08:12:11 keil Exp $ - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden * + * This file is (c) under GNU PUBLIC LICENSE + * For changes and modifications please read + * ../../../Documentation/isdn/HiSax.cert + * * Thanks to Jan den Ouden * Fritz Elfert * * $Log: tei.c,v $ + * Revision 2.12 1999/07/01 08:12:11 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 2.11 1998/11/15 23:55:24 keil + * changes from 2.0 + * + * Revision 2.10 1998/05/25 14:08:10 keil + * HiSax 3.0 + * fixed X.75 and leased line to work again + * Point2Point and fixed TEI are runtime options now: + * hisaxctrl 7 1 set PTP + * hisaxctrl 8 + * set fixed TEI to TEIVALUE (0-63) + * + * Revision 2.9 1998/05/25 12:58:23 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * + * Revision 2.8 1998/03/07 22:57:07 tsbogend + * made HiSax working on Linux/Alpha + * * Revision 2.7 1998/02/12 23:08:11 keil * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * @@ -50,7 +75,7 @@ #include "isdnl2.h" #include -const char *tei_revision = "$Revision: 2.7 $"; +const char *tei_revision = "$Revision: 2.12 $"; #define ID_REQUEST 1 #define ID_ASSIGNED 2 @@ -141,6 +166,7 @@ printk(KERN_WARNING "HiSax: No skb for TEI manager\n"); return; } + SET_SKB_FREE(skb); bp = skb_put(skb, 3); bp[0] = (TEI_SAPI << 2); bp[1] = (GROUP_TEI << 1) | 0x1; @@ -151,26 +177,24 @@ bp[2] = ri & 0xff; bp[3] = m_id; bp[4] = (tei << 1) | 1; - st->l2.l2l1(st, PH_DATA_REQ, skb); + st->l2.l2l1(st, PH_DATA | REQUEST, skb); } static void tei_id_request(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; - char tmp[64]; if (st->l2.tei != -1) { - sprintf(tmp, "assign request for allready asigned tei %d", + st->ma.tei_m.printdebug(&st->ma.tei_m, + "assign request for allready asigned tei %d", st->l2.tei); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); return; } st->ma.ri = random_ri(); - if (st->ma.debug) { - sprintf(tmp, "assign request ri %d", st->ma.ri); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); - } + if (st->ma.debug) + st->ma.tei_m.printdebug(&st->ma.tei_m, + "assign request ri %d", st->ma.ri); put_tei_msg(st, ID_REQUEST, st->ma.ri, 127); FsmChangeState(&st->ma.tei_m, ST_TEI_IDREQ); FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 1); @@ -184,26 +208,24 @@ struct sk_buff *skb = arg; struct IsdnCardState *cs; int ri, tei; - char tmp[64]; ri = ((unsigned int) skb->data[1] << 8) + skb->data[2]; tei = skb->data[4] >> 1; - if (st->ma.debug) { - sprintf(tmp, "identity assign ri %d tei %d", ri, tei); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); - } + if (st->ma.debug) + st->ma.tei_m.printdebug(&st->ma.tei_m, + "identity assign ri %d tei %d", ri, tei); if ((ost = findtei(st, tei))) { /* same tei is in use */ if (ri != ost->ma.ri) { - sprintf(tmp, "possible duplicate assignment tei %d", tei); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); - ost->l2.l2tei(ost, MDL_ERROR_REQ, NULL); + st->ma.tei_m.printdebug(&st->ma.tei_m, + "possible duplicate assignment tei %d", tei); + ost->l2.l2tei(ost, MDL_ERROR | RESPONSE, NULL); } } else if (ri == st->ma.ri) { FsmDelTimer(&st->ma.t202, 1); FsmChangeState(&st->ma.tei_m, ST_TEI_NOP); - st->ma.manl2(st, MDL_ASSIGN_REQ, (void *) (int) tei); + st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) tei); cs = (struct IsdnCardState *) st->l1.hardware; - cs->cardmsg(cs, MDL_ASSIGN_REQ, NULL); + cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL); } } @@ -213,14 +235,12 @@ struct PStack *st = fi->userdata; struct sk_buff *skb = arg; int ri, tei; - char tmp[64]; ri = ((unsigned int) skb->data[1] << 8) + skb->data[2]; tei = skb->data[4] >> 1; - if (st->ma.debug) { - sprintf(tmp, "identity denied ri %d tei %d", ri, tei); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); - } + if (st->ma.debug) + st->ma.tei_m.printdebug(&st->ma.tei_m, + "identity denied ri %d tei %d", ri, tei); } static void @@ -229,13 +249,11 @@ struct PStack *st = fi->userdata; struct sk_buff *skb = arg; int tei; - char tmp[64]; tei = skb->data[4] >> 1; - if (st->ma.debug) { - sprintf(tmp, "identity check req tei %d", tei); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); - } + if (st->ma.debug) + st->ma.tei_m.printdebug(&st->ma.tei_m, + "identity check req tei %d", tei); if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) { FsmDelTimer(&st->ma.t202, 4); FsmChangeState(&st->ma.tei_m, ST_TEI_NOP); @@ -250,19 +268,17 @@ struct sk_buff *skb = arg; struct IsdnCardState *cs; int tei; - char tmp[64]; tei = skb->data[4] >> 1; - if (st->ma.debug) { - sprintf(tmp, "identity remove tei %d", tei); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); - } + if (st->ma.debug) + st->ma.tei_m.printdebug(&st->ma.tei_m, + "identity remove tei %d", tei); if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) { FsmDelTimer(&st->ma.t202, 5); FsmChangeState(&st->ma.tei_m, ST_TEI_NOP); - st->ma.manl2(st, MDL_REMOVE_REQ, 0); + st->l3.l3l2(st, MDL_REMOVE | REQUEST, 0); cs = (struct IsdnCardState *) st->l1.hardware; - cs->cardmsg(cs, MDL_REMOVE_REQ, NULL); + cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL); } } @@ -270,12 +286,10 @@ tei_id_verify(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; - char tmp[64]; - if (st->ma.debug) { - sprintf(tmp, "id verify request for tei %d", st->l2.tei); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); - } + if (st->ma.debug) + st->ma.tei_m.printdebug(&st->ma.tei_m, + "id verify request for tei %d", st->l2.tei); put_tei_msg(st, ID_VERIFY, 0, st->l2.tei); FsmChangeState(&st->ma.tei_m, ST_TEI_IDVERIFY); FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 2); @@ -286,24 +300,21 @@ tei_id_req_tout(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; - char tmp[64]; struct IsdnCardState *cs; if (--st->ma.N202) { st->ma.ri = random_ri(); - if (st->ma.debug) { - sprintf(tmp, "assign req(%d) ri %d", - 4 - st->ma.N202, st->ma.ri); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); - } + if (st->ma.debug) + st->ma.tei_m.printdebug(&st->ma.tei_m, + "assign req(%d) ri %d", 4 - st->ma.N202, + st->ma.ri); put_tei_msg(st, ID_REQUEST, st->ma.ri, 127); FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 3); } else { - sprintf(tmp, "assign req failed"); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); - st->ma.manl2(st, MDL_ERROR_IND, 0); + st->ma.tei_m.printdebug(&st->ma.tei_m, "assign req failed"); + st->l3.l3l2(st, MDL_ERROR | RESPONSE, 0); cs = (struct IsdnCardState *) st->l1.hardware; - cs->cardmsg(cs, MDL_REMOVE_REQ, NULL); + cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL); FsmChangeState(fi, ST_TEI_NOP); } } @@ -312,23 +323,21 @@ tei_id_ver_tout(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; - char tmp[64]; struct IsdnCardState *cs; if (--st->ma.N202) { - if (st->ma.debug) { - sprintf(tmp, "id verify req(%d) for tei %d", + if (st->ma.debug) + st->ma.tei_m.printdebug(&st->ma.tei_m, + "id verify req(%d) for tei %d", 3 - st->ma.N202, st->l2.tei); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); - } put_tei_msg(st, ID_VERIFY, 0, st->l2.tei); FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 4); } else { - sprintf(tmp, "verify req for tei %d failed", st->l2.tei); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); - st->ma.manl2(st, MDL_REMOVE_REQ, 0); + st->ma.tei_m.printdebug(&st->ma.tei_m, + "verify req for tei %d failed", st->l2.tei); + st->l3.l3l2(st, MDL_REMOVE | REQUEST, 0); cs = (struct IsdnCardState *) st->l1.hardware; - cs->cardmsg(cs, MDL_REMOVE_REQ, NULL); + cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL); FsmChangeState(fi, ST_TEI_NOP); } } @@ -338,31 +347,34 @@ { struct sk_buff *skb = arg; int mt; - char tmp[64]; - if (pr == PH_DATA_IND) { + if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) { + idev_kfree_skb(skb, FREE_READ); + return; + } + + if (pr == (PH_DATA | INDICATION)) { if (skb->len < 3) { - sprintf(tmp, "short mgr frame %d/3", skb->len); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); - } else if (((skb->data[0] >> 2) != TEI_SAPI) || - ((skb->data[1] >> 1) != GROUP_TEI)) { - sprintf(tmp, "wrong mgr sapi/tei %x/%x", + st->ma.tei_m.printdebug(&st->ma.tei_m, + "short mgr frame %ld/3", skb->len); + } else if ((skb->data[0] != ((TEI_SAPI << 2) | 2)) || + (skb->data[1] != ((GROUP_TEI << 1) | 1))) { + st->ma.tei_m.printdebug(&st->ma.tei_m, + "wrong mgr sapi/tei %x/%x", skb->data[0], skb->data[1]); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); } else if ((skb->data[2] & 0xef) != UI) { - sprintf(tmp, "mgr frame is not ui %x", - skb->data[2]); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); + st->ma.tei_m.printdebug(&st->ma.tei_m, + "mgr frame is not ui %x", skb->data[2]); } else { skb_pull(skb, 3); if (skb->len < 5) { - sprintf(tmp, "short mgr frame %d/5", skb->len); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); + st->ma.tei_m.printdebug(&st->ma.tei_m, + "short mgr frame %ld/5", skb->len); } else if (skb->data[0] != TEI_ENTITY_ID) { /* wrong management entity identifier, ignore */ - sprintf(tmp, "tei handler wrong entity id %x\n", + st->ma.tei_m.printdebug(&st->ma.tei_m, + "tei handler wrong entity id %x", skb->data[0]); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); } else { mt = skb->data[3]; if (mt == ID_ASSIGNED) @@ -374,36 +386,39 @@ else if (mt == ID_REMOVE) FsmEvent(&st->ma.tei_m, EV_REMOVE, skb); else { - sprintf(tmp, "tei handler wrong mt %x\n", - mt); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); + st->ma.tei_m.printdebug(&st->ma.tei_m, + "tei handler wrong mt %x\n", mt); } } } } else { - sprintf(tmp, "tei handler wrong pr %x\n", pr); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); + st->ma.tei_m.printdebug(&st->ma.tei_m, + "tei handler wrong pr %x\n", pr); } - dev_kfree_skb(skb); + idev_kfree_skb(skb, FREE_READ); } static void tei_l2tei(struct PStack *st, int pr, void *arg) { + struct IsdnCardState *cs; + + if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) { + if (pr == (MDL_ASSIGN | INDICATION)) { + if (st->ma.debug) + st->ma.tei_m.printdebug(&st->ma.tei_m, + "fixed assign tei %d", st->l2.tei); + st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) st->l2.tei); + cs = (struct IsdnCardState *) st->l1.hardware; + cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL); + } + return; + } switch (pr) { - case (MDL_ASSIGN_IND): -#ifdef TEI_FIXED - if (st->ma.debug) { - char tmp[64]; - sprintf(tmp, "fixed assign tei %d", TEI_FIXED); - st->ma.tei_m.printdebug(&st->ma.tei_m, tmp); - } - st->ma.manl2(st, MDL_ASSIGN_REQ, (void *) (int) TEI_FIXED); -#else + case (MDL_ASSIGN | INDICATION): FsmEvent(&st->ma.tei_m, EV_IDREQ, arg); -#endif break; - case (MDL_ERROR_REQ): + case (MDL_ERROR | REQUEST): FsmEvent(&st->ma.tei_m, EV_VERIFY, arg); break; default: @@ -412,14 +427,14 @@ } static void -tei_debug(struct FsmInst *fi, char *s) +tei_debug(struct FsmInst *fi, char *fmt, ...) { + va_list args; struct PStack *st = fi->userdata; - char tm[32], str[256]; - jiftime(tm, jiffies); - sprintf(str, "%s Tei %s\n", tm, s); - HiSax_putstatus(st->l1.hardware, str); + va_start(args, fmt); + VHiSax_putstatus(st->l1.hardware, "tei ", fmt, args); + va_end(args); } void @@ -439,9 +454,8 @@ } void -init_tei(struct IsdnCardState *sp, int protocol) +init_tei(struct IsdnCardState *cs, int protocol) { - } void diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/teleint.c linux.pre11.3/drivers/isdn/hisax/teleint.c --- linux.vanilla/drivers/isdn/hisax/teleint.c Sun Nov 8 15:10:15 1998 +++ linux.pre11.3/drivers/isdn/hisax/teleint.c Mon Jul 19 23:59:34 1999 @@ -1,11 +1,24 @@ -/* $Id: teleint.c,v 1.5 1998/02/02 13:40:47 keil Exp $ +/* $Id: teleint.c,v 1.9 1999/07/12 21:05:30 keil Exp $ * teleint.c low level stuff for TeleInt isdn cards * - * Author Karsten Keil (keil@temic-ech.spacenet.de) + * Author Karsten Keil (keil@isdn4linux.de) * * * $Log: teleint.c,v $ + * Revision 1.9 1999/07/12 21:05:30 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 1.8 1999/07/01 08:12:12 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 1.7 1998/11/15 23:55:26 keil + * changes from 2.0 + * + * Revision 1.6 1998/04/15 16:45:31 keil + * new init code + * * Revision 1.5 1998/02/02 13:40:47 keil * fast io * @@ -32,7 +45,7 @@ extern const char *CardType[]; -const char *TeleInt_revision = "$Revision: 1.5 $"; +const char *TeleInt_revision = "$Revision: 1.9 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -64,17 +77,20 @@ readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { register u_char ret; - int max_delay = 2000; + register int max_delay = 20000; + register int i; + byteout(ale, off); - - ret = HFC_BUSY & bytein(ale); - while (ret && --max_delay) + for (i = 0; ihw.hfc.cip = reg; byteout(cs->hw.hfc.addr | 1, reg); ret = bytein(cs->hw.hfc.addr); - if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2)) { - char tmp[32]; - sprintf(tmp, "hfc RD %02x %02x", reg, ret); - debugl1(cs, tmp); - } + if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2)) + debugl1(cs, "hfc RD %02x %02x", reg, ret); } else ret = bytein(cs->hw.hfc.addr | 1); return (ret); @@ -174,18 +190,15 @@ cs->hw.hfc.cip = reg; if (data) byteout(cs->hw.hfc.addr, value); - if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2)) { - char tmp[32]; - sprintf(tmp, "hfc W%c %02x %02x", data ? 'D' : 'C', reg, value); - debugl1(cs, tmp); - } + if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2)) + debugl1(cs, "hfc W%c %02x %02x", data ? 'D' : 'C', reg, value); } static void TeleInt_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u_char val, stat = 0; + u_char val; if (!cs) { printk(KERN_WARNING "TeleInt: Spurious interrupt!\n"); @@ -193,20 +206,16 @@ } val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA); Start_ISAC: - if (val) { + if (val) isac_interrupt(cs, val); - stat |= 2; - } val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA); if (val) { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ISAC IntStat after IntRoutine"); goto Start_ISAC; } - if (stat & 2) { - writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0xFF); - writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0x0); - } + writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0xFF); + writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0x0); } static void @@ -246,11 +255,11 @@ save_flags(flags); sti(); current->state = TASK_INTERRUPTIBLE; - schedule_timeout(3); + schedule_timeout((30*HZ)/1000); cs->hw.hfc.cirm &= ~HFC_RESET; byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset Off */ current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); + schedule_timeout((10*HZ)/1000); restore_flags(flags); } @@ -264,13 +273,13 @@ case CARD_RELEASE: release_io_TeleInt(cs); return(0); - case CARD_SETIRQ: - return(request_irq(cs->irq, &TeleInt_interrupt, - I4L_IRQ_FLAG, "HiSax", cs)); case CARD_INIT: inithfc(cs); clear_pending_isac_ints(cs); initisac(cs); + /* Reenable all IRQ */ + cs->writeisac(cs, ISAC_MASK, 0); + cs->writeisac(cs, ISAC_CMDR, 0x41); cs->hw.hfc.timer.expires = jiffies + 1; add_timer(&cs->hw.hfc.timer); return(0); @@ -356,6 +365,7 @@ cs->BC_Read_Reg = &ReadHFC; cs->BC_Write_Reg = &WriteHFC; cs->cardmsg = &TeleInt_card_msg; + cs->irq_func = &TeleInt_interrupt; ISACVersion(cs, "TeleInt:"); return (1); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/teles0.c linux.pre11.3/drivers/isdn/hisax/teles0.c --- linux.vanilla/drivers/isdn/hisax/teles0.c Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/hisax/teles0.c Mon Jul 19 23:59:34 1999 @@ -1,4 +1,4 @@ -/* $Id: teles0.c,v 2.6 1998/02/03 23:27:47 keil Exp $ +/* $Id: teles0.c,v 2.9 1999/07/12 21:05:31 keil Exp $ * teles0.c low level stuff for Teles Memory IO isdn cards * based on the teles driver from Jan den Ouden @@ -10,6 +10,16 @@ * Beat Doebeli * * $Log: teles0.c,v $ + * Revision 2.9 1999/07/12 21:05:31 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 2.8 1998/04/15 16:44:28 keil + * new init code + * + * Revision 2.7 1998/03/07 22:57:08 tsbogend + * made HiSax working on Linux/Alpha + * * Revision 2.6 1998/02/03 23:27:47 keil * IRQ 9 * @@ -48,7 +58,7 @@ extern const char *CardType[]; -const char *teles0_revision = "$Revision: 2.6 $"; +const char *teles0_revision = "$Revision: 2.9 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -62,7 +72,7 @@ static inline void writeisac(unsigned int adr, u_char off, u_char data) { - writeb(data, adr + ((off & 1) ? 0x2ff : 0x100) + off); + writeb(data, adr + ((off & 1) ? 0x2ff : 0x100) + off); mb(); } @@ -77,14 +87,14 @@ writehscx(unsigned int adr, int hscx, u_char off, u_char data) { writeb(data, adr + (hscx ? 0x1c0 : 0x180) + - ((off & 1) ? 0x1ff : 0) + off); + ((off & 1) ? 0x1ff : 0) + off); mb(); } static inline void read_fifo_isac(unsigned int adr, u_char * data, int size) { register int i; - register u_char *ad = (u_char *) (adr + 0x100); + register u_char *ad = (u_char *) ((long)adr + 0x100); for (i = 0; i < size; i++) data[i] = readb(ad); } @@ -93,16 +103,17 @@ write_fifo_isac(unsigned int adr, u_char * data, int size) { register int i; - register u_char *ad = (u_char *) (adr + 0x100); - for (i = 0; i < size; i++) - writeb(data[i], ad); + register u_char *ad = (u_char *) ((long)adr + 0x100); + for (i = 0; i < size; i++) { + writeb(data[i], ad); mb(); + } } static inline void read_fifo_hscx(unsigned int adr, int hscx, u_char * data, int size) { register int i; - register u_char *ad = (u_char *) (adr + (hscx ? 0x1c0 : 0x180)); + register u_char *ad = (u_char *) ((long)adr + (hscx ? 0x1c0 : 0x180)); for (i = 0; i < size; i++) data[i] = readb(ad); } @@ -111,9 +122,10 @@ write_fifo_hscx(unsigned int adr, int hscx, u_char * data, int size) { int i; - register u_char *ad = (u_char *) (adr + (hscx ? 0x1c0 : 0x180)); - for (i = 0; i < size; i++) - writeb(data[i], ad); + register u_char *ad = (u_char *) ((long)adr + (hscx ? 0x1c0 : 0x180)); + for (i = 0; i < size; i++) { + writeb(data[i], ad); mb(); + } } /* Interface functions */ @@ -169,7 +181,7 @@ teles0_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u_char val, stat = 0; + u_char val; int count = 0; if (!cs) { @@ -178,39 +190,31 @@ } val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA); Start_HSCX: - if (val) { + if (val) hscx_int_main(cs, val); - stat |= 1; - } val = readisac(cs->hw.teles0.membase, ISAC_ISTA); Start_ISAC: - if (val) { + if (val) isac_interrupt(cs, val); - stat |= 2; - } count++; val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA); - if (val && count < 20) { + if (val && count < 5) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "HSCX IntStat after IntRoutine"); goto Start_HSCX; } val = readisac(cs->hw.teles0.membase, ISAC_ISTA); - if (val && count < 20) { + if (val && count < 5) { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ISAC IntStat after IntRoutine"); goto Start_ISAC; } - if (stat & 1) { - writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF); - writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF); - writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0); - writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0); - } - if (stat & 2) { - writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF); - writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0); - } + writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF); + writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF); + writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF); + writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0); + writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0); + writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0); } void @@ -264,9 +268,9 @@ byteout(cs->hw.teles0.cfg_reg + 4, cfval | 1); HZDELAY(HZ / 10 + 1); } - writeb(0, cs->hw.teles0.membase + 0x80); + writeb(0, cs->hw.teles0.membase + 0x80); mb(); HZDELAY(HZ / 5 + 1); - writeb(1, cs->hw.teles0.membase + 0x80); + writeb(1, cs->hw.teles0.membase + 0x80); mb(); HZDELAY(HZ / 5 + 1); restore_flags(flags); return(0); @@ -282,14 +286,8 @@ case CARD_RELEASE: release_io_teles0(cs); return(0); - case CARD_SETIRQ: - return(request_irq(cs->irq, &teles0_interrupt, - I4L_IRQ_FLAG, "HiSax", cs)); case CARD_INIT: - clear_pending_isac_ints(cs); - clear_pending_hscx_ints(cs); - initisac(cs); - inithscx(cs); + inithscxisac(cs, 3); return(0); case CARD_TEST: return(0); @@ -377,6 +375,7 @@ cs->BC_Write_Reg = &WriteHSCX; cs->BC_Send_Data = &hscx_fill_fifo; cs->cardmsg = &Teles_card_msg; + cs->irq_func = &teles0_interrupt; ISACVersion(cs, "Teles0:"); if (HscxVersion(cs, "Teles0:")) { printk(KERN_WARNING diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/teles3.c linux.pre11.3/drivers/isdn/hisax/teles3.c --- linux.vanilla/drivers/isdn/hisax/teles3.c Sun Nov 8 15:08:09 1998 +++ linux.pre11.3/drivers/isdn/hisax/teles3.c Mon Jul 19 23:59:34 1999 @@ -1,4 +1,4 @@ -/* $Id: teles3.c,v 2.7 1998/02/02 13:29:48 keil Exp $ +/* $Id: teles3.c,v 2.12 1999/07/12 21:05:32 keil Exp $ * teles3.c low level stuff for Teles 16.3 & PNP isdn cards * @@ -11,6 +11,22 @@ * Beat Doebeli * * $Log: teles3.c,v $ + * Revision 2.12 1999/07/12 21:05:32 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 2.11 1999/07/01 08:12:14 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 2.10 1999/02/15 14:37:15 cpetig + * oops, missed something in last commit + * + * Revision 2.9 1999/02/15 14:11:02 cpetig + * fixed a bug with Teles PCMCIA, it doesn't have a config register + * + * Revision 2.8 1998/04/15 16:44:30 keil + * new init code + * * Revision 2.7 1998/02/02 13:29:48 keil * fast io * @@ -69,7 +85,7 @@ #include "isdnl1.h" extern const char *CardType[]; -const char *teles3_revision = "$Revision: 2.7 $"; +const char *teles3_revision = "$Revision: 2.12 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -151,9 +167,9 @@ static void teles3_interrupt(int intno, void *dev_id, struct pt_regs *regs) { -#define MAXCOUNT 20 +#define MAXCOUNT 5 struct IsdnCardState *cs = dev_id; - u_char val, stat = 0; + u_char val; int count = 0; if (!cs) { @@ -162,16 +178,12 @@ } val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA); Start_HSCX: - if (val) { + if (val) hscx_int_main(cs, val); - stat |= 1; - } val = readreg(cs->hw.teles3.isac, ISAC_ISTA); Start_ISAC: - if (val) { + if (val) isac_interrupt(cs, val); - stat |= 2; - } count++; val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA); if (val && count < MAXCOUNT) { @@ -187,16 +199,12 @@ } if (count >= MAXCOUNT) printk(KERN_WARNING "Teles3: more than %d loops in teles3_interrupt\n", count); - if (stat & 1) { - writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF); - writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF); - writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0x0); - writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0x0); - } - if (stat & 2) { - writereg(cs->hw.teles3.isac, ISAC_MASK, 0xFF); - writereg(cs->hw.teles3.isac, ISAC_MASK, 0x0); - } + writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF); + writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF); + writereg(cs->hw.teles3.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.teles3.isac, ISAC_MASK, 0x0); + writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0x0); + writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0x0); } inline static void @@ -213,9 +221,9 @@ void release_io_teles3(struct IsdnCardState *cs) { - if (cs->typ == ISDN_CTYPE_TELESPCMCIA) - release_region(cs->hw.teles3.cfg_reg, 97); - else { + if (cs->typ == ISDN_CTYPE_TELESPCMCIA) { + release_region(cs->hw.teles3.hscx[0], 97); + } else { if (cs->hw.teles3.cfg_reg) { if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { release_region(cs->hw.teles3.cfg_reg, 1); @@ -301,14 +309,8 @@ case CARD_RELEASE: release_io_teles3(cs); return(0); - case CARD_SETIRQ: - return(request_irq(cs->irq, &teles3_interrupt, - I4L_IRQ_FLAG, "HiSax", cs)); case CARD_INIT: - clear_pending_isac_ints(cs); - clear_pending_hscx_ints(cs); - initisac(cs); - inithscx(cs); + inithscxisac(cs, 3); return(0); case CARD_TEST: return(0); @@ -342,7 +344,7 @@ cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20; cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820; } else if (cs->typ == ISDN_CTYPE_TELESPCMCIA) { - cs->hw.teles3.cfg_reg = card->para[1]; + cs->hw.teles3.cfg_reg = 0; cs->hw.teles3.hscx[0] = card->para[1] - 0x20; cs->hw.teles3.hscx[1] = card->para[1]; cs->hw.teles3.isac = card->para[1] + 0x20; @@ -362,12 +364,12 @@ cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e; cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e; if (cs->typ == ISDN_CTYPE_TELESPCMCIA) { - if (check_region((cs->hw.teles3.cfg_reg), 97)) { + if (check_region((cs->hw.teles3.hscx[0]), 97)) { printk(KERN_WARNING "HiSax: %s ports %x-%x already in use\n", CardType[cs->typ], - cs->hw.teles3.cfg_reg, - cs->hw.teles3.cfg_reg + 96); + cs->hw.teles3.hscx[0], + cs->hw.teles3.hscx[0] + 96); return (0); } else request_region(cs->hw.teles3.hscx[0], 97, "HiSax Teles PCMCIA"); @@ -492,6 +494,7 @@ cs->BC_Write_Reg = &WriteHSCX; cs->BC_Send_Data = &hscx_fill_fifo; cs->cardmsg = &Teles_card_msg; + cs->irq_func = &teles3_interrupt; ISACVersion(cs, "Teles3:"); if (HscxVersion(cs, "Teles3:")) { printk(KERN_WARNING diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/teles3c.c linux.pre11.3/drivers/isdn/hisax/teles3c.c --- linux.vanilla/drivers/isdn/hisax/teles3c.c Sun Nov 8 15:10:15 1998 +++ linux.pre11.3/drivers/isdn/hisax/teles3c.c Mon Jul 19 23:59:34 1999 @@ -1,196 +0,0 @@ -/* $Id: teles3c.c,v 1.2 1998/02/02 13:27:07 keil Exp $ - - * teles3c.c low level stuff for teles 16.3c - * - * Author Karsten Keil (keil@temic-ech.spacenet.de) - * - * - * $Log: teles3c.c,v $ - * Revision 1.2 1998/02/02 13:27:07 keil - * New - * - * - * - */ - -#define __NO_VERSION__ -#include "hisax.h" -#include "hfc_2bds0.h" -#include "isdnl1.h" - -extern const char *CardType[]; - -const char *teles163c_revision = "$Revision: 1.2 $"; - -static void -t163c_interrupt(int intno, void *dev_id, struct pt_regs *regs) -{ - struct IsdnCardState *cs = dev_id; - u_char val, stat; - char tmp[32]; - - if (!cs) { - printk(KERN_WARNING "teles3c: Spurious interrupt!\n"); - return; - } - if ((HFCD_ANYINT | HFCD_BUSY_NBUSY) & - (stat = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_STAT))) { - val = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_INT_S1); - if (cs->debug & L1_DEB_ISAC) { - sprintf(tmp, "teles3c: stat(%02x) s1(%02x)", stat, val); - debugl1(cs, tmp); - } - hfc2bds0_interrupt(cs, val); - } else { - if (cs->debug & L1_DEB_ISAC) { - sprintf(tmp, "teles3c: irq_no_irq stat(%02x)", stat); - debugl1(cs, tmp); - } - } -} - -static void -t163c_Timer(struct IsdnCardState *cs) -{ - cs->hw.hfcD.timer.expires = jiffies + 75; - /* WD RESET */ -/* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt | 0x80); - add_timer(&cs->hw.hfcD.timer); -*/ -} - -void -release_io_t163c(struct IsdnCardState *cs) -{ - release2bds0(cs); - del_timer(&cs->hw.hfcD.timer); - if (cs->hw.hfcD.addr) - release_region(cs->hw.hfcD.addr, 2); -} - -static void -reset_t163c(struct IsdnCardState *cs) -{ - long flags; - - printk(KERN_INFO "teles3c: resetting card\n"); - cs->hw.hfcD.cirm = HFCD_RESET | HFCD_MEM8K; - cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset On */ - save_flags(flags); - sti(); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(3); - cs->hw.hfcD.cirm = HFCD_MEM8K; - cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset Off */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - cs->hw.hfcD.cirm |= HFCD_INTB; - cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* INT B */ - cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CLKDEL, 0x0e); - cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_TEST, HFCD_AUTO_AWAKE); /* S/T Auto awake */ - cs->hw.hfcD.ctmt = HFCD_TIM25 | HFCD_AUTO_TIMER; - cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); - cs->hw.hfcD.int_m2 = HFCD_IRQ_ENABLE; - cs->hw.hfcD.int_m1 = HFCD_INTS_B1TRANS | HFCD_INTS_B2TRANS | - HFCD_INTS_DTRANS | HFCD_INTS_B1REC | HFCD_INTS_B2REC | - HFCD_INTS_DREC | HFCD_INTS_L1STATE; - cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M1, cs->hw.hfcD.int_m1); - cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M2, cs->hw.hfcD.int_m2); - cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, HFCD_LOAD_STATE | 2); /* HFC ST 2 */ - udelay(10); - cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, 2); /* HFC ST 2 */ - cs->hw.hfcD.mst_m = 0; - cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, HFCD_MASTER); /* 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 -t163c_card_msg(struct IsdnCardState *cs, int mt, void *arg) -{ - long flags; - char tmp[32]; - - if (cs->debug & L1_DEB_ISAC) { - - sprintf(tmp, "teles3c: card_msg %x", mt); - debugl1(cs, tmp); - } - switch (mt) { - case CARD_RESET: - reset_t163c(cs); - return(0); - case CARD_RELEASE: - release_io_t163c(cs); - return(0); - case CARD_SETIRQ: - cs->hw.hfcD.timer.expires = jiffies + 75; - add_timer(&cs->hw.hfcD.timer); - return(request_irq(cs->irq, &t163c_interrupt, - I4L_IRQ_FLAG, "HiSax", cs)); - case CARD_INIT: - init2bds0(cs); - save_flags(flags); - sti(); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout((80*HZ)/1000); - cs->hw.hfcD.ctmt |= HFCD_TIM800; - cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); - cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); - restore_flags(flags); - return(0); - case CARD_TEST: - return(0); - } - return(0); -} - -__initfunc(int -setup_t163c(struct IsdnCard *card)) -{ - struct IsdnCardState *cs = card->cs; - char tmp[64]; - - strcpy(tmp, teles163c_revision); - printk(KERN_INFO "HiSax: Teles 16.3c driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_TELES3C) - return (0); - cs->debug = 0xff; - cs->hw.hfcD.addr = card->para[1] & 0xfffe; - cs->irq = card->para[0]; - cs->hw.hfcD.cip = 0; - cs->hw.hfcD.int_s1 = 0; - cs->hw.hfcD.send = NULL; - cs->bcs[0].hw.hfc.send = NULL; - cs->bcs[1].hw.hfc.send = NULL; - cs->hw.hfcD.bfifosize = 1024 + 512; - cs->hw.hfcD.dfifosize = 512; - cs->ph_state = 0; - cs->hw.hfcD.fifo = 255; - if (check_region((cs->hw.hfcD.addr), 2)) { - printk(KERN_WARNING - "HiSax: %s config port %x-%x already in use\n", - CardType[card->typ], - cs->hw.hfcD.addr, - cs->hw.hfcD.addr + 2); - return (0); - } else { - request_region(cs->hw.hfcD.addr, 2, "teles3c isdn"); - } - /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */ - outb(0x00, cs->hw.hfcD.addr); - outb(0x56, cs->hw.hfcD.addr | 1); - printk(KERN_INFO - "teles3c: defined at 0x%x IRQ %d HZ %d\n", - cs->hw.hfcD.addr, - cs->irq, HZ); - - set_cs_func(cs); - cs->hw.hfcD.timer.function = (void *) t163c_Timer; - cs->hw.hfcD.timer.data = (long) cs; - init_timer(&cs->hw.hfcD.timer); - reset_t163c(cs); - cs->cardmsg = &t163c_card_msg; - return (1); -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/telespci.c linux.pre11.3/drivers/isdn/hisax/telespci.c --- linux.vanilla/drivers/isdn/hisax/telespci.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/hisax/telespci.c Mon Jul 19 23:59:34 1999 @@ -0,0 +1,406 @@ +/* $Id: telespci.c,v 2.7 1999/07/12 21:05:34 keil Exp $ + + * telespci.c low level stuff for Teles PCI isdn cards + * + * Author Ton van Rosmalen + * Karsten Keil (keil@temic-ech.spacenet.de) + * + * + * $Log: telespci.c,v $ + * Revision 2.7 1999/07/12 21:05:34 keil + * fix race in IRQ handling + * added watchdog for lost IRQs + * + * Revision 2.6 1999/07/01 08:12:15 keil + * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel + * + * Revision 2.5 1998/11/15 23:55:28 keil + * changes from 2.0 + * + * Revision 2.4 1998/10/05 09:38:08 keil + * Fix register addressing + * + * Revision 2.3 1998/05/25 12:58:26 keil + * HiSax golden code from certification, Don't use !!! + * No leased lines, no X75, but many changes. + * + * Revision 2.1 1998/04/15 16:38:23 keil + * Add S0Box and Teles PCI support + * + * + */ +#define __NO_VERSION__ +#include +#include "hisax.h" +#include "isac.h" +#include "hscx.h" +#include "isdnl1.h" +#include +#ifndef COMPAT_HAS_NEW_PCI +#include +#endif + +extern const char *CardType[]; +const char *telespci_revision = "$Revision: 2.7 $"; + +#define ZORAN_PO_RQ_PEN 0x02000000 +#define ZORAN_PO_WR 0x00800000 +#define ZORAN_PO_GID0 0x00000000 +#define ZORAN_PO_GID1 0x00100000 +#define ZORAN_PO_GREG0 0x00000000 +#define ZORAN_PO_GREG1 0x00010000 +#define ZORAN_PO_DMASK 0xFF + +#define WRITE_ADDR_ISAC (ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG0) +#define READ_DATA_ISAC (ZORAN_PO_GID0 | ZORAN_PO_GREG1) +#define WRITE_DATA_ISAC (ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG1) +#define WRITE_ADDR_HSCX (ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG0) +#define READ_DATA_HSCX (ZORAN_PO_GID1 | ZORAN_PO_GREG1) +#define WRITE_DATA_HSCX (ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG1) + +#define ZORAN_WAIT_NOBUSY do { \ + portdata = readl(adr + 0x200); \ + } while (portdata & ZORAN_PO_RQ_PEN) + +static inline u_char +readisac(unsigned int adr, u_char off) +{ + register unsigned int portdata; + + ZORAN_WAIT_NOBUSY; + + /* set address for ISAC */ + writel(WRITE_ADDR_ISAC | off, adr + 0x200); + ZORAN_WAIT_NOBUSY; + + /* read data from ISAC */ + writel(READ_DATA_ISAC, adr + 0x200); + ZORAN_WAIT_NOBUSY; + return((u_char)(portdata & ZORAN_PO_DMASK)); +} + +static inline void +writeisac(unsigned int adr, u_char off, u_char data) +{ + register unsigned int portdata; + + ZORAN_WAIT_NOBUSY; + + /* set address for ISAC */ + writel(WRITE_ADDR_ISAC | off, adr + 0x200); + ZORAN_WAIT_NOBUSY; + + /* write data to ISAC */ + writel(WRITE_DATA_ISAC | data, adr + 0x200); + ZORAN_WAIT_NOBUSY; +} + +static inline u_char +readhscx(unsigned int adr, int hscx, u_char off) +{ + register unsigned int portdata; + + ZORAN_WAIT_NOBUSY; + /* set address for HSCX */ + writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200); + ZORAN_WAIT_NOBUSY; + + /* read data from HSCX */ + writel(READ_DATA_HSCX, adr + 0x200); + ZORAN_WAIT_NOBUSY; + return ((u_char)(portdata & ZORAN_PO_DMASK)); +} + +static inline void +writehscx(unsigned int adr, int hscx, u_char off, u_char data) +{ + register unsigned int portdata; + + ZORAN_WAIT_NOBUSY; + /* set address for HSCX */ + writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200); + ZORAN_WAIT_NOBUSY; + + /* write data to HSCX */ + writel(WRITE_DATA_HSCX | data, adr + 0x200); + ZORAN_WAIT_NOBUSY; +} + +static inline void +read_fifo_isac(unsigned int adr, u_char * data, int size) +{ + register unsigned int portdata; + register int i; + + ZORAN_WAIT_NOBUSY; + /* read data from ISAC */ + for (i = 0; i < size; i++) { + /* set address for ISAC fifo */ + writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200); + ZORAN_WAIT_NOBUSY; + writel(READ_DATA_ISAC, adr + 0x200); + ZORAN_WAIT_NOBUSY; + data[i] = (u_char)(portdata & ZORAN_PO_DMASK); + } +} + +static void +write_fifo_isac(unsigned int adr, u_char * data, int size) +{ + register unsigned int portdata; + register int i; + + ZORAN_WAIT_NOBUSY; + /* write data to ISAC */ + for (i = 0; i < size; i++) { + /* set address for ISAC fifo */ + writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200); + ZORAN_WAIT_NOBUSY; + writel(WRITE_DATA_ISAC | data[i], adr + 0x200); + ZORAN_WAIT_NOBUSY; + } +} + +static inline void +read_fifo_hscx(unsigned int adr, int hscx, u_char * data, int size) +{ + register unsigned int portdata; + register int i; + + ZORAN_WAIT_NOBUSY; + /* read data from HSCX */ + for (i = 0; i < size; i++) { + /* set address for HSCX fifo */ + writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200); + ZORAN_WAIT_NOBUSY; + writel(READ_DATA_HSCX, adr + 0x200); + ZORAN_WAIT_NOBUSY; + data[i] = (u_char) (portdata & ZORAN_PO_DMASK); + } +} + +static inline void +write_fifo_hscx(unsigned int adr, int hscx, u_char * data, int size) +{ + unsigned int portdata; + register int i; + + ZORAN_WAIT_NOBUSY; + /* write data to HSCX */ + for (i = 0; i < size; i++) { + /* set address for HSCX fifo */ + writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200); + ZORAN_WAIT_NOBUSY; + writel(WRITE_DATA_HSCX | data[i], adr + 0x200); + ZORAN_WAIT_NOBUSY; + udelay(10); + } +} + +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) +{ + return (readisac(cs->hw.teles0.membase, offset)); +} + +static void +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) +{ + writeisac(cs->hw.teles0.membase, offset, value); +} + +static void +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + read_fifo_isac(cs->hw.teles0.membase, data, size); +} + +static void +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + write_fifo_isac(cs->hw.teles0.membase, data, size); +} + +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) +{ + return (readhscx(cs->hw.teles0.membase, hscx, offset)); +} + +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) +{ + writehscx(cs->hw.teles0.membase, hscx, offset, value); +} + +/* + * fast interrupt HSCX stuff goes here + */ + +#define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg) +#define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data) +#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt) + +#include "hscx_irq.c" + +static void +telespci_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ +#define MAXCOUNT 20 + struct IsdnCardState *cs = dev_id; + u_char val; + + if (!cs) { + printk(KERN_WARNING "TelesPCI: Spurious interrupt!\n"); + return; + } + val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA); + if (val) + hscx_int_main(cs, val); + val = readisac(cs->hw.teles0.membase, ISAC_ISTA); + if (val) + isac_interrupt(cs, val); + /* Clear interrupt register for Zoran PCI controller */ + writel(0x70000000, cs->hw.teles0.membase + 0x3C); + + writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF); + writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF); + writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF); + writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0); + writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0); + writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0); +} + +void +release_io_telespci(struct IsdnCardState *cs) +{ + iounmap((void *)cs->hw.teles0.membase); +} + +static int +TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + switch (mt) { + case CARD_RESET: + return(0); + case CARD_RELEASE: + release_io_telespci(cs); + return(0); + case CARD_INIT: + inithscxisac(cs, 3); + return(0); + case CARD_TEST: + return(0); + } + return(0); +} + +#ifdef COMPAT_HAS_NEW_PCI +static struct pci_dev *dev_tel __initdata = NULL; +#else +static int pci_index __initdata = 0; +#endif + +__initfunc(int +setup_telespci(struct IsdnCard *card)) +{ + struct IsdnCardState *cs = card->cs; + char tmp[64]; +#ifndef COMPAT_HAS_NEW_PCI + u_char pci_bus, pci_device_fn, pci_irq; + u_int pci_memaddr; + u_char found = 0; +#endif + + strcpy(tmp, telespci_revision); + printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_TELESPCI) + return (0); +#if CONFIG_PCI +#ifdef COMPAT_HAS_NEW_PCI + if (!pci_present()) { + printk(KERN_ERR "TelesPCI: no PCI bus present\n"); + return(0); + } + if ((dev_tel = pci_find_device (0x11DE, 0x6120, dev_tel))) { + cs->irq = dev_tel->irq; + if (!cs->irq) { + printk(KERN_WARNING "Teles: No IRQ for PCI card found\n"); + return(0); + } + cs->hw.teles0.membase = (u_int) ioremap(dev_tel->base_address[0], + PAGE_SIZE); + printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n", + dev_tel->base_address[0], dev_tel->irq); + } else { + printk(KERN_WARNING "TelesPCI: No PCI card found\n"); + return(0); + } +#else + for (; pci_index < 0xff; pci_index++) { + if (pcibios_find_device (0x11DE, 0x6120, + pci_index, &pci_bus, &pci_device_fn) + == PCIBIOS_SUCCESSFUL) { + found = 1; + } else { + break; + } + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_0, &pci_memaddr); + pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_INTERRUPT_LINE, &pci_irq); + + printk(KERN_INFO "Found: Zoran, base-address: 0x%x," + " irq: 0x%x\n", pci_memaddr, pci_irq); + break; + } + if (!found) { + printk(KERN_WARNING "TelesPCI: No PCI card found\n"); + return(0); + } + pci_index++; + cs->irq = pci_irq; + cs->hw.teles0.membase = (u_int) vremap(pci_memaddr, PAGE_SIZE); +#endif /* COMPAT_HAS_NEW_PCI */ +#else + printk(KERN_WARNING "HiSax: Teles/PCI and NO_PCI_BIOS\n"); + printk(KERN_WARNING "HiSax: Teles/PCI unable to config\n"); + return (0); +#endif /* CONFIG_PCI */ + + /* Initialize Zoran PCI controller */ + writel(0x00000000, cs->hw.teles0.membase + 0x28); + writel(0x01000000, cs->hw.teles0.membase + 0x28); + writel(0x01000000, cs->hw.teles0.membase + 0x28); + writel(0x7BFFFFFF, cs->hw.teles0.membase + 0x2C); + writel(0x70000000, cs->hw.teles0.membase + 0x3C); + writel(0x61000000, cs->hw.teles0.membase + 0x40); + /* writel(0x00800000, cs->hw.teles0.membase + 0x200); */ + + printk(KERN_INFO + "HiSax: %s config irq:%d mem:%x\n", + CardType[cs->typ], cs->irq, + cs->hw.teles0.membase); + + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &TelesPCI_card_msg; + cs->irq_func = &telespci_interrupt; + cs->irq_flags |= SA_SHIRQ; + ISACVersion(cs, "TelesPCI:"); + if (HscxVersion(cs, "TelesPCI:")) { + printk(KERN_WARNING + "TelesPCI: wrong HSCX versions check IO/MEM addresses\n"); + release_io_telespci(cs); + return (0); + } + return (1); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/icn/icn.c linux.pre11.3/drivers/isdn/icn/icn.c --- linux.vanilla/drivers/isdn/icn/icn.c Sun Nov 8 15:10:15 1998 +++ linux.pre11.3/drivers/isdn/icn/icn.c Mon Jul 19 23:59:34 1999 @@ -1,4 +1,4 @@ -/* $Id: icn.c,v 1.49 1998/02/13 11:14:15 keil Exp $ +/* $Id: icn.c,v 1.57 1999/07/06 16:15:30 detabc Exp $ * ISDN low-level module for the ICN active ISDN-Card. * @@ -19,6 +19,29 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: icn.c,v $ + * Revision 1.57 1999/07/06 16:15:30 detabc + * remove unused messages + * + * Revision 1.56 1999/04/12 13:15:07 fritz + * Fixed a cast. + * + * Revision 1.55 1999/04/12 12:34:02 fritz + * Changes from 2.0 tree. + * + * Revision 1.54 1999/01/05 18:29:39 he + * merged remaining schedule_timeout() changes from 2.1.127 + * + * Revision 1.53 1998/06/17 19:51:28 he + * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) + * brute force fix to avoid Ugh's in isdn_tty_write() + * cleaned up some dead code + * + * Revision 1.52 1998/05/20 19:29:58 tsbogend + * fixed bug introduced by changes for new BSENT callback + * + * Revision 1.51 1998/03/07 22:29:55 fritz + * Adapted Detlef's chenges for 2.1. + * * Revision 1.49 1998/02/13 11:14:15 keil * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() * @@ -209,7 +232,7 @@ #undef MAP_DEBUG static char -*revision = "$Revision: 1.49 $"; +*revision = "$Revision: 1.57 $"; static int icn_addcard(int, char *, char *); @@ -232,10 +255,10 @@ cli(); card->xlen[channel] = 0; card->sndcount[channel] = 0; - if (card->xskb[channel]) { + if ((skb = card->xskb[channel])) { card->xskb[channel] = NULL; restore_flags(flags); - dev_kfree_skb(card->xskb[channel]); + dev_kfree_skb(skb); } else restore_flags(flags); } @@ -529,6 +552,11 @@ cmd.parm.length = card->xlen[channel]; card->interface.statcallb(&cmd); } + } else { + save_flags(flags); + cli(); + card->xskb[channel] = skb; + restore_flags(flags); } card->xmit_lock[channel] = 0; if (!icn_trymaplock_channel(card, mch)) @@ -580,8 +608,11 @@ { {"BCON_", ISDN_STAT_BCONN, 1}, /* B-Channel connected */ {"BDIS_", ISDN_STAT_BHUP, 2}, /* B-Channel disconnected */ - {"DCON_", ISDN_STAT_DCONN, 0}, /* D-Channel connected */ - {"DDIS_", ISDN_STAT_DHUP, 0}, /* D-Channel disconnected */ + /* + ** add d-channel connect and disconnect support to link-level + */ + {"DCON_", ISDN_STAT_DCONN, 10}, /* D-Channel connected */ + {"DDIS_", ISDN_STAT_DHUP, 11}, /* D-Channel disconnected */ {"DCAL_I", ISDN_STAT_ICALL, 3}, /* Incoming call dialup-line */ {"DSCA_I", ISDN_STAT_ICALL, 3}, /* Incoming call 1TR6-SPV */ {"FCALL", ISDN_STAT_ICALL, 4}, /* Leased line connection up */ @@ -630,7 +661,33 @@ cmd.driver = card->myid; cmd.arg = channel; switch (action) { + case 11: + save_flags(flags); + cli(); + icn_free_queue(card,channel); + card->rcvidx[channel] = 0; + + if (card->flags & + ((channel)?ICN_FLAGS_B2ACTIVE:ICN_FLAGS_B1ACTIVE)) { + + isdn_ctrl ncmd; + + card->flags &= ~((channel)? + ICN_FLAGS_B2ACTIVE:ICN_FLAGS_B1ACTIVE); + + memset(&ncmd, 0, sizeof(ncmd)); + + ncmd.driver = card->myid; + ncmd.arg = channel; + ncmd.command = ISDN_STAT_BHUP; + restore_flags(flags); + card->interface.statcallb(&cmd); + } else + restore_flags(flags); + + break; case 1: + icn_free_queue(card,channel); card->flags |= (channel) ? ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE; break; @@ -1539,7 +1596,7 @@ c->parm.num[0] ? "N" : "ALL", c->parm.num); } else sprintf(cbuf, "%02d;EAZ%s\n", (int) a, - c->parm.num[0] ? c->parm.num : "0123456789"); + c->parm.num[0] ? (char *)(c->parm.num) : "0123456789"); i = icn_writecmd(cbuf, strlen(cbuf), 0, card); } break; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/icn/icn.h linux.pre11.3/drivers/isdn/icn/icn.h --- linux.vanilla/drivers/isdn/icn/icn.h Sat Jan 9 21:50:38 1999 +++ linux.pre11.3/drivers/isdn/icn/icn.h Mon Jul 19 23:59:34 1999 @@ -318,9 +318,9 @@ #ifdef MODULE MODULE_AUTHOR("Fritz Elfert"); MODULE_PARM(portbase, "i"); -MODULE_PARM_DESC(portbase, "Port address of first card"); +MODULE_PARM_DESC(portbase, "Port adress of first card"); MODULE_PARM(membase, "i"); -MODULE_PARM_DESC(membase, "Shared memory address of all cards"); +MODULE_PARM_DESC(membase, "Shared memory adress of all cards"); MODULE_PARM(icn_id, "s"); MODULE_PARM_DESC(icn_id, "ID-String of first card"); MODULE_PARM(icn_id2, "s"); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_audio.c linux.pre11.3/drivers/isdn/isdn_audio.c --- linux.vanilla/drivers/isdn/isdn_audio.c Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/isdn_audio.c Mon Jul 19 23:59:34 1999 @@ -1,9 +1,10 @@ -/* $Id: isdn_audio.c,v 1.10 1998/02/20 17:09:40 fritz Exp $ +/* $Id: isdn_audio.c,v 1.14 1999/07/11 17:14:06 armin Exp $ * Linux ISDN subsystem, audio conversion and compression (linklevel). * - * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) * DTMF code (c) 1996 by Christian Mock (cm@kukuruz.ping.at) + * Silence detection (c) 1998 by Armin Schindler (mac@gismo.telekom.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 @@ -20,6 +21,26 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_audio.c,v $ + * Revision 1.14 1999/07/11 17:14:06 armin + * Added new layer 2 and 3 protocols for Fax and DSP functions. + * Moved "Add CPN to RING message" to new register S23, + * "Display message" is now correct on register S13 bit 7. + * New audio command AT+VDD implemented (deactivate DTMF decoder and + * activate possible existing hardware/DSP decoder). + * Moved some tty defines to .h file. + * Made whitespace possible in AT command line. + * Some AT-emulator output bugfixes. + * First Fax G3 implementations. + * + * Revision 1.13 1999/04/12 12:33:09 fritz + * Changes from 2.0 tree. + * + * Revision 1.12 1998/07/26 18:48:43 armin + * Added silence detection in voice receive mode. + * + * Revision 1.11 1998/04/10 10:35:10 paul + * fixed (silly?) warnings from egcs on Alpha. + * * Revision 1.10 1998/02/20 17:09:40 fritz * Changes for recent kernels. * @@ -61,7 +82,7 @@ #include "isdn_audio.h" #include "isdn_common.h" -char *isdn_audio_revision = "$Revision: 1.10 $"; +char *isdn_audio_revision = "$Revision: 1.14 $"; /* * Misc. lookup-tables. @@ -276,7 +297,7 @@ isdn_audio_tlookup(const char *table, char *buff, unsigned long n) { while (n--) - *buff++ = table[*buff]; + *buff++ = table[*(unsigned char *)buff]; } #endif @@ -659,4 +680,106 @@ } len -= c; } +} + +silence_state * +isdn_audio_silence_init(silence_state * s) +{ + if (!s) + s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC); + if (s) { + s->idx = 0; + s->state = 0; + } + return s; +} + +void +isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt) +{ + silence_state *s = info->silence_state; + int i; + signed char c; + + if (!info->emu.vpar[1]) return; + + for (i = 0; i < len; i++) { + if (fmt) + c = isdn_audio_alaw_to_ulaw[*buf++]; + else + c = *buf++; + + if (c > 0) c -= 128; + c = abs(c); + + if (c > (info->emu.vpar[1] * 4)) { + s->idx = 0; + s->state = 1; + } else { + if (s->idx < 210000) s->idx++; + } + } +} + +void +isdn_audio_put_dle_code(modem_info * info, u_char code) +{ + struct sk_buff *skb; + unsigned long flags; + int di; + int ch; + char *p; + + skb = dev_alloc_skb(2); + if (!skb) { + printk(KERN_WARNING + "isdn_audio: Could not alloc skb for ttyI%d\n", + info->line); + return; + } + p = (char *) skb_put(skb, 2); + p[0] = 0x10; + p[1] = code; + if (skb_headroom(skb) < sizeof(isdn_audio_skb)) { + printk(KERN_WARNING + "isdn_audio: insufficient skb_headroom, dropping\n"); + kfree_skb(skb); + return; + } + ISDN_AUDIO_SKB_DLECOUNT(skb) = 0; + ISDN_AUDIO_SKB_LOCK(skb) = 0; + save_flags(flags); + cli(); + di = info->isdn_driver; + ch = info->isdn_channel; + __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb); + dev->drv[di]->rcvcount[ch] += 2; + restore_flags(flags); + /* Schedule dequeuing */ + if ((dev->modempoll) && (info->rcvsched)) + isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1); + wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]); +} + +void +isdn_audio_eval_silence(modem_info * info) +{ + silence_state *s = info->silence_state; + char what; + + what = ' '; + + if (s->idx > (info->emu.vpar[2] * 800)) { + s->idx = 0; + if (!s->state) { /* silence from beginning of rec */ + what = 's'; + } else { + what = 'q'; + } + } + if ((what == 's') || (what == 'q')) { + printk(KERN_DEBUG "ttyI%d: %s\n", info->line, + (what=='s') ? "silence":"quiet"); + isdn_audio_put_dle_code(info, what); + } } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_audio.h linux.pre11.3/drivers/isdn/isdn_audio.h --- linux.vanilla/drivers/isdn/isdn_audio.h Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/isdn_audio.h Mon Jul 19 23:59:34 1999 @@ -1,8 +1,8 @@ -/* $Id: isdn_audio.h,v 1.5 1997/02/03 22:45:21 fritz Exp $ +/* $Id: isdn_audio.h,v 1.8 1999/07/11 17:14:07 armin Exp $ * Linux ISDN subsystem, audio conversion and compression (linklevel). * - * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.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 @@ -19,6 +19,23 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_audio.h,v $ + * Revision 1.8 1999/07/11 17:14:07 armin + * Added new layer 2 and 3 protocols for Fax and DSP functions. + * Moved "Add CPN to RING message" to new register S23, + * "Display message" is now correct on register S13 bit 7. + * New audio command AT+VDD implemented (deactivate DTMF decoder and + * activate possible existing hardware/DSP decoder). + * Moved some tty defines to .h file. + * Made whitespace possible in AT command line. + * Some AT-emulator output bugfixes. + * First Fax G3 implementations. + * + * Revision 1.7 1999/04/12 12:33:11 fritz + * Changes from 2.0 tree. + * + * Revision 1.6 1998/07/26 18:48:44 armin + * Added silence detection in voice receive mode. + * * Revision 1.5 1997/02/03 22:45:21 fritz * Reformatted according CodingStyle * @@ -51,6 +68,11 @@ int buf[DTMF_NPOINTS]; } dtmf_state; +typedef struct silence_state { + int state; + unsigned int idx; +} silence_state; + extern void isdn_audio_ulaw2alaw(unsigned char *, unsigned long); extern void isdn_audio_alaw2ulaw(unsigned char *, unsigned long); extern adpcm_state *isdn_audio_adpcm_init(adpcm_state *, int); @@ -60,3 +82,7 @@ extern void isdn_audio_calc_dtmf(modem_info *, unsigned char *, int, int); extern void isdn_audio_eval_dtmf(modem_info *); dtmf_state *isdn_audio_dtmf_init(dtmf_state *); +extern void isdn_audio_calc_silence(modem_info *, unsigned char *, int, int); +extern void isdn_audio_eval_silence(modem_info *); +silence_state *isdn_audio_silence_init(silence_state *); +extern void isdn_audio_put_dle_code(modem_info *, u_char); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_bsdcomp.c linux.pre11.3/drivers/isdn/isdn_bsdcomp.c --- linux.vanilla/drivers/isdn/isdn_bsdcomp.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/isdn_bsdcomp.c Mon Jul 19 23:59:34 1999 @@ -0,0 +1,934 @@ +/* + * BSD compression module + * + * Patched version for ISDN syncPPP written 1997/1998 by Michael Hipp + * The whole module is now SKB based. + * + * Compile with: + * gcc -O2 -I/usr/src/linux/include -D__KERNEL__ -DMODULE -c isdn_bsdcomp.c + */ + +/* + * Original copyright notice: + * + * Copyright (c) 1985, 1986 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * James A. Woods, derived from original work by Spencer Thomas + * and Joseph Orost. + * + * 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 the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#ifndef MODULE +#error This file must be compiled as a module. +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 +#include +#include +#include + +#include + +#include +#include +/* #include */ +#include +#include +#include +#include + +#include "isdn_ppp.h" + +#define BSD_VERSION(x) ((x) >> 5) +#define BSD_NBITS(x) ((x) & 0x1F) + +#define BSD_CURRENT_VERSION 1 + +#define DEBUG 1 + +/* + * A dictionary for doing BSD compress. + */ + +struct bsd_dict { + u32 fcode; + u16 codem1; /* output of hash table -1 */ + u16 cptr; /* map code to hash table entry */ +}; + +struct bsd_db { + int totlen; /* length of this structure */ + unsigned int hsize; /* size of the hash table */ + unsigned char hshift; /* used in hash function */ + unsigned char n_bits; /* current bits/code */ + unsigned char maxbits; /* maximum bits/code */ + unsigned char debug; /* non-zero if debug desired */ + unsigned char unit; /* ppp unit number */ + u16 seqno; /* sequence # of next packet */ + unsigned int mru; /* size of receive (decompress) bufr */ + unsigned int maxmaxcode; /* largest valid code */ + unsigned int max_ent; /* largest code in use */ + unsigned int in_count; /* uncompressed bytes, aged */ + unsigned int bytes_out; /* compressed bytes, aged */ + unsigned int ratio; /* recent compression ratio */ + unsigned int checkpoint; /* when to next check the ratio */ + unsigned int clear_count; /* times dictionary cleared */ + unsigned int incomp_count; /* incompressible packets */ + unsigned int incomp_bytes; /* incompressible bytes */ + unsigned int uncomp_count; /* uncompressed packets */ + unsigned int uncomp_bytes; /* uncompressed bytes */ + unsigned int comp_count; /* compressed packets */ + unsigned int comp_bytes; /* compressed bytes */ + unsigned short *lens; /* array of lengths of codes */ + struct bsd_dict *dict; /* dictionary */ + int xmit; +}; + +#define BSD_OVHD 2 /* BSD compress overhead/packet */ +#define MIN_BSD_BITS 9 +#define BSD_INIT_BITS MIN_BSD_BITS +#define MAX_BSD_BITS 15 + +/* + * the next two codes should not be changed lightly, as they must not + * lie within the contiguous general code space. + */ +#define CLEAR 256 /* table clear output code */ +#define FIRST 257 /* first free entry */ +#define LAST 255 + +#define MAXCODE(b) ((1 << (b)) - 1) +#define BADCODEM1 MAXCODE(MAX_BSD_BITS); + +#define BSD_HASH(prefix,suffix,hshift) ((((unsigned long)(suffix))<<(hshift)) \ + ^ (unsigned long)(prefix)) +#define BSD_KEY(prefix,suffix) ((((unsigned long)(suffix)) << 16) \ + + (unsigned long)(prefix)) + +#define CHECK_GAP 10000 /* Ratio check interval */ + +#define RATIO_SCALE_LOG 8 +#define RATIO_SCALE (1<>RATIO_SCALE_LOG) + +/* + * clear the dictionary + */ + +static void bsd_clear(struct bsd_db *db) +{ + db->clear_count++; + db->max_ent = FIRST-1; + db->n_bits = BSD_INIT_BITS; + db->bytes_out = 0; + db->in_count = 0; + db->incomp_count = 0; + db->ratio = 0; + db->checkpoint = CHECK_GAP; +} + +/* + * If the dictionary is full, then see if it is time to reset it. + * + * Compute the compression ratio using fixed-point arithmetic + * with 8 fractional bits. + * + * Since we have an infinite stream instead of a single file, + * watch only the local compression ratio. + * + * Since both peers must reset the dictionary at the same time even in + * the absence of CLEAR codes (while packets are incompressible), they + * must compute the same ratio. + */ +static int bsd_check (struct bsd_db *db) /* 1=output CLEAR */ +{ + unsigned int new_ratio; + + if (db->in_count >= db->checkpoint) + { + /* age the ratio by limiting the size of the counts */ + if (db->in_count >= RATIO_MAX || db->bytes_out >= RATIO_MAX) + { + db->in_count -= (db->in_count >> 2); + db->bytes_out -= (db->bytes_out >> 2); + } + + db->checkpoint = db->in_count + CHECK_GAP; + + if (db->max_ent >= db->maxmaxcode) + { + /* Reset the dictionary only if the ratio is worse, + * or if it looks as if it has been poisoned + * by incompressible data. + * + * This does not overflow, because + * db->in_count <= RATIO_MAX. + */ + + new_ratio = db->in_count << RATIO_SCALE_LOG; + if (db->bytes_out != 0) + { + new_ratio /= db->bytes_out; + } + + if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE) + { + bsd_clear (db); + return 1; + } + db->ratio = new_ratio; + } + } + return 0; +} + +/* + * Return statistics. + */ + +static void bsd_stats (void *state, struct compstat *stats) +{ + struct bsd_db *db = (struct bsd_db *) state; + + stats->unc_bytes = db->uncomp_bytes; + stats->unc_packets = db->uncomp_count; + stats->comp_bytes = db->comp_bytes; + stats->comp_packets = db->comp_count; + stats->inc_bytes = db->incomp_bytes; + stats->inc_packets = db->incomp_count; + stats->in_count = db->in_count; + stats->bytes_out = db->bytes_out; +} + +/* + * Reset state, as on a CCP ResetReq. + */ +static void bsd_reset (void *state,unsigned char code, unsigned char id, + unsigned char *data, unsigned len, + struct isdn_ppp_resetparams *rsparm) +{ + struct bsd_db *db = (struct bsd_db *) state; + + bsd_clear(db); + db->seqno = 0; + db->clear_count = 0; +} + +/* + * Release the compression structure + */ +static void bsd_free (void *state) +{ + struct bsd_db *db = (struct bsd_db *) state; + + if (db) { + /* + * Release the dictionary + */ + if (db->dict) { + vfree (db->dict); + db->dict = NULL; + } + + /* + * Release the string buffer + */ + if (db->lens) { + vfree (db->lens); + db->lens = NULL; + } + + /* + * Finally release the structure itself. + */ + kfree (db); + MOD_DEC_USE_COUNT; + } +} + + +/* + * Allocate space for a (de) compressor. + */ +static void *bsd_alloc (struct isdn_ppp_comp_data *data) +{ + int bits; + unsigned int hsize, hshift, maxmaxcode; + struct bsd_db *db; + int decomp; + + static unsigned int htab[][2] = { + { 5003 , 4 } , { 5003 , 4 } , { 5003 , 4 } , { 5003 , 4 } , + { 9001 , 5 } , { 18013 , 6 } , { 35023 , 7 } , { 69001 , 8 } + }; + + if (data->optlen != 1 || data->num != CI_BSD_COMPRESS + || BSD_VERSION(data->options[0]) != BSD_CURRENT_VERSION) + return NULL; + + bits = BSD_NBITS(data->options[0]); + + if(bits < 9 || bits > 15) + return NULL; + + hsize = htab[bits-9][0]; + hshift = htab[bits-9][1]; + + /* + * Allocate the main control structure for this instance. + */ + maxmaxcode = MAXCODE(bits); + db = (struct bsd_db *) kmalloc (sizeof (struct bsd_db),GFP_KERNEL); + if (!db) + return NULL; + + memset (db, 0, sizeof(struct bsd_db)); + + db->xmit = data->flags & IPPP_COMP_FLAG_XMIT; + decomp = db->xmit ? 0 : 1; + + /* + * Allocate space for the dictionary. This may be more than one page in + * length. + */ + db->dict = (struct bsd_dict *) vmalloc (hsize * sizeof (struct bsd_dict)); + if (!db->dict) { + bsd_free (db); + return NULL; + } + + MOD_INC_USE_COUNT; + + /* + * If this is the compression buffer then there is no length data. + * For decompression, the length information is needed as well. + */ + if (!decomp) + db->lens = NULL; + else { + db->lens = (unsigned short *) vmalloc ((maxmaxcode + 1) * + sizeof (db->lens[0])); + if (!db->lens) { + bsd_free (db); /* calls MOD_DEC_USE_COUNT; */ + return (NULL); + } + } + + /* + * Initialize the data information for the compression code + */ + db->totlen = sizeof (struct bsd_db) + (sizeof (struct bsd_dict) * hsize); + db->hsize = hsize; + db->hshift = hshift; + db->maxmaxcode = maxmaxcode; + db->maxbits = bits; + + return (void *) db; +} + +/* + * Initialize the database. + */ +static int bsd_init (void *state, struct isdn_ppp_comp_data *data, int unit, int debug) +{ + struct bsd_db *db = state; + int indx; + int decomp; + + if(!state || !data) { + printk(KERN_ERR "isdn_bsd_init: [%d] ERR, state %lx data %lx\n",unit,(long)state,(long)data); + return 0; + } + + decomp = db->xmit ? 0 : 1; + + if (data->optlen != 1 || data->num != CI_BSD_COMPRESS + || (BSD_VERSION(data->options[0]) != BSD_CURRENT_VERSION) + || (BSD_NBITS(data->options[0]) != db->maxbits) + || (decomp && db->lens == NULL)) { + printk(KERN_ERR "isdn_bsd: %d %d %d %d %lx\n",data->optlen,data->num,data->options[0],decomp,(unsigned long)db->lens); + return 0; + } + + if (decomp) + for(indx=LAST;indx>=0;indx--) + db->lens[indx] = 1; + + indx = db->hsize; + while (indx-- != 0) { + db->dict[indx].codem1 = BADCODEM1; + db->dict[indx].cptr = 0; + } + + db->unit = unit; + db->mru = 0; + + db->debug = 1; + + bsd_reset(db,0,0,NULL,0,NULL); + + return 1; +} + +/* + * Obtain pointers to the various structures in the compression tables + */ + +#define dict_ptrx(p,idx) &(p->dict[idx]) +#define lens_ptrx(p,idx) &(p->lens[idx]) + +#ifdef DEBUG +static unsigned short *lens_ptr(struct bsd_db *db, int idx) +{ + if ((unsigned int) idx > (unsigned int) db->maxmaxcode) { + printk (KERN_DEBUG "<9>ppp: lens_ptr(%d) > max\n", idx); + idx = 0; + } + return lens_ptrx (db, idx); +} + +static struct bsd_dict *dict_ptr(struct bsd_db *db, int idx) +{ + if ((unsigned int) idx >= (unsigned int) db->hsize) { + printk (KERN_DEBUG "<9>ppp: dict_ptr(%d) > max\n", idx); + idx = 0; + } + return dict_ptrx (db, idx); +} + +#else +#define lens_ptr(db,idx) lens_ptrx(db,idx) +#define dict_ptr(db,idx) dict_ptrx(db,idx) +#endif + +/* + * compress a packet + */ +static int bsd_compress (void *state, struct sk_buff *skb_in, struct sk_buff *skb_out,int proto) +{ + struct bsd_db *db; + int hshift; + unsigned int max_ent; + unsigned int n_bits; + unsigned int bitno; + unsigned long accm; + int ent; + unsigned long fcode; + struct bsd_dict *dictp; + unsigned char c; + int hval,disp,ilen,mxcode; + unsigned char *rptr = skb_in->data; + int isize = skb_in->len; + +#define OUTPUT(ent) \ + { \ + bitno -= n_bits; \ + accm |= ((ent) << bitno); \ + do { \ + if(skb_out && skb_tailroom(skb_out) > 0) \ + *(skb_put(skb_out,1)) = (unsigned char) (accm>>24); \ + accm <<= 8; \ + bitno += 8; \ + } while (bitno <= 24); \ + } + + /* + * If the protocol is not in the range we're interested in, + * just return without compressing the packet. If it is, + * the protocol becomes the first byte to compress. + */ + printk(KERN_DEBUG "bsd_compress called with %x\n",proto); + + ent = proto; + if (proto < 0x21 || proto > 0xf9 || !(proto & 0x1) ) + return 0; + + db = (struct bsd_db *) state; + hshift = db->hshift; + max_ent = db->max_ent; + n_bits = db->n_bits; + bitno = 32; + accm = 0; + mxcode = MAXCODE (n_bits); + + /* This is the PPP header information */ + if(skb_out && skb_tailroom(skb_out) >= 2) { + char *v = skb_put(skb_out,2); + /* we only push our own data on the header, + AC,PC and protos is pushed by caller */ + v[0] = db->seqno >> 8; + v[1] = db->seqno; + } + + ilen = ++isize; /* This is off by one, but that is what is in draft! */ + + while (--ilen > 0) { + c = *rptr++; + fcode = BSD_KEY (ent, c); + hval = BSD_HASH (ent, c, hshift); + dictp = dict_ptr (db, hval); + + /* Validate and then check the entry. */ + if (dictp->codem1 >= max_ent) + goto nomatch; + + if (dictp->fcode == fcode) { + ent = dictp->codem1 + 1; + continue; /* found (prefix,suffix) */ + } + + /* continue probing until a match or invalid entry */ + disp = (hval == 0) ? 1 : hval; + + do { + hval += disp; + if (hval >= db->hsize) + hval -= db->hsize; + dictp = dict_ptr (db, hval); + if (dictp->codem1 >= max_ent) + goto nomatch; + } while (dictp->fcode != fcode); + + ent = dictp->codem1 + 1; /* finally found (prefix,suffix) */ + continue; + +nomatch: + OUTPUT(ent); /* output the prefix */ + + /* code -> hashtable */ + if (max_ent < db->maxmaxcode) { + struct bsd_dict *dictp2; + struct bsd_dict *dictp3; + int indx; + + /* expand code size if needed */ + if (max_ent >= mxcode) { + db->n_bits = ++n_bits; + mxcode = MAXCODE (n_bits); + } + + /* + * Invalidate old hash table entry using + * this code, and then take it over. + */ + dictp2 = dict_ptr (db, max_ent + 1); + indx = dictp2->cptr; + dictp3 = dict_ptr (db, indx); + + if (dictp3->codem1 == max_ent) + dictp3->codem1 = BADCODEM1; + + dictp2->cptr = hval; + dictp->codem1 = max_ent; + dictp->fcode = fcode; + db->max_ent = ++max_ent; + + if (db->lens) { + unsigned short *len1 = lens_ptr (db, max_ent); + unsigned short *len2 = lens_ptr (db, ent); + *len1 = *len2 + 1; + } + } + ent = c; + } + + OUTPUT(ent); /* output the last code */ + + if(skb_out) + db->bytes_out += skb_out->len; /* Do not count bytes from here */ + db->uncomp_bytes += isize; + db->in_count += isize; + ++db->uncomp_count; + ++db->seqno; + + if (bitno < 32) + ++db->bytes_out; /* must be set before calling bsd_check */ + + /* + * Generate the clear command if needed + */ + + if (bsd_check(db)) + OUTPUT (CLEAR); + + /* + * Pad dribble bits of last code with ones. + * Do not emit a completely useless byte of ones. + */ + if (bitno < 32 && skb_out && skb_tailroom(skb_out) > 0) + *(skb_put(skb_out,1)) = (unsigned char) ((accm | (0xff << (bitno-8))) >> 24); + + /* + * Increase code size if we would have without the packet + * boundary because the decompressor will do so. + */ + if (max_ent >= mxcode && max_ent < db->maxmaxcode) + db->n_bits++; + + /* If output length is too large then this is an incompressible frame. */ + if (!skb_out || (skb_out && skb_out->len >= skb_in->len) ) { + ++db->incomp_count; + db->incomp_bytes += isize; + return 0; + } + + /* Count the number of compressed frames */ + ++db->comp_count; + db->comp_bytes += skb_out->len; + return skb_out->len; + +#undef OUTPUT +} + +/* + * Update the "BSD Compress" dictionary on the receiver for + * incompressible data by pretending to compress the incoming data. + */ +static void bsd_incomp (void *state, struct sk_buff *skb_in,int proto) +{ + bsd_compress (state, skb_in, NULL, proto); +} + +/* + * Decompress "BSD Compress". + */ +static int bsd_decompress (void *state, struct sk_buff *skb_in, struct sk_buff *skb_out, + struct isdn_ppp_resetparams *rsparm) +{ + struct bsd_db *db; + unsigned int max_ent; + unsigned long accm; + unsigned int bitno; /* 1st valid bit in accm */ + unsigned int n_bits; + unsigned int tgtbitno; /* bitno when we have a code */ + struct bsd_dict *dictp; + int seq; + unsigned int incode; + unsigned int oldcode; + unsigned int finchar; + unsigned char *p,*ibuf; + int ilen; + int codelen; + int extra; + + db = (struct bsd_db *) state; + max_ent = db->max_ent; + accm = 0; + bitno = 32; /* 1st valid bit in accm */ + n_bits = db->n_bits; + tgtbitno = 32 - n_bits; /* bitno when we have a code */ + + printk(KERN_DEBUG "bsd_decompress called\n"); + + if(!skb_in || !skb_out) { + printk(KERN_ERR "bsd_decompress called with NULL parameter\n"); + return DECOMP_ERROR; + } + + /* + * Get the sequence number. + */ + if( (p = skb_pull(skb_in,2)) == NULL) { + return DECOMP_ERROR; + } + p-=2; + seq = (p[0] << 8) + p[1]; + ilen = skb_in->len; + ibuf = skb_in->data; + + /* + * Check the sequence number and give up if it differs from + * the value we're expecting. + */ + if (seq != db->seqno) { + if (db->debug) { + printk(KERN_DEBUG "bsd_decomp%d: bad sequence # %d, expected %d\n", + db->unit, seq, db->seqno - 1); + } + return DECOMP_ERROR; + } + + ++db->seqno; + db->bytes_out += ilen; + + if(skb_tailroom(skb_out) > 0) + *(skb_put(skb_out,1)) = 0; + else + return DECOMP_ERR_NOMEM; + + oldcode = CLEAR; + + /* + * Keep the checkpoint correctly so that incompressible packets + * clear the dictionary at the proper times. + */ + + for (;;) { + if (ilen-- <= 0) { + db->in_count += (skb_out->len - 1); /* don't count the header */ + break; + } + + /* + * Accumulate bytes until we have a complete code. + * Then get the next code, relying on the 32-bit, + * unsigned accm to mask the result. + */ + + bitno -= 8; + accm |= *ibuf++ << bitno; + if (tgtbitno < bitno) + continue; + + incode = accm >> tgtbitno; + accm <<= n_bits; + bitno += n_bits; + + /* + * The dictionary must only be cleared at the end of a packet. + */ + + if (incode == CLEAR) { + if (ilen > 0) { + if (db->debug) + printk(KERN_DEBUG "bsd_decomp%d: bad CLEAR\n", db->unit); + return DECOMP_FATALERROR; /* probably a bug */ + } + bsd_clear(db); + break; + } + + if ((incode > max_ent + 2) || (incode > db->maxmaxcode) + || (incode > max_ent && oldcode == CLEAR)) { + if (db->debug) { + printk(KERN_DEBUG "bsd_decomp%d: bad code 0x%x oldcode=0x%x ", + db->unit, incode, oldcode); + printk(KERN_DEBUG "max_ent=0x%x skb->Len=%d seqno=%d\n", + max_ent, skb_out->len, db->seqno); + } + return DECOMP_FATALERROR; /* probably a bug */ + } + + /* Special case for KwKwK string. */ + if (incode > max_ent) { + finchar = oldcode; + extra = 1; + } else { + finchar = incode; + extra = 0; + } + + codelen = *(lens_ptr (db, finchar)); + if( skb_tailroom(skb_out) < codelen + extra) { + if (db->debug) { + printk(KERN_DEBUG "bsd_decomp%d: ran out of mru\n", db->unit); +#ifdef DEBUG + printk(KERN_DEBUG " len=%d, finchar=0x%x, codelen=%d,skblen=%d\n", + ilen, finchar, codelen, skb_out->len); +#endif + } + return DECOMP_FATALERROR; + } + + /* + * Decode this code and install it in the decompressed buffer. + */ + + p = skb_put(skb_out,codelen); + p += codelen; + while (finchar > LAST) { + struct bsd_dict *dictp2 = dict_ptr (db, finchar); + + dictp = dict_ptr (db, dictp2->cptr); + +#ifdef DEBUG + if (--codelen <= 0 || dictp->codem1 != finchar-1) { + if (codelen <= 0) { + printk(KERN_ERR "bsd_decomp%d: fell off end of chain ", db->unit); + printk(KERN_ERR "0x%x at 0x%x by 0x%x, max_ent=0x%x\n", incode, finchar, dictp2->cptr, max_ent); + } else { + if (dictp->codem1 != finchar-1) { + printk(KERN_ERR "bsd_decomp%d: bad code chain 0x%x finchar=0x%x ",db->unit, incode, finchar); + printk(KERN_ERR "oldcode=0x%x cptr=0x%x codem1=0x%x\n", oldcode, dictp2->cptr, dictp->codem1); + } + } + return DECOMP_FATALERROR; + } +#endif + + { + u32 fcode = dictp->fcode; + *--p = (fcode >> 16) & 0xff; + finchar = fcode & 0xffff; + } + } + *--p = finchar; + +#ifdef DEBUG + if (--codelen != 0) + printk(KERN_ERR "bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n", db->unit, codelen, incode, max_ent); +#endif + + if (extra) /* the KwKwK case again */ + *(skb_put(skb_out,1)) = finchar; + + /* + * If not first code in a packet, and + * if not out of code space, then allocate a new code. + * + * Keep the hash table correct so it can be used + * with uncompressed packets. + */ + if (oldcode != CLEAR && max_ent < db->maxmaxcode) { + struct bsd_dict *dictp2, *dictp3; + u16 *lens1, *lens2; + unsigned long fcode; + int hval, disp, indx; + + fcode = BSD_KEY(oldcode,finchar); + hval = BSD_HASH(oldcode,finchar,db->hshift); + dictp = dict_ptr (db, hval); + + /* look for a free hash table entry */ + if (dictp->codem1 < max_ent) { + disp = (hval == 0) ? 1 : hval; + do { + hval += disp; + if (hval >= db->hsize) + hval -= db->hsize; + dictp = dict_ptr (db, hval); + } while (dictp->codem1 < max_ent); + } + + /* + * Invalidate previous hash table entry + * assigned this code, and then take it over + */ + + dictp2 = dict_ptr (db, max_ent + 1); + indx = dictp2->cptr; + dictp3 = dict_ptr (db, indx); + + if (dictp3->codem1 == max_ent) + dictp3->codem1 = BADCODEM1; + + dictp2->cptr = hval; + dictp->codem1 = max_ent; + dictp->fcode = fcode; + db->max_ent = ++max_ent; + + /* Update the length of this string. */ + lens1 = lens_ptr (db, max_ent); + lens2 = lens_ptr (db, oldcode); + *lens1 = *lens2 + 1; + + /* Expand code size if needed. */ + if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) { + db->n_bits = ++n_bits; + tgtbitno = 32-n_bits; + } + } + oldcode = incode; + } + + ++db->comp_count; + ++db->uncomp_count; + db->comp_bytes += skb_in->len - BSD_OVHD; + db->uncomp_bytes += skb_out->len; + + if (bsd_check(db)) { + if (db->debug) + printk(KERN_DEBUG "bsd_decomp%d: peer should have cleared dictionary on %d\n", + db->unit, db->seqno - 1); + } + return skb_out->len; +} + +/************************************************************* + * Table of addresses for the BSD compression module + *************************************************************/ + +static struct isdn_ppp_compressor ippp_bsd_compress = { + NULL,NULL, /* prev,next: overwritten by isdn_ppp */ + CI_BSD_COMPRESS, /* compress_proto */ + bsd_alloc, /* alloc */ + bsd_free, /* free */ + bsd_init, /* init */ + bsd_reset, /* reset */ + bsd_compress, /* compress */ + bsd_decompress, /* decompress */ + bsd_incomp, /* incomp */ + bsd_stats /* comp_stat */ +}; + +/************************************************************* + * Module support routines + *************************************************************/ + +int init_module(void) +{ + int answer = isdn_ppp_register_compressor (&ippp_bsd_compress); + if (answer == 0) + printk (KERN_INFO "PPP BSD Compression module registered\n"); + return answer; +} + +void cleanup_module(void) +{ + isdn_ppp_unregister_compressor (&ippp_bsd_compress); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_cards.c linux.pre11.3/drivers/isdn/isdn_cards.c --- linux.vanilla/drivers/isdn/isdn_cards.c Sun Nov 8 15:08:07 1998 +++ linux.pre11.3/drivers/isdn/isdn_cards.c Mon Jul 19 23:59:34 1999 @@ -1,8 +1,8 @@ -/* $Id: isdn_cards.c,v 1.7 1998/02/20 17:24:28 fritz Exp $ +/* $Id: isdn_cards.c,v 1.9 1999/04/12 12:33:11 fritz Exp $ * Linux ISDN subsystem, initialization for non-modularized drivers. * - * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.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 @@ -19,6 +19,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_cards.c,v $ + * Revision 1.9 1999/04/12 12:33:11 fritz + * Changes from 2.0 tree. + * + * Revision 1.8 1999/03/29 11:13:23 armin + * Added eicon driver init. + * * Revision 1.7 1998/02/20 17:24:28 fritz * Added ACT2000 init. * @@ -56,6 +62,10 @@ extern void pcbit_init(void); #endif +#ifdef CONFIG_ISDN_DRV_EICON +extern void eicon_init(void); +#endif + #ifdef CONFIG_ISDN_DRV_AVMB1 extern void avmb1_init(void); extern void capi_init(void); @@ -87,5 +97,8 @@ #endif #if CONFIG_ISDN_DRV_ACT2000 act2000_init(); +#endif +#if CONFIG_ISDN_DRV_EICON + eicon_init(); #endif } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_cards.h linux.pre11.3/drivers/isdn/isdn_cards.h --- linux.vanilla/drivers/isdn/isdn_cards.h Sun Nov 8 15:08:07 1998 +++ linux.pre11.3/drivers/isdn/isdn_cards.h Mon Jul 19 23:59:34 1999 @@ -1,8 +1,8 @@ -/* $Id: isdn_cards.h,v 1.2 1997/02/03 23:31:55 fritz Exp $ +/* $Id: isdn_cards.h,v 1.3 1999/04/12 12:33:13 fritz Exp $ * Linux ISDN subsystem, initialization for non-modularized drivers. * - * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.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 @@ -19,6 +19,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_cards.h,v $ + * Revision 1.3 1999/04/12 12:33:13 fritz + * Changes from 2.0 tree. + * * Revision 1.2 1997/02/03 23:31:55 fritz * Reformatted according CodingStyle * diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_common.c linux.pre11.3/drivers/isdn/isdn_common.c --- linux.vanilla/drivers/isdn/isdn_common.c Sun Jan 24 19:55:34 1999 +++ linux.pre11.3/drivers/isdn/isdn_common.c Mon Jul 19 23:59:35 1999 @@ -1,8 +1,8 @@ -/* $Id: isdn_common.c,v 1.55 1998/02/23 23:35:32 fritz Exp $ +/* $Id: isdn_common.c,v 1.83 1999/07/13 21:02:05 werner Exp $ * Linux ISDN subsystem, common used functions (linklevel). * - * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1995,96 Thinking Objects Software GmbH Wuerzburg * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) * @@ -20,11 +20,111 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Note: This file differs from the corresponding revision as present in the - * isdn4linux CVS repository because some later bug fixes have been extracted - * from the repository and merged into this file. -- Henner Eisen - * * $Log: isdn_common.c,v $ + * Revision 1.83 1999/07/13 21:02:05 werner + * Added limit possibilty of driver b_channel resources (ISDN_STAT_DISCH) + * + * Revision 1.82 1999/07/12 21:06:50 werner + * Fixed problem when loading more than one driver temporary + * + * Revision 1.81 1999/07/11 17:14:09 armin + * Added new layer 2 and 3 protocols for Fax and DSP functions. + * Moved "Add CPN to RING message" to new register S23, + * "Display message" is now correct on register S13 bit 7. + * New audio command AT+VDD implemented (deactivate DTMF decoder and + * activate possible existing hardware/DSP decoder). + * Moved some tty defines to .h file. + * Made whitespace possible in AT command line. + * Some AT-emulator output bugfixes. + * First Fax G3 implementations. + * + * Revision 1.80 1999/07/07 10:14:00 detabc + * remove unused messages + * + * Revision 1.79 1999/07/05 23:51:30 werner + * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl + * hisaxctrl id 10 + * + * Revision 1.78 1999/07/05 20:21:15 werner + * changes to use diversion sources for all kernel versions. + * removed static device, only proc filesystem used + * + * Revision 1.77 1999/07/01 08:29:50 keil + * compatibility to 2.3 kernel + * + * Revision 1.76 1999/06/29 16:16:44 calle + * Let ISDN_CMD_UNLOAD work with open isdn devices without crash again. + * Also right unlocking (ISDN_CMD_UNLOCK) is done now. + * isdnlog should check returncode of read(2) calls. + * + * Revision 1.75 1999/04/18 14:06:47 fritz + * Removed TIMRU stuff. + * + * Revision 1.74 1999/04/12 13:16:45 fritz + * Changes from 2.0 tree. + * + * Revision 1.73 1999/04/12 12:33:15 fritz + * Changes from 2.0 tree. + * + * Revision 1.72 1999/03/02 12:04:44 armin + * -added ISDN_STAT_ADDCH to increase supported channels after + * register_isdn(). + * -ttyI now goes on-hook on ATZ when B-Ch is connected. + * -added timer-function for register S7 (Wait for Carrier). + * -analog modem (ISDN_PROTO_L2_MODEM) implementations. + * -on L2_MODEM a string will be appended to the CONNECT-Message, + * which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN. + * -variable "dialing" used for ATA also, for interrupting call + * establishment and register S7. + * + * Revision 1.71 1999/01/28 09:10:43 armin + * Fixed bad while-loop in isdn_readbch(). + * + * Revision 1.70 1999/01/15 19:58:54 he + * removed compatibiltity macro + * + * Revision 1.69 1998/09/07 21:59:58 he + * flush method for 2.1.118 and above + * updated IIOCTLNETGPN + * + * Revision 1.68 1998/08/31 21:09:45 he + * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface' + * peer phone number) + * + * Revision 1.67 1998/06/26 15:12:21 fritz + * Added handling of STAT_ICALL with incomplete CPN. + * Added AT&L for ttyI emulator. + * Added more locking stuff in tty_write. + * + * Revision 1.66 1998/06/17 19:50:41 he + * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) + * brute force fix to avoid Ugh's in isdn_tty_write() + * cleaned up some dead code + * + * + * Revision 1.62 1998/04/14 16:28:43 he + * Fixed user space access with interrupts off and remaining + * copy_{to,from}_user() -> -EFAULT return codes + * + * Revision 1.61 1998/03/22 18:50:46 hipp + * Added BSD Compression for syncPPP .. UNTESTED at the moment + * + * Revision 1.60 1998/03/19 13:18:18 keil + * Start of a CAPI like interface for supplementary Service + * first service: SUSPEND + * + * Revision 1.59 1998/03/09 17:46:23 he + * merged in 2.1.89 changes + * + * Revision 1.58 1998/03/07 22:35:24 fritz + * Starting generic module support (Nothing usable yet). + * + * Revision 1.57 1998/03/07 18:21:01 cal + * Dynamic Timeout-Rule-Handling vs. 971110 included + * + * Revision 1.56 1998/02/25 17:49:38 he + * Changed return codes caused be failing copy_{to,from}_user to -EFAULT + * * Revision 1.55 1998/02/23 23:35:32 fritz * Eliminated some compiler warnings. * @@ -261,6 +361,9 @@ #ifdef CONFIG_ISDN_AUDIO #include "isdn_audio.h" #endif +#ifdef CONFIG_ISDN_DIVERSION +#include +#endif CONFIG_ISDN_DIVERSION #include "isdn_v110.h" #include "isdn_cards.h" @@ -269,7 +372,7 @@ isdn_dev *dev = (isdn_dev *) 0; -static char *isdn_revision = "$Revision: 1.55 $"; +static char *isdn_revision = "$Revision: 1.83 $"; extern char *isdn_net_revision; extern char *isdn_tty_revision; @@ -285,18 +388,46 @@ #endif extern char *isdn_v110_revision; +#ifdef CONFIG_ISDN_DIVERSION +isdn_divert_if *divert_if = NULL; /* interface to diversion module */ +#endif CONFIG_ISDN_DIVERSION + + static int isdn_writebuf_stub(int, int, const u_char *, int, int); void isdn_MOD_INC_USE_COUNT(void) { + int i; + MOD_INC_USE_COUNT; + for (i = 0; i < dev->drivers; i++) { + isdn_ctrl cmd; + + cmd.driver = i; + cmd.arg = 0; + cmd.command = ISDN_CMD_LOCK; + isdn_command(&cmd); + dev->drv[i]->locks++; + } } void isdn_MOD_DEC_USE_COUNT(void) { + int i; + MOD_DEC_USE_COUNT; + for (i = 0; i < dev->drivers; i++) + if (dev->drv[i]->locks > 0) { + isdn_ctrl cmd; + + cmd.driver = i; + cmd.arg = 0; + cmd.command = ISDN_CMD_UNLOCK; + isdn_command(&cmd); + dev->drv[i]->locks--; + } } #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP) @@ -312,6 +443,82 @@ } #endif +/* + * I picked the pattern-matching-functions from an old GNU-tar version (1.10) + * It was originally written and put to PD by rs@mirror.TMC.COM (Rich Salz) + */ +static int +isdn_star(char *s, char *p) +{ + while (isdn_wildmat(s, p)) { + if (*++s == '\0') + return (2); + } + return (0); +} + +/* + * Shell-type Pattern-matching for incoming caller-Ids + * This function gets a string in s and checks, if it matches the pattern + * given in p. + * + * Return: + * 0 = match. + * 1 = no match. + * 2 = no match. Would eventually match, if s would be longer. + * + * Possible Patterns: + * + * '?' matches one character + * '*' matches zero or more characters + * [xyz] matches the set of characters in brackets. + * [^xyz] matches any single character not in the set of characters + */ + +int +isdn_wildmat(char *s, char *p) +{ + register int last; + register int matched; + register int reverse; + register int nostar = 1; + + for (; *p; s++, p++) + switch (*p) { + case '\\': + /* + * Literal match with following character, + * fall through. + */ + p++; + default: + if (*s != *p) + return (*s == '\0')?2:1; + continue; + case '?': + /* Match anything. */ + if (*s == '\0') + return (2); + continue; + case '*': + nostar = 0; + /* Trailing star matches everything. */ + return (*++p ? isdn_star(s, p) : 0); + case '[': + /* [^....] means inverse character class. */ + if ((reverse = (p[1] == '^'))) + p++; + for (last = 0, matched = 0; *++p && (*p != ']'); last = *p) + /* This next line requires a good C compiler. */ + if (*p == '-' ? *s <= *++p && *s >= last : *s == *p) + matched = 1; + if (matched == reverse) + return (1); + continue; + } + return (*s == '\0')?0:nostar; +} + static void isdn_free_queue(struct sk_buff_head *queue) { @@ -345,7 +552,6 @@ isdn_timer_funct(ulong dummy) { int tf = dev->tflags; - if (tf & ISDN_TIMER_FAST) { if (tf & ISDN_TIMER_MODEMREAD) isdn_tty_readmodem(); @@ -374,13 +580,16 @@ if (tf & ISDN_TIMER_KEEPALIVE) isdn_net_slarp_out(); } + if (tf & ISDN_TIMER_CARRIER) + isdn_tty_carrier_timeout(); #if (defined CONFIG_ISDN_PPP) && (defined CONFIG_ISDN_MPP) if (tf & ISDN_TIMER_IPPP) isdn_ppp_timer_timeout(); #endif } } - if (tf) { + if (tf) + { int flags; save_flags(flags); @@ -506,6 +715,29 @@ isdn_command(&cmd); } +/* + * Begin of a CAPI like LL<->HL interface, currently used only for + * supplementary service (CAPI 2.0 part III) + */ +#include "avmb1/capicmd.h" /* this should be moved in a common place */ + +int +isdn_capi_rec_hl_msg(capi_msg *cm) { + + int di; + int ch; + + di = (cm->adr.Controller & 0x7f) -1; + ch = isdn_dc2minor(di, (cm->adr.Controller>>8)& 0x7f); + switch(cm->Command) { + case CAPI_FACILITY: + /* in the moment only handled in tty */ + return(isdn_tty_capi_facility(cm)); + default: + return(-1); + } +} + static int isdn_status_callback(isdn_ctrl * c) { @@ -540,13 +772,13 @@ wake_up_interruptible(&dev->drv[di]->st_waitq); break; case ISDN_STAT_RUN: - dev->drv[di]->running = 1; + dev->drv[di]->flags |= DRV_FLAG_RUNNING; for (i = 0; i < ISDN_MAX_CHANNELS; i++) if (dev->drvmap[i] == di) isdn_all_eaz(di, dev->chanmap[i]); break; case ISDN_STAT_STOP: - dev->drv[di]->running = 0; + dev->drv[di]->flags &= ~DRV_FLAG_RUNNING; break; case ISDN_STAT_ICALL: if (i < 0) @@ -562,19 +794,23 @@ return 0; } /* Try to find a network-interface which will accept incoming call */ - cmd.driver = di; - cmd.arg = c->arg; - cmd.command = ISDN_CMD_LOCK; - isdn_command(&cmd); - r = isdn_net_find_icall(di, c->arg, i, c->parm.setup); + r = ((c->command == ISDN_STAT_ICALLW) ? 0 : isdn_net_find_icall(di, c->arg, i, c->parm.setup)); switch (r) { case 0: /* No network-device replies. - * Try ttyI's + * Try ttyI's. + * These return 0 on no match, 1 on match and + * 3 on eventually match, if CID is longer. */ - if (isdn_tty_find_icall(di, c->arg, c->parm.setup) >= 0) - retval = 1; - else if (dev->drv[di]->reject_bus) { + if (c->command == ISDN_STAT_ICALL) + if ((retval = isdn_tty_find_icall(di, c->arg, c->parm.setup))) return(retval); +#ifdef CONFIG_ISDN_DIVERSION + if (divert_if) + if ((retval = divert_if->stat_callback(c))) + return(retval); /* processed */ +#endif CONFIG_ISDN_DIVERSION + if ((!retval) && (dev->drv[di]->flags & DRV_FLAG_REJBUS)) { + /* No tty responding */ cmd.driver = di; cmd.arg = c->arg; cmd.command = ISDN_CMD_HANGUP; @@ -606,13 +842,14 @@ /* ... then start callback. */ isdn_net_dial(); break; + case 5: + /* Number would eventually match, if longer */ + retval = 3; + break; } - if (retval != 1) { - cmd.driver = di; - cmd.arg = c->arg; - cmd.command = ISDN_CMD_UNLOCK; - isdn_command(&cmd); - } +#ifdef ISDN_DEBUG_STATCALLB + printk(KERN_DEBUG "ICALL: ret=%d\n", retval); +#endif return retval; break; case ISDN_STAT_CINF: @@ -634,6 +871,20 @@ printk(KERN_INFO "isdn: %s,ch%ld cause: %s\n", dev->drvid[di], c->arg, c->parm.num); isdn_tty_stat_callback(i, c); +#ifdef CONFIG_ISDN_DIVERSION + if (divert_if) + divert_if->stat_callback(c); +#endif CONFIG_ISDN_DIVERSION + break; + case ISDN_STAT_DISPLAY: +#ifdef ISDN_DEBUG_STATCALLB + printk(KERN_DEBUG "DISPLAY: %ld %s\n", c->arg, c->parm.display); +#endif + isdn_tty_stat_callback(i, c); +#ifdef CONFIG_ISDN_DIVERSION + if (divert_if) + divert_if->stat_callback(c); +#endif CONFIG_ISDN_DIVERSION break; case ISDN_STAT_DCONN: if (i < 0) @@ -664,7 +915,7 @@ #endif if (dev->global_flags & ISDN_GLOBAL_STOPPED) return 0; - dev->drv[di]->flags &= ~(1 << (c->arg)); + dev->drv[di]->online &= ~(1 << (c->arg)); isdn_info_update(); /* Signal hangup to network-devices */ if (isdn_net_stat_callback(i, c)) @@ -672,6 +923,11 @@ isdn_v110_stat_callback(i, c); if (isdn_tty_stat_callback(i, c)) break; +#ifdef CONFIG_ISDN_DIVERSION + if (divert_if) + divert_if->stat_callback(c); +#endif CONFIG_ISDN_DIVERSION + break; break; case ISDN_STAT_BCONN: if (i < 0) @@ -682,7 +938,7 @@ /* Signal B-channel-connect to network-devices */ if (dev->global_flags & ISDN_GLOBAL_STOPPED) return 0; - dev->drv[di]->flags |= (1 << (c->arg)); + dev->drv[di]->online |= (1 << (c->arg)); isdn_info_update(); if (isdn_net_stat_callback(i, c)) break; @@ -698,7 +954,7 @@ #endif if (dev->global_flags & ISDN_GLOBAL_STOPPED) return 0; - dev->drv[di]->flags &= ~(1 << (c->arg)); + dev->drv[di]->online &= ~(1 << (c->arg)); isdn_info_update(); #ifdef CONFIG_ISDN_X25 /* Signal hangup to network-devices */ @@ -723,8 +979,38 @@ break; break; case ISDN_STAT_ADDCH: + if (isdn_add_channels(dev->drv[di], di, c->arg, 1)) + return -1; + isdn_info_update(); + break; + case ISDN_STAT_DISCH: + save_flags(flags); + cli(); + for (i = 0; i < ISDN_MAX_CHANNELS; i++) + if ((dev->drvmap[i] == di) && + (dev->chanmap[i] == c->arg)) { + if (c->parm.num[0]) + dev->usage[i] &= ~ISDN_USAGE_DISABLED; + else + if (USG_NONE(dev->usage[i])) { + dev->usage[i] |= ISDN_USAGE_DISABLED; + } + else + retval = -1; + break; + } + restore_flags(flags); + isdn_info_update(); break; case ISDN_STAT_UNLOAD: + while (dev->drv[di]->locks > 0) { + isdn_ctrl cmd; + cmd.driver = di; + cmd.arg = 0; + cmd.command = ISDN_CMD_UNLOCK; + isdn_command(&cmd); + dev->drv[di]->locks--; + } save_flags(flags); cli(); isdn_tty_stat_callback(i, c); @@ -732,6 +1018,7 @@ if (dev->drvmap[i] == di) { dev->drvmap[i] = -1; dev->chanmap[i] = -1; + dev->usage[i] &= ~ISDN_USAGE_DISABLED; } dev->drivers--; dev->channels -= dev->drv[di]->channels; @@ -741,7 +1028,9 @@ isdn_free_queue(&dev->drv[di]->rpqueue[i]); kfree(dev->drv[di]->rpqueue); kfree(dev->drv[di]->rcv_waitq); +#ifndef COMPAT_HAS_NEW_WAITQ kfree(dev->drv[di]->snd_waitq); +#endif kfree(dev->drv[di]); dev->drv[di] = NULL; dev->drvid[di][0] = '\0'; @@ -750,6 +1039,19 @@ return 0; case ISDN_STAT_L1ERR: break; + case CAPI_PUT_MESSAGE: + return(isdn_capi_rec_hl_msg(&c->parm.cmsg)); +#ifdef CONFIG_ISDN_AUDIO + case ISDN_STAT_AUDIO: + isdn_tty_stat_callback(i, c); + break; +#endif +#ifdef CONFIG_ISDN_DIVERSION + case ISDN_STAT_PROT: + case ISDN_STAT_REDIR: + if (divert_if) + return(divert_if->stat_callback(c)); +#endif CONFIG_ISDN_DIVERSION default: return -1; } @@ -785,7 +1087,11 @@ * of the mapping (di,ch)<->minor, happen during the sleep? --he */ int +#ifdef COMPAT_HAS_NEW_WAITQ +isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_queue_head_t *sleep) +#else isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, struct wait_queue **sleep) +#endif { int left; int count; @@ -819,7 +1125,8 @@ dflag = 0; count_pull = count_put = 0; - while ((count_pull < skb->len) && (left-- > 0)) { + while ((count_pull < skb->len) && (left > 0)) { + left--; if (dev->drv[di]->DLEflag & DLEmask) { *cp++ = DLE; dev->drv[di]->DLEflag &= ~DLEmask; @@ -894,8 +1201,6 @@ return (dev->chanmap[minor]); } -#define INF_DV 0x01 /* Data version for /dev/isdninfo */ - static char * isdn_statstr(void) { @@ -931,7 +1236,7 @@ p = istatbuf + strlen(istatbuf); for (i = 0; i < ISDN_MAX_DRIVERS; i++) { if (dev->drv[i]) { - sprintf(p, "%ld ", dev->drv[i]->flags); + sprintf(p, "%ld ", dev->drv[i]->online); p = istatbuf + strlen(istatbuf); } else { sprintf(p, "? "); @@ -997,7 +1302,7 @@ drvidx = isdn_minor2drv(minor); if (drvidx < 0) return -ENODEV; - if (!dev->drv[drvidx]->running) + if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) return -ENODEV; chidx = isdn_minor2chan(minor); if( ! (p = kmalloc(count,GFP_KERNEL)) ) return -ENOMEM; @@ -1067,7 +1372,7 @@ drvidx = isdn_minor2drv(minor); if (drvidx < 0) return -ENODEV; - if (!dev->drv[drvidx]->running) + if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) return -ENODEV; chidx = isdn_minor2chan(minor); while (isdn_writebuf_stub(drvidx, chidx, buf, count, 1) != count) @@ -1081,7 +1386,7 @@ /* * We want to use the isdnctrl device to load the firmware * - if (!dev->drv[drvidx]->running) + if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) return -ENODEV; */ if (dev->drv[drvidx]->interface->writecmd) @@ -1113,11 +1418,11 @@ return mask; } if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) { - poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait); if (drvidx < 0) { - printk(KERN_ERR "isdn_common: isdn_poll 1 -> what the hell\n"); - return POLLERR; + /* driver deregistered while file open */ + return POLLHUP; } + poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait); mask = POLLOUT | POLLWRNORM; if (dev->drv[drvidx]->stavail) { mask |= POLLIN | POLLRDNORM; @@ -1132,143 +1437,6 @@ return POLLERR; } -/* - * This accesses user space with interrupts off, but is not needed by - * any of the isdn4k-util programs anyway. Thus, in contrast to your - * first impression after looking at the code, fixing is trival!*/ -#if 0 -static int -isdn_set_allcfg(char *src) -{ - int ret; - int i; - ulong flags; - isdn_net_ioctl_cfg cfg; - isdn_net_ioctl_phone phone; - - if ((ret = isdn_net_rmall())) - return ret; - if (copy_from_user((char *) &i, src, sizeof(int))) return -EFAULT; - save_flags(flags); - cli(); - src += sizeof(int); - while (i) { - int phone_len; - int out_flag; - - if (copy_from_user((char *) &cfg, src, sizeof(cfg))) { - restore_flags(flags); - return -EFAULT; - } - src += sizeof(cfg); - if (!isdn_net_new(cfg.name, NULL)) { - restore_flags(flags); - return -EIO; - } - if ((ret = isdn_net_setcfg(&cfg))) { - restore_flags(flags); - return ret; - } - phone_len = out_flag = 0; - while (out_flag < 2) { - if ((ret = verify_area(VERIFY_READ, src, 1))) { - restore_flags(flags); - return ret; - } - get_user(phone.phone[phone_len], src++); - if ((phone.phone[phone_len] == ' ') || - (phone.phone[phone_len] == '\0')) { - if (phone_len) { - phone.phone[phone_len] = '\0'; - strcpy(phone.name, cfg.name); - phone.outgoing = out_flag; - if ((ret = isdn_net_addphone(&phone))) { - restore_flags(flags); - return ret; - } - } else - out_flag++; - phone_len = 0; - } - if (++phone_len >= sizeof(phone.phone)) - printk(KERN_WARNING - "%s: IIOCSETSET phone number too long, ignored\n", - cfg.name); - } - i--; - } - restore_flags(flags); - return 0; -} - -static int -isdn_get_allcfg(char *dest) -{ - isdn_net_ioctl_cfg cfg; - isdn_net_ioctl_phone phone; - isdn_net_dev *p; - ulong flags; - int ret; - - /* Walk through netdev-chain */ - save_flags(flags); - cli(); - p = dev->netdev; - while (p) { - isdn_net_local *lp = p->local; - - if ((ret = verify_area(VERIFY_WRITE, (void *) dest, sizeof(cfg) + 200))) { - restore_flags(flags); - return ret; - } - strcpy(cfg.eaz, lp->msn); - cfg.exclusive = lp->exclusive; - if (lp->pre_device >= 0) { - sprintf(cfg.drvid, "%s,%d", dev->drvid[lp->pre_device], - lp->pre_channel); - } else - cfg.drvid[0] = '\0'; - cfg.onhtime = lp->onhtime; - cfg.charge = lp->charge; - cfg.l2_proto = lp->l2_proto; - cfg.l3_proto = lp->l3_proto; - cfg.p_encap = lp->p_encap; - cfg.secure = (lp->flags & ISDN_NET_SECURE) ? 1 : 0; - cfg.callback = (lp->flags & ISDN_NET_CALLBACK) ? 1 : 0; - cfg.chargehup = (lp->hupflags & ISDN_CHARGEHUP) ? 1 : 0; - cfg.ihup = (lp->hupflags & ISDN_INHUP) ? 1 : 0; - cfg.chargeint = lp->chargeint; - if (copy_to_user(dest, lp->name, 10)) { - restore_flags(flags); - return -EFAULT; - } - dest += 10; - if (copy_to_user(dest, (char *) &cfg, sizeof(cfg))) { - restore_flags(flags); - return -EFAULT; - } - dest += sizeof(cfg); - strcpy(phone.name, lp->name); - phone.outgoing = 0; - if ((ret = isdn_net_getphones(&phone, dest)) < 0) { - restore_flags(flags); - return ret; - } else - dest += ret; - strcpy(phone.name, lp->name); - phone.outgoing = 1; - if ((ret = isdn_net_getphones(&phone, dest)) < 0) { - restore_flags(flags); - return ret; - } else - dest += ret; - put_user(0, dest); - p = p->next; - } - restore_flags(flags); - return 0; -} -#endif static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) @@ -1316,6 +1484,17 @@ } else return -EINVAL; break; +#ifdef CONFIG_NETDEVICES + case IIOCNETGPN: + /* Get peer phone number of a connected + * isdn network interface */ + if (arg) { + if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) + return -EFAULT; + return isdn_net_getpeer(&phone, (isdn_net_ioctl_phone *) arg); + } else + return -EINVAL; +#endif default: return -EINVAL; } @@ -1327,7 +1506,7 @@ if (drvidx < 0) return -ENODEV; chidx = isdn_minor2chan(minor); - if (!dev->drv[drvidx]->running) + if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) return -ENODEV; return 0; } @@ -1513,26 +1692,11 @@ } if (drvidx == -1) return -ENODEV; - dev->drv[drvidx]->reject_bus = iocts.arg; - return 0; -#if 0 - case IIOCGETSET: - /* Get complete setup (all network-interfaces and profile- - settings of all tty-devices */ - if (arg) - return (isdn_get_allcfg((char *) arg)); - else - return -EINVAL; - break; - case IIOCSETSET: - /* Set complete setup (all network-interfaces and profile- - settings of all tty-devices */ - if (arg) - return (isdn_set_allcfg((char *) arg)); + if (iocts.arg) + dev->drv[drvidx]->flags |= DRV_FLAG_REJBUS; else - return -EINVAL; - break; -#endif + dev->drv[drvidx]->flags &= ~DRV_FLAG_REJBUS; + return 0; case IIOCSIGPRF: dev->profd = current; return 0; @@ -1544,7 +1708,7 @@ int i; if ((ret = verify_area(VERIFY_WRITE, (void *) arg, - (ISDN_MODEM_ANZREG + ISDN_MSNLEN) + (ISDN_MODEM_ANZREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS))) return ret; @@ -1556,8 +1720,11 @@ if (copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN)) return -EFAULT; p += ISDN_MSNLEN; + if (copy_to_user(p, dev->mdm.info[i].emu.plmsn, ISDN_LMSNLEN)) + return -EFAULT; + p += ISDN_LMSNLEN; } - return (ISDN_MODEM_ANZREG + ISDN_MSNLEN) * ISDN_MAX_CHANNELS; + return (ISDN_MODEM_ANZREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS; } else return -EINVAL; break; @@ -1721,7 +1888,6 @@ uint minor = MINOR(ino->i_rdev); int drvidx; int chidx; - isdn_ctrl c; if (minor == ISDN_MINOR_STATUS) { infostruct *p; @@ -1744,31 +1910,25 @@ if (drvidx < 0) return -ENODEV; chidx = isdn_minor2chan(minor); - if (!dev->drv[drvidx]->running) + if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) return -ENODEV; - if (!(dev->drv[drvidx]->flags & (1 << chidx))) + if (!(dev->drv[drvidx]->online & (1 << chidx))) return -ENODEV; - c.command = ISDN_CMD_LOCK; - c.driver = drvidx; - isdn_command(&c); - MOD_INC_USE_COUNT; + isdn_MOD_INC_USE_COUNT(); return 0; } if (minor <= ISDN_MINOR_CTRLMAX) { drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL); if (drvidx < 0) return -ENODEV; - c.command = ISDN_CMD_LOCK; - c.driver = drvidx; - MOD_INC_USE_COUNT; - isdn_command(&c); + isdn_MOD_INC_USE_COUNT(); return 0; } #ifdef CONFIG_ISDN_PPP if (minor <= ISDN_MINOR_PPPMAX) { int ret; if (!(ret = isdn_ppp_open(minor - ISDN_MINOR_PPP, filep))) - MOD_INC_USE_COUNT; + isdn_MOD_INC_USE_COUNT(); return ret; } #endif @@ -1779,13 +1939,12 @@ isdn_close(struct inode *ino, struct file *filep) { uint minor = MINOR(ino->i_rdev); - int drvidx; - isdn_ctrl c; - MOD_DEC_USE_COUNT; if (minor == ISDN_MINOR_STATUS) { infostruct *p = dev->infochain; infostruct *q = NULL; + + MOD_DEC_USE_COUNT; while (p) { if (p->private == (char *) &(filep->private_data)) { if (q) @@ -1801,24 +1960,12 @@ printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n"); return 0; } - if (minor < ISDN_MINOR_CTRL) { - drvidx = isdn_minor2drv(minor); - if (drvidx < 0) - return 0; - c.command = ISDN_CMD_UNLOCK; - c.driver = drvidx; - isdn_command(&c); + isdn_MOD_DEC_USE_COUNT(); + if (minor < ISDN_MINOR_CTRL) return 0; - } if (minor <= ISDN_MINOR_CTRLMAX) { - drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL); - if (drvidx < 0) - return 0; if (dev->profd == current) dev->profd = NULL; - c.command = ISDN_CMD_UNLOCK; - c.driver = drvidx; - isdn_command(&c); return 0; } #ifdef CONFIG_ISDN_PPP @@ -1872,7 +2019,6 @@ ulong flags; ulong features; ulong vfeatures; - isdn_ctrl cmd; save_flags(flags); cli(); @@ -1890,7 +2036,9 @@ if ((dev->usage[i] & ISDN_USAGE_EXCLUSIVE) && ((pre_dev != d) || (pre_chan != dev->chanmap[i]))) continue; - if ((dev->drv[d]->running)) { + if (dev->usage[i] & ISDN_USAGE_DISABLED) + continue; /* usage not allowed */ + if (dev->drv[d]->flags & DRV_FLAG_RUNNING) { if (((dev->drv[d]->interface->features & features) == features) || (((dev->drv[d]->interface->features & vfeatures) == vfeatures) && (dev->drv[d]->interface->features & ISDN_FEATURE_L2_TRANS))) { @@ -1898,10 +2046,6 @@ dev->usage[i] &= ISDN_USAGE_EXCLUSIVE; dev->usage[i] |= usage; isdn_info_update(); - cmd.driver = d; - cmd.arg = 0; - cmd.command = ISDN_CMD_LOCK; - isdn_command(&cmd); restore_flags(flags); return i; } else { @@ -1909,10 +2053,6 @@ dev->usage[i] &= ISDN_USAGE_EXCLUSIVE; dev->usage[i] |= usage; isdn_info_update(); - cmd.driver = d; - cmd.arg = 0; - cmd.command = ISDN_CMD_LOCK; - isdn_command(&cmd); restore_flags(flags); return i; } @@ -1932,7 +2072,6 @@ { int i; ulong flags; - isdn_ctrl cmd; save_flags(flags); cli(); @@ -1946,12 +2085,6 @@ dev->obytes[i] = 0; isdn_info_update(); isdn_free_queue(&dev->drv[di]->rpqueue[ch]); - cmd.driver = di; - cmd.arg = ch; - cmd.command = ISDN_CMD_UNLOCK; - restore_flags(flags); - isdn_command(&cmd); - return; } restore_flags(flags); } @@ -1996,7 +2129,6 @@ copy_from_user(skb_put(skb, len), buf, len); else memcpy(skb_put(skb, len), buf, len); - ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb); if (ret <= 0) dev_kfree_skb(skb); @@ -2052,19 +2184,233 @@ return ret; } +int +register_isdn_module(isdn_module *m) { +#if 0 + isdn_module_list **pp = &dev->modules; + isdn_module *new = kmalloc(sizeof(isdn_module_list), GFP_KERNEL); + + if (!new) { + printk(KERN_WARNING "isdn: Out of memory in register_isdn_module\n"); + return -1; + } + while (*pp && (*pp)->orig != m) + pp = &(*pp)->next; + if (*pp != NULL) { + printk(KERN_WARNING "isdn: Module %s already registered\n", m->name); + return -1; + } + while (*pp && ((*pp)->module.priority < m->priority)) + pp = &(*pp)->next; + new->next = *pp; + new->orig = m; + new->module = *m; + + *pp = new; +#endif + return 0; +} + +int +unregister_isdn_module(isdn_module *m) { +#if 0 + isdn_module_list **pp = &dev->modules; + + while (*pp && *pp != m) + pp = &(*pp)->next; + if (*pp == NULL) { + printk(KERN_WARNING "isdn: Module %s not found\n", m->name); + return -1; + } +#endif + return 0; +} + +int +isdn_add_channels(driver *d, int drvidx, int n, int adding) +{ + int j, k, m; + ulong flags; + +#ifdef COMPAT_HAS_NEW_WAITQ + init_waitqueue_head(&d->st_waitq); +#endif + if (d->flags & DRV_FLAG_RUNNING) + return -1; + if (n < 1) return 0; + + m = (adding) ? d->channels + n : n; + + if (dev->channels + n > ISDN_MAX_CHANNELS) { + printk(KERN_WARNING "register_isdn: Max. %d channels supported\n", + ISDN_MAX_CHANNELS); + return -1; + } + + if ((adding) && (d->rcverr)) + kfree(d->rcverr); + if (!(d->rcverr = (int *) kmalloc(sizeof(int) * m, GFP_KERNEL))) { + printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n"); + return -1; + } + memset((char *) d->rcverr, 0, sizeof(int) * m); + + if ((adding) && (d->rcvcount)) + kfree(d->rcvcount); + if (!(d->rcvcount = (int *) kmalloc(sizeof(int) * m, GFP_KERNEL))) { + printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n"); + if (!adding) kfree(d->rcverr); + return -1; + } + memset((char *) d->rcvcount, 0, sizeof(int) * m); + + if ((adding) && (d->rpqueue)) { + for (j = 0; j < d->channels; j++) + isdn_free_queue(&d->rpqueue[j]); + kfree(d->rpqueue); + } + if (!(d->rpqueue = + (struct sk_buff_head *) kmalloc(sizeof(struct sk_buff_head) * m, GFP_KERNEL))) { + printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n"); + if (!adding) { + kfree(d->rcvcount); + kfree(d->rcverr); + } + return -1; + } + for (j = 0; j < m; j++) { + skb_queue_head_init(&d->rpqueue[j]); + } + + if ((adding) && (d->rcv_waitq)) + kfree(d->rcv_waitq); +#ifdef COMPAT_HAS_NEW_WAITQ + d->rcv_waitq = (wait_queue_head_t *) + kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_KERNEL); + if (!d->rcv_waitq) { +#else + if (!(d->rcv_waitq = (struct wait_queue **) + kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) { +#endif + printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n"); + if (!adding) { + kfree(d->rpqueue); + kfree(d->rcvcount); + kfree(d->rcverr); + } + return -1; + } +#ifdef COMPAT_HAS_NEW_WAITQ + d->snd_waitq = d->rcv_waitq + m; + for (j = 0; j < m; j++) { + init_waitqueue_head(&d->rcv_waitq[m]); + init_waitqueue_head(&d->snd_waitq[m]); + } +#else + memset((char *) d->rcv_waitq, 0, sizeof(struct wait_queue *) * m); + + if ((adding) && (d->snd_waitq)) + kfree(d->snd_waitq); + if (!(d->snd_waitq = (struct wait_queue **) + kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) { + printk(KERN_WARNING "register_isdn: Could not alloc snd_waitq\n"); + if (!adding) { + kfree(d->rcv_waitq); + kfree(d->rpqueue); + kfree(d->rcvcount); + kfree(d->rcverr); + } + return -1; + } + memset((char *) d->snd_waitq, 0, sizeof(struct wait_queue *) * m); +#endif + + dev->channels += n; + save_flags(flags); + cli(); + for (j = d->channels; j < m; j++) + for (k = 0; k < ISDN_MAX_CHANNELS; k++) + if (dev->chanmap[k] < 0) { + dev->chanmap[k] = j; + dev->drvmap[k] = drvidx; + break; + } + restore_flags(flags); + d->channels = m; + return 0; +} + /* * Low-level-driver registration */ + +#ifdef CONFIG_ISDN_DIVERSION +extern isdn_divert_if *divert_if; + +static char *map_drvname(int di) +{ + if ((di < 0) || (di >= ISDN_MAX_DRIVERS)) + return(NULL); + return(dev->drvid[di]); /* driver name */ +} /* map_drvname */ + +static int map_namedrv(char *id) +{ int i; + + for (i = 0; i < ISDN_MAX_DRIVERS; i++) + { if (!strcmp(dev->drvid[i],id)) + return(i); + } + return(-1); +} /* map_namedrv */ + +int DIVERT_REG_NAME(isdn_divert_if *i_div) +{ + if (i_div->if_magic != DIVERT_IF_MAGIC) + return(DIVERT_VER_ERR); + switch (i_div->cmd) + { + case DIVERT_CMD_REL: + if (divert_if != i_div) + return(DIVERT_REL_ERR); + divert_if = NULL; /* free interface */ + MOD_DEC_USE_COUNT; + return(DIVERT_NO_ERR); + + case DIVERT_CMD_REG: + if (divert_if) + return(DIVERT_REG_ERR); + i_div->ll_cmd = isdn_command; /* set command function */ + i_div->drv_to_name = map_drvname; + i_div->name_to_drv = map_namedrv; + MOD_INC_USE_COUNT; + divert_if = i_div; /* remember interface */ + return(DIVERT_NO_ERR); + + default: + return(DIVERT_CMD_ERR); + } +} /* DIVERT_REG_NAME */ + +EXPORT_SYMBOL(DIVERT_REG_NAME); + +#endif CONFIG_ISDN_DIVERSION + + EXPORT_SYMBOL(register_isdn); +EXPORT_SYMBOL(register_isdn_module); +EXPORT_SYMBOL(unregister_isdn_module); +#ifdef CONFIG_ISDN_PPP +EXPORT_SYMBOL(isdn_ppp_register_compressor); +EXPORT_SYMBOL(isdn_ppp_unregister_compressor); +#endif int register_isdn(isdn_if * i) { driver *d; - int n, - j, - k; + int j; ulong flags; int drvidx; @@ -2073,12 +2419,6 @@ ISDN_MAX_DRIVERS); return 0; } - n = i->channels; - if (dev->channels + n > ISDN_MAX_CHANNELS) { - printk(KERN_WARNING "register_isdn: Max. %d channels supported\n", - ISDN_MAX_CHANNELS); - return 0; - } if (!i->writebuf_skb) { printk(KERN_WARNING "register_isdn: No write routine given.\n"); return 0; @@ -2088,64 +2428,22 @@ return 0; } memset((char *) d, 0, sizeof(driver)); - if (!(d->rcverr = (int *) kmalloc(sizeof(int) * n, GFP_KERNEL))) { - printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n"); - kfree(d); - return 0; - } - memset((char *) d->rcverr, 0, sizeof(int) * n); - if (!(d->rcvcount = (int *) kmalloc(sizeof(int) * n, GFP_KERNEL))) { - printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n"); - kfree(d->rcverr); - kfree(d); - return 0; - } - memset((char *) d->rcvcount, 0, sizeof(int) * n); - if (!(d->rpqueue = - (struct sk_buff_head *) kmalloc(sizeof(struct sk_buff_head) * n, GFP_KERNEL))) { - printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n"); - kfree(d->rcvcount); - kfree(d->rcverr); - kfree(d); - return 0; - } - for (j = 0; j < n; j++) { - skb_queue_head_init(&d->rpqueue[j]); - } - if (!(d->rcv_waitq = (struct wait_queue **) - kmalloc(sizeof(struct wait_queue *) * n, GFP_KERNEL))) { - printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n"); - kfree(d->rpqueue); - kfree(d->rcvcount); - kfree(d->rcverr); - kfree(d); - return 0; - } - memset((char *) d->rcv_waitq, 0, sizeof(struct wait_queue *) * n); - if (!(d->snd_waitq = (struct wait_queue **) - kmalloc(sizeof(struct wait_queue *) * n, GFP_KERNEL))) { - printk(KERN_WARNING "register_isdn: Could not alloc snd_waitq\n"); - kfree(d->rcv_waitq); - kfree(d->rpqueue); - kfree(d->rcvcount); - kfree(d->rcverr); - kfree(d); - return 0; - } - memset((char *) d->snd_waitq, 0, sizeof(struct wait_queue *) * n); - d->channels = n; - d->loaded = 1; + d->maxbufsize = i->maxbufsize; d->pktcount = 0; d->stavail = 0; - d->running = 0; - d->flags = 0; + d->flags = DRV_FLAG_LOADED; + d->online = 0; d->interface = i; + d->channels = 0; for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) if (!dev->drv[drvidx]) break; + if (isdn_add_channels(d, drvidx, i->channels, 0)) { + kfree(d); + return 0; + } i->channels = drvidx; - i->rcvcallb_skb = isdn_receive_skb_callback; i->statcallb = isdn_status_callback; if (!strlen(i->id)) @@ -2155,15 +2453,7 @@ for (j = 0; j < drvidx; j++) if (!strcmp(i->id, dev->drvid[j])) sprintf(i->id, "line%d", drvidx); - for (j = 0; j < n; j++) - for (k = 0; k < ISDN_MAX_CHANNELS; k++) - if (dev->chanmap[k] < 0) { - dev->chanmap[k] = j; - dev->drvmap[k] = drvidx; - break; - } dev->drv[drvidx] = d; - dev->channels += n; strcpy(dev->drvid[drvidx], i->id); isdn_info_update(); dev->drivers++; @@ -2215,12 +2505,21 @@ memset((char *) dev, 0, sizeof(isdn_dev)); init_timer(&dev->timer); dev->timer.function = isdn_timer_funct; +#ifdef COMPAT_HAS_NEW_WAITQ + init_MUTEX(&dev->sem); + init_waitqueue_head(&dev->info_waitq); +#else dev->sem = MUTEX; +#endif for (i = 0; i < ISDN_MAX_CHANNELS; i++) { dev->drvmap[i] = -1; dev->chanmap[i] = -1; dev->m_idx[i] = -1; strcpy(dev->num[i], "???"); +#ifdef COMPAT_HAS_NEW_WAITQ + init_waitqueue_head(&dev->mdm.info[i].open_wait); + init_waitqueue_head(&dev->mdm.info[i].close_wait); +#endif } if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) { printk(KERN_WARNING "isdn: Could not register control devices\n"); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_common.h linux.pre11.3/drivers/isdn/isdn_common.h --- linux.vanilla/drivers/isdn/isdn_common.h Sun Jan 24 19:55:34 1999 +++ linux.pre11.3/drivers/isdn/isdn_common.h Mon Jul 19 23:59:35 1999 @@ -1,8 +1,8 @@ -/* $Id: isdn_common.h,v 1.9 1998/02/20 17:19:01 fritz Exp $ +/* $Id: isdn_common.h,v 1.16 1999/07/01 08:29:54 keil Exp $ * header for Linux ISDN subsystem, common used functions and debugging-switches (linklevel). * - * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) * @@ -20,11 +20,39 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Note: This file differs from the corresponding revision as present in the - * isdn4linux CVS repository because some later bug fixes have been extracted - * from the repository and merged into this file. -- Henner Eisen - * * $Log: isdn_common.h,v $ + * Revision 1.16 1999/07/01 08:29:54 keil + * compatibility to 2.3 kernel + * + * Revision 1.15 1999/04/18 14:06:50 fritz + * Removed TIMRU stuff. + * + * Revision 1.14 1999/04/12 12:33:18 fritz + * Changes from 2.0 tree. + * + * Revision 1.13 1999/03/02 12:04:47 armin + * -added ISDN_STAT_ADDCH to increase supported channels after + * register_isdn(). + * -ttyI now goes on-hook on ATZ when B-Ch is connected. + * -added timer-function for register S7 (Wait for Carrier). + * -analog modem (ISDN_PROTO_L2_MODEM) implementations. + * -on L2_MODEM a string will be appended to the CONNECT-Message, + * which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN. + * -variable "dialing" used for ATA also, for interrupting call + * establishment and register S7. + * + * Revision 1.12 1998/06/26 15:12:27 fritz + * Added handling of STAT_ICALL with incomplete CPN. + * Added AT&L for ttyI emulator. + * Added more locking stuff in tty_write. + * + * Revision 1.11 1998/04/14 16:28:47 he + * Fixed user space access with interrupts off and remaining + * copy_{to,from}_user() -> -EFAULT return codes + * + * Revision 1.10 1998/03/07 18:21:03 cal + * Dynamic Timeout-Rule-Handling vs. 971110 included + * * Revision 1.9 1998/02/20 17:19:01 fritz * Added common stub for sending commands to lowlevel. * @@ -90,10 +118,16 @@ extern void isdn_timer_ctrl(int tf, int onoff); extern void isdn_unexclusive_channel(int di, int ch); extern int isdn_getnum(char **); +#ifdef COMPAT_HAS_NEW_WAITQ +extern int isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *); +#else extern int isdn_readbchan(int, int, u_char *, u_char *, int, struct wait_queue**); +#endif extern int isdn_get_free_channel(int, int, int, int, int); extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *); extern int register_isdn(isdn_if * i); +extern int isdn_wildmat(char *, char *); +extern int isdn_add_channels(driver *, int, int, int); #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP) extern void isdn_dumppkt(char *, u_char *, int, int); #endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_concap.c linux.pre11.3/drivers/isdn/isdn_concap.c --- linux.vanilla/drivers/isdn/isdn_concap.c Sun Nov 8 15:08:10 1998 +++ linux.pre11.3/drivers/isdn/isdn_concap.c Mon Jul 19 23:59:35 1999 @@ -1,10 +1,21 @@ -/* $Id: isdn_concap.c,v 1.2 1998/01/31 22:49:21 keil Exp $ +/* $Id: isdn_concap.c,v 1.5 1998/10/30 18:44:48 he Exp $ * Stuff to support the concap_proto by isdn4linux. isdn4linux - specific * stuff goes here. Stuff that depends only on the concap protocol goes to * another -- protocol specific -- source file. * * $Log: isdn_concap.c,v $ + * Revision 1.5 1998/10/30 18:44:48 he + * pass return value from isdn_net_dial_req for dialmode change + * + * Revision 1.4 1998/10/30 17:55:24 he + * dialmode for x25iface and multulink ppp + * + * Revision 1.3 1998/05/26 22:39:22 he + * sync'ed with 2.1.102 where appropriate (CAPABILITY changes) + * concap typo + * cleared dev.tbusy in isdn_net BCONN status callback + * * Revision 1.2 1998/01/31 22:49:21 keil * correct comments * @@ -20,14 +31,9 @@ #include #include "isdn_concap.h" -/* The declaration of this (or a plublic variant thereof) should really go - in linux/isdn.h. But we really need it here (and isdn_ppp, like us, also - refers to that private function currently owned by isdn_net.c) */ -extern int isdn_net_force_dial_lp(isdn_net_local *); - /* The following set of device service operations are for encapsulation - protocols that require for reliable datalink sematics. That means: + protocols that require for reliable datalink semantics. That means: - before any data is to be submitted the connection must explicitly be set up. @@ -66,9 +72,9 @@ IX25DEBUG( "isdn_concap_dl_connect_req: %s \n", ndev -> name); /* dial ... */ - ret = isdn_net_force_dial_lp( lp ); + ret = isdn_net_dial_req( lp ); if ( ret ) IX25DEBUG("dialing failed\n"); - return 0; + return ret; } int isdn_concap_dl_disconn_req(struct concap_proto *concap) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_net.c linux.pre11.3/drivers/isdn/isdn_net.c --- linux.vanilla/drivers/isdn/isdn_net.c Sun Jan 24 19:55:34 1999 +++ linux.pre11.3/drivers/isdn/isdn_net.c Mon Jul 19 23:59:35 1999 @@ -1,8 +1,8 @@ -/* $Id: isdn_net.c,v 1.55 1998/02/23 19:38:22 fritz Exp $ +/* $Id: isdn_net.c,v 1.88 1999/07/07 10:13:31 detabc Exp $ * Linux ISDN subsystem, network interfaces and related functions (linklevel). * - * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) * @@ -20,11 +20,105 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Note: This file differs from the corresponding revision as present in the - * isdn4linux CVS repository because some later bug fixes have been extracted - * from the repository and merged into this file. -- Henner Eisen - * * $Log: isdn_net.c,v $ + * Revision 1.88 1999/07/07 10:13:31 detabc + * remove unused messages + * + * Revision 1.87 1999/07/06 07:53:53 calle + * calls to dev_alloc_skb waste 16 bytes of memory, if we calculate the + * right header space for the lowlevel driver. using alloc_skb instead. + * + * Revision 1.86 1999/06/09 10:12:05 paul + * thinko in previous patch + * + * Revision 1.85 1999/06/07 19:42:39 paul + * isdn_net_getpeer() fixed to return correct `outgoing' flag + * + * Revision 1.84 1999/04/18 14:06:55 fritz + * Removed TIMRU stuff. + * + * Revision 1.83 1999/04/12 12:33:23 fritz + * Changes from 2.0 tree. + * + * Revision 1.82 1999/01/17 00:55:58 he + * added mark_bh in BCONN statcallb and cleaned up some dead code + * + * Revision 1.81 1999/01/15 16:36:52 he + * replaced icmp_send() by dst_link_failure() + * + * Revision 1.80 1998/12/01 13:06:22 paul + * Also huptimeout with dialmode == manual + * + * Revision 1.79 1998/10/30 17:55:27 he + * dialmode for x25iface and multulink ppp + * + * Revision 1.78 1998/10/26 18:20:46 he + * re-inserted p=p->next in isdn_net_find_icall() (fixes kernel lock up + * on incoming call not matching the first interface) + * + * Revision 1.77 1998/10/23 10:18:44 paul + * Implementation of "dialmode" (successor of "status") + * You also need current isdnctrl for this! + * + * Revision 1.76 1998/09/07 22:00:05 he + * flush method for 2.1.118 and above + * updated IIOCTLNETGPN + * + * Revision 1.75 1998/08/31 21:09:50 he + * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface' + * peer phone number) + * + * Revision 1.74 1998/07/30 11:28:32 paul + * printk message only appeared when status is off and interface is rawIP, + * which is confusing for people who don't know about "isdnctrl status on". + * + * Revision 1.73 1998/06/26 22:01:37 keil + * tx_queue_len = 5 was too small + * + * Revision 1.72 1998/06/26 15:12:31 fritz + * Added handling of STAT_ICALL with incomplete CPN. + * Added AT&L for ttyI emulator. + * Added more locking stuff in tty_write. + * + * Revision 1.71 1998/06/18 22:43:08 fritz + * Bugfix: Setting ndev->do_ioctl had beed accidetly removed at cleanup. + * + * Revision 1.70 1998/06/17 19:50:49 he + * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) + * brute force fix to avoid Ugh's in isdn_tty_write() + * cleaned up some dead code + * + * Revision 1.69 1998/06/09 12:27:37 cal + * Changed default of local netdev flags: ISDN_NET_STOPPED is default now, + * so autodial is suppressed for that device until it is switched on using + * 'isdnctrl status dev-name on'. + * + * + * + * Revision 1.66 1998/05/26 22:39:24 he + * sync'ed with 2.1.102 where appropriate (CAPABILITY changes) + * concap typo + * cleared dev.tbusy in isdn_net BCONN status callback + * + * Revision 1.61 1998/04/16 19:19:42 keil + * Fix from vger (tx max qlength) + * + * Revision 1.60 1998/04/14 16:28:49 he + * Fixed user space access with interrupts off and remaining + * copy_{to,from}_user() -> -EFAULT return codes + * + * Revision 1.59 1998/03/07 22:37:33 fritz + * Bugfix: restore_flags missing. + * + * Revision 1.58 1998/03/07 18:21:05 cal + * Dynamic Timeout-Rule-Handling vs. 971110 included + * + * Revision 1.57 1998/02/25 18:31:13 fritz + * Added debugging output in adjust_header. + * + * Revision 1.56 1998/02/25 17:49:42 he + * Changed return codes caused be failing copy_{to,from}_user to -EFAULT + * * Revision 1.55 1998/02/23 19:38:22 fritz * Corrected check for modified feature-flags. * @@ -248,9 +342,7 @@ #include #include #include -#ifndef DEV_NUMBUFFS #include -#endif #include #include "isdn_common.h" #include "isdn_net.h" @@ -265,14 +357,10 @@ /* Prototypes */ int isdn_net_force_dial_lp(isdn_net_local *); -static int isdn_net_wildmat(char *s, char *p); static int isdn_net_start_xmit(struct sk_buff *, struct device *); static int isdn_net_xmit(struct device *, isdn_net_local *, struct sk_buff *); -#ifdef DEV_NUMBUFFS -static void dev_purge_queues(struct device *dev); /* move this to net/core/dev.c */ -#endif -char *isdn_net_revision = "$Revision: 1.55 $"; +char *isdn_net_revision = "$Revision: 1.88 $"; /* * Code for raw-networking over ISDN @@ -293,16 +381,21 @@ dst_link_failure(skb); } + else { /* dial not triggered by rawIP packet */ + printk(KERN_DEBUG "isdn_net: %s: %s\n", + dev->name, + (reason != NULL) ? reason : "reason unknown"); + } } static void isdn_net_reset(struct device *dev) { #ifdef CONFIG_ISDN_X25 - struct concap_device_ops * dops = + struct concap_device_ops * dops = ( (isdn_net_local *) dev->priv ) -> dops; - struct concap_proto * cprot = - ( (isdn_net_local *) dev->priv ) -> netdev -> cprot; + struct concap_proto * cprot = + ( (isdn_net_local *) dev->priv ) -> netdev -> cprot; #endif ulong flags; @@ -311,7 +404,7 @@ dev->interrupt = 0; dev->tbusy = 0; #ifdef CONFIG_ISDN_X25 - if( cprot && cprot -> pops && dops ) + if( cprot && cprot -> pops && dops ) cprot -> pops -> restart ( cprot, dev, dops ); #endif restore_flags(flags); @@ -338,7 +431,7 @@ if (ifa != NULL) memcpy(dev->dev_addr+2, &ifa->ifa_local, 4); } - + /* If this interface has slaves, start them also */ if ((p = (((isdn_net_local *) dev->priv)->slave))) { @@ -362,6 +455,7 @@ save_flags(flags); cli(); + lp->flags |= ISDN_NET_CONNECTED; lp->isdn_device = dev->drvmap[idx]; lp->isdn_channel = dev->chanmap[idx]; dev->rx_netdev[idx] = lp->netdev; @@ -387,10 +481,6 @@ dev_kfree_skb(lp->sav_skb); lp->sav_skb = NULL; } -#ifdef DEV_NUMBUFFS - if (!lp->master) /* purge only for master device */ - dev_purge_queues(&lp->netdev->dev); -#else if (!lp->master) { /* reset only master device */ /* Moral equivalent of dev_purge_queues(): BEWARE! This chunk of code cannot be called from hardware @@ -398,7 +488,6 @@ */ qdisc_reset(lp->netdev->dev.qdisc); } -#endif 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; @@ -444,7 +533,13 @@ if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) { anymore = 1; l->huptimer++; - if ((l->onhtime) && (l->huptimer > l->onhtime)) { + /* + * if there is some dialmode where timeout-hangup + * should _not_ be done, check for that here + */ + if ((l->onhtime) && + (l->huptimer > l->onhtime)) + { if (l->hupflags & ISDN_MANCHARGE && l->hupflags & ISDN_CHARGEHUP) { while (jiffies - l->chargetime > l->chargeint) @@ -469,6 +564,11 @@ } else if (l->hupflags & ISDN_INHUP) isdn_net_hangup(&p->dev); } + + if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF)) { + isdn_net_hangup(&p->dev); + break; + } } p = (isdn_net_dev *) p->next; } @@ -487,7 +587,7 @@ { isdn_net_dev *p = dev->st_netdev[idx]; int cmd = c->command; - + if (p) { isdn_net_local *lp = p->local; #ifdef CONFIG_ISDN_X25 @@ -538,23 +638,12 @@ failed. If there are generic encap protocol receiver routines signal the closure of the link*/ - - if( !(lp->flags & ISDN_NET_CONNECTED) + + 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)) { - lp->flags &= ~ISDN_NET_CONNECTED; - if (lp->first_skb) { - dev_kfree_skb(lp->first_skb); - lp->first_skb = NULL; - } - if (lp->sav_skb) { - dev_kfree_skb(lp->sav_skb); - lp->sav_skb = NULL; - } - isdn_free_channel(lp->isdn_device, lp->isdn_channel, - ISDN_USAGE_NET); #ifdef CONFIG_ISDN_PPP isdn_ppp_free(lp); #endif @@ -562,10 +651,7 @@ printk(KERN_INFO "%s: remote hangup\n", lp->name); printk(KERN_INFO "%s: Chargesum is %d\n", lp->name, lp->charge); - lp->isdn_device = -1; - lp->isdn_channel = -1; - dev->st_netdev[idx] = NULL; - dev->rx_netdev[idx] = NULL; + isdn_net_unbind_channel(lp); return 1; } break; @@ -607,6 +693,11 @@ lp->chargetime = jiffies; printk(KERN_DEBUG "isdn_net: chargetime of %s now %d\n", lp->name, lp->chargetime); + + /* reset dial-timeout */ + lp->dialstarted = 0; + lp->dialwait_timer = 0; + /* Immediately send first skb to speed up arp */ #ifdef CONFIG_ISDN_PPP if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) @@ -617,13 +708,13 @@ if( pops ) if( pops->connect_ind) pops->connect_ind(cprot); - #endif /* CONFIG_ISDN_X25 */ if (lp->first_skb) { - + if (!(isdn_net_xmit(&p->dev, lp, lp->first_skb))) lp->first_skb = NULL; - } else { + } + else { /* * dev.tbusy is usually cleared implicitly by isdn_net_xmit(,,lp->first_skb). * With an empty lp->first_skb, we need to do this ourselves @@ -721,6 +812,13 @@ break; } anymore = 1; + + if(lp->dialtimeout > 0) + if(lp->dialstarted == 0 || jiffies > (lp->dialstarted + lp->dialtimeout + lp->dialwait)) { + lp->dialstarted = jiffies; + lp->dialwait_timer = 0; + } + lp->dialstate++; /* Fall through */ case 2: @@ -735,12 +833,22 @@ lp->dialretry = 0; anymore = 1; lp->dialstate++; - /* Falls through */ + /* Fall through */ case 3: /* Setup interface, dial current phone-number, switch to next number. * If list of phone-numbers is exhausted, increment * retry-counter. */ + if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) { + char *s; + if (dev->global_flags & ISDN_GLOBAL_STOPPED) + s = "dial suppressed: isdn system stopped"; + else + s = "dial suppressed: dialmode `off'"; + isdn_net_unreachable(&p->dev, lp->first_skb, s); + isdn_net_hangup(&p->dev); + break; + } cmd.driver = lp->isdn_device; cmd.command = ISDN_CMD_SETL2; cmd.arg = lp->isdn_channel + (lp->l2_proto << 8); @@ -765,6 +873,16 @@ lp->dialstate = 4; printk(KERN_INFO "%s: Open leased line ...\n", lp->name); } else { + if(lp->dialtimeout > 0) + if(jiffies > (lp->dialstarted + lp->dialtimeout)) { + restore_flags(flags); + lp->dialwait_timer = jiffies + lp->dialwait; + lp->dialstarted = 0; + isdn_net_unreachable(&p->dev, lp->first_skb, "dial: timed out"); + isdn_net_hangup(&p->dev); + break; + } + sprintf(cmd.parm.setup.phone, "%s", lp->dial->num); /* * Switch to next number or back to start if at end of list. @@ -772,6 +890,17 @@ if (!(lp->dial = (isdn_net_phone *) lp->dial->next)) { lp->dial = lp->phone[1]; lp->dialretry++; + + if (lp->dialretry > lp->dialmax) { + restore_flags(flags); + if (lp->dialtimeout == 0) { + lp->dialwait_timer = jiffies + lp->dialwait; + lp->dialstarted = 0; + isdn_net_unreachable(&p->dev, lp->first_skb, "dial: tried all numbers dialmax times"); + } + isdn_net_hangup(&p->dev); + break; + } } restore_flags(flags); cmd.driver = lp->isdn_device; @@ -786,7 +915,7 @@ isdn_info_update(); } printk(KERN_INFO "%s: dialing %d %s...\n", lp->name, - lp->dialretry - 1, cmd.parm.setup.phone); + lp->dialretry, cmd.parm.setup.phone); lp->dtimer = 0; #ifdef ISDN_DEBUG_NET_DIAL printk(KERN_DEBUG "dial: d=%d c=%d\n", lp->isdn_device, @@ -810,15 +939,11 @@ break; case 4: /* Wait for D-Channel-connect. - * If timeout and max retries not - * reached, switch back to state 3. + * If timeout, switch back to state 3. + * Dialmax-handling moved to state 3. */ - if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) { - if (lp->dialretry < lp->dialmax) { - lp->dialstate = 3; - } else - isdn_net_hangup(&p->dev); - } + if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) + lp->dialstate = 3; anymore = 1; break; case 5: @@ -895,7 +1020,8 @@ /* Remote does callback. Hangup after cbdelay, then wait for incoming * call (in state 4). */ - if (lp->dtimer++ > lp->cbdelay) { + if (lp->dtimer++ > lp->cbdelay) + { printk(KERN_INFO "%s: hangup waiting for callback ...\n", lp->name); lp->dtimer = 0; lp->dialstate = 4; @@ -930,7 +1056,6 @@ #endif if (lp->flags & ISDN_NET_CONNECTED) { - lp->flags &= ~ISDN_NET_CONNECTED; printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name); #ifdef CONFIG_ISDN_PPP isdn_ppp_free(lp); @@ -938,7 +1063,7 @@ #ifdef CONFIG_ISDN_X25 /* try if there are generic encap protocol receiver routines and signal the closure of - the link */ + the link */ if( pops && pops -> disconn_ind ) pops -> disconn_ind(cprot); #endif /* CONFIG_ISDN_X25 */ @@ -968,7 +1093,7 @@ char addinfo[100]; addinfo[0] = '\0'; - /* This check stolen from 2.1.72 dev_queue_xmit_nit() */ + /* This check stolen from 2.1.72 dev_queue_xmit_nit() */ if (skb->nh.raw < skb->data || skb->nh.raw >= skb->tail) { /* fall back to old isdn_net_log_packet method() */ char * buf = skb->data; @@ -1062,20 +1187,17 @@ if (ret == len) { lp->transcount += len; clear_bit(0, (void *) &(ndev->tbusy)); - mark_bh(NET_BH); return 0; } if (ret < 0) { dev_kfree_skb(skb); lp->stats.tx_errors++; clear_bit(0, (void *) &(ndev->tbusy)); - mark_bh(NET_BH); return 0; } return 1; } - /* * Helper function for isdn_net_start_xmit. * When called, the connection is already established. @@ -1150,9 +1272,11 @@ if (!skb) return; if (lp->p_encap == ISDN_NET_ENCAP_ETHER) { - ulong pullsize = (ulong)skb->nh.raw - (ulong)skb->data - ETH_HLEN; - if (pullsize) + int pullsize = (ulong)skb->nh.raw - (ulong)skb->data - ETH_HLEN; + if (pullsize > 0) { + printk(KERN_DEBUG "isdn_net: Pull junk %d\n", pullsize); skb_pull(skb, pullsize); + } } } @@ -1166,7 +1290,7 @@ { isdn_net_local *lp = (isdn_net_local *) ndev->priv; #ifdef CONFIG_ISDN_X25 - struct concap_proto * cprot = lp -> netdev -> cprot; + struct concap_proto * cprot = lp -> netdev -> cprot; #endif if (ndev->tbusy) { @@ -1179,7 +1303,7 @@ ndev->tbusy = 1; /* left instead of obsolete test_and_set_bit() */ #ifdef CONFIG_ISDN_X25 /* At this point hard_start_xmit() passes control to the encapsulation - protocol (if present). + protocol (if present). For X.25 auto-dialing is completly bypassed because: - It does not conform with the semantics of a reliable datalink service as needed by X.25 PLP. @@ -1205,17 +1329,46 @@ #endif if (!(lp->flags & ISDN_NET_CONNECTED)) { int chi; + /* only do autodial if allowed by config */ + if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) { + isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'"); + dev_kfree_skb(skb); + ndev->tbusy = 0; + return 0; + } if (lp->phone[1]) { ulong flags; save_flags(flags); cli(); + + if(lp->dialwait_timer <= 0) + if(lp->dialstarted > 0 && lp->dialtimeout > 0 && jiffies < lp->dialstarted + lp->dialtimeout + lp->dialwait) + lp->dialwait_timer = lp->dialstarted + lp->dialtimeout + lp->dialwait; + + if(lp->dialwait_timer > 0) { + if(jiffies < lp->dialwait_timer) { + isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached"); + dev_kfree_skb(skb); + ndev->tbusy = 0; + restore_flags(flags); + return 0; + } else + lp->dialwait_timer = 0; + } + /* Grab a free ISDN-Channel */ - if ((chi = + if (((chi = isdn_get_free_channel(ISDN_USAGE_NET, lp->l2_proto, lp->l3_proto, lp->pre_device, - lp->pre_channel)) < 0) { + lp->pre_channel)) < 0) && + ((chi = + isdn_get_free_channel(ISDN_USAGE_NET, + lp->l2_proto, + lp->l3_proto, + lp->pre_device, + lp->pre_channel^1)) < 0)) { restore_flags(flags); isdn_net_unreachable(ndev, skb, "No channel"); @@ -1227,7 +1380,6 @@ if (dev->net_verbose) isdn_net_log_skb(skb, lp); lp->dialstate = 1; - lp->flags |= ISDN_NET_CONNECTED; /* Connect interface with channel */ isdn_net_bind_channel(lp, chi); #ifdef CONFIG_ISDN_PPP @@ -1290,8 +1442,8 @@ { struct device *p; #ifdef CONFIG_ISDN_X25 - struct concap_proto * cprot = - ( (isdn_net_local *) dev->priv ) -> netdev -> cprot; + struct concap_proto * cprot = + ( (isdn_net_local *) dev->priv ) -> netdev -> cprot; /* printk(KERN_DEBUG "isdn_net_close %s\n" , dev-> name ); */ #endif @@ -1304,9 +1456,9 @@ /* If this interface has slaves, stop them also */ while (p) { #ifdef CONFIG_ISDN_X25 - cprot = ( (isdn_net_local *) p->priv ) - -> netdev -> cprot; - if( cprot && cprot -> pops ) + cprot = ( (isdn_net_local *) p->priv ) + -> netdev -> cprot; + if( cprot && cprot -> pops ) cprot -> pops -> close( cprot ); #endif isdn_net_hangup(p); @@ -1387,12 +1539,12 @@ isdn_net_slarp_send(isdn_net_local *lp, int is_reply) { unsigned short hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; - struct sk_buff *skb = dev_alloc_skb(hl + sizeof(cisco_hdr) + sizeof(cisco_slarp)); + struct sk_buff *skb = alloc_skb(hl + sizeof(cisco_hdr) + sizeof(cisco_slarp), GFP_ATOMIC); unsigned long t = (jiffies / HZ * 1000000); int len; cisco_hdr *ch; cisco_slarp *s; - + if (!skb) { printk(KERN_WARNING "%s: Could not allocate SLARP reply\n", lp->name); @@ -1406,7 +1558,7 @@ s = (cisco_slarp *)skb_put(skb, sizeof(cisco_slarp)); if (is_reply) { s->code = htonl(CISCO_SLARP_REPLY); - memset(&s->slarp.reply.ifaddr, 0, sizeof(__u32)); + memset(&s->slarp.reply.ifaddr, 0, sizeof(__u32)); memset(&s->slarp.reply.netmask, 0, sizeof(__u32)); } else { lp->cisco_myseq++; @@ -1589,7 +1741,7 @@ default: #ifdef CONFIG_ISDN_X25 /* try if there are generic sync_device receiver routines */ - if(cprot) if(cprot -> pops) + if(cprot) if(cprot -> pops) if( cprot -> pops -> data_ind){ cprot -> pops -> data_ind(cprot,skb); return; @@ -1600,6 +1752,7 @@ kfree_skb(skb); return; } + netif_rx(skb); return; } @@ -1788,16 +1941,12 @@ ndev->type = ARPHRD_ETHER; ndev->addr_len = ETH_ALEN; - ndev->tx_queue_len = 10; /* for clients without MPPP 5 is better. */ + /* for clients with MPPP maybe higher values better */ + ndev->tx_queue_len = 30; for (i = 0; i < ETH_ALEN; i++) ndev->broadcast[i] = 0xff; -#ifdef DEV_NUMBUFFS - for (i = 0; i < DEV_NUMBUFFS; i++) - skb_queue_head_init(&ndev->buffs[i]); -#endif - /* The ISDN-specific entries in the device structure. */ ndev->open = &isdn_net_open; ndev->hard_start_xmit = &isdn_net_start_xmit; @@ -1813,86 +1962,15 @@ max_hlhdr_len = dev->drv[drvidx]->interface->hl_hdrlen; ndev->hard_header_len = ETH_HLEN + max_hlhdr_len; - ndev->stop = &isdn_net_close; ndev->get_stats = &isdn_net_get_stats; ndev->rebuild_header = &isdn_net_rebuild_header; - #ifdef CONFIG_ISDN_PPP ndev->do_ioctl = isdn_ppp_dev_ioctl; #endif return 0; } -/* - * I picked the pattern-matching-functions from an old GNU-tar version (1.10) - * It was originally written and put to PD by rs@mirror.TMC.COM (Rich Salz) - */ - -static int -isdn_net_Star(char *s, char *p) -{ - while (isdn_net_wildmat(s, p) == 0) - if (*++s == '\0') - return (0); - return (1); -} - -/* - * Shell-type Pattern-matching for incoming caller-Ids - * This function gets a string in s and checks, if it matches the pattern - * given in p. It returns 1 on success, 0 otherwise. - * - * Possible Patterns: - * - * '?' matches one character - * '*' matches zero or more characters - * [xyz] matches the set of characters in brackets. - * [^xyz] matches any single character not in the set of characters - */ - -static int -isdn_net_wildmat(char *s, char *p) -{ - register int last; - register int matched; - register int reverse; - - for (; *p; s++, p++) - switch (*p) { - case '\\': - /* - * Literal match with following character, - * fall through. - */ - p++; - default: - if (*s != *p) - return (0); - continue; - case '?': - /* Match anything. */ - if (*s == '\0') - return (0); - continue; - case '*': - /* Trailing star matches everything. */ - return (*++p ? isdn_net_Star(s, p) : 1); - case '[': - /* [^....] means inverse character class. */ - if ((reverse = (p[1] == '^'))) - p++; - for (last = 0, matched = 0; *++p && (*p != ']'); last = *p) - /* This next line requires a good C compiler. */ - if (*p == '-' ? *s <= *++p && *s >= last : *s == *p) - matched = 1; - if (matched == reverse) - return (0); - continue; - } - return (*s == '\0'); -} - static void isdn_net_swapbind(int drvidx) { @@ -1945,6 +2023,8 @@ * 2 = Reject call, wait cbdelay, then call back * 3 = Reject call * 4 = Wait cbdelay, then call back + * 5 = No appropriate interface for this call, + * would eventually match if CID was longer. */ int isdn_net_find_icall(int di, int ch, int idx, setup_parm setup) @@ -1953,6 +2033,7 @@ int si1; int si2; int ematch; + int wret; int swapped; int sidx = 0; isdn_net_dev *p; @@ -1987,13 +2068,13 @@ } n = (isdn_net_phone *) 0; p = dev->netdev; - ematch = 0; + ematch = wret = swapped = 0; #ifdef ISDN_DEBUG_NET_ICALL printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx, dev->usage[idx]); #endif - swapped = 0; while (p) { + int matchret; isdn_net_local *lp = p->local; /* If last check has triggered as binding-swap, revert it */ @@ -2006,18 +2087,22 @@ break; } swapped = 0; - if (!strcmp(isdn_map_eaz2msn(lp->msn, di), eaz)) + if (!(matchret = isdn_wildmat(eaz, isdn_map_eaz2msn(lp->msn, di)))) ematch = 1; + /* Remember if more numbers eventually can match */ + if (matchret > wret) + wret = matchret; #ifdef ISDN_DEBUG_NET_ICALL printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n", lp->name, lp->msn, lp->flags, lp->dialstate); #endif - if ((!strcmp(isdn_map_eaz2msn(lp->msn, di), eaz)) && /* EAZ is matching */ - (((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */ - (USG_NONE(dev->usage[idx]))) || /* and ch. unused or */ - ((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing */ - (!(lp->flags & ISDN_NET_CALLBACK))) /* but no callback */ - ))) { + if ((!matchret) && /* EAZ is matching */ + (((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */ + (USG_NONE(dev->usage[idx]))) || /* and ch. unused or */ + ((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing */ + (!(lp->flags & ISDN_NET_CALLBACK))) /* but no callback */ + ))) + { #ifdef ISDN_DEBUG_NET_ICALL printk(KERN_DEBUG "n_fi: match1, pdev=%d pch=%d\n", lp->pre_device, lp->pre_channel); @@ -2085,8 +2170,6 @@ #ifdef ISDN_DEBUG_NET_ICALL printk(KERN_DEBUG "n_fi: already on 2nd channel\n"); #endif - p = (isdn_net_dev *) p->next; - continue; } } } @@ -2096,7 +2179,7 @@ n = lp->phone[0]; if (lp->flags & ISDN_NET_SECURE) { while (n) { - if (isdn_net_wildmat(nr, n->num)) + if (!isdn_wildmat(nr, n->num)) break; n = (isdn_net_phone *) n->next; } @@ -2105,7 +2188,21 @@ #ifdef ISDN_DEBUG_NET_ICALL printk(KERN_DEBUG "n_fi: match3\n"); #endif - /* Here we got an interface matched, now see if it is up. + /* matching interface found */ + + /* + * Is the state STOPPED? + * If so, no dialin is allowed, + * so reject actively. + * */ + if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) { + restore_flags(flags); + printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n", + lp->name); + return 3; + } + /* + * Is the interface up? * If not, reject the call actively. */ if (!p->dev.start) { @@ -2140,6 +2237,17 @@ } if (lp->flags & ISDN_NET_CALLBACK) { int chi; + /* + * Is the state MANUAL? + * If so, no callback can be made, + * so reject actively. + * */ + if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) { + restore_flags(flags); + printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n", + lp->name); + return 3; + } printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n", lp->name, nr, eaz); if (lp->phone[1]) { @@ -2155,7 +2263,6 @@ /* Setup dialstate. */ lp->dtimer = 0; lp->dialstate = 11; - lp->flags |= ISDN_NET_CONNECTED; /* Connect interface with channel */ isdn_net_bind_channel(lp, chi); #ifdef CONFIG_ISDN_PPP @@ -2217,10 +2324,10 @@ p = (isdn_net_dev *) p->next; } /* If none of configured EAZ/MSN matched and not verbose, be silent */ - if (ematch || dev->net_verbose) + if (!ematch || dev->net_verbose) printk(KERN_INFO "isdn_net: call from %s -> %d %s ignored\n", nr, di, eaz); restore_flags(flags); - return 0; + return (wret == 2)?5:0; } /* @@ -2253,6 +2360,7 @@ ulong flags; save_flags(flags); cli(); + /* Grab a free ISDN-Channel */ if ((chi = isdn_get_free_channel(ISDN_USAGE_NET, lp->l2_proto, lp->l3_proto, @@ -2263,7 +2371,6 @@ return -EAGAIN; } lp->dialstate = 1; - lp->flags |= ISDN_NET_CONNECTED; /* Connect interface with channel */ isdn_net_bind_channel(lp, chi); #ifdef CONFIG_ISDN_PPP @@ -2285,6 +2392,20 @@ } /* + * This is called from certain upper protocol layers (multilink ppp + * and x25iface encapsulation module) that want to initiate dialing + * themselves. + */ +int +isdn_net_dial_req(isdn_net_local * lp) +{ + /* is there a better error code? */ + if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) return -EBUSY; + + return isdn_net_force_dial_lp(lp); +} + +/* * Force a net-interface to dial out. * This is always called from within userspace (ISDN_IOCTL_NET_DIAL). */ @@ -2383,8 +2504,13 @@ netdev->local->onhtime = 10; /* Default hangup-time for saving costs of those who forget configuring this */ netdev->local->dialmax = 1; - netdev->local->flags = ISDN_NET_CBHUP; /* Hangup before Callback */ + netdev->local->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL; /* Hangup before Callback, manual dial */ netdev->local->cbdelay = 25; /* Wait 5 secs before Callback */ + netdev->local->dialtimeout = -1; /* Infinite Dial-Timeout */ + netdev->local->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */ + netdev->local->dialstarted = 0; /* Jiffies of last dial-start */ + netdev->local->dialwait_timer = 0; /* Jiffies of earliest next dial-start */ + /* Put into to netdev-chain */ netdev->next = (void *) dev->netdev; dev->netdev = netdev; @@ -2465,7 +2591,7 @@ save_flags(flags); cli(); /* avoid races with incoming events trying to call cprot->pops methods */ - if( cprot && cprot -> pops ) + if( cprot && cprot -> pops ) cprot -> pops -> proto_del ( cprot ); p -> cprot = NULL; lp -> dops = NULL; @@ -2479,7 +2605,7 @@ p -> cprot = isdn_concap_new( cfg -> p_encap ); /* p -> cprot == NULL now if p_encap is not supported by means of the concap_proto mechanism */ - /* the protocol is not configured yet; this will + /* the protocol is not configured yet; this will happen later when isdn_net_reset() is called */ #endif } @@ -2508,7 +2634,7 @@ if( cfg->p_encap >= 0 && cfg->p_encap <= ISDN_NET_ENCAP_MAX_ENCAP ) break; - printk(KERN_WARNING + printk(KERN_WARNING "%s: encapsulation protocol %d not supported\n", p->local->name, cfg->p_encap); return -EINVAL; @@ -2583,6 +2709,8 @@ lp->triggercps = cfg->triggercps; lp->slavedelay = cfg->slavedelay * HZ; lp->pppbind = cfg->pppbind; + lp->dialtimeout = cfg->dialtimeout >= 0 ? cfg->dialtimeout * HZ : -1; + lp->dialwait = cfg->dialwait * HZ; if (cfg->secure) lp->flags |= ISDN_NET_SECURE; else @@ -2604,6 +2732,16 @@ lp->flags &= ~ISDN_NET_CALLBACK; break; } + lp->flags &= ~ISDN_NET_DIALMODE_MASK; /* first all bits off */ + if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) { + /* old isdnctrl version, where only 0 or 1 is given */ + printk(KERN_WARNING + "Old isdnctrl version detected! Please update.\n"); + lp->flags |= ISDN_NET_DM_OFF; /* turn on `off' bit */ + } + else { + lp->flags |= cfg->dialmode; /* turn on selected bits */ + } if (cfg->chargehup) lp->hupflags |= ISDN_CHARGEHUP; else @@ -2671,6 +2809,7 @@ if (lp->flags & ISDN_NET_CBOUT) cfg->callback = 2; cfg->cbhup = (lp->flags & ISDN_NET_CBHUP) ? 1 : 0; + cfg->dialmode = lp->flags & ISDN_NET_DIALMODE_MASK; cfg->chargehup = (lp->hupflags & 4) ? 1 : 0; cfg->ihup = (lp->hupflags & 8) ? 1 : 0; cfg->cbdelay = lp->cbdelay; @@ -2680,6 +2819,8 @@ cfg->chargeint = (lp->hupflags & ISDN_CHARGEHUP) ? (lp->chargeint / HZ) : 0; cfg->pppbind = lp->pppbind; + cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1; + cfg->dialwait = lp->dialwait / HZ; if (lp->slave) strcpy(cfg->slave, ((isdn_net_local *) lp->slave->priv)->name); else @@ -2749,9 +2890,37 @@ } /* - * Delete a phone-number from an interface. + * Copy a string containing the peer's phone number of a connected interface + * to user space. */ +int +isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone *peer) +{ + isdn_net_dev *p = isdn_net_findif(phone->name); + int ch, dv, idx; + if (!p) return -ENODEV; + /* + * Theoretical race: while this executes, the remote number might + * become invalid (hang up) or change (new connection), resulting + * in (partially) wrong number copied to user. This race + * currently ignored. + */ + ch = p->local->isdn_channel; + dv = p->local->isdn_device; + if(ch<0 && dv<0) return -ENOTCONN; + idx = isdn_dc2minor(dv, ch); + if (idx<0) return -ENODEV; + /* for pre-bound channels, we need this extra check */ + 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; + return 0; +} +/* + * Delete a phone-number from an interface. + */ int isdn_net_delphone(isdn_net_ioctl_phone * phone) { @@ -2957,21 +3126,3 @@ restore_flags(flags); return 0; } - -#ifdef DEV_NUMBUFFS -/* - * helper function to flush device queues - * the better place would be net/core/dev.c - */ -static void -dev_purge_queues(struct device *dev) -{ - int i; - for (i = 0; i < DEV_NUMBUFFS; i++) { - struct sk_buff *skb; - while ((skb = skb_dequeue(&dev->buffs[i]))) - dev_kfree_skb(skb); - } - -} -#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_net.h linux.pre11.3/drivers/isdn/isdn_net.h --- linux.vanilla/drivers/isdn/isdn_net.h Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/isdn_net.h Mon Jul 19 23:59:35 1999 @@ -1,8 +1,8 @@ -/* $Id: isdn_net.h,v 1.6 1997/10/09 21:28:54 fritz Exp $ +/* $Id: isdn_net.h,v 1.9 1999/04/12 12:33:27 fritz Exp $ * header for Linux ISDN subsystem, network related functions (linklevel). * - * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) * @@ -21,6 +21,16 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_net.h,v $ + * Revision 1.9 1999/04/12 12:33:27 fritz + * Changes from 2.0 tree. + * + * Revision 1.8 1998/10/30 17:55:33 he + * dialmode for x25iface and multulink ppp + * + * Revision 1.7 1998/08/31 21:09:55 he + * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface' + * peer phone number) + * * Revision 1.6 1997/10/09 21:28:54 fritz * New HL<->LL interface: * New BSENT callback with nr. of bytes included. @@ -99,6 +109,7 @@ extern int isdn_net_getcfg(isdn_net_ioctl_cfg *); extern int isdn_net_addphone(isdn_net_ioctl_phone *); extern int isdn_net_getphones(isdn_net_ioctl_phone *, char *); +extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *); extern int isdn_net_delphone(isdn_net_ioctl_phone *); extern int isdn_net_find_icall(int, int, int, setup_parm); extern void isdn_net_hangup(struct device *); @@ -111,3 +122,4 @@ struct sk_buff *); extern int isdn_net_rcv_skb(int, struct sk_buff *); extern void isdn_net_slarp_out(void); +extern int isdn_net_dial_req(isdn_net_local *); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_ppp.c linux.pre11.3/drivers/isdn/isdn_ppp.c --- linux.vanilla/drivers/isdn/isdn_ppp.c Sun Jan 24 19:55:34 1999 +++ linux.pre11.3/drivers/isdn/isdn_ppp.c Mon Jul 19 23:59:35 1999 @@ -1,4 +1,4 @@ -/* $Id: isdn_ppp.c,v 1.33 1998/02/20 17:11:54 fritz Exp $ +/* $Id: isdn_ppp.c,v 1.49 1999/07/06 07:47:11 calle Exp $ * * Linux ISDN subsystem, functions for synchronous PPP (linklevel). * @@ -18,11 +18,58 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Note: This file differs from the corresponding revision as present in the - * isdn4linux CVS repository because some later bug fixes have been extracted - * from the repository and merged into this file. -- Henner Eisen - * * $Log: isdn_ppp.c,v $ + * Revision 1.49 1999/07/06 07:47:11 calle + * bugfix: dev_alloc_skb only reserve 16 bytes. We need to look at the + * hdrlen the driver want. So I changed dev_alloc_skb calls + * to alloc_skb and skb_reserve. + * + * Revision 1.48 1999/07/01 08:29:56 keil + * compatibility to 2.3 kernel + * + * Revision 1.47 1999/04/18 14:06:59 fritz + * Removed TIMRU stuff. + * + * Revision 1.46 1999/04/12 12:33:35 fritz + * Changes from 2.0 tree. + * + * Revision 1.45 1998/12/30 17:48:24 paul + * fixed syncPPP callback out + * + * Revision 1.44 1998/10/30 17:55:34 he + * dialmode for x25iface and multulink ppp + * + * Revision 1.43 1998/10/29 17:23:54 hipp + * Minor MPPP fixes, verboser logging. + * + * Revision 1.42 1998/07/20 11:30:07 hipp + * Readded compression check + * + * Revision 1.41 1998/07/08 16:50:57 hipp + * Compression changes + * + * Revision 1.40 1998/04/06 19:07:27 hipp + * added check, whether compression is enabled. + * + * Revision 1.39 1998/03/25 22:46:53 hipp + * Some additional CCP changes. + * + * Revision 1.38 1998/03/24 16:33:06 hipp + * More CCP changes. BSD compression now "works" on a local loopback link. + * Moved some isdn_ppp stuff from isdn.h to isdn_ppp.h + * + * Revision 1.37 1998/03/22 18:50:49 hipp + * Added BSD Compression for syncPPP .. UNTESTED at the moment + * + * Revision 1.36 1998/03/09 17:46:30 he + * merged in 2.1.89 changes + * + * Revision 1.35 1998/03/07 18:21:11 cal + * Dynamic Timeout-Rule-Handling vs. 971110 included + * + * Revision 1.34 1998/02/25 17:49:48 he + * Changed return codes caused be failing copy_{to,from}_user to -EFAULT + * * Revision 1.33 1998/02/20 17:11:54 fritz * Changes for recent kernels. * @@ -157,13 +204,16 @@ * experimental for dynamic addressing: readdress IP frames */ #undef ISDN_SYNCPPP_READDRESS +#define CONFIG_ISDN_CCP 1 #include #define __NO_VERSION__ #include #include -#include #include +#include +#include + #include "isdn_common.h" #include "isdn_ppp.h" #include "isdn_net.h" @@ -180,13 +230,33 @@ static void isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb, int proto); static int isdn_ppp_if_get_unit(char *namebuf); -static int isdn_ppp_set_compressor(struct ippp_struct *is,int num); +static int isdn_ppp_set_compressor(struct ippp_struct *is,struct isdn_ppp_comp_data *); static struct sk_buff *isdn_ppp_decompress(struct sk_buff *, - struct ippp_struct *,struct ippp_struct *); + struct ippp_struct *,struct ippp_struct *,int proto); static void isdn_ppp_receive_ccp(isdn_net_dev * net_dev, isdn_net_local * lp, - struct sk_buff *skb); + struct sk_buff *skb,int proto); static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto, struct ippp_struct *is,struct ippp_struct *master,int type); +static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, + struct sk_buff *skb); + +/* New CCP stuff */ +static void isdn_ppp_ccp_kickup(struct ippp_struct *is); +static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, + unsigned char code, unsigned char id, + unsigned char *data, int len); +static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is); +static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is, + unsigned char id); +static void isdn_ppp_ccp_timer_callback(unsigned long closure); +static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is, + unsigned char id); +static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is, + struct isdn_ppp_resetparams *rp); +static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is, + unsigned char id); + + #ifdef CONFIG_ISDN_MPP static int isdn_ppp_bundle(struct ippp_struct *, int unit); @@ -199,18 +269,16 @@ static void isdn_ppp_free_mpqueue(isdn_net_dev *); #endif -char *isdn_ppp_revision = "$Revision: 1.33 $"; +char *isdn_ppp_revision = "$Revision: 1.49 $"; static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS]; static struct isdn_ppp_compressor *ipc_head = NULL; -extern int isdn_net_force_dial_lp(isdn_net_local *); - /* * frame log (debug) */ static void -isdn_ppp_frame_log(char *info, char *data, int len, int maxlen) +isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot) { int cnt, j, @@ -223,13 +291,14 @@ for (i = 0, cnt = 0; cnt < maxlen; i++) { for (j = 0; j < 16 && cnt < maxlen; j++, cnt++) sprintf(buf + j * 3, "%02x ", (unsigned char) data[cnt]); - printk(KERN_DEBUG "%s[%d]: %s\n", info, i, buf); + printk(KERN_DEBUG "[%d/%d].%s[%d]: %s\n",unit,slot, info, i, buf); } } /* * unbind isdn_net_local <=> ippp-device * note: it can happen, that we hangup/free the master before the slaves + * in this case we bind another lp to the master device */ int isdn_ppp_free(isdn_net_local * lp) @@ -267,8 +336,7 @@ if ((is->state & IPPP_CONNECT)) isdn_ppp_closewait(lp->ppp_slot); /* force wakeup on ippp device */ else if (is->state & IPPP_ASSIGNED) - is->state = IPPP_OPEN; /* fallback to 'OPEN but not ASSIGEND' staet */ - + is->state = IPPP_OPEN; /* fallback to 'OPEN but not ASSIGNED' state */ if (is->debug & 0x1) printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp, (long) is->lp); @@ -320,14 +388,16 @@ } } } else { - for (i = 0; i < ISDN_MAX_CHANNELS; i++) - if (ippp_table[i]->minor == lp->pppbind && ippp_table[i]->state == IPPP_OPEN) + for (i = 0; i < ISDN_MAX_CHANNELS; i++) { + if (ippp_table[i]->minor == lp->pppbind && + (ippp_table[i]->state & IPPP_OPEN) == IPPP_OPEN) break; + } } if (i >= ISDN_MAX_CHANNELS) { restore_flags(flags); - printk(KERN_WARNING "isdn_ppp_bind: Can't find usable ippp device.\n"); + printk(KERN_WARNING "isdn_ppp_bind: Can't find a (free) connection to the ipppd daemon.\n"); return -1; } unit = isdn_ppp_if_get_unit(lp->name); /* get unit number from interface name .. ugly! */ @@ -336,6 +406,15 @@ return -1; } lp->ppp_slot = i; + + /* reset some values */ + lp->netdev->ib.bundled = 0; + lp->netdev->ib.next_num = 0; + lp->netdev->ib.modify = 0; + lp->netdev->ib.last = NULL; + lp->netdev->ib.min = 0; + lp->netdev->ib.sq = NULL; + is = ippp_table[i]; is->lp = lp; is->unit = unit; @@ -359,7 +438,9 @@ ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK; +#ifndef COMPAT_HAS_NEW_WAITQ if (ippp_table[lp->ppp_slot]->wq) +#endif wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq); } @@ -377,7 +458,11 @@ return 0; is = ippp_table[slot]; +#ifdef COMPAT_HAS_NEW_WAITQ + if (is->state) +#else if (is->state && is->wq) +#endif wake_up_interruptible(&is->wq); is->state = IPPP_CLOSEWAIT; @@ -418,14 +503,19 @@ } is = file->private_data = ippp_table[slot]; +#if 0 if (is->debug & 0x1) +#endif printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n", slot, min, is->state); /* compression stuff */ - is->compressor = NULL; - is->decomp_stat = is->comp_stat = NULL; - is->link_compressor = NULL; - is->link_decomp_stat = is->link_comp_stat = NULL; + is->link_compressor = is->compressor = NULL; + is->link_decompressor = is->decompressor = NULL; + is->link_comp_stat = is->comp_stat = NULL; + is->link_decomp_stat = is->decomp_stat = NULL; + is->compflags = 0; + + is->reset = isdn_ppp_ccp_reset_alloc(is); is->lp = NULL; is->mp_seqno = 0; /* MP sequence number */ @@ -437,8 +527,11 @@ is->mru = 1524; /* MRU, default 1524 */ is->maxcid = 16; /* VJ: maxcid */ is->tk = current; +#ifdef COMPAT_HAS_NEW_WAITQ + init_waitqueue_head(&is->wq); +#else is->wq = NULL; /* read() wait queue */ - is->wq1 = NULL; /* select() wait queue */ +#endif is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */ is->last = is->rq; is->minor = min; @@ -491,10 +584,30 @@ is->last = is->rq; #ifdef CONFIG_ISDN_PPP_VJ +/* TODO: if this was the previous master: link the slcomp to the new master */ slhc_free(is->slcomp); is->slcomp = NULL; #endif +/* TODO: if this was the previous master: link the the stuff to the new master */ + if(is->comp_stat) + is->compressor->free(is->comp_stat); + if(is->link_comp_stat) + is->link_compressor->free(is->link_comp_stat); + if(is->link_decomp_stat) + is->link_decompressor->free(is->link_decomp_stat); + if(is->decomp_stat) + is->decompressor->free(is->decomp_stat); + is->compressor = is->link_compressor = NULL; + is->decompressor = is->link_decompressor = NULL; + is->comp_stat = is->link_comp_stat = NULL; + is->decomp_stat = is->link_decomp_stat = NULL; + + if(is->reset) + kfree(is->reset); + is->reset = NULL; + + /* this slot is ready for new connections */ is->state = 0; } @@ -505,7 +618,7 @@ get_arg(void *b, void *val, int len) { if (len <= 0) - len = sizeof(unsigned long); + len = sizeof(void *); if (copy_from_user((void *) val, b, len)) return -EFAULT; return 0; @@ -515,15 +628,12 @@ * set arg .. ioctl helper */ static int -set_arg(void *b, unsigned long val, void *str) +set_arg(void *b, void *val,int len) { - if (!str) { - if (copy_to_user(b, (void *) &val, 4)) - return -EFAULT; - } else { - if (copy_to_user(b, str, val)) - return -EFAULT; - } + if(len <= 0) + len = sizeof(void *); + if (copy_to_user(b, (void *) val, len)) + return -EFAULT; return 0; } @@ -534,9 +644,10 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) { unsigned long val; - int num,r; + int r,i,j; struct ippp_struct *is; isdn_net_local *lp; + struct isdn_ppp_comp_data data; is = (struct ippp_struct *) file->private_data; lp = is->lp; @@ -552,7 +663,7 @@ #ifdef CONFIG_ISDN_MPP if (!(is->state & IPPP_CONNECT)) return -EINVAL; - if ((r = get_arg((void *) arg, &val, 0))) + if ((r = get_arg((void *) arg, &val, sizeof(val) ))) return r; printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n", (int) min, (int) is->unit, (int) val); @@ -562,24 +673,30 @@ #endif break; case PPPIOCGUNIT: /* get ppp/isdn unit number */ - if ((r = set_arg((void *) arg, is->unit, NULL))) + if ((r = set_arg((void *) arg, &is->unit, sizeof(is->unit) ))) + return r; + break; + case PPPIOCGIFNAME: + if(!lp) + return -EINVAL; + if ((r = set_arg((void *) arg, lp->name,strlen(lp->name)))) return r; break; case PPPIOCGMPFLAGS: /* get configuration flags */ - if ((r = set_arg((void *) arg, is->mpppcfg, NULL))) + if ((r = set_arg((void *) arg, &is->mpppcfg, sizeof(is->mpppcfg) ))) return r; break; case PPPIOCSMPFLAGS: /* set configuration flags */ - if ((r = get_arg((void *) arg, &val, 0))) + if ((r = get_arg((void *) arg, &val, sizeof(val) ))) return r; is->mpppcfg = val; break; case PPPIOCGFLAGS: /* get configuration flags */ - if ((r = set_arg((void *) arg, is->pppcfg, NULL))) + if ((r = set_arg((void *) arg, &is->pppcfg,sizeof(is->pppcfg) ))) return r; break; case PPPIOCSFLAGS: /* set configuration flags */ - if ((r = get_arg((void *) arg, &val, 0))) { + if ((r = get_arg((void *) arg, &val, sizeof(val) ))) { return r; } if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) { @@ -598,12 +715,12 @@ if (lp) { struct ppp_idle pidle; pidle.xmit_idle = pidle.recv_idle = lp->huptimer; - if ((r = set_arg((void *) arg, sizeof(struct ppp_idle), &pidle))) + if ((r = set_arg((void *) arg, &pidle,sizeof(struct ppp_idle)))) return r; } break; case PPPIOCSMRU: /* set receive unit size for PPP */ - if ((r = get_arg((void *) arg, &val, 0))) + if ((r = get_arg((void *) arg, &val, sizeof(val) ))) return r; is->mru = val; break; @@ -612,7 +729,7 @@ case PPPIOCSMPMTU: break; case PPPIOCSMAXCID: /* set the maximum compression slot id */ - if ((r = get_arg((void *) arg, &val, 0))) + if ((r = get_arg((void *) arg, &val, sizeof(val) ))) return r; val++; if (is->maxcid != val) { @@ -635,31 +752,33 @@ } break; case PPPIOCGDEBUG: - if ((r = set_arg((void *) arg, is->debug, 0))) + if ((r = set_arg((void *) arg, &is->debug, sizeof(is->debug) ))) return r; break; case PPPIOCSDEBUG: - if ((r = get_arg((void *) arg, &val, 0))) + if ((r = get_arg((void *) arg, &val, sizeof(val) ))) return r; is->debug = val; break; case PPPIOCGCOMPRESSORS: { - unsigned long protos = 0; + unsigned long protos[8] = {0,}; struct isdn_ppp_compressor *ipc = ipc_head; while(ipc) { - protos |= (0x1<num); + j = ipc->num / (sizeof(long)*8); + i = ipc->num % (sizeof(long)*8); + if(j < 8) + protos[j] |= (0x1<next; } - if ((r = set_arg((void *) arg, protos, 0))) + if ((r = set_arg((void *) arg,protos,8*sizeof(long) ))) return r; } break; case PPPIOCSCOMPRESSOR: - if ((r = get_arg((void *) arg, &num, sizeof(int)))) + if ((r = get_arg((void *) arg, &data, sizeof(struct isdn_ppp_comp_data)))) return r; - return isdn_ppp_set_compressor(is, num); - break; + return isdn_ppp_set_compressor(is, &data); case PPPIOCGCALLINFO: { struct pppcallinfo pci; @@ -678,7 +797,7 @@ if(lp->flags & ISDN_NET_CALLBACK) pci.calltype |= CALLTYPE_CALLBACK; } - return set_arg((void *)arg,sizeof(struct pppcallinfo),&pci); + return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo)); } default: break; @@ -701,9 +820,12 @@ printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n", MINOR(file->f_dentry->d_inode->i_rdev)); + /* just registers wait_queue hook. This doesn't really wait. */ poll_wait(file, &is->wq, wait); if (!(is->state & IPPP_OPEN)) { + if(is->state == IPPP_CLOSEWAIT) + return POLLHUP; printk(KERN_DEBUG "isdn_ppp: device not open\n"); return POLLERR; } @@ -777,7 +899,9 @@ is->last = bl->next; restore_flags(flags); +#ifndef COMPAT_HAS_NEW_WAITQ if (is->wq) +#endif wake_up_interruptible(&is->wq); return len; @@ -864,21 +988,33 @@ if (lp->isdn_device < 0 || lp->isdn_channel < 0) return 0; - if (dev->drv[lp->isdn_device]->running && lp->dialstate == 0 && + if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) && + lp->dialstate == 0 && (lp->flags & ISDN_NET_CONNECTED)) { + unsigned short hl; int cnt; struct sk_buff *skb; - skb = dev_alloc_skb(count); + /* + * we need to reserve enought space in front of + * sk_buff. old call to dev_alloc_skb only reserved + * 16 bytes, now we are looking what the driver want + */ + hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; + skb = alloc_skb(hl+count, GFP_ATOMIC); if (!skb) { printk(KERN_WARNING "isdn_ppp_write: out of memory!\n"); return count; } + skb_reserve(skb, hl); if (copy_from_user(skb_put(skb, count), buf, count)) return -EFAULT; if (is->debug & 0x40) { printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len); - isdn_ppp_frame_log("xmit", skb->data, skb->len, 32); + isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,is->unit,lp->ppp_slot); } + + isdn_ppp_send_ccp(lp->netdev,lp,skb); /* keeps CCP/compression states in sync */ + if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb)) != count) { if (lp->sav_skb) { dev_kfree_skb(lp->sav_skb); @@ -962,8 +1098,9 @@ is = ippp_table[lp->ppp_slot]; if (is->debug & 0x4) { - printk(KERN_DEBUG "ippp_receive: len: %d\n", (int) skb->len); - isdn_ppp_frame_log("receive", skb->data, skb->len, 32); + printk(KERN_DEBUG "ippp_receive: is:%08lx lp:%08lx slot:%d unit:%d len:%d\n", + (long)is,(long)lp,lp->ppp_slot,is->unit,(int) skb->len); + isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,lp->ppp_slot); } if (net_dev->local->master) { printk(KERN_WARNING "isdn_ppp_receice: net_dev != master\n"); @@ -981,13 +1118,18 @@ #ifdef CONFIG_ISDN_MPP if (!(is->mpppcfg & SC_REJ_MP_PROT)) { int sqno_end; - - if(proto == PPP_LINK_COMP) { - printk(KERN_DEBUG "received single link compressed frame\n"); - skb = isdn_ppp_decompress(skb,is,NULL); - if(!skb) - return; - proto = isdn_ppp_strip_proto(skb); + + if(is->compflags & SC_LINK_DECOMP_ON) { + if(proto == PPP_LINK_COMP) { + if(is->debug & 0x10) + printk(KERN_DEBUG "received single link compressed frame\n"); + skb = isdn_ppp_decompress(skb,is,NULL,proto); + if(!skb) + return; + proto = isdn_ppp_strip_proto(skb); + } + else + isdn_ppp_decompress(skb,is,NULL,proto); } if (proto == PPP_MP) { @@ -1054,7 +1196,8 @@ } min_sqno &= mask; for (lpq = net_dev->queue;;) { - ippp_table[lpq->ppp_slot]->last_link_seqno &= mask; + if(ippp_table[lpq->ppp_slot]->last_link_seqno >= 0) + ippp_table[lpq->ppp_slot]->last_link_seqno &= mask; lpq = lpq->next; if (lpq == net_dev->queue) break; @@ -1149,17 +1292,31 @@ if (is->debug & 0x10) { printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto); - isdn_ppp_frame_log("rpush", skb->data, skb->len, 32); + isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit,lp->ppp_slot); } if(proto == PPP_COMP) { if(!lp->master) - skb = isdn_ppp_decompress(skb,is,is); + skb = isdn_ppp_decompress(skb,is,is,proto); else - skb = isdn_ppp_decompress(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot]); - if(!skb) + skb = isdn_ppp_decompress(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot],proto); + + if(!skb) { + printk(KERN_DEBUG "ippp: compressed frame discarded!\n"); return; + } + proto = isdn_ppp_strip_proto(skb); + if (is->debug & 0x10) { + printk(KERN_DEBUG "RPostDecomp, skb %d %04x\n", (int) skb->len, proto); + isdn_ppp_frame_log("R-Decomp", skb->data, skb->len, 32,is->unit,lp->ppp_slot); + } + } + else if(is->compflags & SC_DECOMP_ON) { /* If decomp is ON */ + if(!lp->master) + isdn_ppp_decompress(skb,is,is,proto); + else + isdn_ppp_decompress(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot],proto); } switch (proto) { @@ -1226,7 +1383,13 @@ #endif break; case PPP_CCP: - isdn_ppp_receive_ccp(net_dev,lp,skb); + case PPP_LINK_CCP: + isdn_ppp_receive_ccp(net_dev,lp,skb,proto); + /* Dont pop up ResetReq/Ack stuff to the daemon any + longer - the job is done already */ + if(skb->data[0] == CCP_RESETREQ || + skb->data[0] == CCP_RESETACK) + break; /* fall through */ default: isdn_ppp_fill_rq(skb->data, skb->len, proto, lp->ppp_slot); /* push data to pppd device */ @@ -1234,10 +1397,10 @@ return; } + /* Reset hangup-timer */ + lp->huptimer = 0; netif_rx(skb); /* net_dev->local->stats.rx_packets++; *//* done in isdn_net.c */ - /* Reset hangup-timer */ - lp->huptimer = 0; return; } @@ -1269,9 +1432,9 @@ */ int -isdn_ppp_xmit(struct sk_buff *skb, struct device *dev) +isdn_ppp_xmit(struct sk_buff *skb, struct device *netdev) { - struct device *mdev = ((isdn_net_local *) (dev->priv))->master; /* get master (for redundancy) */ + struct device *mdev = ((isdn_net_local *) (netdev->priv))->master; /* get master (for redundancy) */ isdn_net_local *lp,*mlp; isdn_net_dev *nd; unsigned int proto = PPP_IP; /* 0x21 */ @@ -1280,8 +1443,8 @@ if (mdev) mlp = (isdn_net_local *) (mdev->priv); else { - mdev = dev; - mlp = (isdn_net_local *) (dev->priv); + mdev = netdev; + mlp = (isdn_net_local *) (netdev->priv); } nd = mlp->netdev; /* get master lp */ ipts = ippp_table[mlp->ppp_slot]; @@ -1294,7 +1457,7 @@ ipts->old_pa_dstaddr = mdev->pa_dstaddr; #endif if (ipts->debug & 0x1) - printk(KERN_INFO "%s: IP frame delayed.\n", dev->name); + printk(KERN_INFO "%s: IP frame delayed.\n", netdev->name); return 1; } @@ -1338,7 +1501,6 @@ lp = nlp; } ipt = ippp_table[lp->ppp_slot]; - lp->huptimer = 0; /* @@ -1354,16 +1516,25 @@ if (ipt->debug & 0x4) printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len); + if (ipts->debug & 0x40) + isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32,ipts->unit,lp->ppp_slot); #ifdef CONFIG_ISDN_PPP_VJ if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes, but check this again */ struct sk_buff *new_skb; - - new_skb = dev_alloc_skb(skb->len); + unsigned short hl; + /* + * we need to reserve enought space in front of + * sk_buff. old call to dev_alloc_skb only reserved + * 16 bytes, now we are looking what the driver want. + */ + hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; + new_skb = alloc_skb(hl+skb->len, GFP_ATOMIC); if (new_skb) { u_char *buf; int pktlen; + skb_reserve(new_skb, hl); new_skb->dev = skb->dev; skb_put(new_skb, skb->len); buf = skb->data; @@ -1393,10 +1564,11 @@ } #endif - /* - * normal or bundle compression - */ - skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0); + /* + * normal (single link) or bundle compression + */ + if(ipts->compflags & SC_COMP_ON) + skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0); if (ipt->debug & 0x24) printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto); @@ -1430,9 +1602,10 @@ #endif /* - * 'link' compression + * 'link in bundle' compression ... */ - skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1); + if(ipt->compflags & SC_LINK_COMP_ON) + skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1); if( (ipt->pppcfg & SC_COMP_PROT) && (proto <= 0xff) ) { unsigned char *data = isdn_ppp_skb_push(&skb,1); @@ -1459,11 +1632,11 @@ if (ipts->debug & 0x40) { printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len); - isdn_ppp_frame_log("xmit", skb->data, skb->len, 32); + isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,ipt->unit,lp->ppp_slot); } - if (isdn_net_send_skb(dev, lp, skb)) { + if (isdn_net_send_skb(netdev, lp, skb)) { if (lp->sav_skb) { /* whole sav_skb processing with disabled IRQs ?? */ - printk(KERN_ERR "%s: whoops .. there is another stored skb!\n", dev->name); + printk(KERN_ERR "%s: whoops .. there is another stored skb!\n", netdev->name); dev_kfree_skb(skb); } else lp->sav_skb = skb; @@ -1473,6 +1646,12 @@ #ifdef CONFIG_ISDN_MPP +/* + * free SQ queue + * ------------- + * Note: We need two queues for MPPP. The SQ queue holds fully (re)assembled frames, + * that can't be delivered, because there is an outstanding earlier frame + */ static void isdn_ppp_free_sqqueue(isdn_net_dev * p) { @@ -1489,6 +1668,12 @@ } +/* + * free MP queue + * ------------- + * Note: The MP queue holds all frame fragments of frames, that can't be + * reassembled, because there is at least one missing fragment. + */ static void isdn_ppp_free_mpqueue(isdn_net_dev * p) { @@ -1550,7 +1735,9 @@ return 0; } - +/* + * Mask sequence numbers in MP queue + */ static void isdn_ppp_mask_queue(isdn_net_dev * dev, long mask) { @@ -1561,6 +1748,11 @@ } } +/* + * put a fragment at the right place into the MP queue + * Also checks, whether this fragment completes a frame. In this case + * the fragments are copied together into one SKB + */ static int isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff **skb, int BEbyte, long *sqnop, int min_sqno) { @@ -1761,13 +1953,11 @@ slhc_toss(ippp_table[dev->local->ppp_slot]->slcomp); #endif } +#endif /* * a buffered packet timed-out? */ - -#endif - void isdn_ppp_timer_timeout(void) { @@ -1939,7 +2129,7 @@ if (!sdev) return 2; - isdn_net_force_dial_lp((isdn_net_local *) sdev->priv); + isdn_net_dial_req((isdn_net_local *) sdev->priv); return 0; #else return -1; @@ -1980,47 +2170,440 @@ /* * PPP compression stuff */ -static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struct *is,struct ippp_struct *master) + + +/* Push an empty CCP Data Frame up to the daemon to wake it up and let it + generate a CCP Reset-Request or tear down CCP altogether */ + +static void isdn_ppp_ccp_kickup(struct ippp_struct *is) +{ + isdn_ppp_fill_rq(NULL, 0, PPP_COMP, is->lp->ppp_slot); +} + +/* In-kernel handling of CCP Reset-Request and Reset-Ack is necessary, + but absolutely nontrivial. The most abstruse problem we are facing is + that the generation, reception and all the handling of timeouts and + resends including proper request id management should be entirely left + to the (de)compressor, but indeed is not covered by the current API to + the (de)compressor. The API is a prototype version from PPP where only + some (de)compressors have yet been implemented and all of them are + rather simple in their reset handling. Especially, their is only one + outstanding ResetAck at a time with all of them and ResetReq/-Acks do + not have parameters. For this very special case it was sufficient to + just return an error code from the decompressor and have a single + reset() entry to communicate all the necessary information between + the framework and the (de)compressor. Bad enough, LZS is different + (and any other compressor may be different, too). It has multiple + histories (eventually) and needs to Reset each of them independently + and thus uses multiple outstanding Acks and history numbers as an + additional parameter to Reqs/Acks. + All that makes it harder to port the reset state engine into the + kernel because it is not just the same simple one as in (i)pppd but + it must be able to pass additional parameters and have multiple out- + standing Acks. We are trying to achieve the impossible by handling + reset transactions independent by their id. The id MUST change when + the data portion changes, thus any (de)compressor who uses more than + one resettable state must provide and recognize individual ids for + each individual reset transaction. The framework itself does _only_ + differentiate them by id, because it has no other semantics like the + (de)compressor might. + This looks like a major redesign of the interface would be nice, + but I don't have an idea how to do it better. */ + +/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. This is + getting that lengthy because there is no simple "send-this-frame-out" + function above but every wrapper does a bit different. Hope I guess + correct in this hack... */ + +static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, + unsigned char code, unsigned char id, + unsigned char *data, int len) +{ + struct sk_buff *skb; + unsigned char *p; + int count; + int cnt = 0; + isdn_net_local *lp = is->lp; + + /* Alloc large enough skb */ + skb = dev_alloc_skb(len + 16); + if(!skb) { + printk(KERN_WARNING + "ippp: CCP cannot send reset - out of memory\n"); + return; + } + + /* We may need to stuff an address and control field first */ + if(!(is->pppcfg & SC_COMP_AC)) { + p = skb_put(skb, 2); + *p++ = 0xff; + *p++ = 0x03; + } + + /* Stuff proto, code, id and length */ + p = skb_put(skb, 6); + *p++ = (proto >> 8); + *p++ = (proto & 0xff); + *p++ = code; + *p++ = id; + cnt = 4 + len; + *p++ = (cnt >> 8); + *p++ = (cnt & 0xff); + + /* Now stuff remaining bytes */ + if(len) { + p = skb_put(skb, len); + memcpy(p, data, len); + } + + /* skb is now ready for xmit */ + printk(KERN_DEBUG "Sending CCP Frame:\n"); + isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot); + + /* Just ripped from isdn_ppp_write. Dunno whether it makes sense, + especially dunno what the sav_skb stuff is good for. */ + + count = skb->len; + if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, + 1, skb)) != count) { + if (lp->sav_skb) { + dev_kfree_skb(lp->sav_skb); + printk(KERN_INFO + "isdn_ppp_write: freeing sav_skb (%d,%d)!\n", + cnt, count); + } else + printk(KERN_INFO + "isdn_ppp_write: Can't write PPP frame to LL (%d,%d)!\n", + cnt, count); + lp->sav_skb = skb; + } +} + +/* Allocate the reset state vector */ +static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is) +{ + struct ippp_ccp_reset *r; + printk(KERN_DEBUG "ippp_ccp: allocating reset data structure\n"); + r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL); + if(!r) + return NULL; + memset(r, 0, sizeof(struct ippp_ccp_reset)); + is->reset = r; + return r; +} + +/* Free a given state and clear everything up for later reallocation */ +static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is, + unsigned char id) +{ + struct ippp_ccp_reset_state *rs; + + if(is->reset->rs[id]) { + printk(KERN_DEBUG "ippp_ccp: freeing state for id %d\n", id); + rs = is->reset->rs[id]; + /* Make sure the kernel will not call back later */ + if(rs->ta) + del_timer(&rs->timer); + is->reset->rs[id] = NULL; + kfree(rs); + } else { + printk(KERN_WARNING "ippp_ccp: id %d is not allocated\n", id); + } +} + +/* The timer callback function which is called when a ResetReq has timed out, + aka has never been answered by a ResetAck */ +static void isdn_ppp_ccp_timer_callback(unsigned long closure) +{ + struct ippp_ccp_reset_state *rs = + (struct ippp_ccp_reset_state *)closure; + + if(!rs) { + printk(KERN_ERR "ippp_ccp: timer cb with zero closure.\n"); + return; + } + if(rs->ta && rs->state == CCPResetSentReq) { + /* We are correct here */ + printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n", + rs->id); + if(!rs->expra) { + /* Hmm, there is no Ack really expected. We can clean + up the state now, it will be reallocated if the + decompressor insists on another reset */ + rs->ta = 0; + isdn_ppp_ccp_reset_free_state(rs->is, rs->id); + return; + } + /* Push it again */ + isdn_ppp_ccp_xmit_reset(rs->is, PPP_CCP, CCP_RESETREQ, rs->id, + rs->data, rs->dlen); + /* Restart timer */ + rs->timer.expires = jiffies + HZ*5; + add_timer(&rs->timer); + } else { + printk(KERN_WARNING "ippp_ccp: timer cb in wrong state %d\n", + rs->state); + } +} + +/* Allocate a new reset transaction state */ +static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is, + unsigned char id) +{ + struct ippp_ccp_reset_state *rs; + if(is->reset->rs[id]) { + printk(KERN_WARNING "ippp_ccp: old state exists for id %d\n", + id); + return NULL; + } else { + rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL); + if(!rs) + return NULL; + memset(rs, 0, sizeof(struct ippp_ccp_reset_state)); + rs->state = CCPResetIdle; + rs->is = is; + rs->id = id; + rs->timer.data = (unsigned long)rs; + rs->timer.function = isdn_ppp_ccp_timer_callback; + is->reset->rs[id] = rs; + } + return rs; +} + + +/* A decompressor wants a reset with a set of parameters - do what is + necessary to fulfill it */ +static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is, + struct isdn_ppp_resetparams *rp) +{ + struct ippp_ccp_reset_state *rs; + + if(rp->valid) { + /* The decompressor defines parameters by itself */ + if(rp->rsend) { + /* And he wants us to send a request */ + if(!(rp->idval)) { + printk(KERN_ERR "ippp_ccp: decompressor must" + " specify reset id\n"); + return; + } + if(is->reset->rs[rp->id]) { + /* There is already a transaction in existence + for this id. May be still waiting for a + Ack or may be wrong. */ + rs = is->reset->rs[rp->id]; + if(rs->state == CCPResetSentReq && rs->ta) { + printk(KERN_DEBUG "ippp_ccp: reset" + " trans still in progress" + " for id %d\n", rp->id); + } else { + printk(KERN_WARNING "ippp_ccp: reset" + " trans in wrong state %d for" + " id %d\n", rs->state, rp->id); + } + } else { + /* Ok, this is a new transaction */ + printk(KERN_DEBUG "ippp_ccp: new trans for id" + " %d to be started\n", rp->id); + rs = isdn_ppp_ccp_reset_alloc_state(is, rp->id); + if(!rs) { + printk(KERN_ERR "ippp_ccp: out of mem" + " allocing ccp trans\n"); + return; + } + rs->state = CCPResetSentReq; + rs->expra = rp->expra; + if(rp->dtval) { + rs->dlen = rp->dlen; + memcpy(rs->data, rp->data, rp->dlen); + } + /* HACK TODO - add link comp here */ + isdn_ppp_ccp_xmit_reset(is, PPP_CCP, + CCP_RESETREQ, rs->id, + rs->data, rs->dlen); + /* Start the timer */ + rs->timer.expires = jiffies + 5*HZ; + add_timer(&rs->timer); + rs->ta = 1; + } + } else { + printk(KERN_DEBUG "ippp_ccp: no reset sent\n"); + } + } else { + /* The reset params are invalid. The decompressor does not + care about them, so we just send the minimal requests + and increase ids only when an Ack is received for a + given id */ + if(is->reset->rs[is->reset->lastid]) { + /* There is already a transaction in existence + for this id. May be still waiting for a + Ack or may be wrong. */ + rs = is->reset->rs[is->reset->lastid]; + if(rs->state == CCPResetSentReq && rs->ta) { + printk(KERN_DEBUG "ippp_ccp: reset" + " trans still in progress" + " for id %d\n", rp->id); + } else { + printk(KERN_WARNING "ippp_ccp: reset" + " trans in wrong state %d for" + " id %d\n", rs->state, rp->id); + } + } else { + printk(KERN_DEBUG "ippp_ccp: new trans for id" + " %d to be started\n", is->reset->lastid); + rs = isdn_ppp_ccp_reset_alloc_state(is, + is->reset->lastid); + if(!rs) { + printk(KERN_ERR "ippp_ccp: out of mem" + " allocing ccp trans\n"); + return; + } + rs->state = CCPResetSentReq; + /* We always expect an Ack if the decompressor doesnt + know better */ + rs->expra = 1; + rs->dlen = 0; + /* HACK TODO - add link comp here */ + isdn_ppp_ccp_xmit_reset(is, PPP_CCP, CCP_RESETREQ, + rs->id, NULL, 0); + /* Start the timer */ + rs->timer.expires = jiffies + 5*HZ; + add_timer(&rs->timer); + rs->ta = 1; + } + } +} + +/* An Ack was received for this id. This means we stop the timer and clean + up the state prior to calling the decompressors reset routine. */ +static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is, + unsigned char id) +{ + struct ippp_ccp_reset_state *rs = is->reset->rs[id]; + + if(rs) { + if(rs->ta && rs->state == CCPResetSentReq) { + /* Great, we are correct */ + if(!rs->expra) + printk(KERN_DEBUG "ippp_ccp: ResetAck received" + " for id %d but not expected\n", id); + } else { + printk(KERN_INFO "ippp_ccp: ResetAck received out of" + "sync for id %d\n", id); + } + if(rs->ta) { + rs->ta = 0; + del_timer(&rs->timer); + } + isdn_ppp_ccp_reset_free_state(is, id); + } else { + printk(KERN_INFO "ippp_ccp: ResetAck received for unknown id" + " %d\n", id); + } + /* Make sure the simple reset stuff uses a new id next time */ + is->reset->lastid++; +} + +static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struct *is,struct ippp_struct *master, + int proto) { -#if 1 - printk(KERN_ERR "compression not included!\n"); - dev_kfree_skb(skb); - return NULL; +#ifndef CONFIG_ISDN_CCP + if(proto == PPP_COMP || proto == PPP_LINK_COMP) { + printk(KERN_ERR "isdn_ppp: Ouch! Compression not included!\n"); + dev_kfree_skb(skb); + return NULL; + } + return skb; #else + void *stat = NULL; + struct isdn_ppp_compressor *ipc = NULL; + struct sk_buff *skb_out; + int len; + struct ippp_struct *ri; + struct isdn_ppp_resetparams rsparm; + unsigned char rsdata[IPPP_RESET_MAXDATABYTES]; + if(!master) { /* - * single link compression + * single link decompression */ - if(!is->link_compressor) { - printk(KERN_ERR "ippp: no (link) compressor defined!\n"); + if(!is->link_decompressor) { + printk(KERN_ERR "ippp: no link decompressor defined!\n"); dev_kfree_skb(skb); return NULL; } if(!is->link_decomp_stat) { - printk(KERN_DEBUG "ippp: initialize link compressor\n"); + printk(KERN_DEBUG "ippp: no link decompressor data allocated\n"); + dev_kfree_skb(skb); + return NULL; } -/* - -> decompress link -*/ - } + stat = is->link_decomp_stat; + ipc = is->link_decompressor; + ri = is; + } else { /* * 'normal' or bundle-compression */ - if(!master->compressor) { - printk(KERN_ERR "ippp: no (link) compressor defined!\n"); + if(!master->decompressor) { + printk(KERN_ERR "ippp: no decompressor defined!\n"); dev_kfree_skb(skb); return NULL; } if(!master->decomp_stat) { -#if 0 - master->decomp_stat = (master->compressor->decomp_alloc)( .. ); -#endif - printk(KERN_DEBUG "ippp: initialize compressor\n"); + printk(KERN_DEBUG "ippp: no decompressor data allocated\n"); + dev_kfree_skb(skb); + return NULL; } + stat = master->decomp_stat; + ipc = master->decompressor; + ri = master; + } + + /* + printk(KERN_DEBUG "ippp: Decompress valid!\n"); + */ + + if((master && proto == PPP_COMP) || (!master && proto == PPP_LINK_COMP) ) { + /* Set up reset params for the decompressor */ + memset(&rsparm, 0, sizeof(rsparm)); + rsparm.data = rsdata; + rsparm.maxdlen = IPPP_RESET_MAXDATABYTES; + +/* !!!HACK,HACK,HACK!!! 2048 is only assumed */ + skb_out = dev_alloc_skb(2048); + len = ipc->decompress(stat,skb,skb_out, &rsparm); + dev_kfree_skb(skb); + if(len <= 0) { + /* Ok, some error */ + switch(len) { + case DECOMP_ERROR: + ri->pppcfg |= SC_DC_ERROR; + printk(KERN_INFO "ippp: decomp wants reset %s params\n", + rsparm.valid ? "with" : "without"); + + isdn_ppp_ccp_reset_trans(ri, &rsparm); + + break; + case DECOMP_FATALERROR: + ri->pppcfg |= SC_DC_FERROR; + /* Kick ipppd to recognize the error */ + isdn_ppp_ccp_kickup(ri); + break; + } + /* Did I see a leak here ? */ + dev_kfree_skb(skb_out); + return NULL; + } + return skb_out; + } + else { + /* + printk(KERN_DEBUG "isdn_ppp: [%d] Calling incomp with this frame!\n",is->unit); + */ + ipc->incomp(stat,skb,proto); + return skb; } - - return skb; #endif } @@ -2034,19 +2617,29 @@ static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto, struct ippp_struct *is,struct ippp_struct *master,int type) { -#if 1 - return skb_in; -#else int ret; int new_proto; struct isdn_ppp_compressor *compressor; void *stat; struct sk_buff *skb_out; +#ifdef CONFIG_ISDN_CCP + /* we do not compress control protocols */ + if(*proto < 0 || *proto > 0x3fff) { +#else + { +#endif + return skb_in; + } + if(type) { /* type=1 => Link compression */ +#if 0 compressor = is->link_compressor; stat = is->link_comp_stat; new_proto = PPP_LINK_COMP; +#else + return skb_in; +#endif } else { if(!master) { @@ -2061,15 +2654,16 @@ } if(!compressor) { - printk(KERN_ERR "No compressor set!\n"); + printk(KERN_ERR "isdn_ppp: No compressor set!\n"); return skb_in; } if(!stat) { - /* init here ? */ + printk(KERN_ERR "isdn_ppp: Compressor not initialized?\n"); return skb_in; } - skb_out = dev_alloc_skb(skb_in->len); + /* Allow for at least 150 % expansion (for now) */ + skb_out = dev_alloc_skb(skb_in->len + skb_in->len/2 + 32); if(!skb_out) return skb_in; @@ -2082,24 +2676,225 @@ dev_kfree_skb(skb_in); *proto = new_proto; return skb_out; -#endif - } /* * we received a CCP frame .. - * not a clean solution, but we SHOULD handle a few cased in the kernel + * not a clean solution, but we MUST handle a few cases in the kernel */ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, - struct sk_buff *skb) + struct sk_buff *skb,int proto) { -#if 0 - printk(KERN_DEBUG "isdn_ppp_receive_cpp: %02x %02x %02x %02x %02x %02x %02x %02x\n", - skb->data[0],skb->data[1],skb->data[2],skb->data[3], - skb->data[4],skb->data[5],skb->data[6],skb->data[7] ); -#endif + struct ippp_struct *is = ippp_table[lp->ppp_slot]; + struct ippp_struct *mis; + int len; + struct isdn_ppp_resetparams rsparm; + unsigned char rsdata[IPPP_RESET_MAXDATABYTES]; + + printk(KERN_DEBUG "Received CCP frame from peer\n"); + isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit,lp->ppp_slot); + + if(lp->master) + mis = ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot]; + else + mis = is; + + switch(skb->data[0]) { + case CCP_CONFREQ: + case CCP_TERMREQ: + case CCP_TERMACK: + if(is->debug & 0x10) + printk(KERN_DEBUG "Disable (de)compression here!\n"); + if(proto == PPP_CCP) + mis->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON); + else + is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON); + break; + case CCP_CONFACK: + /* if we RECEIVE an ackowledge we enable the decompressor */ + if(is->debug & 0x10) + printk(KERN_DEBUG "Enable decompression here!\n"); + if(proto == PPP_CCP) + mis->compflags |= SC_DECOMP_ON; + else + is->compflags |= SC_LINK_DECOMP_ON; + break; + + case CCP_RESETACK: + printk(KERN_DEBUG "Received ResetAck from peer\n"); + len = (skb->data[2] << 8) | skb->data[3]; + len -= 4; + + if(proto == PPP_CCP) { + /* If a reset Ack was outstanding for this id, then + clean up the state engine */ + isdn_ppp_ccp_reset_ack_rcvd(mis, skb->data[1]); + if(mis->decompressor && mis->decomp_stat) + mis->decompressor-> + reset(mis->decomp_stat, + skb->data[0], + skb->data[1], + len ? &skb->data[4] : NULL, + len, NULL); + /* TODO: This is not easy to decide here */ + mis->compflags &= ~SC_DECOMP_DISCARD; + mis->pppcfg &= ~SC_DC_ERROR; + } + else { + isdn_ppp_ccp_reset_ack_rcvd(is, skb->data[1]); + if(is->link_decompressor && is->link_decomp_stat) + is->link_decompressor-> + reset(is->link_decomp_stat, + skb->data[0], + skb->data[1], + len ? &skb->data[4] : NULL, + len, NULL); + /* TODO: neither here */ + is->compflags &= ~SC_LINK_DECOMP_DISCARD; + is->pppcfg &= ~SC_DC_ERROR; + } + break; + + case CCP_RESETREQ: + printk(KERN_DEBUG "Received ResetReq from peer\n"); + /* Receiving a ResetReq means we must reset our compressor */ + /* Set up reset params for the reset entry */ + memset(&rsparm, 0, sizeof(rsparm)); + rsparm.data = rsdata; + rsparm.maxdlen = IPPP_RESET_MAXDATABYTES; + /* Isolate data length */ + len = (skb->data[2] << 8) | skb->data[3]; + len -= 4; + if(proto == PPP_CCP) { + if(mis->compressor && mis->comp_stat) + mis->compressor-> + reset(mis->comp_stat, + skb->data[0], + skb->data[1], + len ? &skb->data[4] : NULL, + len, &rsparm); + } + else { + if(is->link_compressor && is->link_comp_stat) + is->link_compressor-> + reset(is->link_comp_stat, + skb->data[0], + skb->data[1], + len ? &skb->data[4] : NULL, + len, &rsparm); + } + /* Ack the Req as specified by rsparm */ + if(rsparm.valid) { + /* Compressor reset handler decided how to answer */ + if(rsparm.rsend) { + /* We should send a Frame */ + isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK, + rsparm.idval ? rsparm.id + : skb->data[1], + rsparm.dtval ? + rsparm.data : NULL, + rsparm.dtval ? + rsparm.dlen : 0); + } else { + printk(KERN_DEBUG "ResetAck suppressed\n"); + } + } else { + /* We answer with a straight reflected Ack */ + isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK, + skb->data[1], + len ? &skb->data[4] : NULL, + len); + } + break; + } +} + + +/* + * Daemon sends a CCP frame ... + */ + +/* TODO: Clean this up with new Reset semantics */ + +static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb) +{ + struct ippp_struct *mis,*is = ippp_table[lp->ppp_slot]; + int proto; + unsigned char *data; + + if(!skb || skb->len < 3) + return; + + /* Daemon may send with or without address and control field comp */ + data = skb->data; + if(!(is->pppcfg & SC_COMP_AC) && data[0] == 0xff && data[1] == 0x03) { + data += 2; + if(skb->len < 5) + return; + } + + proto = ((int)data[0]<<8)+data[1]; + if(proto != PPP_CCP && proto != PPP_LINK_CCP) + return; + + printk(KERN_DEBUG "Received CCP frame from daemon:\n"); + isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot); + + if(lp->master) + mis = ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot]; + else + mis = is; + + if(mis != is) + printk(KERN_DEBUG "isdn_ppp: Ouch! Master CCP sends on slave slot!\n"); + + switch(data[2]) { + case CCP_CONFREQ: + case CCP_TERMREQ: + case CCP_TERMACK: + if(is->debug & 0x10) + printk(KERN_DEBUG "Disable (de)compression here!\n"); + if(proto == PPP_CCP) + is->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON); + else + is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON); + break; + case CCP_CONFACK: + /* if we SEND an ackowledge we can/must enable the compressor */ + if(is->debug & 0x10) + printk(KERN_DEBUG "Enable compression here!\n"); + if(proto == PPP_CCP) + is->compflags |= SC_COMP_ON; + else + is->compflags |= SC_LINK_COMP_ON; + break; + case CCP_RESETACK: + /* If we send a ACK we should reset our compressor */ + if(is->debug & 0x10) + printk(KERN_DEBUG "Reset decompression state here!\n"); + printk(KERN_DEBUG "ResetAck from daemon passed by\n"); + if(proto == PPP_CCP) { + /* link to master? */ + if(is->compressor && is->comp_stat) + is->compressor->reset(is->comp_stat, 0, 0, + NULL, 0, NULL); + is->compflags &= ~SC_COMP_DISCARD; + } + else { + if(is->link_compressor && is->link_comp_stat) + is->link_compressor->reset(is->link_comp_stat, + 0, 0, NULL, 0, NULL); + is->compflags &= ~SC_LINK_COMP_DISCARD; + } + break; + case CCP_RESETREQ: + /* Just let it pass by */ + printk(KERN_DEBUG "ResetReq from daemon passed by\n"); + break; + } } + int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc) { ipc->next = ipc_head; @@ -2123,32 +2918,67 @@ return 0; } -static int isdn_ppp_set_compressor(struct ippp_struct *is,int num) +static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_data *data) { struct isdn_ppp_compressor *ipc = ipc_head; + int ret; + void *stat; + int num = data->num; + + if(is->debug & 0x10) + printk(KERN_DEBUG "[%d] Set %s type %d\n",is->unit, + (data->flags&IPPP_COMP_FLAG_XMIT)?"compressor":"decompressor",num); while(ipc) { if(ipc->num == num) { - return 0; - is->compressor = ipc; - is->link_compressor = ipc; + stat = ipc->alloc(data); + if(stat) { + ret = ipc->init(stat,data,is->unit,0); + if(!ret) { + printk(KERN_ERR "Can't init (de)compression!\n"); + ipc->free(stat); + stat = NULL; + break; + } + } + else { + printk(KERN_ERR "Can't alloc (de)compression!\n"); + break; + } + + if(data->flags & IPPP_COMP_FLAG_XMIT) { + if(data->flags & IPPP_COMP_FLAG_LINK) { + if(is->link_comp_stat) + is->link_compressor->free(is->link_comp_stat); + is->link_comp_stat = stat; + is->link_compressor = ipc; + } + else { + if(is->comp_stat) + is->compressor->free(is->comp_stat); + is->comp_stat = stat; + is->compressor = ipc; + } + } + else { + if(data->flags & IPPP_COMP_FLAG_LINK) { + if(is->link_decomp_stat) + is->link_decompressor->free(is->link_decomp_stat); + is->link_decomp_stat = stat; + is->link_decompressor = ipc; + } + else { + if(is->decomp_stat) + is->decompressor->free(is->decomp_stat); + is->decomp_stat = stat; + is->decompressor = ipc; + } + } + return 0; } ipc = ipc->next; } return -EINVAL; } - - -#if 0 -static struct symbol_table isdn_ppp_syms = -{ -#include - X(isdn_ppp_register_compressor), - X(isdn_ppp_unregister_compressor), -#include -}; -#endif - - diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_ppp.h linux.pre11.3/drivers/isdn/isdn_ppp.h --- linux.vanilla/drivers/isdn/isdn_ppp.h Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/isdn_ppp.h Mon Jul 19 23:59:35 1999 @@ -1,4 +1,4 @@ -/* $Id: isdn_ppp.h,v 1.12 1998/01/31 22:07:48 keil Exp $ +/* $Id: isdn_ppp.h,v 1.13 1998/03/22 18:50:50 hipp Exp $ * header for Linux ISDN subsystem, functions for synchronous PPP (linklevel). * @@ -19,6 +19,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_ppp.h,v $ + * Revision 1.13 1998/03/22 18:50:50 hipp + * Added BSD Compression for syncPPP .. UNTESTED at the moment + * * Revision 1.12 1998/01/31 22:07:48 keil * changes for newer kernels * @@ -83,6 +86,9 @@ extern void isdn_ppp_release(int, struct file *); extern int isdn_ppp_dial_slave(char *); extern void isdn_ppp_wakeup_daemon(isdn_net_local *); + +extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc); +extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc); #define IPPP_OPEN 0x01 #define IPPP_CONNECT 0x02 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_syms.c linux.pre11.3/drivers/isdn/isdn_syms.c --- linux.vanilla/drivers/isdn/isdn_syms.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/isdn/isdn_syms.c Mon Jul 19 23:59:35 1999 @@ -0,0 +1,114 @@ +/* $Id: isdn_syms.c,v 1.3.2.1 1999/04/22 21:09:37 werner Exp $ + + * Linux ISDN subsystem, exported symbols (linklevel). + * + * This program is free software; you can redistribute 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. + * + * 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. + * + * $Log: isdn_syms.c,v $ + * Revision 1.3.2.1 1999/04/22 21:09:37 werner + * Added support for dss1 diversion services + * + * Revision 1.3 1997/02/16 01:02:47 fritz + * Added GPL-Header, Id and Log + * + */ +#include +#include +#include + +#ifndef __GENKSYMS__ /* Don't want genksyms report unneeded structs */ +#include +#endif +#include "isdn_common.h" +#ifdef CONFIG_ISDN_DIVERSION + #include +extern isdn_divert_if *divert_if; + +static char *map_drvname(int di) +{ + if ((di < 0) || (di >= ISDN_MAX_DRIVERS)) + return(NULL); + return(dev->drvid[di]); /* driver name */ +} /* map_drvname */ + +static int map_namedrv(char *id) +{ int i; + + for (i = 0; i < ISDN_MAX_DRIVERS; i++) + { if (!strcmp(dev->drvid[i],id)) + return(i); + } + return(-1); +} /* map_namedrv */ + +int DIVERT_REG_NAME(isdn_divert_if *i_div) +{ + if (i_div->if_magic != DIVERT_IF_MAGIC) + return(DIVERT_VER_ERR); + switch (i_div->cmd) + { + case DIVERT_CMD_REL: + if (divert_if != i_div) + return(DIVERT_REL_ERR); + divert_if = NULL; /* free interface */ + MOD_DEC_USE_COUNT; + return(DIVERT_NO_ERR); + + case DIVERT_CMD_REG: + if (divert_if) + return(DIVERT_REG_ERR); + i_div->ll_cmd = isdn_command; /* set command function */ + i_div->drv_to_name = map_drvname; + i_div->name_to_drv = map_namedrv; + MOD_INC_USE_COUNT; + divert_if = i_div; /* remember interface */ + return(DIVERT_NO_ERR); + + default: + return(DIVERT_CMD_ERR); + } +} /* DIVERT_REG_NAME */ + +#endif CONFIG_ISDN_DIVERSION + +#if (LINUX_VERSION_CODE < 0x020111) +static int has_exported; + +static struct symbol_table isdn_syms = { +#include + X(register_isdn), +#ifdef CONFIG_ISDN_DIVERSION + X(DIVERT_REG_NAME), +#endif CONFIG_ISDN_DIVERSION +#include +}; + +void +isdn_export_syms(void) +{ + if (has_exported) + return; + register_symtab(&isdn_syms); + has_exported = 1; +} + +#else + +EXPORT_SYMBOL(register_isdn); +#ifdef CONFIG_ISDN_DIVERSION + EXPORT(DIVERT_REG_NAME); +#endif CONFIG_ISDN_DIVERSION + +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_tty.c linux.pre11.3/drivers/isdn/isdn_tty.c --- linux.vanilla/drivers/isdn/isdn_tty.c Sun Nov 8 15:10:15 1998 +++ linux.pre11.3/drivers/isdn/isdn_tty.c Mon Jul 19 23:59:35 1999 @@ -1,8 +1,8 @@ -/* $Id: isdn_tty.c,v 1.47 1998/02/22 19:44:14 fritz Exp $ +/* $Id: isdn_tty.c,v 1.68 1999/07/11 17:51:51 armin Exp $ * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel). * - * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg * * This program is free software; you can redistribute it and/or modify @@ -20,6 +20,84 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_tty.c,v $ + * Revision 1.68 1999/07/11 17:51:51 armin + * Bugfix, "-" was missing for AT&L settings. + * + * Revision 1.67 1999/07/11 17:14:12 armin + * Added new layer 2 and 3 protocols for Fax and DSP functions. + * Moved "Add CPN to RING message" to new register S23, + * "Display message" is now correct on register S13 bit 7. + * New audio command AT+VDD implemented (deactivate DTMF decoder and + * activate possible existing hardware/DSP decoder). + * Moved some tty defines to .h file. + * Made whitespace possible in AT command line. + * Some AT-emulator output bugfixes. + * First Fax G3 implementations. + * + * Revision 1.66 1999/07/07 10:13:46 detabc + * remove unused messages + * + * Revision 1.65 1999/07/04 21:01:59 werner + * Added support for keypad and display (ported from 2.0) + * + * Revision 1.64 1999/07/01 08:30:00 keil + * compatibility to 2.3 kernel + * + * Revision 1.63 1999/04/12 12:33:39 fritz + * Changes from 2.0 tree. + * + * Revision 1.62 1999/03/02 12:04:48 armin + * -added ISDN_STAT_ADDCH to increase supported channels after + * register_isdn(). + * -ttyI now goes on-hook on ATZ when B-Ch is connected. + * -added timer-function for register S7 (Wait for Carrier). + * -analog modem (ISDN_PROTO_L2_MODEM) implementations. + * -on L2_MODEM a string will be appended to the CONNECT-Message, + * which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN. + * -variable "dialing" used for ATA also, for interrupting call + * establishment and register S7. + * + * Revision 1.61 1999/01/27 22:53:11 he + * minor updates (spellings, jiffies wrap around in isdn_tty) + * + * Revision 1.60 1998/11/15 23:57:32 keil + * changes for 2.1.127 + * + * Revision 1.59 1998/08/20 13:50:15 keil + * More support for hybrid modem (not working yet) + * + * Revision 1.58 1998/07/26 18:48:45 armin + * Added silence detection in voice receive mode. + * + * Revision 1.57 1998/06/26 15:12:36 fritz + * Added handling of STAT_ICALL with incomplete CPN. + * Added AT&L for ttyI emulator. + * Added more locking stuff in tty_write. + * + * Revision 1.56 1998/06/18 23:31:51 fritz + * Replaced cli()/restore_flags() in isdn_tty_write() by locking. + * Removed direct-senddown feature in isdn_tty_write because it will + * never succeed with locking and is useless anyway. + * + * Revision 1.55 1998/06/17 19:50:55 he + * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) + * brute force fix to avoid Ugh's in isdn_tty_write() + * cleaned up some dead code + * + * + * + * Revision 1.52 1998/03/19 13:18:21 keil + * Start of a CAPI like interface for supplementary Service + * first service: SUSPEND + * + * + * Revision 1.49 1998/03/08 00:01:59 fritz + * Bugfix: Lowlevel module usage and channel usage were not + * reset on NO DCHANNEL. + * + * Revision 1.48 1998/03/07 12:28:15 tsbogend + * fixed kernel unaligned traps on Linux/Alpha + * * Revision 1.47 1998/02/22 19:44:14 fritz * Bugfixes and improvements regarding V.110, V.110 now running. * @@ -236,7 +314,6 @@ static void isdn_tty_check_esc(const u_char *, u_char, int, int *, int *, int); static void isdn_tty_modem_reset_regs(modem_info *, int); static void isdn_tty_cmd_ATA(modem_info *); -static void isdn_tty_at_cout(char *, modem_info *); static void isdn_tty_flush_buffer(struct tty_struct *); static void isdn_tty_modem_result(int, modem_info *); #ifdef CONFIG_ISDN_AUDIO @@ -254,62 +331,8 @@ static int si2bit[8] = {4, 1, 4, 4, 4, 4, 4, 4}; -char *isdn_tty_revision = "$Revision: 1.47 $"; +char *isdn_tty_revision = "$Revision: 1.68 $"; -#define DLE 0x10 -#define ETX 0x03 -#define DC4 0x14 - -/* - * Definition of some special Registers of AT-Emulator - */ -#define REG_RINGATA 0 -#define REG_RINGCNT 1 -#define REG_ESC 2 -#define REG_CR 3 -#define REG_LF 4 -#define REG_BS 5 - -#define REG_RESP 12 -#define BIT_RESP 1 -#define REG_RESPNUM 12 -#define BIT_RESPNUM 2 -#define REG_ECHO 12 -#define BIT_ECHO 4 -#define REG_DCD 12 -#define BIT_DCD 8 -#define REG_CTS 12 -#define BIT_CTS 16 -#define REG_DTRR 12 -#define BIT_DTRR 32 -#define REG_DSR 12 -#define BIT_DSR 64 -#define REG_CPPP 12 -#define BIT_CPPP 128 - -#define REG_DELXMT 13 -#define BIT_DELXMT 1 -#define REG_T70 13 -#define BIT_T70 2 -#define BIT_T70_EXT 32 -#define REG_DTRHUP 13 -#define BIT_DTRHUP 4 -#define REG_RESPXT 13 -#define BIT_RESPXT 8 -#define REG_CIDONCE 13 -#define BIT_CIDONCE 16 -#define REG_RUNG 13 -#define BIT_RUNG 64 - -#define REG_L2PROT 14 -#define REG_L3PROT 15 -#define REG_PSIZE 16 -#define REG_WSIZE 17 -#define REG_SI1 18 -#define REG_SI2 19 -#define REG_SI1I 20 -#define REG_PLAN 21 -#define REG_SCREEN 22 /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb() * to stuff incoming data directly into a tty's flip-buffer. This @@ -389,6 +412,8 @@ r = 0; #ifdef CONFIG_ISDN_AUDIO isdn_audio_eval_dtmf(info); + if ((info->vonline & 1) && (info->emu.vpar[1])) + isdn_audio_eval_silence(info); #endif if ((tty = info->tty)) { if (info->mcr & UART_MCR_RTS) { @@ -443,8 +468,10 @@ #ifdef CONFIG_ISDN_AUDIO ifmt = 1; - if (info->vonline) + if ((info->vonline) && (!info->emu.vpar[4])) isdn_audio_calc_dtmf(info, skb->data, skb->len, ifmt); + if ((info->vonline & 1) && (info->emu.vpar[1])) + isdn_audio_calc_silence(info, skb->data, skb->len, ifmt); #endif if ((info->online < 2) #ifdef CONFIG_ISDN_AUDIO @@ -566,8 +593,8 @@ info->isdn_channel, 1, skb)) == len) { struct tty_struct *tty = info->tty; info->send_outstanding++; - info->msr |= UART_MSR_CTS; - info->lsr |= UART_LSR_TEMT; + info->msr &= ~UART_MSR_CTS; + info->lsr &= ~UART_LSR_TEMT; if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) (tty->ldisc.write_wakeup) (tty); @@ -579,8 +606,6 @@ dev_kfree_skb(skb); return; } - if (slen) - skb_pull(skb, slen); skb_queue_head(&info->xmit_queue, skb); } @@ -702,7 +727,6 @@ int audio_len; #endif struct sk_buff *skb; - unsigned long flags; #ifdef CONFIG_ISDN_AUDIO if (info->vonline & 4) { @@ -717,18 +741,20 @@ } } #endif - save_flags(flags); - cli(); - if (!(buflen = info->xmit_count)) { - restore_flags(flags); + if (!(buflen = info->xmit_count)) return; - } - if ((info->emu.mdmreg[REG_CTS] & BIT_CTS) != 0) + if ((info->emu.mdmreg[REG_CTS] & BIT_CTS) != 0) info->msr &= ~UART_MSR_CTS; - info->lsr &= ~UART_LSR_TEMT; + info->lsr &= ~UART_LSR_TEMT; + /* info->xmit_count is modified here and in isdn_tty_write(). + * So we return here if isdn_tty_write() is in the + * critical section. + */ + atomic_inc(&info->xmit_lock); + if (!(atomic_dec_and_test(&info->xmit_lock))) + return; if (info->isdn_driver < 0) { info->xmit_count = 0; - restore_flags(flags); return; } skb_res = dev->drv[info->isdn_driver]->interface->hl_hdrlen + 4; @@ -742,7 +768,6 @@ skb = dev_alloc_skb(skb_res + buflen); #endif if (!skb) { - restore_flags(flags); printk(KERN_WARNING "isdn_tty: Out of memory in ttyI%d senddown\n", info->line); @@ -751,7 +776,6 @@ skb_reserve(skb, skb_res); memcpy(skb_put(skb, buflen), info->xmit_buf, buflen); info->xmit_count = 0; - restore_flags(flags); #ifdef CONFIG_ISDN_AUDIO if (info->vonline & 2) { /* For now, ifmt is fixed to 1 (alaw), since this @@ -859,7 +883,7 @@ break; } #ifdef CONFIG_ISDN_AUDIO - if (si == 1) { + if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) { l2 = ISDN_PROTO_L2_TRANS; usg = ISDN_USAGE_VOICE; } @@ -907,9 +931,11 @@ cmd.parm.setup.si2 = m->mdmreg[REG_SI2]; cmd.command = ISDN_CMD_DIAL; info->dialing = 1; + info->emu.carrierwait = 0; strcpy(dev->num[i], n); isdn_info_update(); isdn_command(&cmd); + isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1); } } @@ -938,10 +964,16 @@ } #ifdef CONFIG_ISDN_AUDIO info->vonline = 0; + info->emu.vpar[4] = 0; + info->emu.vpar[5] = 8; if (info->dtmf_state) { kfree(info->dtmf_state); info->dtmf_state = NULL; } + if (info->silence_state) { + kfree(info->silence_state); + info->silence_state = NULL; + } if (info->adpcms) { kfree(info->adpcms); info->adpcms = NULL; @@ -965,8 +997,9 @@ } isdn_all_eaz(info->isdn_driver, info->isdn_channel); info->emu.mdmreg[REG_RINGCNT] = 0; - usage = (info->emu.mdmreg[REG_SI1I] == 1) ? - ISDN_USAGE_VOICE : ISDN_USAGE_MODEM; + usage = ((info->emu.mdmreg[REG_SI1I] != 1) || + (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM)) ? + ISDN_USAGE_MODEM : ISDN_USAGE_VOICE; isdn_free_channel(info->isdn_driver, info->isdn_channel, usage); } @@ -978,6 +1011,226 @@ } } +/* + * Begin of a CAPI like interface, currently used only for + * supplementary service (CAPI 2.0 part III) + */ +#include "avmb1/capicmd.h" /* this should be moved in a common place */ + +int +isdn_tty_capi_facility(capi_msg *cm) { + return(-1); /* dummy */ +} + +/* isdn_tty_suspend() tries to suspend the current tty connection + */ +static void +isdn_tty_suspend(char *id, modem_info * info, atemu * m) +{ + isdn_ctrl cmd; + + int l; + + if (!info) + return; + +#ifdef ISDN_DEBUG_MODEM_SERVICES + printk(KERN_DEBUG "Msusp ttyI%d\n", info->line); +#endif + l = strlen(id); + if ((info->isdn_driver >= 0) && l) { + cmd.parm.cmsg.Length = l+17; + cmd.parm.cmsg.Command = CAPI_FACILITY; + cmd.parm.cmsg.Subcommand = CAPI_REQ; + cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1; + cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */ + cmd.parm.cmsg.para[1] = 0; + cmd.parm.cmsg.para[2] = l + 3; + cmd.parm.cmsg.para[3] = 4; /* 16 bit 0x0004 Suspend */ + cmd.parm.cmsg.para[4] = 0; + cmd.parm.cmsg.para[5] = l; + strncpy(&cmd.parm.cmsg.para[6], id, l); + cmd.command = CAPI_PUT_MESSAGE; + cmd.driver = info->isdn_driver; + cmd.arg = info->isdn_channel; + isdn_command(&cmd); + } +} + +/* isdn_tty_resume() tries to resume a suspended call + * setup of the lower levels before that. unfortunatly here is no + * checking for compatibility of used protocols implemented by Q931 + * It does the same things like isdn_tty_dial, the last command + * is different, may be we can merge it. + */ + +static void +isdn_tty_resume(char *id, modem_info * info, atemu * m) +{ + int usg = ISDN_USAGE_MODEM; + int si = 7; + int l2 = m->mdmreg[REG_L2PROT]; + isdn_ctrl cmd; + ulong flags; + int i; + int j; + int l; + + l = strlen(id); + if (!l) { + isdn_tty_modem_result(4, info); + return; + } + for (j = 7; j >= 0; j--) + if (m->mdmreg[REG_SI1] & (1 << j)) { + si = bit2si[j]; + break; + } +#ifdef CONFIG_ISDN_AUDIO + if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) { + l2 = ISDN_PROTO_L2_TRANS; + usg = ISDN_USAGE_VOICE; + } +#endif + m->mdmreg[REG_SI1I] = si2bit[si]; + save_flags(flags); + cli(); + i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1); + if (i < 0) { + restore_flags(flags); + isdn_tty_modem_result(6, info); + } else { + info->isdn_driver = dev->drvmap[i]; + info->isdn_channel = dev->chanmap[i]; + info->drv_index = i; + dev->m_idx[i] = info->line; + dev->usage[i] |= ISDN_USAGE_OUTGOING; + info->last_dir = 1; +// strcpy(info->last_num, n); + isdn_info_update(); + restore_flags(flags); + cmd.driver = info->isdn_driver; + cmd.arg = info->isdn_channel; + cmd.command = ISDN_CMD_CLREAZ; + isdn_command(&cmd); + strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver)); + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_SETEAZ; + isdn_command(&cmd); + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_SETL2; + info->last_l2 = l2; + cmd.arg = info->isdn_channel + (l2 << 8); + isdn_command(&cmd); + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_SETL3; + cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8); + isdn_command(&cmd); + cmd.driver = info->isdn_driver; + cmd.arg = info->isdn_channel; + cmd.parm.cmsg.Length = l+17; + cmd.parm.cmsg.Command = CAPI_FACILITY; + cmd.parm.cmsg.Subcommand = CAPI_REQ; + cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1; + cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */ + cmd.parm.cmsg.para[1] = 0; + cmd.parm.cmsg.para[2] = l+3; + cmd.parm.cmsg.para[3] = 5; /* 16 bit 0x0005 Resume */ + cmd.parm.cmsg.para[4] = 0; + cmd.parm.cmsg.para[5] = l; + strncpy(&cmd.parm.cmsg.para[6], id, l); + cmd.command =CAPI_PUT_MESSAGE; +/* info->dialing = 1; + strcpy(dev->num[i], n); + isdn_info_update(); +*/ + isdn_command(&cmd); + } +} + +/* isdn_tty_send_msg() sends a message to a HL driver + * This is used for hybrid modem cards to send AT commands to it + */ + +static void +isdn_tty_send_msg(modem_info * info, atemu * m, char *msg) +{ + int usg = ISDN_USAGE_MODEM; + int si = 7; + int l2 = m->mdmreg[REG_L2PROT]; + isdn_ctrl cmd; + ulong flags; + int i; + int j; + int l; + + l = strlen(msg); + if (!l) { + isdn_tty_modem_result(4, info); + return; + } + for (j = 7; j >= 0; j--) + if (m->mdmreg[REG_SI1] & (1 << j)) { + si = bit2si[j]; + break; + } +#ifdef CONFIG_ISDN_AUDIO + if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) { + l2 = ISDN_PROTO_L2_TRANS; + usg = ISDN_USAGE_VOICE; + } +#endif + m->mdmreg[REG_SI1I] = si2bit[si]; + save_flags(flags); + cli(); + i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1); + if (i < 0) { + restore_flags(flags); + isdn_tty_modem_result(6, info); + } else { + info->isdn_driver = dev->drvmap[i]; + info->isdn_channel = dev->chanmap[i]; + info->drv_index = i; + dev->m_idx[i] = info->line; + dev->usage[i] |= ISDN_USAGE_OUTGOING; + info->last_dir = 1; + isdn_info_update(); + restore_flags(flags); + cmd.driver = info->isdn_driver; + cmd.arg = info->isdn_channel; + cmd.command = ISDN_CMD_CLREAZ; + isdn_command(&cmd); + strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver)); + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_SETEAZ; + isdn_command(&cmd); + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_SETL2; + info->last_l2 = l2; + cmd.arg = info->isdn_channel + (l2 << 8); + isdn_command(&cmd); + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_SETL3; + cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8); + isdn_command(&cmd); + cmd.driver = info->isdn_driver; + cmd.arg = info->isdn_channel; + cmd.parm.cmsg.Length = l+14; + cmd.parm.cmsg.Command = CAPI_MANUFACTURER; + cmd.parm.cmsg.Subcommand = CAPI_REQ; + cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1; + cmd.parm.cmsg.para[0] = l+1; + strncpy(&cmd.parm.cmsg.para[1], msg, l); + cmd.parm.cmsg.para[l+1] = 0xd; + cmd.command =CAPI_PUT_MESSAGE; +/* info->dialing = 1; + strcpy(dev->num[i], n); + isdn_info_update(); +*/ + isdn_command(&cmd); + } +} + static inline int isdn_tty_paranoia_check(modem_info * info, kdev_t device, const char *routine) { @@ -1138,15 +1391,16 @@ { int c; int total = 0; - ulong flags; modem_info *info = (modem_info *) tty->driver_data; if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_write")) return 0; if (!tty) return 0; - save_flags(flags); - cli(); + if (from_user) + down(&info->write_sem); + /* See isdn_tty_senddown() */ + atomic_inc(&info->xmit_lock); while (1) { c = MIN(count, info->xmit_size - info->xmit_count); if (info->isdn_driver >= 0) @@ -1205,10 +1459,6 @@ } else #endif info->xmit_count += c; - if (m->mdmreg[REG_DELXMT] & BIT_DELXMT) { - isdn_tty_senddown(info); - isdn_tty_tint(info); - } } else { info->msr |= UART_MSR_CTS; info->lsr |= UART_LSR_TEMT; @@ -1228,7 +1478,9 @@ } if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue))) isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1); - restore_flags(flags); + atomic_dec(&info->xmit_lock); + if (from_user) + up(&info->write_sem); return total; } @@ -1359,7 +1611,7 @@ status = info->lsr; restore_flags(flags); result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); - put_user(result, (ulong *) value); + put_user(result, (uint *) value); return 0; } @@ -1383,7 +1635,7 @@ | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); - put_user(result, (ulong *) value); + put_user(result, (uint *) value); return 0; } @@ -1567,8 +1819,12 @@ static int isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * info) { +#ifdef COMPAT_HAS_NEW_WAITQ + DECLARE_WAITQUEUE(wait, NULL); +#else struct wait_queue wait = {current, NULL}; +#endif int do_clocal = 0; unsigned long flags; int retval; @@ -1891,7 +2147,9 @@ m->profile[18] = 4; m->profile[19] = 0; m->profile[20] = 0; + m->profile[23] = 0; m->pmsn[0] = '\0'; + m->plmsn[0] = '\0'; } #ifdef CONFIG_ISDN_AUDIO @@ -1902,6 +2160,8 @@ m->vpar[1] = 0; /* Silence detection level (0 = none ) */ m->vpar[2] = 70; /* Silence interval (7 sec. ) */ m->vpar[3] = 2; /* Compression type (1 = ADPCM-2 ) */ + m->vpar[4] = 0; /* DTMF detection level (0 = softcode ) */ + m->vpar[5] = 8; /* DTMF interval (8 * 5 ms. ) */ } #endif @@ -1912,6 +2172,7 @@ if ((m->mdmreg[REG_DTRR] & BIT_DTRR) || force) { memcpy(m->mdmreg, m->profile, ISDN_MODEM_ANZREG); memcpy(m->msn, m->pmsn, ISDN_MSNLEN); + memcpy(m->lmsn, m->plmsn, ISDN_LMSNLEN); info->xmit_size = m->mdmreg[REG_PSIZE] * 16; } #ifdef CONFIG_ISDN_AUDIO @@ -1925,6 +2186,7 @@ { memcpy(m->profile, m->mdmreg, ISDN_MODEM_ANZREG); memcpy(m->pmsn, m->msn, ISDN_MSNLEN); + memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN); if (dev->profd) send_sig(SIGIO, dev->profd, 1); } @@ -1988,6 +2250,11 @@ } for (i = 0; i < ISDN_MAX_CHANNELS; i++) { info = &m->info[i]; +#ifdef COMPAT_HAS_NEW_WAITQ + init_MUTEX(&info->write_sem); +#else + info->write_sem = MUTEX; +#endif sprintf(info->last_cause, "0000"); sprintf(info->last_num, "none"); info->last_dir = 0; @@ -2004,9 +2271,14 @@ info->blocked_open = 0; info->callout_termios = m->cua_modem.init_termios; info->normal_termios = m->tty_modem.init_termios; +#ifdef COMPAT_HAS_NEW_WAITQ + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); +#else info->open_wait = 0; info->close_wait = 0; info->isdn_driver = -1; +#endif info->isdn_channel = -1; info->drv_index = -1; info->xmit_size = ISDN_SERIAL_XMIT_SIZE; @@ -2024,25 +2296,67 @@ return 0; } +static int +isdn_tty_match_icall(char *cid, atemu *emu, int di) +{ +#ifdef ISDN_DEBUG_MODEM_ICALL + printk(KERN_DEBUG "m_fi: msn=%s lmsn=%s mmsn=%s mreg[SI1]=%d mreg[SI2]=%d\n", + emu->msn, emu->lmsn, isdn_map_eaz2msn(emu->msn, di), + emu->mdmreg[REG_SI1], emu->mdmreg[REG_SI2]); +#endif + if (strlen(emu->lmsn)) { + char *p = emu->lmsn; + char *q; + int tmp; + int ret = 0; + + while (1) { + if ((q = strchr(p, ';'))) + *q = '\0'; + if ((tmp = isdn_wildmat(cid, isdn_map_eaz2msn(p, di))) > ret) + ret = tmp; +#ifdef ISDN_DEBUG_MODEM_ICALL + printk(KERN_DEBUG "m_fi: lmsnX=%s mmsn=%s -> tmp=%d\n", + p, isdn_map_eaz2msn(emu->msn, di), tmp); +#endif + if (q) { + *q = ';'; + p = q; + p++; + } + if (!tmp) + return 0; + if (!q) + break; + } + return ret; + } else + return isdn_wildmat(cid, isdn_map_eaz2msn(emu->msn, di)); +} + /* * An incoming call-request has arrived. * Search the tty-devices for an appropriate device and bind * it to the ISDN-Channel. - * Return Index to dev->mdm or -1 if none found. + * Return: + * + * 0 = No matching device found. + * 1 = A matching device found. + * 3 = No match found, but eventually would match, if + * CID is longer. */ int isdn_tty_find_icall(int di, int ch, setup_parm setup) { char *eaz; int i; + int wret; int idx; int si1; int si2; char nr[32]; ulong flags; - save_flags(flags); - cli(); if (!setup.phone[0]) { nr[0] = '0'; nr[1] = '\0'; @@ -2059,17 +2373,14 @@ #ifdef ISDN_DEBUG_MODEM_ICALL printk(KERN_DEBUG "m_fi: eaz=%s si1=%d si2=%d\n", eaz, si1, si2); #endif + wret = 0; + save_flags(flags); + cli(); for (i = 0; i < ISDN_MAX_CHANNELS; i++) { modem_info *info = &dev->mdm.info[i]; -#ifdef ISDN_DEBUG_MODEM_ICALL - printk(KERN_DEBUG "m_fi: i=%d msn=%s mmsn=%s mreg18=%d mreg19=%d\n", i, - info->emu.msn, isdn_map_eaz2msn(info->emu.msn, di), - info->emu.mdmreg[REG_SI1], info->emu.mdmreg[REG_SI2]); -#endif - if ((!strcmp(isdn_map_eaz2msn(info->emu.msn, di), - eaz)) && /* EAZ is matching */ - (info->emu.mdmreg[REG_SI1] & si2bit[si1]) && /* SI1 is matching */ - (info->emu.mdmreg[REG_SI2] == si2)) { /* SI2 is matching */ + + 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\n"); @@ -2081,34 +2392,42 @@ #ifndef FIX_FILE_TRANSFER (info->flags & ISDN_ASYNC_NORMAL_ACTIVE) && #endif - (info->isdn_driver == -1) && - (info->isdn_channel == -1) && - (USG_NONE(dev->usage[idx]))) { - info->isdn_driver = di; - info->isdn_channel = ch; - info->drv_index = idx; - dev->m_idx[idx] = info->line; - dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE; - dev->usage[idx] |= (si1 == 1) ? ISDN_USAGE_VOICE : ISDN_USAGE_MODEM; - strcpy(dev->num[idx], nr); - info->emu.mdmreg[REG_SI1I] = si2bit[si1]; - info->emu.mdmreg[REG_PLAN] = setup.plan; - info->emu.mdmreg[REG_SCREEN] = setup.screen; - isdn_info_update(); - restore_flags(flags); - printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr, - info->line); - info->msr |= UART_MSR_RI; - isdn_tty_modem_result(2, info); - isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1); - return info->line; + (info->isdn_driver == -1) && + (info->isdn_channel == -1) && + (USG_NONE(dev->usage[idx]))) { + int matchret; + + if ((matchret = isdn_tty_match_icall(eaz, &info->emu, di)) > wret) + wret = matchret; + if (!matchret) { /* EAZ is matching */ + info->isdn_driver = di; + info->isdn_channel = ch; + info->drv_index = idx; + dev->m_idx[idx] = info->line; + dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE; + dev->usage[idx] |= ((si1 != 1) || (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM)) ? + ISDN_USAGE_MODEM : ISDN_USAGE_VOICE; + strcpy(dev->num[idx], nr); + strcpy(info->emu.cpn, eaz); + info->emu.mdmreg[REG_SI1I] = si2bit[si1]; + info->emu.mdmreg[REG_PLAN] = setup.plan; + info->emu.mdmreg[REG_SCREEN] = setup.screen; + isdn_info_update(); + restore_flags(flags); + printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr, + info->line); + info->msr |= UART_MSR_RI; + isdn_tty_modem_result(2, info); + isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1); + return 1; + } } } } - printk(KERN_INFO "isdn_tty: call from %s -> %s %s\n", nr, eaz, - dev->drv[di]->reject_bus ? "rejected" : "ignored"); restore_flags(flags); - return -1; + printk(KERN_INFO "isdn_tty: call from %s -> %s %s\n", nr, eaz, + ((dev->drv[di]->flags & DRV_FLAG_REJBUS) && (wret != 2))? "rejected" : "ignored"); + return (wret == 2)?3:0; } #define TTY_IS_ACTIVE(info) \ @@ -2129,7 +2448,7 @@ case ISDN_STAT_CINF: printk(KERN_DEBUG "CHARGEINFO on ttyI%d: %ld %s\n", info->line, c->arg, c->parm.num); info->emu.charge = (unsigned) simple_strtoul(c->parm.num, &e, 10); - if (e == c->parm.num) + if (e == (char *)c->parm.num) info->emu.charge = 0; break; @@ -2154,6 +2473,19 @@ /* Signal cause to tty-device */ strncpy(info->last_cause, c->parm.num, 5); return 1; + case ISDN_STAT_DISPLAY: +#ifdef ISDN_TTY_STAT_DEBUG + printk(KERN_DEBUG "tty_STAT_DISPLAY ttyI%d\n", info->line); +#endif + /* Signal display to tty-device */ + if ((info->emu.mdmreg[REG_DISPLAY] & BIT_DISPLAY) && + !(info->emu.mdmreg[REG_RESPNUM] & BIT_RESPNUM)) { + isdn_tty_at_cout("\r\n", info); + isdn_tty_at_cout("DISPLAY: ", info); + isdn_tty_at_cout(c->parm.display, info); + isdn_tty_at_cout("\r\n", info); + } + return 1; case ISDN_STAT_DCONN: #ifdef ISDN_TTY_STAT_DEBUG printk(KERN_DEBUG "tty_STAT_DCONN ttyI%d\n", info->line); @@ -2170,10 +2502,11 @@ printk(KERN_DEBUG "tty_STAT_DHUP ttyI%d\n", info->line); #endif if (TTY_IS_ACTIVE(info)) { - if (info->dialing == 1) { - info->dialing = 0; + if (info->dialing == 1) isdn_tty_modem_result(7, info); - } + if (info->dialing > 1) + isdn_tty_modem_result(3, info); + info->dialing = 0; #ifdef ISDN_DEBUG_MODEM_HUP printk(KERN_DEBUG "Mhup in ISDN_STAT_DHUP\n"); #endif @@ -2192,14 +2525,20 @@ if (TTY_IS_ACTIVE(info)) { info->msr |= UART_MSR_DCD; info->emu.charge = 0; - if (info->dialing) { - info->dialing = 0; + if (info->dialing & 0xf) info->last_dir = 1; - } else + else info->last_dir = 0; + info->dialing = 0; info->rcvsched = 1; - if (USG_MODEM(dev->usage[i])) - isdn_tty_modem_result(5, info); + if (USG_MODEM(dev->usage[i])) { + if (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) { + strcpy(info->emu.connmsg, c->parm.num); + isdn_tty_modem_result(1, info); + } + else + isdn_tty_modem_result(5, info); + } if (USG_VOICE(dev->usage[i])) isdn_tty_modem_result(11, info); return 1; @@ -2229,11 +2568,7 @@ sprintf(info->last_cause, "0000"); isdn_tty_modem_result(6, info); } - info->msr &= ~UART_MSR_DCD; - if (info->online) { - isdn_tty_modem_result(3, info); - info->online = 0; - } + isdn_tty_modem_hup(info, 0); return 1; } break; @@ -2249,6 +2584,20 @@ } } return 1; +#ifdef CONFIG_ISDN_AUDIO + case ISDN_STAT_AUDIO: + if (TTY_IS_ACTIVE(info)) { + switch(c->parm.num[0]) { + case ISDN_AUDIO_DTMF: + if (info->vonline) { + isdn_audio_put_dle_code(info, + c->parm.num[1]); + } + break; + } + } + break; +#endif } } return 0; @@ -2258,13 +2607,13 @@ Modem-Emulator-Routines *********************************************************************/ -#define cmdchar(c) ((c>' ')&&(c<=0x7f)) +#define cmdchar(c) ((c>=' ')&&(c<=0x7f)) /* * Put a message from the AT-emulator into receive-buffer of tty, * convert CR, LF, and BS to values in modem-registers 3, 4 and 5. */ -static void +void isdn_tty_at_cout(char *msg, modem_info * info) { struct tty_struct *tty; @@ -2394,7 +2743,7 @@ "CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER", "RINGING", "NO MSN/EAZ", "VCON", "RUNG"}; ulong flags; - char s[10]; + char s[ISDN_MSNLEN+10]; switch (code) { case 2: @@ -2474,7 +2823,20 @@ } isdn_tty_at_cout(msg[code], info); switch (code) { + case 1: + switch (m->mdmreg[REG_L2PROT]) { + case ISDN_PROTO_L2_MODEM: + isdn_tty_at_cout(" ", info); + isdn_tty_at_cout(m->connmsg, info); + break; + } + break; case 2: + /* Append CPN, if enabled */ + if ((m->mdmreg[REG_CPN] & BIT_CPN)) { + sprintf(s, "/%s", m->cpn); + isdn_tty_at_cout(s, info); + } /* Print CID only once, _after_ 1.st RING */ if ((m->mdmreg[REG_CIDONCE] & BIT_CIDONCE) && (m->mdmreg[REG_RINGCNT] == 1)) { @@ -2561,7 +2923,9 @@ static void isdn_tty_get_msnstr(char *n, char **p) { - while ((*p[0] >= '0' && *p[0] <= '9') || (*p[0] == ',')) + while ((*p[0] >= '0' && *p[0] <= '9') || + /* Why a comma ??? */ + (*p[0] == ',')) *n++ = *p[0]++; *n = '\0'; } @@ -2576,8 +2940,9 @@ int limit=39; /* MUST match the size in isdn_tty_parse to avoid buffer overflow */ - while (strchr("0123456789,#.*WPTS-", *p) && *p && --cnt>0) { - if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first)) + while (strchr(" 0123456789,#.*WPTS-", *p) && *p && --cnt>0) { + if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first) || + (*p == '*') || (*p == '#')) *q++ = *p; p++; if(!--limit) @@ -2627,6 +2992,12 @@ case ISDN_PROTO_L2_TRANS: isdn_tty_at_cout("transparent", info); break; + case ISDN_PROTO_L2_MODEM: + isdn_tty_at_cout("modem", info); + break; + case ISDN_PROTO_L2_FAX: + isdn_tty_at_cout("fax", info); + break; default: isdn_tty_at_cout("unknown", info); break; @@ -2669,6 +3040,8 @@ int i; char rb[100]; +#define MAXRB (sizeof(rb) - 1) + switch (*p[0]) { case 'B': /* &B - Set Buffersize */ @@ -2720,6 +3093,15 @@ isdn_tty_reset_profile(m); isdn_tty_modem_reset_regs(info, 1); break; + case 'L': + /* &L -Set Numbers to listen on */ + p[0]++; + i = 0; + while ((strchr("0123456789,-*[]?;", *p[0])) && + (i < ISDN_LMSNLEN) && *p[0]) + m->lmsn[i++] = *p[0]++; + m->lmsn[i] = '\0'; + break; case 'R': /* &R - Set V.110 bitrate adaption */ p[0]++; @@ -2775,6 +3157,11 @@ sprintf(rb, "\r\nEAZ/MSN: %.50s\r\n", strlen(m->msn) ? m->msn : "None"); isdn_tty_at_cout(rb, info); + if (strlen(m->lmsn)) { + isdn_tty_at_cout("\r\nListen: ", info); + isdn_tty_at_cout(m->lmsn, info); + isdn_tty_at_cout("\r\n", info); + } break; case 'W': /* &W - Write Profile */ @@ -2867,7 +3254,7 @@ int bval; mreg = isdn_getnum(p); - if (mreg < 0 || mreg > ISDN_MODEM_ANZREG) + if (mreg < 0 || mreg >= ISDN_MODEM_ANZREG) PARSE_ERROR1; switch (*p[0]) { case '=': @@ -2940,9 +3327,10 @@ #ifdef CONFIG_ISDN_AUDIO /* If more than one bit set in reg18, autoselect Layer2 */ if ((m->mdmreg[REG_SI1] & m->mdmreg[REG_SI1I]) != m->mdmreg[REG_SI1]) { - if (m->mdmreg[REG_SI1I] == 1) - l2 = ISDN_PROTO_L2_TRANS; - else + if (m->mdmreg[REG_SI1I] == 1) { + if (l2 != ISDN_PROTO_L2_MODEM) + l2 = ISDN_PROTO_L2_TRANS; + } else l2 = ISDN_PROTO_L2_X75I; } #endif @@ -2958,7 +3346,10 @@ cmd.driver = info->isdn_driver; cmd.arg = info->isdn_channel; cmd.command = ISDN_CMD_ACCEPTD; + info->dialing = 16; + info->emu.carrierwait = 0; isdn_command(&cmd); + isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1); } else isdn_tty_modem_result(8, info); } @@ -3133,8 +3524,9 @@ isdn_tty_cmd_PLUSV(char **p, modem_info * info) { atemu *m = &info->emu; + isdn_ctrl cmd; static char *vcmd[] = - {"NH", "IP", "LS", "RX", "SD", "SM", "TX", NULL}; + {"NH", "IP", "LS", "RX", "SD", "SM", "TX", "DD", NULL}; int i; int par1; int par2; @@ -3222,6 +3614,11 @@ printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n"); PARSE_ERROR1; } + info->silence_state = isdn_audio_silence_init(info->silence_state); + if (!info->silence_state) { + printk(KERN_WARNING "isdn_tty: Couldn't malloc silence state\n"); + PARSE_ERROR1; + } if (m->vpar[3] < 5) { info->adpcmr = isdn_audio_adpcm_init(info->adpcmr, m->vpar[3]); if (!info->adpcmr) { @@ -3248,31 +3645,27 @@ break; case '=': p[0]++; - switch (*p[0]) { - case '0': - case '1': - case '2': - case '3': - par1 = isdn_getnum(p); - if ((par1 < 0) || (par1 > 31)) - PARSE_ERROR1; - if (*p[0] != ',') - PARSE_ERROR1; - p[0]++; - par2 = isdn_getnum(p); - if ((par2 < 0) || (par2 > 255)) - PARSE_ERROR1; - m->vpar[1] = par1; - m->vpar[2] = par2; - break; - case '?': - p[0]++; - isdn_tty_at_cout("\r\n<0-31>,<0-255>", - info); - break; - default: + if ((*p[0]>='0') && (*p[0]<='9')) { + par1 = isdn_getnum(p); + if ((par1 < 0) || (par1 > 31)) PARSE_ERROR1; - } + if (*p[0] != ',') + PARSE_ERROR1; + p[0]++; + par2 = isdn_getnum(p); + if ((par2 < 0) || (par2 > 255)) + PARSE_ERROR1; + m->vpar[1] = par1; + m->vpar[2] = par2; + break; + } else + if (*p[0] == '?') { + p[0]++; + isdn_tty_at_cout("\r\n<0-31>,<0-255>", + info); + break; + } else + PARSE_ERROR1; break; default: PARSE_ERROR1; @@ -3309,9 +3702,9 @@ info); isdn_tty_at_cout("4;ADPCM;4;0;(8000)\r\n", info); - isdn_tty_at_cout("5;ALAW;8;0;(8000)", + isdn_tty_at_cout("5;ALAW;8;0;(8000)\r\n", info); - isdn_tty_at_cout("6;ULAW;8;0;(8000)", + isdn_tty_at_cout("6;ULAW;8;0;(8000)\r\n", info); break; default: @@ -3350,6 +3743,52 @@ isdn_tty_modem_result(1, info); return 0; break; + case 7: + /* AT+VDD - DTMF detection */ + switch (*p[0]) { + case '?': + p[0]++; + sprintf(rs, "\r\n<%d>,<%d>", + m->vpar[4], + m->vpar[5]); + isdn_tty_at_cout(rs, info); + break; + case '=': + p[0]++; + if ((*p[0]>='0') && (*p[0]<='9')) { + if (info->online != 1) + PARSE_ERROR1; + par1 = isdn_getnum(p); + if ((par1 < 0) || (par1 > 15)) + PARSE_ERROR1; + if (*p[0] != ',') + PARSE_ERROR1; + p[0]++; + par2 = isdn_getnum(p); + if ((par2 < 0) || (par2 > 255)) + PARSE_ERROR1; + m->vpar[4] = par1; + m->vpar[5] = par2; + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_AUDIO; + cmd.arg = info->isdn_channel + (ISDN_AUDIO_SETDD << 8); + cmd.parm.num[0] = par1; + cmd.parm.num[1] = par2; + isdn_command(&cmd); + break; + } else + if (*p[0] == '?') { + p[0]++; + isdn_tty_at_cout("\r\n<0-15>,<0-255>", + info); + break; + } else + PARSE_ERROR1; + break; + default: + PARSE_ERROR1; + } + break; default: PARSE_ERROR1; } @@ -3372,6 +3811,9 @@ #endif for (p = &m->mdmcmd[2]; *p;) { switch (*p) { + case ' ': + p++; + break; case 'A': /* A - Accept incoming call */ p++; @@ -3446,7 +3888,7 @@ p++; if (info->msr & UART_MSR_DCD) /* if B-Channel is up */ - isdn_tty_modem_result(5, info); + isdn_tty_modem_result((m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) ? 1:5, info); else isdn_tty_modem_result(3, info); return; @@ -3487,29 +3929,46 @@ case 'Z': /* Z - Load Registers from Profile */ p++; + if (info->msr & UART_MSR_DCD) { + info->online = 0; + isdn_tty_on_hook(info); + } isdn_tty_modem_reset_regs(info, 1); break; -#ifdef CONFIG_ISDN_AUDIO case '+': p++; switch (*p) { +#ifdef CONFIG_ISDN_AUDIO case 'F': p++; if (isdn_tty_cmd_PLUSF(&p, info)) return; break; case 'V': - if (!(m->mdmreg[REG_SI1] & 1)) + if ((!(m->mdmreg[REG_SI1] & 1)) || + (m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM)) PARSE_ERROR; p++; if (isdn_tty_cmd_PLUSV(&p, info)) return; break; +#endif /* CONFIG_ISDN_AUDIO */ + case 'S': /* SUSPEND */ + p++; + isdn_tty_get_msnstr(ds, &p); + isdn_tty_suspend(ds, info, m); + break; + case 'R': /* RESUME */ + isdn_tty_get_msnstr(ds, &p); + isdn_tty_resume(ds, info, m); + case 'M': /* MESSAGE */ + p++; + isdn_tty_send_msg(info, m, p); + break; default: PARSE_ERROR; } break; -#endif /* CONFIG_ISDN_AUDIO */ case '&': p++; if (isdn_tty_cmd_ATand(&p, info)) @@ -3562,7 +4021,7 @@ eb[1] = 0; isdn_tty_at_cout(eb, info); } - if (m->mdmcmdl >= 2) + if ((m->mdmcmdl >= 2) && (!(strncmp(m->mdmcmd, "AT", 2)))) isdn_tty_parse_at(info); m->mdmcmdl = 0; continue; @@ -3588,15 +4047,16 @@ switch (m->mdmcmdl) { case 0: if (c == 'A') - m->mdmcmd[m->mdmcmdl++] = c; + m->mdmcmd[m->mdmcmdl] = c; break; case 1: if (c == 'T') - m->mdmcmd[m->mdmcmdl++] = c; + m->mdmcmd[m->mdmcmdl] = c; break; default: - m->mdmcmd[m->mdmcmdl++] = c; + m->mdmcmd[m->mdmcmdl] = c; } + m->mdmcmd[++m->mdmcmdl] = 0; } } } @@ -3673,4 +4133,29 @@ } } isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, ton); +} + +/* + * Check all channels if we have a 'no carrier' timeout. + * Timeout value is set by Register S7. + */ +void +isdn_tty_carrier_timeout(void) +{ + int ton = 0; + int i; + + for (i = 0; i < ISDN_MAX_CHANNELS; i++) { + modem_info *info = &dev->mdm.info[i]; + if (info->dialing) { + if (info->emu.carrierwait++ > info->emu.mdmreg[REG_WAITC]) { + info->dialing = 0; + isdn_tty_modem_result(3, info); + isdn_tty_modem_hup(info, 1); + } + else + ton = 1; + } + } + isdn_timer_ctrl(ISDN_TIMER_CARRIER, ton); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_tty.h linux.pre11.3/drivers/isdn/isdn_tty.h --- linux.vanilla/drivers/isdn/isdn_tty.h Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/isdn_tty.h Mon Jul 19 23:59:35 1999 @@ -1,8 +1,8 @@ -/* $Id: isdn_tty.h,v 1.10 1997/03/02 14:29:26 fritz Exp $ +/* $Id: isdn_tty.h,v 1.14 1999/07/11 17:14:15 armin Exp $ * header for Linux ISDN subsystem, tty related functions (linklevel). * - * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg * * This program is free software; you can redistribute it and/or modify @@ -20,6 +20,35 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_tty.h,v $ + * Revision 1.14 1999/07/11 17:14:15 armin + * Added new layer 2 and 3 protocols for Fax and DSP functions. + * Moved "Add CPN to RING message" to new register S23, + * "Display message" is now correct on register S13 bit 7. + * New audio command AT+VDD implemented (deactivate DTMF decoder and + * activate possible existing hardware/DSP decoder). + * Moved some tty defines to .h file. + * Made whitespace possible in AT command line. + * Some AT-emulator output bugfixes. + * First Fax G3 implementations. + * + * Revision 1.13 1999/04/12 12:33:46 fritz + * Changes from 2.0 tree. + * + * Revision 1.12 1999/03/02 12:04:51 armin + * -added ISDN_STAT_ADDCH to increase supported channels after + * register_isdn(). + * -ttyI now goes on-hook on ATZ when B-Ch is connected. + * -added timer-function for register S7 (Wait for Carrier). + * -analog modem (ISDN_PROTO_L2_MODEM) implementations. + * -on L2_MODEM a string will be appended to the CONNECT-Message, + * which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN. + * -variable "dialing" used for ATA also, for interrupting call + * establishment and register S7. + * + * Revision 1.11 1998/03/19 13:18:27 keil + * Start of a CAPI like interface for supplementary Service + * first service: SUSPEND + * * Revision 1.10 1997/03/02 14:29:26 fritz * More ttyI related cleanup. * @@ -54,8 +83,71 @@ * */ + +#define DLE 0x10 +#define ETX 0x03 +#define DC4 0x14 + + +/* + * Definition of some special Registers of AT-Emulator + */ +#define REG_RINGATA 0 +#define REG_RINGCNT 1 +#define REG_ESC 2 +#define REG_CR 3 +#define REG_LF 4 +#define REG_BS 5 + +#define REG_WAITC 7 + +#define REG_RESP 12 +#define BIT_RESP 1 +#define REG_RESPNUM 12 +#define BIT_RESPNUM 2 +#define REG_ECHO 12 +#define BIT_ECHO 4 +#define REG_DCD 12 +#define BIT_DCD 8 +#define REG_CTS 12 +#define BIT_CTS 16 +#define REG_DTRR 12 +#define BIT_DTRR 32 +#define REG_DSR 12 +#define BIT_DSR 64 +#define REG_CPPP 12 +#define BIT_CPPP 128 + +#define REG_T70 13 +#define BIT_T70 2 +#define BIT_T70_EXT 32 +#define REG_DTRHUP 13 +#define BIT_DTRHUP 4 +#define REG_RESPXT 13 +#define BIT_RESPXT 8 +#define REG_CIDONCE 13 +#define BIT_CIDONCE 16 +#define REG_RUNG 13 +#define BIT_RUNG 64 +#define REG_DISPLAY 13 +#define BIT_DISPLAY 128 + +#define REG_L2PROT 14 +#define REG_L3PROT 15 +#define REG_PSIZE 16 +#define REG_WSIZE 17 +#define REG_SI1 18 +#define REG_SI2 19 +#define REG_SI1I 20 +#define REG_PLAN 21 +#define REG_SCREEN 22 + +#define REG_CPN 23 +#define BIT_CPN 1 + extern void isdn_tty_modem_escape(void); extern void isdn_tty_modem_ring(void); +extern void isdn_tty_carrier_timeout(void); extern void isdn_tty_modem_xmit(void); extern int isdn_tty_modem_init(void); extern void isdn_tty_readmodem(void); @@ -63,3 +155,5 @@ extern void isdn_tty_cleanup_xmit(modem_info *); extern int isdn_tty_stat_callback(int, isdn_ctrl *); extern int isdn_tty_rcv_skb(int, int, int, struct sk_buff *); +extern int isdn_tty_capi_facility(capi_msg *cm); +extern void isdn_tty_at_cout(char *, modem_info *); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_x25iface.c linux.pre11.3/drivers/isdn/isdn_x25iface.c --- linux.vanilla/drivers/isdn/isdn_x25iface.c Sat Jan 9 21:50:38 1999 +++ linux.pre11.3/drivers/isdn/isdn_x25iface.c Mon Jul 19 23:59:35 1999 @@ -1,4 +1,4 @@ -/* $Id: isdn_x25iface.c,v 1.3 1998/02/20 17:25:20 fritz Exp $ +/* $Id: isdn_x25iface.c,v 1.6 1999/01/27 22:53:19 he Exp $ * stuff needed to support the Linux X.25 PLP code on top of devices that * can provide a lab_b service using the concap_proto mechanism. * This module supports a network interface wich provides lapb_sematics @@ -10,6 +10,17 @@ * goes to another -- device related -- concap_proto support source file. * * $Log: isdn_x25iface.c,v $ + * Revision 1.6 1999/01/27 22:53:19 he + * minor updates (spellings, jiffies wrap around in isdn_tty) + * + * Revision 1.5 1998/10/30 17:55:39 he + * dialmode for x25iface and multulink ppp + * + * Revision 1.4 1998/06/17 19:51:00 he + * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) + * brute force fix to avoid Ugh's in isdn_tty_write() + * cleaned up some dead code + * * Revision 1.3 1998/02/20 17:25:20 fritz * Changes for recent kernels. * @@ -302,7 +313,12 @@ case 0x01: /* dl_connect request */ if( *state == WAN_DISCONNECTED ){ *state = WAN_CONNECTING; - cprot -> dops -> connect_req(cprot); + ret = cprot -> dops -> connect_req(cprot); + if(ret){ + /* reset state and notify upper layer about + * immidiatly failed attempts */ + isdn_x25iface_disconn_ind(cprot); + } } else { illegal_state_warn( *state, firstbyte ); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdnloop/isdnloop.c linux.pre11.3/drivers/isdn/isdnloop/isdnloop.c --- linux.vanilla/drivers/isdn/isdnloop/isdnloop.c Sun Nov 8 15:10:15 1998 +++ linux.pre11.3/drivers/isdn/isdnloop/isdnloop.c Mon Jul 19 23:59:35 1999 @@ -1,4 +1,4 @@ -/* $Id: isdnloop.c,v 1.4 1998/02/24 21:39:05 he Exp $ +/* $Id: isdnloop.c,v 1.8 1998/11/18 18:59:43 armin Exp $ * ISDN low-level module implementing a dummy loop driver. * @@ -19,6 +19,20 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdnloop.c,v $ + * Revision 1.8 1998/11/18 18:59:43 armin + * changes for 2.1.127 + * + * Revision 1.7 1998/10/30 18:58:03 he + * typecast to suppress a compiler warning + * + * Revision 1.6 1998/06/17 19:51:37 he + * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) + * brute force fix to avoid Ugh's in isdn_tty_write() + * cleaned up some dead code + * + * Revision 1.5 1998/04/14 20:59:32 he + * merged 2.1.94 changes + * * Revision 1.4 1998/02/24 21:39:05 he * L2_PROT_X25DTE / DCE * additional state 17 and new internal signal messages "BCON_I" @@ -42,7 +56,7 @@ #include "isdnloop.h" static char -*revision = "$Revision: 1.4 $"; +*revision = "$Revision: 1.8 $"; static int isdnloop_addcard(char *); @@ -1312,7 +1326,7 @@ c->parm.num[0] ? "N" : "ALL", c->parm.num); } else sprintf(cbuf, "%02d;EAZ%s\n", (int) a, - c->parm.num[0] ? c->parm.num : "0123456789"); + c->parm.num[0] ? c->parm.num : (u_char *) "0123456789"); i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); } break; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdnloop/isdnloop.h linux.pre11.3/drivers/isdn/isdnloop/isdnloop.h --- linux.vanilla/drivers/isdn/isdnloop/isdnloop.h Sun Nov 8 15:08:10 1998 +++ linux.pre11.3/drivers/isdn/isdnloop/isdnloop.h Mon Jul 19 23:59:35 1999 @@ -1,4 +1,4 @@ -/* $Id: isdnloop.h,v 1.2 1997/10/01 09:22:07 fritz Exp $ +/* $Id: isdnloop.h,v 1.3 1998/04/14 20:59:35 he Exp $ * Loopback lowlevel module for testing of linklevel. * @@ -19,6 +19,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdnloop.h,v $ + * Revision 1.3 1998/04/14 20:59:35 he + * merged 2.1.94 changes + * * Revision 1.2 1997/10/01 09:22:07 fritz * Removed old compatibility stuff for 2.0.X kernels. * From now on, this code is for 2.1.X ONLY! diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/pcbit/callbacks.c linux.pre11.3/drivers/isdn/pcbit/callbacks.c --- linux.vanilla/drivers/isdn/pcbit/callbacks.c Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/pcbit/callbacks.c Mon Jul 19 23:59:35 1999 @@ -11,6 +11,13 @@ * callbacks for the FSM */ +/* + * Fix: 19981230 - Carlos Morgado + * Port of Nelson Escravana's fix to CalledPN + * NULL pointer dereference in cb_in_1 (originally fixed in 2.0) + */ + + #define __NO_VERSION__ #include @@ -164,12 +171,24 @@ * ictl.num >= strlen() + strlen() + 5 */ + if (cbdata->data.setup.CallingPN == NULL) { + printk(KERN_DEBUG "NULL CallingPN to phone; using 0\n"); + strcpy(ictl.parm.setup.phone, "0"); + } + else { strcpy(ictl.parm.setup.phone, cbdata->data.setup.CallingPN); + } + if (cbdata->data.setup.CalledPN == NULL) { + printk(KERN_DEBUG "NULL CalledPN to eazmsn; using 0\n"); + strcpy(ictl.parm.setup.eazmsn, "0"); + } + else { strcpy(ictl.parm.setup.eazmsn, cbdata->data.setup.CalledPN); - ictl.parm.setup.si1 = 7; - ictl.parm.setup.si2 = 0; - ictl.parm.setup.plan = 0; - ictl.parm.setup.screen = 0; + } + ictl.parm.setup.si1 = 7; + ictl.parm.setup.si2 = 0; + ictl.parm.setup.plan = 0; + ictl.parm.setup.screen = 0; #ifdef DEBUG printk(KERN_DEBUG "statstr: %s\n", ictl.num); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/pcbit/drv.c linux.pre11.3/drivers/isdn/pcbit/drv.c --- linux.vanilla/drivers/isdn/pcbit/drv.c Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/pcbit/drv.c Mon Jul 19 23:59:35 1999 @@ -86,6 +86,9 @@ dev_pcbit[board] = dev; memset(dev, 0, sizeof(struct pcbit_dev)); +#ifdef COMPAT_HAS_NEW_WAITQ + init_waitqueue_head(&dev->set_running_wq); +#endif if (mem_base >= 0xA0000 && mem_base <= 0xFFFFF ) dev->sh_mem = (unsigned char*) mem_base; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/pcbit/pcbit.h linux.pre11.3/drivers/isdn/pcbit/pcbit.h --- linux.vanilla/drivers/isdn/pcbit/pcbit.h Sun Nov 8 15:08:08 1998 +++ linux.pre11.3/drivers/isdn/pcbit/pcbit.h Mon Jul 19 23:59:35 1999 @@ -68,7 +68,11 @@ struct frame_buf *write_queue; /* Protocol start */ +#ifdef COMPAT_HAS_NEW_WAITQ + wait_queue_head_t set_running_wq; +#else struct wait_queue *set_running_wq; +#endif struct timer_list set_running_timer; struct timer_list error_recover_timer; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/sc/message.c linux.pre11.3/drivers/isdn/sc/message.c --- linux.vanilla/drivers/isdn/sc/message.c Sun Nov 8 15:10:15 1998 +++ linux.pre11.3/drivers/isdn/sc/message.c Mon Jul 19 23:59:35 1999 @@ -1,5 +1,5 @@ /* - * $Id: message.c,v 1.3 1998/01/31 22:10:55 keil Exp $ + * $Id: message.c,v 1.4 1999/01/05 18:29:47 he Exp $ * Copyright (C) 1996 SpellCaster Telecommunications Inc. * * message.c - functions for sending and receiving control messages diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/Config.in linux.pre11.3/drivers/net/Config.in --- linux.vanilla/drivers/net/Config.in Tue Jun 15 16:49:49 1999 +++ linux.pre11.3/drivers/net/Config.in Mon Jul 19 23:27:25 1999 @@ -2,6 +2,9 @@ # Network device configuration # +mainmenu_option next_comment +comment 'ARCnet devices' + tristate 'ARCnet support' CONFIG_ARCNET if [ "$CONFIG_ARCNET" != "n" ]; then bool ' Enable arc0e (ARCnet "Ether-Encap" packet format)' CONFIG_ARCNET_ETH @@ -12,6 +15,8 @@ dep_tristate ' ARCnet COM20020 chipset driver' CONFIG_ARCNET_COM20020 $CONFIG_ARCNET fi +endmenu + tristate 'Dummy net driver support' CONFIG_DUMMY tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then @@ -22,6 +27,10 @@ # # Ethernet # + +mainmenu_option next_comment +comment 'Ethernet (10 or 100Mbit)' + bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET if [ "$CONFIG_NET_ETHERNET" = "y" ]; then if [ "$CONFIG_ARM" = "y" ]; then @@ -42,7 +51,7 @@ tristate 'Hydra support' CONFIG_HYDRA fi if [ "$CONFIG_MIPS_JAZZ" = "y" ]; then - bool 'MIPS JAZZ onboard SONIC Ethernet support' CONFIG_MIPS_JAZZ_SONIC + tristate 'MIPS JAZZ onboard SONIC Ethernet support' CONFIG_MIPS_JAZZ_SONIC fi bool '3COM cards' CONFIG_NET_VENDOR_3COM if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then @@ -82,18 +91,15 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate 'RealTek 8129/8139 (not 8019/8029!) support' CONFIG_RTL8139 tristate 'Packet Engines Yellowfin Gigabit-NIC support' CONFIG_YELLOWFIN - tristate 'Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support' CONFIG_ACENIC fi bool 'Other ISA cards' CONFIG_NET_ISA if [ "$CONFIG_NET_ISA" = "y" ]; then - tristate 'AT1700/1720 support' CONFIG_AT1700 + tristate 'AT1700/1720 support (EXPERIMENTAL)' CONFIG_AT1700 tristate 'Cabletron E21xx support' CONFIG_E2100 tristate 'DEPCA, DE10x, DE200, DE201, DE202, DE422 support' CONFIG_DEPCA tristate 'EtherWORKS 3 (DE203, DE204, DE205) support' CONFIG_EWRK3 tristate 'EtherExpress 16 support' CONFIG_EEXPRESS - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'EtherExpressPro support' CONFIG_EEXPRESS_PRO - fi + tristate 'EtherExpressPro support' CONFIG_EEXPRESS_PRO tristate 'FMV-181/182/183/184 support' CONFIG_FMV18X tristate 'HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS tristate 'HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN @@ -103,7 +109,7 @@ fi tristate 'NE2000/NE1000 support' CONFIG_NE2000 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool 'SEEQ8005 support (EXPERIMENTAL)' CONFIG_SEEQ8005 + tristate 'SEEQ8005 support (EXPERIMENTAL)' CONFIG_SEEQ8005 fi bool 'SK_G16 support' CONFIG_SK_G16 fi @@ -115,6 +121,7 @@ if [ "$CONFIG_NET_EISA" = "y" ]; then tristate 'AMD PCnet32 (VLB and PCI) support' CONFIG_PCNET32 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support' CONFIG_ACENIC tristate 'Ansel Communications EISA 3200 support (EXPERIMENTAL)' CONFIG_AC3200 fi @@ -145,6 +152,8 @@ fi fi +endmenu + bool 'FDDI driver support' CONFIG_FDDI if [ "$CONFIG_FDDI" = "y" ]; then bool 'Digital DEFEA and DEFPA adapter support' CONFIG_DEFXX @@ -153,25 +162,20 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool 'HIPPI driver support (EXPERIMENTAL)' CONFIG_HIPPI if [ "$CONFIG_HIPPI" = "y" ]; then - bool 'CERN HIPPI PCI adapter support' CONFIG_CERN_HIPPI - bool 'Essential RoadRunner HIPPI PCI adapter support' CONFIG_ROADRUNNER + tristate 'Essential RoadRunner HIPPI PCI adapter support' CONFIG_ROADRUNNER if [ "$CONFIG_ROADRUNNER" != "n" ]; then bool ' Use large TX/RX rings' CONFIG_ROADRUNNER_LARGE_RINGS fi fi fi -tristate 'Frame relay DLCI support' CONFIG_DLCI -if [ "$CONFIG_DLCI" = "y" -o "$CONFIG_DLCI" = "m" ]; then - int ' Max open DLCI' CONFIG_DLCI_COUNT 24 - int ' Max DLCI per device' CONFIG_DLCI_MAX 8 - dep_tristate ' SDLA (Sangoma S502/S508) support' CONFIG_SDLA $CONFIG_DLCI -fi - # # AppleTalk # + if [ "$CONFIG_ATALK" != "n" ]; then + mainmenu_option next_comment + comment 'Appletalk devices' dep_tristate 'Apple/Farallon LocalTalk PC support' CONFIG_LTPC $CONFIG_ATALK dep_tristate 'COPS LocalTalk PC support' CONFIG_COPS $CONFIG_ATALK if [ "$CONFIG_COPS" != "n" ]; then @@ -183,6 +187,7 @@ bool 'IP to Appletalk-IP Encapsulation support' CONFIG_IPDDP_ENCAP bool 'Appletalk-IP to IP Decapsulation support' CONFIG_IPDDP_DECAP fi + endmenu fi if [ ! "$CONFIG_PARPORT" = "n" ]; then @@ -203,23 +208,38 @@ bool 'Wireless LAN (non-hamradio)' CONFIG_NET_RADIO if [ "$CONFIG_NET_RADIO" = "y" ]; then - tristate 'STRIP (Metricom starmode radio IP)' CONFIG_STRIP + dep_tristate 'STRIP (Metricom starmode radio IP)' CONFIG_STRIP $CONFIG_INET tristate 'AT&T WaveLAN & DEC RoamAbout DS support' CONFIG_WAVELAN + tristate 'Aironet Arlan 655 & IC2200 DS support' CONFIG_ARLAN + fi +mainmenu_option next_comment +comment 'Token ring devices' + bool 'Token Ring driver support' CONFIG_TR if [ "$CONFIG_TR" = "y" ]; then tristate 'IBM Tropic chipset based adaptor support' CONFIG_IBMTR # tristate 'IBM Lanstreamer PCI adaptor support' CONFIG_IBMLS + tristate 'IBM Olympic chipset PCI adapter support' CONFIG_IBMOL tristate 'SysKonnect adapter support' CONFIG_SKTR fi +endmenu + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'Red Creek Hardware VPN (EXPERIMENTAL)' CONFIG_RCPCI tristate 'Traffic Shaper (EXPERIMENTAL)' CONFIG_SHAPER fi + # # WAN drivers support # + +mainmenu_option next_comment +comment 'Wan interfaces' + + # There is no way to detect a comtrol sv11 - force it modular for now. # dep_tristate 'Comtrol Hostess SV-11 support' CONFIG_HOSTESS_SV11 m @@ -227,8 +247,22 @@ # The COSA/SRP driver has not been tested as non-modular yet. # dep_tristate 'COSA/SRP sync serial boards support' CONFIG_COSA m -tristate 'Red Creek Hardware VPN (EXPERIMENTAL)' CONFIG_RCPCI # +# There is no way to detect a Sealevel board. Force it modular +# +dep_tristate 'Sealevel Systems 4021 support' CONFIG_SEALEVEL_4021 m + +tristate 'Frame relay DLCI support' CONFIG_DLCI +if [ "$CONFIG_DLCI" != "n" ]; then + int ' Max open DLCI' CONFIG_DLCI_COUNT 24 + int ' Max DLCI per device' CONFIG_DLCI_MAX 8 + dep_tristate ' SDLA (Sangoma S502/S508) support' CONFIG_SDLA $CONFIG_DLCI +fi + +# +# Wan router core. +# + if [ "$CONFIG_WAN_ROUTER" != "n" ]; then bool 'WAN drivers' CONFIG_WAN_DRIVERS if [ "$CONFIG_WAN_DRIVERS" = "y" ]; then @@ -238,14 +272,18 @@ bool ' WANPIPE X.25 support' CONFIG_WANPIPE_X25 bool ' WANPIPE Frame Relay support' CONFIG_WANPIPE_FR bool ' WANPIPE PPP support' CONFIG_WANPIPE_PPP + # bool ' WANPIPE Cisco HDLC support' CONFIG_WANPIPE_CHDLC fi fi fi + +endmenu + # # X.25 network drivers # if [ "$CONFIG_X25" != "n" ]; then -if [ "$CONFIG_LAPB" != "n" ]; then +if [ "$CONFIG_LAPB" = "y" -o "$CONFIG_LAPB" = "m" ]; then dep_tristate 'LAPB over Ethernet driver' CONFIG_LAPBETHER $CONFIG_LAPB dep_tristate 'X.25 async driver' CONFIG_X25_ASY $CONFIG_LAPB fi diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/Makefile linux.pre11.3/drivers/net/Makefile --- linux.vanilla/drivers/net/Makefile Tue Jun 15 16:49:49 1999 +++ linux.pre11.3/drivers/net/Makefile Mon Jul 19 23:27:25 1999 @@ -67,6 +67,14 @@ endif endif +ifeq ($(CONFIG_IBMOL),y) +L_OBJS += olympic.o +else + ifeq ($(CONFIG_IBMOL),m) + M_OBJS += olympic.o + endif +endif + ifeq ($(CONFIG_SKTR),y) L_OBJS += sktr.o else @@ -143,14 +151,6 @@ endif endif -ifeq ($(CONFIG_ETHERH),y) -CONFIG_8390_BUILTIN = y -else - ifeq ($(CONFIG_ETHERH),m) - CONFIG_8390_MODULE = y - endif -endif - ifeq ($(CONFIG_WD80x3),y) L_OBJS += wd.o CONFIG_8390_BUILTIN = y @@ -171,14 +171,6 @@ endif endif -ifeq ($(CONFIG_ETHERH),y) -CONFIG_8390_BUILTIN = y -else - ifeq ($(CONFIG_ETHERH),m) - CONFIG_8390_MODULE = y - endif -endif - ifeq ($(CONFIG_NE2K_PCI),y) L_OBJS += ne2k-pci.o CONFIG_8390_BUILTIN = y @@ -438,6 +430,14 @@ endif endif +ifeq ($(CONFIG_SUNBMAC),y) +L_OBJS += sunbmac.o +else + ifeq ($(CONFIG_SUNBMAC),m) + M_OBJS += sunbmac.o + endif +endif + ifeq ($(CONFIG_MYRI_SBUS),y) L_OBJS += myri_sbus.o else @@ -582,6 +582,14 @@ endif endif +ifeq ($(CONFIG_ARLAN),y) +LX_OBJS += arlan.o arlan-proc.o +else + ifeq ($(CONFIG_ARLAN),m) + MX_OBJS += arlan.o arlan-proc.o + endif +endif + ifeq ($(CONFIG_TLAN),y) L_OBJS += tlan.o else @@ -780,6 +788,19 @@ endif endif +ifeq ($(CONFIG_SEALEVEL_4021),y) +L_OBJS += sealevel.o +CONFIG_85230_BUILTIN = y +CONFIG_SYNCPPP_BUILTIN = y +else + ifeq ($(CONFIG_SEALEVEL_4021),m) + CONFIG_85230_MODULE = y + CONFIG_SYNCPPP_MODULE = y + M_OBJS += sealevel.o + endif +endif + + ifeq ($(CONFIG_COSA),y) L_OBJS += cosa.o CONFIG_SYNCPPP_BUILTIN = y @@ -892,10 +913,26 @@ endif ifeq ($(CONFIG_MIPS_JAZZ_SONIC),y) -L_OBJS += sonic.o +L_OBJS += jazzsonic.o else ifeq ($(CONFIG_MIPS_JAZZ_SONIC),m) - M_OBJS += sonic.o + M_OBJS += jazzsonic.o + endif +endif + +ifeq ($(CONFIG_BAGETLANCE),y) +L_OBJS += bagetlance.o +else + ifeq ($(CONFIG_BAGETLANCE),m) + M_OBJS += bagetlance.o + endif +endif + +ifeq ($(CONFIG_DECLANCE),y) +L_OBJS += declance.o +else + ifeq ($(CONFIG_DECLANCE),m) + M_OBJS += declance.o endif endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/Space.c linux.pre11.3/drivers/net/Space.c --- linux.vanilla/drivers/net/Space.c Tue Jun 15 16:49:49 1999 +++ linux.pre11.3/drivers/net/Space.c Tue Jul 20 00:45:35 1999 @@ -67,6 +67,7 @@ extern int de4x5_probe(struct device *); extern int el1_probe(struct device *); extern int wavelan_probe(struct device *); +extern int arlan_probe(struct device *); extern int el16_probe(struct device *); extern int elmc_probe(struct device *); extern int skmca_probe(struct device *); @@ -111,6 +112,8 @@ extern int epic100_probe(struct device *dev); extern int rtl8139_probe(struct device *dev); extern int hplance_probe(struct device *dev); +extern int bagetlance_probe(struct device *); +extern int dec_lance_probe(struct device *); extern int via_rhine_probe(struct device *dev); extern int tc515_probe(struct device *dev); extern int lance_probe(struct device *dev); @@ -357,6 +360,9 @@ #ifdef CONFIG_WAVELAN /* WaveLAN */ {wavelan_probe, 0}, #endif +#ifdef CONFIG_ARLAN /* Aironet */ + {arlan_probe, 0}, +#endif #ifdef CONFIG_EL16 /* 3c507 */ {el16_probe, 0}, #endif @@ -443,6 +449,12 @@ #ifdef CONFIG_MIPS_JAZZ_SONIC {sonic_probe, 0}, #endif +#ifdef CONFIG_DECLANCE /* DECstation on-board controller */ + {dec_lance_probe, 0}, /* and maybe TURBOchannel option boards */ +#endif +#ifdef CONFIG_BAGETLANCE /* Lance-based Baget ethernet boards */ + {bagetlance_probe, 0}, +#endif {NULL, 0}, }; @@ -668,6 +680,14 @@ #define NEXT_DEV (&mkiss_bootstrap) #endif /* MKISS */ +#if defined(CONFIG_YAM) +extern int yam_init(struct device *); +static struct device yam_bootstrap = { + "yam", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, yam_init, }; +#undef NEXT_DEV +#define NEXT_DEV (&yam_bootstrap) +#endif /* CONFIG_YAM */ + #if defined(CONFIG_STRIP) extern int strip_init_ctrl_dev(struct device *); static struct device strip_bootstrap = { @@ -711,6 +731,7 @@ #ifdef CONFIG_TR /* Token-ring device probe */ extern int ibmtr_probe(struct device *); +extern int olympic_probe(struct device *); static int trif_probe(struct device *dev) @@ -718,6 +739,9 @@ if (1 #ifdef CONFIG_IBMTR && ibmtr_probe(dev) +#endif +#ifdef CONFIG_IBMOL + && olympic_probe(dev) #endif #ifdef CONFIG_SKTR && sktr_probe(dev) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/arcnet.c linux.pre11.3/drivers/net/arcnet.c --- linux.vanilla/drivers/net/arcnet.c Sun Nov 8 15:07:21 1998 +++ linux.pre11.3/drivers/net/arcnet.c Mon Jul 19 23:59:55 1999 @@ -471,9 +471,16 @@ #ifdef CONFIG_ARCNET_1051 /* Initialize the RFC1051-encap protocol driver */ - lp->sdev=(struct device *)kmalloc(sizeof(struct device),GFP_KERNEL); + lp->sdev=(struct device *)kmalloc(sizeof(struct device)+10,GFP_KERNEL); + if(lp->sdev = NULL) + { + if(lp->edev) + kfree(lp->edev); + lp->edev=NULL; + return -ENOMEM; + } memcpy(lp->sdev,dev,sizeof(struct device)); - lp->sdev->name=(char *)kmalloc(10,GFP_KERNEL); + lp->sdev->name=(char *)(lp+1); sprintf(lp->sdev->name,"%ss",dev->name); lp->sdev->init=arcnetS_init; register_netdevice(lp->sdev); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/arlan-proc.c linux.pre11.3/drivers/net/arlan-proc.c --- linux.vanilla/drivers/net/arlan-proc.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/net/arlan-proc.c Mon Jul 19 23:59:55 1999 @@ -0,0 +1,1059 @@ +#include +#include "arlan.h" + +#ifdef CONFIG_PROC_FS + + +#include +#include + +/* void enableReceive(struct device* dev); +*/ + +static int arlan_command(struct device * dev, int command); + + +#define ARLAN_STR_SIZE 0x2ff0 +#define DEV_ARLAN_INFO 1 +#define DEV_ARLAN 1 +#define SARLG(type,var) {\ + pos += sprintf(arlan_drive_info+pos, "%s\t=\t0x%x\n", #var, READSHMB(priva->card->var)); \ + } + +#define SARLBN(type,var,nn) {\ + pos += sprintf(arlan_drive_info+pos, "%s\t=\t0x",#var);\ + for (i=0; i < nn; i++ ) pos += sprintf(arlan_drive_info+pos, "%02x",READSHMB(priva->card->var[i]));\ + pos += sprintf(arlan_drive_info+pos, "\n"); \ + } + +#define SARLBNpln(type,var,nn) {\ + for (i=0; i < nn; i++ ) pos += sprintf(arlan_drive_info+pos, "%02x",READSHMB(priva->card->var[i]));\ + } + +#define SARLSTR(var,nn) {\ + char tmpStr[400];\ + int tmpLn = nn;\ + if (nn > 399 ) tmpLn = 399; \ + memcpy(tmpStr,(char *) priva->conf->var,tmpLn);\ + tmpStr[tmpLn] = 0; \ + pos += sprintf(arlan_drive_info+pos, "%s\t=\t%s \n",#var,priva->conf->var);\ + } + +#define SARLUC(var) SARLG(u_char, var) +#define SARLUCN(var,nn) SARLBN(u_char,var, nn) +#define SARLUS(var) SARLG(u_short, var) +#define SARLUSN(var,nn) SARLBN(u_short,var, nn) +#define SARLUI(var) SARLG(u_int, var) + +#define SARLUSA(var) {\ + u_short tmpVar;\ + memcpy(&tmpVar, (short *) priva->conf->var,2); \ + pos += sprintf(arlan_drive_info+pos, "%s\t=\t0x%x\n",#var, tmpVar);\ +} + +#define SARLUIA(var) {\ + u_int tmpVar;\ + memcpy(&tmpVar, (int* )priva->conf->var,4); \ + pos += sprintf(arlan_drive_info+pos, "%s\t=\t0x%x\n",#var, tmpVar);\ +} + + +const char *arlan_diagnostic_info_string(struct device *dev) +{ + + volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card; + u_char diagnosticInfo; + + READSHM(diagnosticInfo, arlan->diagnosticInfo, u_char); + + switch (diagnosticInfo) + { + case 0xFF: + return "Diagnostic info is OK"; + case 0xFE: + return "ERROR EPROM Checksum error "; + case 0xFD: + return "ERROR Local Ram Test Failed "; + case 0xFC: + return "ERROR SCC failure "; + case 0xFB: + return "ERROR BackBone failure "; + case 0xFA: + return "ERROR tranceiver not found "; + case 0xF9: + return "ERROR no more address space "; + case 0xF8: + return "ERROR Checksum error "; + case 0xF7: + return "ERROR Missing SS Code"; + case 0xF6: + return "ERROR Invalid config format"; + case 0xF5: + return "ERROR Reserved errorcode F5"; + case 0xF4: + return "ERROR Invalid spreading code/channel number"; + case 0xF3: + return "ERROR Load Code Error"; + case 0xF2: + return "ERROR Reserver errorcode F2 "; + case 0xF1: + return "ERROR Invalid command receivec by LAN card "; + case 0xF0: + return "ERROR Invalid parameter found in command "; + case 0xEF: + return "ERROR On-chip timer failure "; + case 0xEE: + return "ERROR T410 timer failure "; + case 0xED: + return "ERROR Too Many TxEnable commands "; + case 0xEC: + return "ERROR EEPROM error on radio module "; + default: + return "ERROR unknown Diagnostic info reply code "; + } +}; + +static const char *arlan_hardware_type_string(struct device *dev) +{ + u_char hardwareType; + volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card; + + READSHM(hardwareType, arlan->hardwareType, u_char); + switch (hardwareType) + { + case 0x00: + return "type A450"; + case 0x01: + return "type A650 "; + case 0x04: + return "type TMA coproc"; + case 0x0D: + return "type A650E "; + case 0x18: + return "type TMA coproc Australian"; + case 0x19: + return "type A650A "; + case 0x26: + return "type TMA coproc European"; + case 0x2E: + return "type A655 "; + case 0x2F: + return "type A655A "; + case 0x30: + return "type A655E "; + case 0x0B: + return "type A670 "; + case 0x0C: + return "type A670E "; + case 0x2D: + return "type A670A "; + case 0x0F: + return "type A411T"; + case 0x16: + return "type A411TA"; + case 0x1B: + return "type A440T"; + case 0x1C: + return "type A412T"; + case 0x1E: + return "type A412TA"; + case 0x22: + return "type A411TE"; + case 0x24: + return "type A412TE"; + case 0x27: + return "type A671T "; + case 0x29: + return "type A671TA "; + case 0x2B: + return "type A671TE "; + case 0x31: + return "type A415T "; + case 0x33: + return "type A415TA "; + case 0x35: + return "type A415TE "; + case 0x37: + return "type A672"; + case 0x39: + return "type A672A "; + case 0x3B: + return "type A672T"; + case 0x6B: + return "type IC2200"; + default: + return "type A672T"; + } +} + +static void arlan_print_diagnostic_info(struct device *dev) +{ + int i; + u_char diagnosticInfo; + u_short diagnosticOffset; + u_char hardwareType; + volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card; + + // ARLAN_DEBUG_ENTRY("arlan_print_diagnostic_info"); + + if (READSHMB(arlan->configuredStatusFlag) == 0) + printk("Arlan: Card NOT configured\n"); + else + printk("Arlan: Card is configured\n"); + + READSHM(diagnosticInfo, arlan->diagnosticInfo, u_char); + READSHM(diagnosticOffset, arlan->diagnosticOffset, u_short); + + printk(KERN_INFO "%s\n", arlan_diagnostic_info_string(dev)); + + if (diagnosticInfo != 0xff) + printk("%s arlan: Diagnostic Offset %d \n", dev->name, diagnosticOffset); + + printk("arlan: LAN CODE ID = "); + for (i = 0; i < 6; i++) + DEBUGSHM(1, "%03d:", arlan->lanCardNodeId[i], u_char); + printk("\n"); + + printk("arlan: Arlan BroadCast address = "); + for (i = 0; i < 6; i++) + DEBUGSHM(1, "%03d:", arlan->broadcastAddress[i], u_char); + printk("\n"); + + READSHM(hardwareType, arlan->hardwareType, u_char); + printk(KERN_INFO "%s\n", arlan_hardware_type_string(dev)); + + + DEBUGSHM(1, "arlan: channelNumber=%d\n", arlan->channelNumber, u_char); + DEBUGSHM(1, "arlan: channelSet=%d\n", arlan->channelSet, u_char); + DEBUGSHM(1, "arlan: spreadingCode=%d\n", arlan->spreadingCode, u_char); + DEBUGSHM(1, "arlan: radioNodeId=%d\n", arlan->radioNodeId, u_short); + DEBUGSHM(1, "arlan: SID =%d\n", arlan->SID, u_short); + DEBUGSHM(1, "arlan: rxOffset=%d\n", arlan->rxOffset, u_short); + + DEBUGSHM(1, "arlan: registration mode is %d\n", arlan->registrationMode, u_char); + + printk("arlan: name= "); + IFDEBUG(1) + + for (i = 0; i < 16; i++) + { + char c; + READSHM(c, arlan->name[i], char); + if (c) + printk("%c", c); + } + printk("\n"); + +// ARLAN_DEBUG_EXIT("arlan_print_diagnostic_info"); + +} + + +/****************************** TEST MEMORY **************/ + +static int arlan_hw_test_memory(struct device *dev) +{ + u_char *ptr; + int i; + int memlen = sizeof(struct arlan_shmem) - 0xF; /* avoid control register */ + volatile char *arlan_mem = (char *) (dev->mem_start); + volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card; + char pattern; + + ptr = NULL; + + /* hold card in reset state */ + setHardwareReset(dev); + + /* test memory */ + pattern = 0; + for (i = 0; i < memlen; i++) + WRITESHM(arlan_mem[i], ((u_char) pattern++), u_char); + + pattern = 0; + for (i = 0; i < memlen; i++) + { + char res; + READSHM(res, arlan_mem[i], char); + if (res != pattern++) + { + printk(KERN_ERR "Arlan driver memory test 1 failed \n"); + return -1; + } + } + + pattern = 0; + for (i = 0; i < memlen; i++) + WRITESHM(arlan_mem[i], ~(pattern++), char); + + pattern = 0; + for (i = 0; i < memlen; i++) + { + char res; + READSHM(res, arlan_mem[i], char); + if (res != ~(pattern++)) + { + printk(KERN_ERR "Arlan driver memory test 2 failed \n"); + return -1; + } + } + + /* zero memory */ + for (i = 0; i < memlen; i++) + WRITESHM(arlan_mem[i], 0x00, char); + + IFDEBUG(1) printk(KERN_INFO "Arlan: memory tests ok\n"); + + /* set reset flag and then release reset */ + WRITESHM(arlan->resetFlag, 0xff, u_char); + + clearChannelAttention(dev); + clearHardwareReset(dev); + + /* wait for reset flag to become zero, we'll wait for two seconds */ + if (arlan_command(dev, ARLAN_COMMAND_LONG_WAIT_NOW)) + { + printk(KERN_ERR "%s arlan: failed to come back from memory test\n", dev->name); + return -1; + } + return 0; +} + + +static int arlan_setup_card_by_book(struct device *dev) +{ + u_char irqLevel, configuredStatusFlag; + volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card; + +// ARLAN_DEBUG_ENTRY("arlan_setup_card"); + + READSHM(configuredStatusFlag, arlan->configuredStatusFlag, u_char); + + IFDEBUG(10) + if (configuredStatusFlag != 0) + IFDEBUG(10) printk("arlan: CARD IS CONFIGURED\n"); + else + IFDEBUG(10) printk("arlan: card is NOT configured\n"); + + if (testMemory || (READSHMB(arlan->diagnosticInfo) != 0xff)) + if (arlan_hw_test_memory(dev)) + return -1; + + DEBUGSHM(4, "arlan configuredStatus = %d \n", arlan->configuredStatusFlag, u_char); + DEBUGSHM(4, "arlan driver diagnostic: 0x%2x\n", arlan->diagnosticInfo, u_char); + + /* issue nop command - no interupt */ + arlan_command(dev, ARLAN_COMMAND_NOOP); + if (arlan_command(dev, ARLAN_COMMAND_WAIT_NOW) != 0) + return -1; + + IFDEBUG(50) printk("1st Noop successfully executed !!\n"); + + /* try to turn on the arlan interrupts */ + clearClearInterrupt(dev); + setClearInterrupt(dev); + setInterruptEnable(dev); + + /* issue nop command - with interrupt */ + + arlan_command(dev, ARLAN_COMMAND_NOOPINT); + if (arlan_command(dev, ARLAN_COMMAND_WAIT_NOW) != 0) + return -1; + + + IFDEBUG(50) printk("2nd Noop successfully executed !!\n"); + + READSHM(irqLevel, arlan->irqLevel, u_char) + + if (irqLevel != dev->irq) + { + IFDEBUG(1) printk(KERN_WARNING "arlan dip switches set irq to %d\n", irqLevel); + printk(KERN_WARNING "device driver irq set to %d - does not match\n", dev->irq); + dev->irq = irqLevel; + } + else + IFDEBUG(2) printk("irq level is OK\n"); + + + IFDEBUG(3) arlan_print_diagnostic_info(dev); + + arlan_command(dev, ARLAN_COMMAND_CONF); + + READSHM(configuredStatusFlag, arlan->configuredStatusFlag, u_char); + if (configuredStatusFlag == 0) + { + printk(KERN_WARNING "arlan configure failed\n"); + return -1; + } + arlan_command(dev, ARLAN_COMMAND_LONG_WAIT_NOW); + arlan_command(dev, ARLAN_COMMAND_RX); + arlan_command(dev, ARLAN_COMMAND_LONG_WAIT_NOW); + printk(KERN_NOTICE "%s: arlan driver version %s loaded\n", + dev->name, arlan_version); + +// ARLAN_DEBUG_EXIT("arlan_setup_card"); + + return 0; /* no errors */ +} + + +#ifdef ARLAN_PROC_INTERFACE +#ifdef ARLAN_PROC_SHM_DUMP + +static char arlan_drive_info[ARLAN_STR_SIZE] = "A655\n\0"; + +static int arlan_sysctl_info(ctl_table * ctl, int write, struct file *filp, + void *buffer, size_t * lenp) +{ + int i; + int retv, pos, devnum; + struct arlan_private *priva = NULL; + struct device *dev; + pos = 0; + if (write) + { + printk("wrirte: "); + for (i = 0; i < 100; i++) + printk("adi %x \n", arlan_drive_info[i]); + } + if (ctl->procname == NULL || arlan_drive_info == NULL) + { + printk(KERN_WARNING " procname is NULL in sysctl_table or arlan_drive_info is NULL \n at arlan module\n "); + return -1; + } + devnum = ctl->procname[5] - '0'; + if (devnum < 0 || devnum > MAX_ARLANS - 1) + { + printk(KERN_WARNING "too strange devnum in procfs parse\n "); + return -1; + } + else if (arlan_device[devnum] == NULL) + { + if (ctl->procname) + pos += sprintf(arlan_drive_info + pos, "\t%s\n\n", ctl->procname); + pos += sprintf(arlan_drive_info + pos, "No device found here \n"); + goto final; + } + else + priva = arlan_device[devnum]->priv; + + if (priva == NULL) + { + printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n "); + return -1; + } + dev = arlan_device[devnum]; + + memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem)); + + pos = sprintf(arlan_drive_info, "Arlan info \n"); + /* Header Signature */ + SARLSTR(textRegion, 48); + SARLUC(resetFlag); + pos += sprintf(arlan_drive_info + pos, "diagnosticInfo\t=\t%s \n", arlan_diagnostic_info_string(dev)); + SARLUC(diagnosticInfo); + SARLUS(diagnosticOffset); + SARLUCN(_1, 12); + SARLUCN(lanCardNodeId, 6); + SARLUCN(broadcastAddress, 6); + pos += sprintf(arlan_drive_info + pos, "hardwareType =\t %s \n", arlan_hardware_type_string(dev)); + SARLUC(hardwareType); + SARLUC(majorHardwareVersion); + SARLUC(minorHardwareVersion); + SARLUC(radioModule); + SARLUC(defaultChannelSet); + SARLUCN(_2, 47); + + /* Control/Status Block - 0x0080 */ + SARLUC(interruptInProgress); + SARLUC(cntrlRegImage); + + SARLUCN(_3, 14); + SARLUC(commandByte); + SARLUCN(commandParameter, 15); + + /* Receive Status - 0x00a0 */ + SARLUC(rxStatus); + SARLUC(rxFrmType); + SARLUS(rxOffset); + SARLUS(rxLength); + SARLUCN(rxSrc, 6); + SARLUC(rxBroadcastFlag); + SARLUC(rxQuality); + SARLUC(scrambled); + SARLUCN(_4, 1); + + /* Transmit Status - 0x00b0 */ + SARLUC(txStatus); + SARLUC(txAckQuality); + SARLUC(numRetries); + SARLUCN(_5, 14); + SARLUCN(registeredRouter, 6); + SARLUCN(backboneRouter, 6); + SARLUC(registrationStatus); + SARLUC(configuredStatusFlag); + SARLUCN(_6, 1); + SARLUCN(ultimateDestAddress, 6); + SARLUCN(immedDestAddress, 6); + SARLUCN(immedSrcAddress, 6); + SARLUS(rxSequenceNumber); + SARLUC(assignedLocaltalkAddress); + SARLUCN(_7, 27); + + /* System Parameter Block */ + + /* - Driver Parameters (Novell Specific) */ + + SARLUS(txTimeout); + SARLUS(transportTime); + SARLUCN(_8, 4); + + /* - Configuration Parameters */ + SARLUC(irqLevel); + SARLUC(spreadingCode); + SARLUC(channelSet); + SARLUC(channelNumber); + SARLUS(radioNodeId); + SARLUCN(_9, 2); + SARLUC(scramblingDisable); + SARLUC(radioType); + SARLUS(routerId); + SARLUCN(_10, 9); + SARLUC(txAttenuation); + SARLUIA(systemId); + SARLUS(globalChecksum); + SARLUCN(_11, 4); + SARLUS(maxDatagramSize); + SARLUS(maxFrameSize); + SARLUC(maxRetries); + SARLUC(receiveMode); + SARLUC(priority); + SARLUC(rootOrRepeater); + SARLUCN(specifiedRouter, 6); + SARLUS(fastPollPeriod); + SARLUC(pollDecay); + SARLUSA(fastPollDelay); + SARLUC(arlThreshold); + SARLUC(arlDecay); + SARLUCN(_12, 1); + SARLUS(specRouterTimeout); + SARLUCN(_13, 5); + + /* Scrambled Area */ + SARLUIA(SID); + SARLUCN(encryptionKey, 12); + SARLUIA(_14); + SARLUSA(waitTime); + SARLUSA(lParameter); + SARLUCN(_15, 3); + SARLUS(headerSize); + SARLUS(sectionChecksum); + + SARLUC(registrationMode); + SARLUC(registrationFill); + SARLUS(pollPeriod); + SARLUS(refreshPeriod); + SARLSTR(name, 16); + SARLUCN(NID, 6); + SARLUC(localTalkAddress); + SARLUC(codeFormat); + SARLUC(numChannels); + SARLUC(channel1); + SARLUC(channel2); + SARLUC(channel3); + SARLUC(channel4); + SARLUCN(SSCode, 59); + +/* SARLUCN( _16, 0x140); + */ + /* Statistics Block - 0x0300 */ + SARLUC(hostcpuLock); + SARLUC(lancpuLock); + SARLUCN(resetTime, 18); + SARLUIA(numDatagramsTransmitted); + SARLUIA(numReTransmissions); + SARLUIA(numFramesDiscarded); + SARLUIA(numDatagramsReceived); + SARLUIA(numDuplicateReceivedFrames); + SARLUIA(numDatagramsDiscarded); + SARLUS(maxNumReTransmitDatagram); + SARLUS(maxNumReTransmitFrames); + SARLUS(maxNumConsecutiveDuplicateFrames); + /* misaligned here so we have to go to characters */ + SARLUIA(numBytesTransmitted); + SARLUIA(numBytesReceived); + SARLUIA(numCRCErrors); + SARLUIA(numLengthErrors); + SARLUIA(numAbortErrors); + SARLUIA(numTXUnderruns); + SARLUIA(numRXOverruns); + SARLUIA(numHoldOffs); + SARLUIA(numFramesTransmitted); + SARLUIA(numFramesReceived); + SARLUIA(numReceiveFramesLost); + SARLUIA(numRXBufferOverflows); + SARLUIA(numFramesDiscardedAddrMismatch); + SARLUIA(numFramesDiscardedSIDMismatch); + SARLUIA(numPollsTransmistted); + SARLUIA(numPollAcknowledges); + SARLUIA(numStatusTimeouts); + SARLUIA(numNACKReceived); + SARLUS(auxCmd); + SARLUCN(dumpPtr, 4); + SARLUC(dumpVal); + SARLUC(wireTest); + + /* next 4 seems too long for procfs, over single page ? + SARLUCN( _17, 0x86); + SARLUCN( txBuffer, 0x800); + SARLUCN( rxBuffer, 0x800); + SARLUCN( _18, 0x0bff); + */ + + pos += sprintf(arlan_drive_info + pos, "rxRing\t=\t0x"); + for (i = 0; i < 0x50; i++) + pos += sprintf(arlan_drive_info + pos, "%02x", ((char *) priva->conf)[priva->conf->rxOffset + i]); + pos += sprintf(arlan_drive_info + pos, "\n"); + + SARLUC(configStatus); + SARLUC(_22); + SARLUC(progIOCtrl); + SARLUC(shareMBase); + SARLUC(controlRegister); + + pos += sprintf(arlan_drive_info + pos, " total %d chars\n", pos); + if (ctl) + if (ctl->procname) + pos += sprintf(arlan_drive_info + pos, " driver name : %s\n", ctl->procname); +final: + *lenp = pos; + + if (!write) + retv = proc_dostring(ctl, write, filp, buffer, lenp); + else + { + *lenp = 0; + return -1; + } + return retv; +} + + +static int arlan_sysctl_info161719(ctl_table * ctl, int write, struct file *filp, + void *buffer, size_t * lenp) +{ + int i; + int retv, pos, devnum; + struct arlan_private *priva = NULL; + + pos = 0; + devnum = ctl->procname[5] - '0'; + if (arlan_device[devnum] == NULL) + { + pos += sprintf(arlan_drive_info + pos, "No device found here \n"); + goto final; + } + else + priva = arlan_device[devnum]->priv; + if (priva == NULL) + { + printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n "); + return -1; + } + memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem)); + SARLUCN(_16, 0xC0); + SARLUCN(_17, 0x6A); + SARLUCN(_18, 14); + SARLUCN(_19, 0x86); + SARLUCN(_21, 0x3fd); + +final: + *lenp = pos; + retv = proc_dostring(ctl, write, filp, buffer, lenp); + return retv; +} + +static int arlan_sysctl_infotxRing(ctl_table * ctl, int write, struct file *filp, + void *buffer, size_t * lenp) +{ + int i; + int retv, pos, devnum; + struct arlan_private *priva = NULL; + + pos = 0; + devnum = ctl->procname[5] - '0'; + if (arlan_device[devnum] == NULL) + { + pos += sprintf(arlan_drive_info + pos, "No device found here \n"); + goto final; + } + else + priva = arlan_device[devnum]->priv; + if (priva == NULL) + { + printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n "); + return -1; + } + memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem)); + SARLBNpln(u_char, txBuffer, 0x800); +final: + *lenp = pos; + retv = proc_dostring(ctl, write, filp, buffer, lenp); + return retv; +} + +static int arlan_sysctl_inforxRing(ctl_table * ctl, int write, struct file *filp, + void *buffer, size_t * lenp) +{ + int i; + int retv, pos, devnum; + struct arlan_private *priva = NULL; + + pos = 0; + devnum = ctl->procname[5] - '0'; + if (arlan_device[devnum] == NULL) + { + pos += sprintf(arlan_drive_info + pos, "No device found here \n"); + goto final; + } else + priva = arlan_device[devnum]->priv; + if (priva == NULL) + { + printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n "); + return -1; + } + memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem)); + SARLBNpln(u_char, rxBuffer, 0x800); +final: + *lenp = pos; + retv = proc_dostring(ctl, write, filp, buffer, lenp); + return retv; +} + +static int arlan_sysctl_info18(ctl_table * ctl, int write, struct file *filp, + void *buffer, size_t * lenp) +{ + int i; + int retv, pos, devnum; + struct arlan_private *priva = NULL; + + pos = 0; + devnum = ctl->procname[5] - '0'; + if (arlan_device[devnum] == NULL) + { + pos += sprintf(arlan_drive_info + pos, "No device found here \n"); + goto final; + } + else + priva = arlan_device[devnum]->priv; + if (priva == NULL) + { + printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n "); + return -1; + } + memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem)); + SARLBNpln(u_char, _18, 0x800); + +final: + *lenp = pos; + retv = proc_dostring(ctl, write, filp, buffer, lenp); + return retv; +} + + +#endif /* #ifdef ARLAN_PROC_SHM_DUMP */ + + +static char conf_reset_result[200]; + +static int arlan_configure(ctl_table * ctl, int write, struct file *filp, + void *buffer, size_t * lenp) +{ + int pos = 0; + int devnum = ctl->procname[6] - '0'; + struct arlan_private *priv; + + if (devnum < 0 || devnum > MAX_ARLANS - 1) + { + printk(KERN_WARNING "too strange devnum in procfs parse\n "); + return -1; + } + else if (arlan_device[devnum] != NULL) + { + priv = arlan_device[devnum]->priv; + + arlan_command(arlan_device[devnum], ARLAN_COMMAND_CLEAN_AND_CONF); + } + else + return -1; + + *lenp = pos; + return proc_dostring(ctl, write, filp, buffer, lenp); +} + +int arlan_sysctl_reset(ctl_table * ctl, int write, struct file *filp, + void *buffer, size_t * lenp) +{ + int pos = 0; + int devnum = ctl->procname[5] - '0'; + struct arlan_private *priv; + + if (devnum < 0 || devnum > MAX_ARLANS - 1) + { + printk(KERN_WARNING "too strange devnum in procfs parse\n "); + return -1; + } + else if (arlan_device[devnum] != NULL) + { + priv = arlan_device[devnum]->priv; + arlan_command(arlan_device[devnum], ARLAN_COMMAND_CLEAN_AND_RESET); + + } else + return -1; + *lenp = pos + 3; + return proc_dostring(ctl, write, filp, buffer, lenp); +} + + +/* Place files in /proc/sys/dev/arlan */ +#define CTBLN(num,card,nam) \ + {num , #nam, &(arlan_conf[card].nam), \ + sizeof(int), 0600, NULL, &proc_dointvec} + + +#define ARLAN_SYSCTL_TABLE_TOTAL(cardNo)\ + CTBLN(1,cardNo,spreadingCode),\ + CTBLN(2,cardNo, channelNumber),\ + CTBLN(3,cardNo, scramblingDisable),\ + CTBLN(4,cardNo, txAttenuation),\ + CTBLN(5,cardNo, systemId), \ + CTBLN(6,cardNo, maxDatagramSize),\ + CTBLN(7,cardNo, maxFrameSize),\ + CTBLN(8,cardNo, maxRetries),\ + CTBLN(9,cardNo, receiveMode),\ + CTBLN(10,cardNo, priority),\ + CTBLN(11,cardNo, rootOrRepeater),\ + CTBLN(12,cardNo, SID),\ + CTBLN(13,cardNo, registrationMode),\ + CTBLN(14,cardNo, registrationFill),\ + CTBLN(15,cardNo, localTalkAddress),\ + CTBLN(16,cardNo, codeFormat),\ + CTBLN(17,cardNo, numChannels),\ + CTBLN(18,cardNo, channel1),\ + CTBLN(19,cardNo, channel2),\ + CTBLN(20,cardNo, channel3),\ + CTBLN(21,cardNo, channel4),\ + CTBLN(22,cardNo, txClear),\ + CTBLN(23,cardNo, txRetries),\ + CTBLN(24,cardNo, txRouting),\ + CTBLN(25,cardNo, txScrambled),\ + CTBLN(26,cardNo, rxParameter),\ + CTBLN(27,cardNo, txTimeoutMs),\ + CTBLN(28,cardNo, waitCardTimeout),\ + CTBLN(29,cardNo, channelSet), \ + {30, "name", arlan_conf[cardNo].siteName, \ + 16, 0600, NULL, &proc_dostring},\ + CTBLN(31,cardNo,waitTime),\ + CTBLN(32,cardNo,lParameter),\ + CTBLN(33,cardNo,_15),\ + CTBLN(34,cardNo,headerSize),\ + CTBLN(35,cardNo,async),\ + CTBLN(36,cardNo,tx_delay_ms),\ + CTBLN(37,cardNo,retries),\ + CTBLN(38,cardNo,ReTransmitPacketMaxSize),\ + CTBLN(39,cardNo,waitReTransmitPacketMaxSize),\ + CTBLN(40,cardNo,fastReTransCount),\ + CTBLN(41,cardNo,driverRetransmissions),\ + CTBLN(42,cardNo,txAckTimeoutMs),\ + CTBLN(43,cardNo,registrationInterrupts),\ + CTBLN(44,cardNo,hardwareType),\ + CTBLN(45,cardNo,radioType),\ + CTBLN(46,cardNo,writeEEPROM),\ + CTBLN(47,cardNo,writeRadioType),\ + {48, "entry_exit_debug", &arlan_entry_and_exit_debug, \ + sizeof(int), 0600, NULL, &proc_dointvec},\ + {49, "debug", &arlan_debug, \ + sizeof(int), 0600, NULL, &proc_dointvec},\ + CTBLN(50,cardNo,in_speed),\ + CTBLN(51,cardNo,out_speed),\ + CTBLN(52,cardNo,in_speed10),\ + CTBLN(53,cardNo,out_speed10),\ + CTBLN(54,cardNo,in_speed_max),\ + CTBLN(55,cardNo,out_speed_max),\ + CTBLN(56,cardNo,measure_rate),\ + CTBLN(57,cardNo,pre_Command_Wait),\ + CTBLN(58,cardNo,rx_tweak1),\ + CTBLN(59,cardNo,rx_tweak2),\ + CTBLN(60,cardNo,tx_queue_len),\ + + + +static ctl_table arlan_conf_table0[] = +{ + ARLAN_SYSCTL_TABLE_TOTAL(0) + +#ifdef ARLAN_PROC_SHM_DUMP + {150, "arlan0-txRing", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing}, + {151, "arlan0-rxRing", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing}, + {152, "arlan0-18", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18}, + {153, "arlan0-ring", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719}, + {154, "arlan0-shm-cpy", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info}, +#endif + {155, "config0", &conf_reset_result, \ + 100, 0400, NULL, &arlan_configure}, \ + {156, "reset0", &conf_reset_result, \ + 100, 0400, NULL, &arlan_sysctl_reset}, \ + {0} +}; + +static ctl_table arlan_conf_table1[] = +{ + + ARLAN_SYSCTL_TABLE_TOTAL(1) + +#ifdef ARLAN_PROC_SHM_DUMP + {150, "arlan1-txRing", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing}, + {151, "arlan1-rxRing", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing}, + {152, "arlan1-18", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18}, + {153, "arlan1-ring", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719}, + {154, "arlan1-shm-cpy", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info}, +#endif + {155, "config1", &conf_reset_result, + 100, 0400, NULL, &arlan_configure}, + {156, "reset1", &conf_reset_result, + 100, 0400, NULL, &arlan_sysctl_reset}, + {0} +}; + +static ctl_table arlan_conf_table2[] = +{ + + ARLAN_SYSCTL_TABLE_TOTAL(2) + +#ifdef ARLAN_PROC_SHM_DUMP + {150, "arlan2-txRing", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing}, + {151, "arlan2-rxRing", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing}, + {152, "arlan2-18", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18}, + {153, "arlan2-ring", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719}, + {154, "arlan2-shm-cpy", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info}, +#endif + {155, "config2", &conf_reset_result, + 100, 0400, NULL, &arlan_configure}, + {156, "reset2", &conf_reset_result, + 100, 0400, NULL, &arlan_sysctl_reset}, + {0} +}; + +static ctl_table arlan_conf_table3[] = +{ + + ARLAN_SYSCTL_TABLE_TOTAL(3) + +#ifdef ARLAN_PROC_SHM_DUMP + {150, "arlan3-txRing", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing}, + {151, "arlan3-rxRing", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing}, + {152, "arlan3-18", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18}, + {153, "arlan3-ring", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719}, + {154, "arlan3-shm-cpy", &arlan_drive_info, + ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info}, +#endif + {155, "config3", &conf_reset_result, + 100, 0400, NULL, &arlan_configure}, + {156, "reset3", &conf_reset_result, + 100, 0400, NULL, &arlan_sysctl_reset}, + {0} +}; + + + +static ctl_table arlan_table[] = +{ + {0, "arlan0", NULL, 0, 0600, arlan_conf_table0}, + {0, "arlan1", NULL, 0, 0600, arlan_conf_table1}, + {0, "arlan2", NULL, 0, 0600, arlan_conf_table2}, + {0, "arlan3", NULL, 0, 0600, arlan_conf_table3}, + {0} +}; + +#else + +static ctl_table arlan_table[MAX_ARLANS + 1] = +{ + {0} +}; +#endif +#endif + +static int mmtu = 1234; + +static ctl_table arlan_root_table[] = +{ + {254, "arlan", NULL, 0, 0555, arlan_table}, + {0} +}; + +/* Make sure that /proc/sys/dev is there */ +static ctl_table arlan_device_root_table[] = +{ + {CTL_DEV, "dev", NULL, 0, 0555, arlan_root_table}, + {0} +}; + + + +static struct ctl_table_header *arlan_device_sysctl_header = NULL; + +int init_arlan_proc(void) +{ + + int i = 0; + if (arlan_device_sysctl_header) + return 0; + for (i = 0; i < MAX_ARLANS && arlan_device[i]; i++) + arlan_table[i].ctl_name = i + 1; + arlan_device_sysctl_header = register_sysctl_table(arlan_root_table, 0); + if (!arlan_device_sysctl_header) + return -1; + + return 0; + +}; + + + +#ifdef MODULE + +int init_module(void) +{ + + return init_arlan_proc(); +}; + +void cleanup_module(void) +{ + unregister_sysctl_table(arlan_device_sysctl_header); + arlan_device_sysctl_header = NULL; + + return; +}; + +#endif // MODULE diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/arlan.c linux.pre11.3/drivers/net/arlan.c --- linux.vanilla/drivers/net/arlan.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/net/arlan.c Mon Jul 19 23:59:55 1999 @@ -0,0 +1,2080 @@ +/* + * Copyright (C) 1997 Cullen Jennings + * Copyright (C) 1998 Elmer.Joandi@ut.ee, +37-255-13500 + * Gnu Public License applies + * This module provides support for the Arlan 655 card made by Aironet + */ + + +#include +#include "arlan.h" + +static const char *arlan_version = "C.Jennigs 97 & Elmer.Joandi@ut.ee Oct'98, http://www.ylenurme.ee/~elmer/655/"; + +struct device *arlan_device[MAX_ARLANS]; +int last_arlan = 0; + +static int SID = SIDUNKNOWN; +static int radioNodeId = radioNodeIdUNKNOWN; +static char encryptionKey[12] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}; +static char *siteName = siteNameUNKNOWN; +static int irq = irqUNKNOWN; +static int mem = memUNKNOWN; +static int arlan_debug = debugUNKNOWN; +static int probe = probeUNKNOWN; +static int numDevices = numDevicesUNKNOWN; +static int testMemory = testMemoryUNKNOWN; +static int spreadingCode = spreadingCodeUNKNOWN; +static int channelNumber = channelNumberUNKNOWN; +static int channelSet = channelSetUNKNOWN; +static int systemId = systemIdUNKNOWN; +static int registrationMode = registrationModeUNKNOWN; +static int txScrambled = 1; +static int keyStart = 0; +static int mdebug = 0; +static int tx_delay_ms = 0; +static int retries = 5; +static int async = 1; +static int tx_queue_len = 1; +static int arlan_entry_debug = 0; +static int arlan_exit_debug = 0; +static int arlan_entry_and_exit_debug = 0; +static int arlan_EEPROM_bad = 0; + +#if LINUX_VERSION_CODE > 0x20100 +MODULE_PARM(irq, "i"); +MODULE_PARM(mem, "i"); +MODULE_PARM(probe, "i"); +MODULE_PARM(arlan_debug, "i"); +MODULE_PARM(numDevices, "i"); +MODULE_PARM(testMemory, "i"); +MODULE_PARM(spreadingCode, "i"); +MODULE_PARM(channelNumber, "i"); +MODULE_PARM(channelSet, "i"); +MODULE_PARM(systemId, "i"); +MODULE_PARM(registrationMode, "i"); +MODULE_PARM(radioNodeId, "i"); +MODULE_PARM(SID, "i"); +MODULE_PARM(txScrambled, "i"); +MODULE_PARM(keyStart, "i"); +MODULE_PARM(mdebug, "i"); +MODULE_PARM(tx_delay_ms, "i"); +MODULE_PARM(retries, "i"); +MODULE_PARM(async, "i"); +MODULE_PARM(tx_queue_len, "i"); +MODULE_PARM(arlan_entry_debug, "i"); +MODULE_PARM(arlan_exit_debug, "i"); +MODULE_PARM(arlan_entry_and_exit_debug, "i"); +MODULE_PARM(arlan_EEPROM_bad, "i"); + +EXPORT_SYMBOL(arlan_device); +EXPORT_SYMBOL(last_arlan); + + +// #warning kernel 2.1.110 tested +#define myATOMIC_INIT(a,b) atomic_set(&(a),b) +#define __initfunctio(a) __initfunc(a) + +#else +#define test_and_set_bit set_bit +#define __initfunctio(a) a +#if LINUX_VERSION_CODE != 0x20024 + // #warning kernel 2.0.36 tested +#endif +#define myATOMIC_INIT(a,b) a = b; + +#endif + +struct arlan_conf_stru arlan_conf[MAX_ARLANS]; +int arlans_found = 0; + +static int arlan_probe_here(struct device *dev, int ioaddr); +static int arlan_open(struct device *dev); +static int arlan_tx(struct sk_buff *skb, struct device *dev); +static void arlan_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static int arlan_close(struct device *dev); +static struct enet_statistics * + arlan_statistics (struct device *dev); +static void arlan_set_multicast (struct device *dev); +static int arlan_hw_tx (struct device* dev, char *buf, int length ); +static int arlan_hw_config (struct device * dev); +static void arlan_tx_done_interrupt (struct device * dev, int status); +static void arlan_rx_interrupt (struct device * dev, u_char rxStatus, u_short, u_short); +static void arlan_process_interrupt (struct device * dev); +static int arlan_command(struct device * dev, int command); + +EXPORT_SYMBOL(arlan_command); + +extern inline long long arlan_time(void) +{ + struct timeval timev; + do_gettimeofday(&timev); + return ((long long) timev.tv_sec * 1000000 + timev.tv_usec); +}; + +#ifdef ARLAN_ENTRY_EXIT_DEBUGING +#define ARLAN_DEBUG_ENTRY(name) \ + {\ + struct timeval timev;\ + do_gettimeofday(&timev);\ + if (arlan_entry_debug || arlan_entry_and_exit_debug)\ + printk("--->>>" name " %ld " "\n",((long int) timev.tv_sec * 1000000 + timev.tv_usec));\ + } +#define ARLAN_DEBUG_EXIT(name) \ + {\ + struct timeval timev;\ + do_gettimeofday(&timev);\ + if (arlan_exit_debug || arlan_entry_and_exit_debug)\ + printk("<<<---" name " %ld " "\n",((long int) timev.tv_sec * 1000000 + timev.tv_usec) );\ + } +#else +#define ARLAN_DEBUG_ENTRY(name) +#define ARLAN_DEBUG_EXIT(name) +#endif + + +#define arlan_interrupt_ack(dev)\ + clearClearInterrupt(dev);\ + setClearInterrupt(dev); + + +#define ARLAN_COMMAND_LOCK(dev) \ + if (atomic_dec_and_test(&((struct arlan_private * )dev->priv)->card_users))\ + arlan_wait_command_complete_short(dev,__LINE__); +#define ARLAN_COMMAND_UNLOCK(dev) \ + atomic_inc(&((struct arlan_private * )dev->priv)->card_users); + + +#define ARLAN_COMMAND_INC(dev) \ + {((struct arlan_private *) dev->priv)->under_command++;} +#define ARLAN_COMMAND_ZERO(dev) \ + {((struct arlan_private *) dev->priv)->under_command =0;} +#define ARLAN_UNDER_COMMAND(dev)\ + (((struct arlan_private *) dev->priv)->under_command) + +#define ARLAN_COMMAND_START(dev) ARLAN_COMMAND_INC(dev) +#define ARLAN_COMMAND_END(dev) ARLAN_COMMAND_ZERO(dev) +#define ARLAN_TOGGLE_START(dev)\ + {((struct arlan_private *) dev->priv)->under_toggle++;} +#define ARLAN_TOGGLE_END(dev)\ + {((struct arlan_private *) dev->priv)->under_toggle=0;} +#define ARLAN_UNDER_TOGGLE(dev)\ + (((struct arlan_private *) dev->priv)->under_toggle) + + + +extern inline int arlan_drop_tx(struct device *dev) +{ + struct arlan_private *priv = ((struct arlan_private *) dev->priv); + + priv->stats.tx_errors++; + if (priv->Conf->tx_delay_ms) + { + priv->tx_done_delayed = jiffies + priv->Conf->tx_delay_ms * HZ / 1000 + 1; + } + else + { + priv->waiting_command_mask &= ~ARLAN_COMMAND_TX; + TXHEAD(dev).offset = 0; + TXTAIL(dev).offset = 0; + priv->txLast = 0; + priv->txOffset = 0; + priv->bad = 0; + if (!priv->under_reset && !priv->under_config) + { + dev->tbusy = 0; + mark_bh(NET_BH); + } + } + return 1; +}; + + +static int arlan_command(struct device *dev, int command_p) +{ + + volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card; + struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf; + struct arlan_private *priv = (struct arlan_private *) dev->priv; + int udelayed = 0; + int i = 0; + long long time_mks = arlan_time(); + + ARLAN_DEBUG_ENTRY("arlan_command"); + + if (priv->card_polling_interval) + priv->card_polling_interval = 1; + + if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS) + printk(KERN_DEBUG "arlan_command, %lx lock %x commandByte %x waiting %x incoming %x \n", + jiffies, priv->command_lock, READSHMB(arlan->commandByte), + priv->waiting_command_mask, command_p); + + priv->waiting_command_mask |= command_p; + + if (priv->waiting_command_mask & ARLAN_COMMAND_RESET) + if (jiffies - priv->lastReset < 5 * HZ) + priv->waiting_command_mask &= ~ARLAN_COMMAND_RESET; + + if (priv->waiting_command_mask & ARLAN_COMMAND_INT_ACK) + { + arlan_interrupt_ack(dev); + priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_ACK; + } + if (priv->waiting_command_mask & ARLAN_COMMAND_INT_ENABLE) + { + setInterruptEnable(dev); + priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_ENABLE; + } + + /* Card access serializing lock */ + + if (test_and_set_bit(0, (void *) &priv->command_lock)) + { + if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS) + printk(KERN_DEBUG "arlan_command: entered when command locked \n"); + goto command_busy_end; + } + /* Check cards status and waiting */ + + if (priv->waiting_command_mask & (ARLAN_COMMAND_LONG_WAIT_NOW | ARLAN_COMMAND_WAIT_NOW)) + { + while (priv->waiting_command_mask & (ARLAN_COMMAND_LONG_WAIT_NOW | ARLAN_COMMAND_WAIT_NOW)) + { + if (READSHMB(arlan->resetFlag) || + READSHMB(arlan->commandByte)) /* || + (readControlRegister(dev) & ARLAN_ACCESS)) + */ + udelay(40); + else + priv->waiting_command_mask &= ~(ARLAN_COMMAND_LONG_WAIT_NOW | ARLAN_COMMAND_WAIT_NOW); + + udelayed++; + + if (priv->waiting_command_mask & ARLAN_COMMAND_LONG_WAIT_NOW) + { + if (udelayed * 40 > 1000000) + { + printk(KERN_ERR "%s long wait too long \n", dev->name); + priv->waiting_command_mask |= ARLAN_COMMAND_RESET; + break; + } + } + else if (priv->waiting_command_mask & ARLAN_COMMAND_WAIT_NOW) + { + if (udelayed * 40 > 1000) + { + printk(KERN_ERR "%s short wait too long \n", dev->name); + goto bad_end; + } + } + } + } + else + { + i = 0; + while ((READSHMB(arlan->resetFlag) || + READSHMB(arlan->commandByte)) && + conf->pre_Command_Wait > (i++) * 10) + udelay(10); + + + if ((READSHMB(arlan->resetFlag) || + READSHMB(arlan->commandByte)) && + !(priv->waiting_command_mask & ARLAN_COMMAND_RESET)) + { + goto card_busy_end; + } + } + if (priv->waiting_command_mask & ARLAN_COMMAND_RESET) + { + priv->under_reset = 1; + dev->start = 0; + } + if (priv->waiting_command_mask & ARLAN_COMMAND_CONF) + { + priv->under_config = 1; + dev->start = 0; + } + + /* Issuing command */ + arlan_lock_card_access(dev); + if (priv->waiting_command_mask & ARLAN_COMMAND_POWERUP) + { + // if (readControlRegister(dev) & (ARLAN_ACCESS && ARLAN_POWER)) + setPowerOn(dev); + arlan_interrupt_lancpu(dev); + priv->waiting_command_mask &= ~ARLAN_COMMAND_POWERUP; + priv->waiting_command_mask |= ARLAN_COMMAND_RESET; + priv->card_polling_interval = HZ / 10; + } + else if (priv->waiting_command_mask & ARLAN_COMMAND_ACTIVATE) + { + WRITESHMB(arlan->commandByte, ARLAN_COM_ACTIVATE); + arlan_interrupt_lancpu(dev); + priv->waiting_command_mask &= ~ARLAN_COMMAND_ACTIVATE; + priv->card_polling_interval = HZ / 10; + } + else if (priv->waiting_command_mask & ARLAN_COMMAND_RX_ABORT) + { + if (priv->rx_command_given) + { + WRITESHMB(arlan->commandByte, ARLAN_COM_RX_ABORT); + arlan_interrupt_lancpu(dev); + priv->rx_command_given = 0; + } + priv->waiting_command_mask &= ~ARLAN_COMMAND_RX_ABORT; + priv->card_polling_interval = 1; + } + else if (priv->waiting_command_mask & ARLAN_COMMAND_TX_ABORT) + { + if (priv->tx_command_given) + { + WRITESHMB(arlan->commandByte, ARLAN_COM_TX_ABORT); + arlan_interrupt_lancpu(dev); + priv->tx_command_given = 0; + } + priv->waiting_command_mask &= ~ARLAN_COMMAND_TX_ABORT; + priv->card_polling_interval = 1; + } + else if (priv->waiting_command_mask & ARLAN_COMMAND_RESET) + { + arlan_drop_tx(dev); + if (priv->tx_command_given || priv->rx_command_given) + { + printk(KERN_ERR "%s: Reset under tx or rx command \n", dev->name); + }; + if (arlan_debug & ARLAN_DEBUG_RESET) + printk(KERN_ERR "%s: Doing chip reset\n", dev->name); + priv->lastReset = jiffies; + WRITESHM(arlan->commandByte, 0, u_char); + /* hold card in reset state */ + setHardwareReset(dev); + /* set reset flag and then release reset */ + WRITESHM(arlan->resetFlag, 0xff, u_char); + clearChannelAttention(dev); + clearHardwareReset(dev); + priv->numResets++; + priv->card_polling_interval = HZ / 4; + priv->waiting_command_mask &= ~ARLAN_COMMAND_RESET; + priv->waiting_command_mask |= ARLAN_COMMAND_INT_RACK; +// priv->waiting_command_mask |= ARLAN_COMMAND_INT_RENABLE; +// priv->waiting_command_mask |= ARLAN_COMMAND_RX; + } + else if (priv->waiting_command_mask & ARLAN_COMMAND_INT_RACK) + { + clearHardwareReset(dev); + clearClearInterrupt(dev); + setClearInterrupt(dev); + setInterruptEnable(dev); + priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_RACK; + priv->waiting_command_mask |= ARLAN_COMMAND_CONF; + priv->under_config = 1; + priv->under_reset = 0; + } + else if (priv->waiting_command_mask & ARLAN_COMMAND_INT_RENABLE) + { + setInterruptEnable(dev); + priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_RENABLE; + } + else if (priv->waiting_command_mask & ARLAN_COMMAND_CONF) + { + if (priv->tx_command_given || priv->rx_command_given) + { + printk(KERN_ERR "%s: Reset under tx or rx command \n", dev->name); + } + dev->start = 0; + arlan_drop_tx(dev); + setInterruptEnable(dev); + arlan_hw_config(dev); + arlan_interrupt_lancpu(dev); + priv->waiting_command_mask &= ~ARLAN_COMMAND_CONF; + priv->card_polling_interval = HZ / 10; +// priv->waiting_command_mask |= ARLAN_COMMAND_INT_RACK; +// priv->waiting_command_mask |= ARLAN_COMMAND_INT_ENABLE; + priv->waiting_command_mask |= ARLAN_COMMAND_CONF_WAIT; + } + else if (priv->waiting_command_mask & ARLAN_COMMAND_CONF_WAIT) + { + if (READSHMB(arlan->configuredStatusFlag) != 0 && + READSHMB(arlan->diagnosticInfo) == 0xff) + { + priv->waiting_command_mask &= ~ARLAN_COMMAND_CONF_WAIT; + priv->waiting_command_mask |= ARLAN_COMMAND_RX; + priv->card_polling_interval = HZ / 10; + priv->tx_command_given = 0; + priv->under_config = 0; + if (dev->tbusy || !dev->start) + { + dev->tbusy = 0; + dev->start = 1; + mark_bh(NET_BH); + }; + } + else + { + priv->card_polling_interval = 1; + if (arlan_debug & ARLAN_DEBUG_TIMING) + printk(KERN_ERR "configure delayed \n"); + } + } + else if (priv->waiting_command_mask & ARLAN_COMMAND_RX) + { + if (!registrationBad(dev)) + { + setInterruptEnable(dev); + memset_io((void *) arlan->commandParameter, 0, 0xf); + WRITESHMB(arlan->commandByte, ARLAN_COM_INT | ARLAN_COM_RX_ENABLE); + WRITESHMB(arlan->commandParameter[0], conf->rxParameter); + arlan_interrupt_lancpu(dev); + priv->rx_command_given; + priv->last_rx_time = arlan_time(); + priv->waiting_command_mask &= ~ARLAN_COMMAND_RX; + priv->card_polling_interval = 1; + } + else + priv->card_polling_interval = 2; + } + else if (priv->waiting_command_mask & ARLAN_COMMAND_TX) + { + if (!test_and_set_bit(0, (void *) &priv->tx_command_given)) + { + if ((time_mks - priv->last_tx_time > conf->rx_tweak1) || + (time_mks - priv->last_rx_int_ack_time < conf->rx_tweak2)) + { + setInterruptEnable(dev); + memset_io((void *) arlan->commandParameter, 0, 0xf); + WRITESHMB(arlan->commandByte, ARLAN_COM_TX_ENABLE | ARLAN_COM_INT); + memcpy_toio((void *) arlan->commandParameter, &TXLAST(dev), 14); +// for ( i=1 ; i < 15 ; i++) printk("%02x:",READSHMB(arlan->commandParameter[i])); + priv->last_command_was_rx = 0; + priv->tx_last_sent = jiffies; + arlan_interrupt_lancpu(dev); + priv->last_tx_time = arlan_time(); + priv->tx_command_given = 1; + priv->waiting_command_mask &= ~ARLAN_COMMAND_TX; + priv->card_polling_interval = 1; + } + else + { + priv->tx_command_given = 0; + priv->card_polling_interval = 1; + } + } + else if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS) + printk(KERN_ERR "tx command when tx chain locked \n"); + } + else if (priv->waiting_command_mask & ARLAN_COMMAND_NOOPINT) + { + { + WRITESHMB(arlan->commandByte, ARLAN_COM_NOP | ARLAN_COM_INT); + } + arlan_interrupt_lancpu(dev); + priv->waiting_command_mask &= ~ARLAN_COMMAND_NOOPINT; + priv->card_polling_interval = HZ / 3; + } + else if (priv->waiting_command_mask & ARLAN_COMMAND_NOOP) + { + WRITESHMB(arlan->commandByte, ARLAN_COM_NOP); + arlan_interrupt_lancpu(dev); + priv->waiting_command_mask &= ~ARLAN_COMMAND_NOOP; + priv->card_polling_interval = HZ / 3; + } + else if (priv->waiting_command_mask & ARLAN_COMMAND_SLOW_POLL) + { + WRITESHMB(arlan->commandByte, ARLAN_COM_GOTO_SLOW_POLL); + arlan_interrupt_lancpu(dev); + priv->waiting_command_mask &= ~ARLAN_COMMAND_SLOW_POLL; + priv->card_polling_interval = HZ / 3; + } + else if (priv->waiting_command_mask & ARLAN_COMMAND_POWERDOWN) + { + setPowerOff(dev); + if (arlan_debug & ARLAN_DEBUG_CARD_STATE) + printk(KERN_WARNING "%s: Arlan Going Standby\n", dev->name); + priv->waiting_command_mask &= ~ARLAN_COMMAND_POWERDOWN; + priv->card_polling_interval = 3 * HZ; + } + arlan_unlock_card_access(dev); + for (i = 0; READSHMB(arlan->commandByte) && i < 20; i++) + udelay(10); + if (READSHMB(arlan->commandByte)) + if (arlan_debug & ARLAN_DEBUG_CARD_STATE) + printk(KERN_ERR "card busy leaving command %x \n", priv->waiting_command_mask); + + priv->command_lock = 0; + ARLAN_DEBUG_EXIT("arlan_command"); + priv->last_command_buff_free_time = jiffies; + return 0; + +card_busy_end: + if (jiffies - priv->last_command_buff_free_time > HZ) + priv->waiting_command_mask |= ARLAN_COMMAND_CLEAN_AND_RESET; + + if (arlan_debug & ARLAN_DEBUG_CARD_STATE) + printk(KERN_ERR "%s arlan_command card busy end \n", dev->name); + priv->command_lock = 0; + ARLAN_DEBUG_EXIT("arlan_command"); + return 1; + +bad_end: + printk(KERN_ERR "%s arlan_command bad end \n", dev->name); + + priv->command_lock = 0; + ARLAN_DEBUG_EXIT("arlan_command"); + + return -1; + +command_busy_end: + if (arlan_debug & ARLAN_DEBUG_CARD_STATE) + printk(KERN_ERR "%s arlan_command command busy end \n", dev->name); + ARLAN_DEBUG_EXIT("arlan_command"); + return 2; + +}; + +extern inline void arlan_command_process(struct device *dev) +{ + struct arlan_private *priv = ((struct arlan_private *) dev->priv); + + int times = 0; + while (priv->waiting_command_mask && times < 8) + { + if (priv->waiting_command_mask) + { + if (arlan_command(dev, 0)) + break; + times++; + } + /* if long command, we wont repeat trying */ ; + if (priv->card_polling_interval > 1) + break; + times++; + } +} + + +extern inline void arlan_retransmit_now(struct device *dev) +{ + struct arlan_private *priv = ((struct arlan_private *) dev->priv); + + + ARLAN_DEBUG_ENTRY("arlan_retransmit_now"); + if (TXLAST(dev).offset == 0) + { + if (TXHEAD(dev).offset) + { + priv->txLast = 0; + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk(KERN_DEBUG "TX buff switch to head \n"); + + } + else if (TXTAIL(dev).offset) + { + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk(KERN_DEBUG "TX buff switch to tail \n"); + priv->txLast = 1; + } + else + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk(KERN_ERR "ReTransmit buff empty"); + priv->txOffset = 0; + dev->tbusy = 0; + mark_bh(NET_BH); + return; + + } + arlan_command(dev, ARLAN_COMMAND_TX); + + priv->nof_tx++; + + priv->Conf->driverRetransmissions++; + priv->retransmissions++; + + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk("Retransmit %d bytes \n", TXLAST(dev).length); + + ARLAN_DEBUG_EXIT("arlan_retransmit_now"); +} + + + +static void arlan_registration_timer(unsigned long data) +{ + struct device *dev = (struct device *) data; + struct arlan_private *priv = (struct arlan_private *) dev->priv; + + int lostTime = ((int) (jiffies - priv->registrationLastSeen)) * 1000 / HZ; + int bh_mark_needed = 0; + int next_tick = 1; + + + priv->timer_chain_active = 1; + + + if (registrationBad(dev)) + { + //debug=100; + priv->registrationLostCount++; + if (lostTime > 7000 && lostTime < 7200) + { + printk(KERN_NOTICE "%s registration Lost \n", dev->name); + } + if (lostTime / priv->reRegisterExp > 2000) + arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_CONF); + if (lostTime / (priv->reRegisterExp) > 3500) + arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_RESET); + if (priv->reRegisterExp < 400) + priv->reRegisterExp += 2; + if (lostTime > 7200) + { + next_tick = HZ; + arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_RESET); + } + } + else + { + if (priv->Conf->registrationMode && lostTime > 10000 && + priv->registrationLostCount) + { + printk(KERN_NOTICE "%s registration is back after %d milliseconds\n", dev->name, + ((int) (jiffies - priv->registrationLastSeen) * 1000) / HZ); + } + priv->registrationLastSeen = jiffies; + priv->registrationLostCount = 0; + priv->reRegisterExp = 1; + if (dev->start == 0) + { + dev->start = 1; + mark_bh(NET_BH); + } + } + + + if (!registrationBad(dev) && priv->ReTransmitRequested) + { + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) + printk(KERN_ERR "Retranmit from timer \n"); + priv->ReTransmitRequested = 0; + arlan_retransmit_now(dev); + } + if (!registrationBad(dev) && + priv->tx_done_delayed < jiffies && + priv->tx_done_delayed != 0) + { + TXLAST(dev).offset = 0; + if (priv->txLast) + priv->txLast = 0; + else if (TXTAIL(dev).offset) + priv->txLast = 1; + if (TXLAST(dev).offset) + { + arlan_retransmit_now(dev); + dev->trans_start = jiffies; + } + if (!(TXHEAD(dev).offset && TXTAIL(dev).offset)) + { + priv->txOffset = 0; + dev->tbusy = 0; + mark_bh(NET_BH); + } + priv->tx_done_delayed = 0; + bh_mark_needed = 1; + } + if (bh_mark_needed) + { + priv->txOffset = 0; + dev->tbusy = 0; + mark_bh(NET_BH); + } + arlan_process_interrupt(dev); + + if (next_tick < priv->card_polling_interval) + next_tick = priv->card_polling_interval; + + priv->timer_chain_active = 0; + priv->timer.expires = jiffies + next_tick; + + add_timer(&priv->timer); +} + + + + +static void arlan_print_registers(struct device *dev, int line) +{ + volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card; + + u_char hostcpuLock, lancpuLock, controlRegister, cntrlRegImage, + txStatus, rxStatus, interruptInProgress, commandByte; + + + ARLAN_DEBUG_ENTRY("arlan_print_registers"); + READSHM(interruptInProgress, arlan->interruptInProgress, u_char); + READSHM(hostcpuLock, arlan->hostcpuLock, u_char); + READSHM(lancpuLock, arlan->lancpuLock, u_char); + READSHM(controlRegister, arlan->controlRegister, u_char); + READSHM(cntrlRegImage, arlan->cntrlRegImage, u_char); + READSHM(txStatus, arlan->txStatus, u_char); + READSHM(rxStatus, arlan->rxStatus, u_char); + READSHM(commandByte, arlan->commandByte, u_char); + + printk(KERN_WARNING "line %04d IP %02x HL %02x LL %02x CB %02x CR %02x CRI %02x TX %02x RX %02x\n", + line, interruptInProgress, hostcpuLock, lancpuLock, commandByte, + controlRegister, cntrlRegImage, txStatus, rxStatus); + + ARLAN_DEBUG_EXIT("arlan_print_registers"); +} + + +static int arlan_hw_tx(struct device *dev, char *buf, int length) +{ + int i; + + struct arlan_private *priv = (struct arlan_private *) dev->priv; + volatile struct arlan_shmem *arlan = priv->card; + struct arlan_conf_stru *conf = priv->Conf; + + int tailStarts = 0x800; + int headEnds = 0x0; + + + ARLAN_DEBUG_ENTRY("arlan_hw_tx"); + if (TXHEAD(dev).offset) + headEnds = (((TXHEAD(dev).offset + TXHEAD(dev).length - (((int) arlan->txBuffer) - ((int) arlan))) / 64) + 1) * 64; + if (TXTAIL(dev).offset) + tailStarts = 0x800 - (((TXTAIL(dev).offset - (((int) arlan->txBuffer) - ((int) arlan))) / 64) + 2) * 64; + + + if (!TXHEAD(dev).offset && length < tailStarts) + { + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) + printk(KERN_ERR "TXHEAD insert, tailStart %d\n", tailStarts); + + TXHEAD(dev).offset = + (((int) arlan->txBuffer) - ((int) arlan)); + TXHEAD(dev).length = length - ARLAN_FAKE_HDR_LEN; + for (i = 0; i < 6; i++) + TXHEAD(dev).dest[i] = buf[i]; + TXHEAD(dev).clear = conf->txClear; + TXHEAD(dev).retries = conf->txRetries; /* 0 is use default */ + TXHEAD(dev).routing = conf->txRouting; + TXHEAD(dev).scrambled = conf->txScrambled; + memcpy_toio(((char *) arlan + TXHEAD(dev).offset), buf + ARLAN_FAKE_HDR_LEN, TXHEAD(dev).length); + } + else if (!TXTAIL(dev).offset && length < (0x800 - headEnds)) + { + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) + printk(KERN_ERR "TXTAIL insert, headEnd %d\n", headEnds); + + TXTAIL(dev).offset = + (((int) arlan->txBuffer) - ((int) arlan)) + 0x800 - (length / 64 + 2) * 64; + TXTAIL(dev).length = length - ARLAN_FAKE_HDR_LEN; + for (i = 0; i < 6; i++) + TXTAIL(dev).dest[i] = buf[i]; + TXTAIL(dev).clear = conf->txClear; + TXTAIL(dev).retries = conf->txRetries; + TXTAIL(dev).routing = conf->txRouting; + TXTAIL(dev).scrambled = conf->txScrambled; + memcpy_toio(((char *) arlan + TXTAIL(dev).offset), buf + ARLAN_FAKE_HDR_LEN, TXTAIL(dev).length); + } + else + { + dev->tbusy = 1; + return -1; + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) + printk(KERN_ERR "TX TAIL & HEAD full, return, tailStart %d headEnd %d\n", tailStarts, headEnds); + } + priv->out_bytes += length; + priv->out_bytes10 += length; + if (conf->measure_rate < 1) + conf->measure_rate = 1; + if (jiffies - priv->out_time > conf->measure_rate * HZ) + { + conf->out_speed = priv->out_bytes / conf->measure_rate; + priv->out_bytes = 0; + priv->out_time = jiffies; + } + if (jiffies - priv->out_time10 > conf->measure_rate * HZ * 10) + { + conf->out_speed10 = priv->out_bytes10 / (10 * conf->measure_rate); + priv->out_bytes10 = 0; + priv->out_time10 = jiffies; + } + if (TXHEAD(dev).offset && TXTAIL(dev).offset) + { + dev->tbusy = 1; + return 0; + } + else + dev->tbusy = 0; + + + IFDEBUG(ARLAN_DEBUG_HEADER_DUMP) + printk(KERN_WARNING "%s Transmit t %2x:%2x:%2x:%2x:%2x:%2x f %2x:%2x:%2x:%2x:%2x:%2x \n", dev->name, + (unsigned char) buf[0], (unsigned char) buf[1], (unsigned char) buf[2], (unsigned char) buf[3], + (unsigned char) buf[4], (unsigned char) buf[5], (unsigned char) buf[6], (unsigned char) buf[7], + (unsigned char) buf[8], (unsigned char) buf[9], (unsigned char) buf[10], (unsigned char) buf[11]); + + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk(KERN_ERR "TX command prepare for buffer %d\n", priv->txLast); + + arlan_command(dev, ARLAN_COMMAND_TX); + + priv->last_command_was_rx = 0; + priv->tx_last_sent = jiffies; + priv->nof_tx++; + + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk("%s TX Qued %d bytes \n", dev->name, length); + + ARLAN_DEBUG_EXIT("arlan_hw_tx"); + + return 0; +} + + +static int arlan_hw_config(struct device *dev) +{ + volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card; + struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf; + struct arlan_private *priv = (struct arlan_private *) dev->priv; + + ARLAN_DEBUG_ENTRY("arlan_hw_config"); + + printk(KERN_NOTICE "%s arlan configure called \n", dev->name); + if (arlan_EEPROM_bad) + printk(KERN_NOTICE "arlan configure with eeprom bad option \n"); + + + WRITESHM(arlan->spreadingCode, conf->spreadingCode, u_char); + WRITESHM(arlan->channelSet, conf->channelSet, u_char); + + if (arlan_EEPROM_bad) + WRITESHM(arlan->defaultChannelSet, conf->channelSet, u_char); + + WRITESHM(arlan->channelNumber, conf->channelNumber, u_char); + + WRITESHM(arlan->scramblingDisable, conf->scramblingDisable, u_char); + WRITESHM(arlan->txAttenuation, conf->txAttenuation, u_char); + + WRITESHM(arlan->systemId, conf->systemId, u_int); + + WRITESHM(arlan->maxRetries, conf->maxRetries, u_char); + WRITESHM(arlan->receiveMode, conf->receiveMode, u_char); + WRITESHM(arlan->priority, conf->priority, u_char); + WRITESHM(arlan->rootOrRepeater, conf->rootOrRepeater, u_char); + WRITESHM(arlan->SID, conf->SID, u_int); + + WRITESHM(arlan->registrationMode, conf->registrationMode, u_char); + + WRITESHM(arlan->registrationFill, conf->registrationFill, u_char); + WRITESHM(arlan->localTalkAddress, conf->localTalkAddress, u_char); + WRITESHM(arlan->codeFormat, conf->codeFormat, u_char); + WRITESHM(arlan->numChannels, conf->numChannels, u_char); + WRITESHM(arlan->channel1, conf->channel1, u_char); + WRITESHM(arlan->channel2, conf->channel2, u_char); + WRITESHM(arlan->channel3, conf->channel3, u_char); + WRITESHM(arlan->channel4, conf->channel4, u_char); + WRITESHM(arlan->radioNodeId, conf->radioNodeId, u_short); + WRITESHM(arlan->SID, conf->SID, u_int); + WRITESHM(arlan->waitTime, conf->waitTime, u_short); + WRITESHM(arlan->lParameter, conf->lParameter, u_short); + memcpy_toio(&(arlan->_15), &(conf->_15), 3); + WRITESHM(arlan->_15, conf->_15, u_short); + WRITESHM(arlan->headerSize, conf->headerSize, u_short); + if (arlan_EEPROM_bad) + WRITESHM(arlan->hardwareType, conf->hardwareType, u_char); + WRITESHM(arlan->radioType, conf->radioType, u_char); + if (arlan_EEPROM_bad) + WRITESHM(arlan->radioModule, conf->radioType, u_char); + + memcpy_toio(arlan->encryptionKey + keyStart, encryptionKey, 8); + memcpy_toio(arlan->name, conf->siteName, 16); + + WRITESHMB(arlan->commandByte, ARLAN_COM_INT | ARLAN_COM_CONF); /* do configure */ + memset_io(arlan->commandParameter, 0, 0xf); /* 0xf */ + memset_io(arlan->commandParameter + 1, 0, 2); + if (conf->writeEEPROM) + { + memset_io(arlan->commandParameter, conf->writeEEPROM, 1); +// conf->writeEEPROM=0; + } + if (conf->registrationMode && conf->registrationInterrupts) + memset_io(arlan->commandParameter + 3, 1, 1); + else + memset_io(arlan->commandParameter + 3, 0, 1); + + priv->irq_test_done = 0; + + if (conf->tx_queue_len) + dev->tx_queue_len = conf->tx_queue_len; + udelay(100); + + ARLAN_DEBUG_EXIT("arlan_hw_config"); + return 0; +} + + +static int arlan_read_card_configuration(struct device *dev) +{ + u_char tlx415; + volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card; + struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf; + + ARLAN_DEBUG_ENTRY("arlan_read_card_configuration"); + + if (radioNodeId == radioNodeIdUNKNOWN) + { + READSHM(conf->radioNodeId, arlan->radioNodeId, u_short); + } + else + conf->radioNodeId = radioNodeId; + + if (SID == SIDUNKNOWN) + { + READSHM(conf->SID, arlan->SID, u_int); + } + else conf->SID = SID; + + if (spreadingCode == spreadingCodeUNKNOWN) + { + READSHM(conf->spreadingCode, arlan->spreadingCode, u_char); + } + else + conf->spreadingCode = spreadingCode; + + if (channelSet == channelSetUNKNOWN) + { + READSHM(conf->channelSet, arlan->channelSet, u_char); + } + else conf->channelSet = channelSet; + + if (channelNumber == channelNumberUNKNOWN) + { + READSHM(conf->channelNumber, arlan->channelNumber, u_char); + } + else conf->channelNumber = channelNumber; + + READSHM(conf->scramblingDisable, arlan->scramblingDisable, u_char); + READSHM(conf->txAttenuation, arlan->txAttenuation, u_char); + + if (systemId == systemIdUNKNOWN) + { + READSHM(conf->systemId, arlan->systemId, u_int); + } + else conf->systemId = systemId; + + READSHM(conf->maxDatagramSize, arlan->maxDatagramSize, u_short); + READSHM(conf->maxFrameSize, arlan->maxFrameSize, u_short); + READSHM(conf->maxRetries, arlan->maxRetries, u_char); + READSHM(conf->receiveMode, arlan->receiveMode, u_char); + READSHM(conf->priority, arlan->priority, u_char); + READSHM(conf->rootOrRepeater, arlan->rootOrRepeater, u_char); + + if (SID == SIDUNKNOWN) + { + READSHM(conf->SID, arlan->SID, u_int); + } + else conf->SID = SID; + + if (registrationMode == registrationModeUNKNOWN) + { + READSHM(conf->registrationMode, arlan->registrationMode, u_char); + } + else conf->registrationMode = registrationMode; + + READSHM(conf->registrationFill, arlan->registrationFill, u_char); + READSHM(conf->localTalkAddress, arlan->localTalkAddress, u_char); + READSHM(conf->codeFormat, arlan->codeFormat, u_char); + READSHM(conf->numChannels, arlan->numChannels, u_char); + READSHM(conf->channel1, arlan->channel1, u_char); + READSHM(conf->channel2, arlan->channel2, u_char); + READSHM(conf->channel3, arlan->channel3, u_char); + READSHM(conf->channel4, arlan->channel4, u_char); + READSHM(conf->waitTime, arlan->waitTime, u_short); + READSHM(conf->lParameter, arlan->lParameter, u_short); + READSHM(conf->_15, arlan->_15, u_short); + READSHM(conf->headerSize, arlan->headerSize, u_short); + READSHM(conf->hardwareType, arlan->hardwareType, u_char); + READSHM(conf->radioType, arlan->radioModule, u_char); + + if (conf->radioType == 0) + conf->radioType = 0xc; + + WRITESHM(arlan->configStatus, 0xA5, u_char); + READSHM(tlx415, arlan->configStatus, u_char); + + if (tlx415 != 0xA5) + printk(KERN_INFO "%s tlx415 chip \n", dev->name); + + conf->txClear = 0; + conf->txRetries = 1; + conf->txRouting = 1; + conf->txScrambled = 0; + conf->rxParameter = 1; + conf->txTimeoutMs = 4000; + conf->waitCardTimeout = 100000; + conf->receiveMode = ARLAN_RCV_CLEAN; + memcpy_fromio(conf->siteName, arlan->name, 16); + conf->siteName[16] = '\0'; + conf->retries = retries; + conf->tx_delay_ms = tx_delay_ms; + conf->async = async; + conf->ReTransmitPacketMaxSize = 200; + conf->waitReTransmitPacketMaxSize = 200; + conf->txAckTimeoutMs = 900; + conf->fastReTransCount = 3; + + ARLAN_DEBUG_EXIT("arlan_read_card_configuration"); + + return 0; +} + + +static int lastFoundAt = 0xbe000; + + +/* + * This is the real probe routine. Linux has a history of friendly device + * probes on the ISA bus. A good device probes avoids doing writes, and + * verifies that the correct device exists and functions. + */ + +__initfunctio(static int arlan_check_fingerprint(int memaddr)) +{ + static char probeText[] = "TELESYSTEM SLW INC. ARLAN \0"; + char tempBuf[49]; + volatile struct arlan_shmem *arlan = (struct arlan_shmem *) memaddr; + + ARLAN_DEBUG_ENTRY("arlan_check_fingerprint"); + memcpy_fromio(tempBuf, arlan->textRegion, 29); + tempBuf[30] = 0; + + /* check for card at this address */ + if (0 != strncmp(tempBuf, probeText, 29)) + return -ENODEV; + +// printk(KERN_INFO "arlan found at 0x%x \n",memaddr); + ARLAN_DEBUG_EXIT("arlan_check_fingerprint"); + + return 0; + + +} + +__initfunctio(int arlan_probe_everywhere(struct device *dev)) +{ + int m; + int probed = 0; + int found = 0; + + ARLAN_DEBUG_ENTRY("arlan_probe_everywhere"); + if (mem != 0 && numDevices == 1) /* Check a single specified location. */ + { + if (arlan_probe_here(dev, mem) == 0) + return 0; + else + return -ENODEV; + } + for (m = lastFoundAt + 0x2000; m <= 0xDE000; m += 0x2000) + { + if (arlan_probe_here(dev, m) == 0) + { + found++; + lastFoundAt = m; + break; + } + probed++; + } + if (found == 0 && probed != 0) + { + if (lastFoundAt == 0xbe000) + printk(KERN_ERR "arlan: No Arlan devices found \n"); + return ENODEV; + } + else + return 0; + + ARLAN_DEBUG_EXIT("arlan_probe_everywhere"); + + return ENODEV; +} + +__initfunctio(int arlan_find_devices(void)) +{ + int m; + int found = 0; + + ARLAN_DEBUG_ENTRY("arlan_find_devices"); + if (mem != 0 && numDevices == 1) /* Check a single specified location. */ + return 1; + for (m = 0xc000; m <= 0xDE000; m += 0x2000) + { + if (arlan_check_fingerprint(m) == 0) + found++; + } + ARLAN_DEBUG_EXIT("arlan_find_devices"); + + return found; +} + + +static int arlan_change_mtu(struct device *dev, int new_mtu) +{ + struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf; + + ARLAN_DEBUG_ENTRY("arlan_change_mtu"); + if ((new_mtu < 68) || (new_mtu > 2032)) + return -EINVAL; + dev->mtu = new_mtu; + if (new_mtu < 256) + new_mtu = 256; /* cards book suggests 1600 */ + conf->maxDatagramSize = new_mtu; + conf->maxFrameSize = new_mtu + 48; + + arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_CONF); + printk(KERN_NOTICE "%s mtu changed to %d \n", dev->name, new_mtu); + + ARLAN_DEBUG_EXIT("arlan_change_mtu"); + + return 0; +} + +static int arlan_mac_addr(struct device *dev, void *p) +{ + struct sockaddr *addr = p; + + + ARLAN_DEBUG_ENTRY("arlan_mac_addr"); + return -EINVAL; + + if (dev->start) + return -EBUSY; + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + ARLAN_DEBUG_EXIT("arlan_mac_addr"); + return 0; +} + + + + +__initfunctio(static int + arlan_allocate_device(int num, struct device *devs)) +{ + + struct device *dev; + + ARLAN_DEBUG_ENTRY("arlan_allocate_device"); + + if (!devs) + dev = init_etherdev(0, sizeof(struct arlan_private)); + else + { + dev = devs; + dev->priv = kmalloc(sizeof(struct arlan_private), GFP_KERNEL); + }; + + if (dev == NULL || dev->priv == NULL) + { + printk(KERN_CRIT "init_etherdev failed "); + return 0; + } + ((struct arlan_private *) dev->priv)->conf = + kmalloc(sizeof(struct arlan_shmem), GFP_KERNEL); + + if (dev == NULL || dev->priv == NULL || + ((struct arlan_private *) dev->priv)->conf == NULL) + { + return 0; + printk(KERN_CRIT " No memory at arlan_allocate_device \n"); + } + /* Fill in the 'dev' fields. */ + dev->base_addr = 0; + dev->mem_start = 0; + dev->mem_end = 0; + dev->mtu = 1500; + dev->flags = 0; /* IFF_BROADCAST & IFF_MULTICAST & IFF_PROMISC; */ + dev->irq = 0; + dev->dma = 0; + dev->tx_queue_len = tx_queue_len; + ether_setup(dev); + dev->tx_queue_len = tx_queue_len; + dev->open = arlan_open; + dev->stop = arlan_close; + dev->hard_start_xmit = arlan_tx; + dev->get_stats = arlan_statistics; + dev->set_multicast_list = arlan_set_multicast; + dev->change_mtu = arlan_change_mtu; + dev->set_mac_address = arlan_mac_addr; + ((struct arlan_private *) dev->priv)->irq_test_done = 0; + arlan_device[num] = dev; + ((struct arlan_private *) arlan_device[num]->priv)->Conf = &(arlan_conf[num]); + + ((struct arlan_private *) dev->priv)->Conf->pre_Command_Wait = 40; + ((struct arlan_private *) dev->priv)->Conf->rx_tweak1 = 30; + ((struct arlan_private *) dev->priv)->Conf->rx_tweak2 = 0; + + ARLAN_DEBUG_EXIT("arlan_allocate_device"); + return (int) dev; +} + + +__initfunctio(int arlan_probe_here(struct device *dev, int memaddr)) +{ + volatile struct arlan_shmem *arlan; + + ARLAN_DEBUG_ENTRY("arlan_probe_here"); + + if (arlan_check_fingerprint(memaddr)) + return -ENODEV; + + printk(KERN_NOTICE "%s: Arlan found at %#5x, \n ", dev->name, memaddr); + + if (!arlan_allocate_device(arlans_found, dev)) + return -1; + + ((struct arlan_private *) dev->priv)->card = (struct arlan_shmem *) memaddr; + arlan = (void *) memaddr; + + dev->mem_start = memaddr; + dev->mem_end = memaddr + 0x1FFF; + + if (dev->irq < 2) + { + READSHM(dev->irq, arlan->irqLevel, u_char); + } else if (dev->irq == 2) + dev->irq = 9; + + arlan_read_card_configuration(dev); + + ARLAN_DEBUG_EXIT("arlan_probe_here"); + return 0; +} + + + + +static int arlan_open(struct device *dev) +{ + struct arlan_private *priv = (struct arlan_private *) dev->priv; + volatile struct arlan_shmem *arlan = priv->card; + int ret = 0; + + ARLAN_DEBUG_ENTRY("arlan_open"); + + if (dev->mem_start == 0) + ret = arlan_probe_everywhere(dev); + if (ret != 0) + return ret; + + arlan = ((struct arlan_private *) dev->priv)->card; + + if (request_irq(dev->irq, &arlan_interrupt, 0, dev->name, dev)) + { + printk(KERN_ERR "%s: unable to get IRQ %d .\n", + dev->name, dev->irq); + return -EAGAIN; + } + arlan_command(dev, ARLAN_COMMAND_POWERUP | ARLAN_COMMAND_LONG_WAIT_NOW); + + priv->bad = 0; + priv->lastReset = 0; + priv->reset = 0; + priv->open_time = jiffies; + memcpy_fromio(dev->dev_addr, arlan->lanCardNodeId, 6); + memset(dev->broadcast, 0xff, 6); + dev->tbusy = 1; + priv->txOffset = 0; + dev->interrupt = 0; + dev->start = 1; + dev->tx_queue_len = tx_queue_len; + init_timer(&priv->timer); + priv->timer.expires = jiffies + HZ / 10; + priv->timer.data = (unsigned long) dev; + priv->timer.function = &arlan_registration_timer; /* timer handler */ + priv->interrupt_processing_active = 0; + priv->command_lock = 0; + add_timer(&priv->timer); + + priv->card_lock = MUTEX; + myATOMIC_INIT(priv->card_users, 1); /* damn 2.0.33 */ + priv->registrationLostCount = 0; + priv->registrationLastSeen = jiffies; + priv->txLast = 0; + priv->tx_command_given = 0; + + priv->reRegisterExp = 1; + priv->nof_tx = 0; + priv->nof_tx_ack = 0; + priv->last_command_was_rx = 0; + priv->tx_last_sent = jiffies - 1; + priv->tx_last_cleared = jiffies; + priv->Conf->writeEEPROM = 0; + priv->Conf->registrationInterrupts = 1; + + dev->tbusy = 0; + + MOD_INC_USE_COUNT; +#ifdef CONFIG_PROC_FS +#ifndef MODULE + if (arlan_device[0]) + init_arlan_proc(); +#endif +#endif + ARLAN_DEBUG_EXIT("arlan_open"); + return 0; +} + + + + +static int arlan_tx(struct sk_buff *skb, struct device *dev) +{ + struct arlan_private *priv = ((struct arlan_private *) dev->priv); + struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf; + + ARLAN_DEBUG_ENTRY("arlan_tx"); + + if (dev->tbusy) + { + /* + * If we get here, some higher level has decided we are broken. + * There should really be a "kick me" function call instead. + */ + int tickssofar = jiffies - dev->trans_start; + + if (((tickssofar * 1000) / HZ) * 2 > conf->txTimeoutMs) + arlan_command(dev, ARLAN_COMMAND_TX_ABORT); + + if (((tickssofar * 1000) / HZ) < conf->txTimeoutMs) + { + // up(&priv->card_lock); + goto bad_end; + } + printk(KERN_ERR "%s: arlan transmit timed out, kernel decided\n", dev->name); + /* Try to restart the adaptor. */ + arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_RESET); + dev->trans_start = jiffies; + goto bad_end; + + } + /* + * Block a timer-based transmit from overlapping. This could better be + * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. + */ + if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) + { + printk(KERN_ERR "%s: Transmitter access conflict.\n", + dev->name); + } + else + { + short length; + unsigned char *buf; + + /* + * If some higher layer thinks we've missed an tx-done interrupt + * we are passed NULL. Caution: dev_tint() handles the cli()/sti() + * itself. + */ + + length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + buf = skb->data; + + if (priv->txOffset + length + 0x12 > 0x800) + printk(KERN_ERR "TX RING overflow \n"); + + if (arlan_hw_tx(dev, buf, length) == -1) + goto bad_end; + + dev->trans_start = jiffies; + } + dev_kfree_skb(skb); + + arlan_process_interrupt(dev); + priv->tx_chain_active = 0; + ARLAN_DEBUG_EXIT("arlan_tx"); + return 0; + +bad_end: + arlan_process_interrupt(dev); + priv->tx_chain_active = 0; + ARLAN_DEBUG_EXIT("arlan_tx"); + return 1; +} + + +extern inline int DoNotReTransmitCrap(struct device *dev) +{ + struct arlan_private *priv = ((struct arlan_private *) dev->priv); + + if (TXLAST(dev).length < priv->Conf->ReTransmitPacketMaxSize) + return 1; + return 0; + +} + +extern inline int DoNotWaitReTransmitCrap(struct device *dev) +{ + struct arlan_private *priv = ((struct arlan_private *) dev->priv); + + if (TXLAST(dev).length < priv->Conf->waitReTransmitPacketMaxSize) + return 1; + return 0; +} + +extern inline void arlan_queue_retransmit(struct device *dev) +{ + struct arlan_private *priv = ((struct arlan_private *) dev->priv); + + ARLAN_DEBUG_ENTRY("arlan_queue_retransmit"); + + if (DoNotWaitReTransmitCrap(dev)) + { + arlan_drop_tx(dev); + } else + priv->ReTransmitRequested++; + + ARLAN_DEBUG_EXIT("arlan_queue_retransmit"); +}; + +extern inline void RetryOrFail(struct device *dev) +{ + struct arlan_private *priv = ((struct arlan_private *) dev->priv); + + ARLAN_DEBUG_ENTRY("RetryOrFail"); + + if (priv->retransmissions > priv->Conf->retries || + DoNotReTransmitCrap(dev)) + { + arlan_drop_tx(dev); + } + else if (priv->bad <= priv->Conf->fastReTransCount) + { + arlan_retransmit_now(dev); + } + else arlan_queue_retransmit(dev); + + ARLAN_DEBUG_EXIT("RetryOrFail"); +} + + +static void arlan_tx_done_interrupt(struct device *dev, int status) +{ + struct arlan_private *priv = ((struct arlan_private *) dev->priv); + + ARLAN_DEBUG_ENTRY("arlan_tx_done_interrupt"); + + priv->tx_last_cleared = jiffies; + priv->tx_command_given = 0; + priv->nof_tx_ack++; + switch (status) + { + case 1: + { + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) + printk("arlan intr: transmit OK\n"); + priv->stats.tx_packets++; + priv->bad = 0; + priv->reset = 0; + priv->retransmissions = 0; + if (priv->Conf->tx_delay_ms) + { + priv->tx_done_delayed = jiffies + (priv->Conf->tx_delay_ms * HZ) / 1000 + 1;; + } + else + { + TXLAST(dev).offset = 0; + if (priv->txLast) + priv->txLast = 0; + else if (TXTAIL(dev).offset) + priv->txLast = 1; + if (TXLAST(dev).offset) + { + arlan_retransmit_now(dev); + dev->trans_start = jiffies; + } + if (!TXHEAD(dev).offset || !TXTAIL(dev).offset) + { + priv->txOffset = 0; + dev->tbusy = 0; + mark_bh(NET_BH); + } + } + } + break; + + case 2: + { + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) + printk("arlan intr: transmit timed out\n"); + priv->bad += 1; + //arlan_queue_retransmit(dev); + RetryOrFail(dev); + } + break; + + case 3: + { + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) + printk("arlan intr: transmit max retries\n"); + priv->bad += 1; + priv->reset = 0; + //arlan_queue_retransmit(dev); + RetryOrFail(dev); + } + break; + + case 4: + { + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) + printk("arlan intr: transmit aborted\n"); + priv->bad += 1; + arlan_queue_retransmit(dev); + //RetryOrFail(dev); + } + break; + + case 5: + { + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) + printk("arlan intr: transmit not registered\n"); + priv->bad += 1; + //debug=101; + arlan_queue_retransmit(dev); + } + break; + + case 6: + { + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) + printk("arlan intr: transmit destination full\n"); + priv->bad += 1; + priv->reset = 0; + //arlan_drop_tx(dev); + arlan_queue_retransmit(dev); + } + break; + + case 7: + { + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) + printk("arlan intr: transmit unknown ack\n"); + priv->bad += 1; + priv->reset = 0; + arlan_queue_retransmit(dev); + } + break; + + case 8: + { + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) + printk("arlan intr: transmit dest mail box full\n"); + priv->bad += 1; + priv->reset = 0; + //arlan_drop_tx(dev); + arlan_queue_retransmit(dev); + } + break; + + case 9: + { + IFDEBUG(ARLAN_DEBUG_TX_CHAIN) + printk("arlan intr: transmit root dest not reg.\n"); + priv->bad += 1; + priv->reset = 1; + //arlan_drop_tx(dev); + arlan_queue_retransmit(dev); + } + break; + + default: + { + printk(KERN_ERR "arlan intr: transmit status unknown\n"); + priv->bad += 1; + priv->reset = 1; + arlan_drop_tx(dev); + } + } + + ARLAN_DEBUG_EXIT("arlan_tx_done_interrupt"); +} + + +static void arlan_rx_interrupt(struct device *dev, u_char rxStatus, u_short rxOffset, u_short pkt_len) +{ + char *skbtmp; + int i = 0; + + struct arlan_private *priv = (struct arlan_private *) dev->priv; + volatile struct arlan_shmem *arlan = priv->card; + struct arlan_conf_stru *conf = priv->Conf; + + + ARLAN_DEBUG_ENTRY("arlan_rx_interrupt"); + // by spec, not WRITESHMB(arlan->rxStatus,0x00); + // prohibited here arlan_command(dev, ARLAN_COMMAND_RX); + + if (pkt_len < 10 || pkt_len > 2048) + { + printk(KERN_WARNING "%s: got too short or long packet, len %d \n", dev->name, pkt_len); + return; + } + if (rxOffset + pkt_len > 0x2000) + { + printk("%s: got too long packet, len %d offset %x\n", dev->name, pkt_len, rxOffset); + return; + } + priv->in_bytes += pkt_len; + priv->in_bytes10 += pkt_len; + if (conf->measure_rate < 1) + conf->measure_rate = 1; + if (jiffies - priv->in_time > conf->measure_rate * HZ) + { + conf->in_speed = priv->in_bytes / conf->measure_rate; + priv->in_bytes = 0; + priv->in_time = jiffies; + } + if (jiffies - priv->in_time10 > conf->measure_rate * HZ * 10) + { + conf->in_speed10 = priv->in_bytes10 / (10 * conf->measure_rate); + priv->in_bytes10 = 0; + priv->in_time10 = jiffies; + } + DEBUGSHM(1, "arlan rcv pkt rxStatus= %d ", arlan->rxStatus, u_char); + switch (rxStatus) + { + case 1: + case 2: + case 3: + { + /* Malloc up new buffer. */ + struct sk_buff *skb; + + DEBUGSHM(50, "arlan recv pkt offs=%d\n", arlan->rxOffset, u_short); + DEBUGSHM(1, "arlan rxFrmType = %d \n", arlan->rxFrmType, u_char); + DEBUGSHM(1, KERN_INFO "arlan rx scrambled = %d \n", arlan->scrambled, u_char); + + /* here we do multicast filtering to avoid slow 8-bit memcopy */ +#ifdef ARLAN_MULTICAST + if (!(dev->flags & IFF_ALLMULTI) && + !(dev->flags & IFF_PROMISC) && + dev->mc_list) + { + char hw_dst_addr[6]; + struct dev_mc_list *dmi = dev->mc_list; + int i; + + memcpy_fromio(hw_dst_addr, arlan->ultimateDestAddress, 6); + if (hw_dst_addr[0] == 0x01) + { + if (mdebug) + if (hw_dst_addr[1] == 0x00) + printk(KERN_ERR "%s mcast 0x0100 \n", dev->name); + else if (hw_dst_addr[1] == 0x40) + printk(KERN_ERR "%s m/bcast 0x0140 \n", dev->name); + while (dmi) + { if (dmi->dmi_addrlen == 6) + { + if (arlan_debug & ARLAN_DEBUG_HEADER_DUMP) + printk(KERN_ERR "%s mcl %2x:%2x:%2x:%2x:%2x:%2x \n", dev->name, + dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2], + dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5]); + for (i = 0; i < 6; i++) + if (dmi->dmi_addr[i] != hw_dst_addr[i]) + break; + if (i == 6) + break; + } + else + printk(KERN_ERR "%s: invalid multicast address length given.\n", dev->name); + dmi = dmi->next; + } + /* we reach here if multicast filtering is on and packet + * is multicast and not for receive */ + goto end_of_interupt; + } + } +#endif // ARLAN_MULTICAST + /* multicast filtering ends here */ + pkt_len += ARLAN_FAKE_HDR_LEN; + + skb = dev_alloc_skb(pkt_len + 4); + if (skb == NULL) + { + printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n", dev->name); + priv->stats.rx_dropped++; + break; + } + skb_reserve(skb, 2); + skb->dev = dev; + skbtmp = skb_put(skb, pkt_len); + + memcpy_fromio(skbtmp + ARLAN_FAKE_HDR_LEN, ((char *) arlan) + rxOffset, pkt_len - ARLAN_FAKE_HDR_LEN); + memcpy_fromio(skbtmp, arlan->ultimateDestAddress, 6); + memcpy_fromio(skbtmp + 6, arlan->rxSrc, 6); + WRITESHMB(arlan->rxStatus, 0x00); + arlan_command(dev, ARLAN_COMMAND_RX); + + IFDEBUG(ARLAN_DEBUG_HEADER_DUMP) + { + char immedDestAddress[6]; + char immedSrcAddress[6]; + memcpy_fromio(immedDestAddress, arlan->immedDestAddress, 6); + memcpy_fromio(immedSrcAddress, arlan->immedSrcAddress, 6); + + printk(KERN_WARNING "%s t %2x:%2x:%2x:%2x:%2x:%2x f %2x:%2x:%2x:%2x:%2x:%2x imd %2x:%2x:%2x:%2x:%2x:%2x ims %2x:%2x:%2x:%2x:%2x:%2x\n", dev->name, + (unsigned char) skbtmp[0], (unsigned char) skbtmp[1], (unsigned char) skbtmp[2], (unsigned char) skbtmp[3], + (unsigned char) skbtmp[4], (unsigned char) skbtmp[5], (unsigned char) skbtmp[6], (unsigned char) skbtmp[7], + (unsigned char) skbtmp[8], (unsigned char) skbtmp[9], (unsigned char) skbtmp[10], (unsigned char) skbtmp[11], + immedDestAddress[0], immedDestAddress[1], immedDestAddress[2], + immedDestAddress[3], immedDestAddress[4], immedDestAddress[5], + immedSrcAddress[0], immedSrcAddress[1], immedSrcAddress[2], + immedSrcAddress[3], immedSrcAddress[4], immedSrcAddress[5]); + } + skb->protocol = eth_type_trans(skb, dev); + IFDEBUG(ARLAN_DEBUG_HEADER_DUMP) + if (skb->protocol != 0x608 && skb->protocol != 0x8) + { + for (i = 0; i <= 22; i++) + printk("%02x:", (u_char) skbtmp[i + 12]); + printk(KERN_ERR "\n"); + printk(KERN_WARNING "arlan kernel pkt type trans %x \n", skb->protocol); + } + netif_rx(skb); + priv->stats.rx_packets++; + } + break; + + default: + printk(KERN_ERR "arlan intr: recieved unknown status\n"); + priv->stats.rx_crc_errors++; + break; + } + ARLAN_DEBUG_EXIT("arlan_rx_interrupt"); +} + +static void arlan_process_interrupt(struct device *dev) +{ + struct arlan_private *priv = (struct arlan_private *) dev->priv; + volatile struct arlan_shmem *arlan = priv->card; + u_char rxStatus = READSHMB(arlan->rxStatus); + u_char txStatus = READSHMB(arlan->txStatus); + u_short rxOffset = READSHMS(arlan->rxOffset); + u_short pkt_len = READSHMS(arlan->rxLength); + int interrupt_count = 0; + + ARLAN_DEBUG_ENTRY("arlan_process_interrupt"); + + if (test_and_set_bit(0, (void *) &priv->interrupt_processing_active)) + { + if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS) + printk(KERN_ERR "interrupt chain reentering \n"); + goto end_int_process; + } + while ((rxStatus || txStatus || priv->interrupt_ack_requested) + && (interrupt_count < 5)) + { + if (rxStatus) + priv->last_rx_int_ack_time = arlan_time(); + + arlan_command(dev, ARLAN_COMMAND_INT_ACK); + arlan_command(dev, ARLAN_COMMAND_INT_ENABLE); + + IFDEBUG(ARLAN_DEBUG_INTERRUPT) + printk(KERN_ERR "%s: got IRQ rx %x tx %x comm %x rxOff %x rxLen %x \n", + dev->name, rxStatus, txStatus, READSHMB(arlan->commandByte), + rxOffset, pkt_len); + + if (rxStatus == 0 && txStatus == 0) + { + priv->last_command_was_rx = 0; + if (priv->irq_test_done) + { + if (!registrationBad(dev)) + IFDEBUG(ARLAN_DEBUG_INTERRUPT) printk(KERN_ERR "%s unknown interrupt(nop? regLost ?) reason tx %d rx %d ", + dev->name, txStatus, rxStatus); + } else { + IFDEBUG(ARLAN_DEBUG_INTERRUPT) + printk(KERN_INFO "%s irq $%d test OK \n", dev->name, dev->irq); + + } + priv->interrupt_ack_requested = 0; + goto ends; + } + if (txStatus != 0) + { + WRITESHMB(arlan->txStatus, 0x00); + arlan_tx_done_interrupt(dev, txStatus); + goto ends; + } + if (rxStatus == 1 || rxStatus == 2) + { /* a packet waiting */ + arlan_rx_interrupt(dev, rxStatus, rxOffset, pkt_len); + goto ends; + } + if (rxStatus > 2 && rxStatus < 0xff) + { + priv->last_command_was_rx = 0; + WRITESHMB(arlan->rxStatus, 0x00); + printk(KERN_ERR "%s unknown rxStatus reason tx %d rx %d ", + dev->name, txStatus, rxStatus); + goto ends; + } + if (rxStatus == 0xff) + { + priv->last_command_was_rx = 0; + WRITESHMB(arlan->rxStatus, 0x00); + arlan_command(dev, ARLAN_COMMAND_RX); + if (registrationBad(dev)) + dev->start = 0; + if (!registrationBad(dev)) + { + priv->registrationLastSeen = jiffies; + if (!dev->tbusy && !priv->under_reset && !priv->under_config) + { + mark_bh(NET_BH); + dev->start = 1; + } + } + goto ends; + } +ends: + + arlan_command_process(dev); + + rxStatus = READSHMB(arlan->rxStatus); + txStatus = READSHMB(arlan->txStatus); + rxOffset = READSHMS(arlan->rxOffset); + pkt_len = READSHMS(arlan->rxLength); + + + priv->irq_test_done = 1; + + interrupt_count++; + } + priv->interrupt_processing_active = 0; + +end_int_process: + arlan_command_process(dev); + + ARLAN_DEBUG_EXIT("arlan_process_interrupt"); + return; +} + +static void arlan_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct device *dev = dev_id; + struct arlan_private *priv = (struct arlan_private *) dev->priv; + volatile struct arlan_shmem *arlan = priv->card; + u_char rxStatus = READSHMB(arlan->rxStatus); + u_char txStatus = READSHMB(arlan->txStatus); + + ARLAN_DEBUG_ENTRY("arlan_interrupt"); + + + if (!rxStatus && !txStatus) + priv->interrupt_ack_requested++; + dev->interrupt++; + + arlan_process_interrupt(dev); + + priv->irq_test_done = 1; + dev->interrupt--; + + ARLAN_DEBUG_EXIT("arlan_interrupt"); + return; + +} + + +static int arlan_close(struct device *dev) +{ + struct arlan_private *priv = (struct arlan_private *) dev->priv; + + if (!dev) + { + printk(KERN_CRIT "arlan: No Device\n"); + return 0; + } + priv = (struct arlan_private *) dev->priv; + if (!priv) + { + printk(KERN_CRIT "arlan: No Device priv \n"); + return 0; + } + ARLAN_DEBUG_ENTRY("arlan_close"); + + IFDEBUG(ARLAN_DEBUG_STARTUP) + printk(KERN_NOTICE "%s: Closing device\n", dev->name); + + priv->open_time = 0; + dev->tbusy = 1; + dev->start = 0; + del_timer(&priv->timer); + free_irq(dev->irq, dev); + + MOD_DEC_USE_COUNT; + + ARLAN_DEBUG_EXIT("arlan_close"); + return 0; +} + + +static long alignLong(volatile u_char * ptr) +{ + long ret; + memcpy_fromio(&ret, (void *) ptr, 4); + return ret; +} + + +/* + * Get the current statistics. + * This may be called with the card open or closed. + */ + +static struct enet_statistics *arlan_statistics(struct device *dev) +{ + struct arlan_private *priv = (struct arlan_private *) dev->priv; + volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card; + + + ARLAN_DEBUG_ENTRY("arlan_statistics"); + + /* Update the statistics from the device registers. */ + + READSHM(priv->stats.collisions, arlan->numReTransmissions, u_int); + READSHM(priv->stats.rx_crc_errors, arlan->numCRCErrors, u_int); + READSHM(priv->stats.rx_dropped, arlan->numFramesDiscarded, u_int); + READSHM(priv->stats.rx_fifo_errors, arlan->numRXBufferOverflows, u_int); + READSHM(priv->stats.rx_frame_errors, arlan->numReceiveFramesLost, u_int); + READSHM(priv->stats.rx_over_errors, arlan->numRXOverruns, u_int); + READSHM(priv->stats.rx_packets, arlan->numDatagramsReceived, u_int); + READSHM(priv->stats.tx_aborted_errors, arlan->numAbortErrors, u_int); + READSHM(priv->stats.tx_carrier_errors, arlan->numStatusTimeouts, u_int); + READSHM(priv->stats.tx_dropped, arlan->numDatagramsDiscarded, u_int); + READSHM(priv->stats.tx_fifo_errors, arlan->numTXUnderruns, u_int); + READSHM(priv->stats.tx_packets, arlan->numDatagramsTransmitted, u_int); + READSHM(priv->stats.tx_window_errors, arlan->numHoldOffs, u_int); + + ARLAN_DEBUG_EXIT("arlan_statistics"); + + return &priv->stats; +} + + +static void arlan_set_multicast(struct device *dev) +{ + volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card; + struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf; + int board_conf_needed = 0; + + + ARLAN_DEBUG_ENTRY("arlan_set_multicast"); + + if (dev->flags & IFF_PROMISC) + { + unsigned char recMode; + READSHM(recMode, arlan->receiveMode, u_char); + conf->receiveMode = (ARLAN_RCV_PROMISC | ARLAN_RCV_CONTROL); + if (conf->receiveMode != recMode) + board_conf_needed = 1; + } + else + { + /* turn off promiscuous mode */ + unsigned char recMode; + READSHM(recMode, arlan->receiveMode, u_char); + conf->receiveMode = ARLAN_RCV_CLEAN | ARLAN_RCV_CONTROL; + if (conf->receiveMode != recMode) + board_conf_needed = 1; + } + if (board_conf_needed) + arlan_command(dev, ARLAN_COMMAND_CONF); + + ARLAN_DEBUG_EXIT("arlan_set_multicast"); +} + + +__initfunctio(int arlan_probe(struct device *dev)) +{ + printk("Arlan driver %s\n", arlan_version); + + if (arlan_probe_everywhere(dev)) + return ENODEV; + + arlans_found++; + + if (arlans_found == 1) + siteName = kmalloc(100, GFP_KERNEL); + return 0; +} + +#ifdef MODULE + +int init_module(void) +{ + int i = 0; + + ARLAN_DEBUG_ENTRY("init_module"); + + if (channelSet != channelSetUNKNOWN || channelNumber != channelNumberUNKNOWN || systemId != systemIdUNKNOWN) + { + printk(KERN_WARNING "arlan: wrong module params for multiple devices\n "); + return -1; + } + numDevices = arlan_find_devices(); + if (numDevices == 0) + { + printk(KERN_ERR "arlan: no devices found \n"); + return -1; + } + + siteName = kmalloc(100, GFP_KERNEL); + if(siteName==NULL) + { + printk(KERN_ERR "arlan: No memory for site name.\n"); + return -1; + } + for (i = 0; i < numDevices && i < MAX_ARLANS; i++) + { + if (!arlan_allocate_device(i, NULL)) + return -1; + if (arlan_device[i] == NULL) + { + printk(KERN_CRIT "arlan: Not Enough memory \n"); + return -1; + } + if (probe) + arlan_probe_everywhere(arlan_device[i]); + } + printk(KERN_INFO "Arlan driver %s\n", arlan_version); + ARLAN_DEBUG_EXIT("init_module"); + return 0; +} + + +void cleanup_module(void) +{ + int i = 0; + + ARLAN_DEBUG_ENTRY("cleanup_module"); + + IFDEBUG(ARLAN_DEBUG_SHUTDOWN) + printk(KERN_INFO "arlan: unloading module\n"); + for (i = 0; i < MAX_ARLANS; i++) + { + if (arlan_device[i]) + { + unregister_netdev(arlan_device[i]); + if (arlan_device[i]->priv) + { + if (((struct arlan_private *) arlan_device[i]->priv)->conf) + kfree(((struct arlan_private *) arlan_device[i]->priv)->conf); + kfree(arlan_device[i]); + } + arlan_device[i] = NULL; + } + } + ARLAN_DEBUG_EXIT("cleanup_module"); +} + + +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/arlan.h linux.pre11.3/drivers/net/arlan.h --- linux.vanilla/drivers/net/arlan.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/net/arlan.h Tue Jul 20 02:02:45 1999 @@ -0,0 +1,574 @@ +/* + * Copyright (C) 1997 Cullen Jennings + * Copyright (C) 1998 Elmer.Joandi@ut.ee, +37-255-13500 + * Gnu Public License applies + */ +#include + +#include +#include +#include +#include +#include +#include /* For the statistics structure. */ +#include /* For ARPHRD_ETHER */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DEBUG 1 + +#define ARLAN_PROC_INTERFACE +#define MAX_ARLANS 4 /* not more than 4 ! */ +#define ARLAN_PROC_SHM_DUMP /* shows all card registers, makes driver way larger */ + +#define ARLAN_MAX_MULTICAST_ADDRS 16 +#define ARLAN_RCV_CLEAN 0 +#define ARLAN_RCV_PROMISC 1 +#define ARLAN_RCV_CONTROL 2 + + +#ifdef CONFIG_PROC_FS +extern int init_arlan_proc(void); +#endif + +extern struct device *arlan_device[MAX_ARLANS]; +static int arlan_debug; +static char * siteName; +static int arlan_entry_debug; +static int arlan_exit_debug; +static int arlan_entry_and_exit_debug; +static int testMemory; +static const char* arlan_version; + +#define SIDUNKNOWN -1 +#define radioNodeIdUNKNOWN -1 +#define encryptionKeyUNKNOWN '\0'; +#define irqUNKNOWN 0 +#define memUNKNOWN 0 +#define debugUNKNOWN 0 +#define probeUNKNOWN 1 +#define numDevicesUNKNOWN 1 +#define testMemoryUNKNOWN 1 +#define spreadingCodeUNKNOWN 0 +#define channelNumberUNKNOWN 0 +#define channelSetUNKNOWN 0 +#define systemIdUNKNOWN -1 +#define registrationModeUNKNOWN -1 +#define siteNameUNKNOWN "LinuxSite" + + + +#define IFDEBUG( L ) if ( (L) & arlan_debug ) +#define ARLAN_FAKE_HDR_LEN 12 + +#ifdef DEBUG + #define ARLAN_ENTRY_EXIT_DEBUGING 1 + #define ARLAN_DEBUG(a,b) printk(KERN_DEBUG a, b) +#else + #define ARLAN_DEBUG(a,b) +#endif + +struct arlan_shmem +{ + /* Header Signature */ + volatile char textRegion[48]; + volatile u_char resetFlag; + volatile u_char diagnosticInfo; + volatile u_short diagnosticOffset; + volatile u_char _1[12]; + volatile u_char lanCardNodeId[6]; + volatile u_char broadcastAddress[6]; + volatile u_char hardwareType; + volatile u_char majorHardwareVersion; + volatile u_char minorHardwareVersion; + volatile u_char radioModule;// shows EEPROM, can be overridden at 0x111 + volatile u_char defaultChannelSet; // shows EEProm, can be overriiden at 0x10A + volatile u_char _2[47]; + + /* Control/Status Block - 0x0080 */ + volatile u_char interruptInProgress; /* not used by lancpu */ + volatile u_char cntrlRegImage; /* not used by lancpu */ + volatile u_char _3[13]; + volatile u_char dumpByte; + volatile u_char commandByte; /* non-zero = active */ + volatile u_char commandParameter[15]; + + /* Receive Status - 0x00a0 */ + volatile u_char rxStatus; /* 1- data, 2-control, 0xff - registr change */ + volatile u_char rxFrmType; + volatile u_short rxOffset; + volatile u_short rxLength; + volatile u_char rxSrc[6]; + volatile u_char rxBroadcastFlag; + volatile u_char rxQuality; + volatile u_char scrambled; + volatile u_char _4[1]; + + /* Transmit Status - 0x00b0 */ + volatile u_char txStatus; + volatile u_char txAckQuality; + volatile u_char numRetries; + volatile u_char _5[14]; + volatile u_char registeredRouter[6]; + volatile u_char backboneRouter[6]; + volatile u_char registrationStatus; + volatile u_char configuredStatusFlag; + volatile u_char _6[1]; + volatile u_char ultimateDestAddress[6]; + volatile u_char immedDestAddress[6]; + volatile u_char immedSrcAddress[6]; + volatile u_short rxSequenceNumber; + volatile u_char assignedLocaltalkAddress; + volatile u_char _7[27]; + + /* System Parameter Block */ + + /* - Driver Parameters (Novell Specific) */ + + volatile u_short txTimeout; + volatile u_short transportTime; + volatile u_char _8[4]; + + /* - Configuration Parameters */ + volatile u_char irqLevel; + volatile u_char spreadingCode; + volatile u_char channelSet; + volatile u_char channelNumber; + volatile u_short radioNodeId; + volatile u_char _9[2]; + volatile u_char scramblingDisable; + volatile u_char radioType; + volatile u_short routerId; + volatile u_char _10[9]; + volatile u_char txAttenuation; + volatile u_char systemId[4]; + volatile u_short globalChecksum; + volatile u_char _11[4]; + volatile u_short maxDatagramSize; + volatile u_short maxFrameSize; + volatile u_char maxRetries; + volatile u_char receiveMode; + volatile u_char priority; + volatile u_char rootOrRepeater; + volatile u_char specifiedRouter[6]; + volatile u_short fastPollPeriod; + volatile u_char pollDecay; + volatile u_char fastPollDelay[2]; + volatile u_char arlThreshold; + volatile u_char arlDecay; + volatile u_char _12[1]; + volatile u_short specRouterTimeout; + volatile u_char _13[5]; + + /* Scrambled Area */ + volatile u_char SID[4]; + volatile u_char encryptionKey[12]; + volatile u_char _14[2]; + volatile u_char waitTime[2]; + volatile u_char lParameter[2]; + volatile u_char _15[3]; + volatile u_short headerSize; + volatile u_short sectionChecksum; + + volatile u_char registrationMode; + volatile u_char registrationFill; + volatile u_short pollPeriod; + volatile u_short refreshPeriod; + volatile u_char name[16]; + volatile u_char NID[6]; + volatile u_char localTalkAddress; + volatile u_char codeFormat; + volatile u_char numChannels; + volatile u_char channel1; + volatile u_char channel2; + volatile u_char channel3; + volatile u_char channel4; + volatile u_char SSCode[59]; + + volatile u_char _16[0xC0]; + volatile u_short auxCmd; + volatile u_char dumpPtr[4]; + volatile u_char dumpVal; + volatile u_char _17[0x6A]; + volatile u_char wireTest; + volatile u_char _18[14]; + + /* Statistics Block - 0x0300 */ + volatile u_char hostcpuLock; + volatile u_char lancpuLock; + volatile u_char resetTime[18]; + + volatile u_char numDatagramsTransmitted[4]; + volatile u_char numReTransmissions[4]; + volatile u_char numFramesDiscarded[4]; + volatile u_char numDatagramsReceived[4]; + volatile u_char numDuplicateReceivedFrames[4]; + volatile u_char numDatagramsDiscarded[4]; + + volatile u_short maxNumReTransmitDatagram; + volatile u_short maxNumReTransmitFrames; + volatile u_short maxNumConsecutiveDuplicateFrames; + /* misaligned here so we have to go to characters */ + + volatile u_char numBytesTransmitted[4]; + volatile u_char numBytesReceived[4]; + volatile u_char numCRCErrors[4]; + volatile u_char numLengthErrors[4]; + volatile u_char numAbortErrors[4]; + volatile u_char numTXUnderruns[4]; + volatile u_char numRXOverruns[4]; + volatile u_char numHoldOffs[4]; + volatile u_char numFramesTransmitted[4]; + volatile u_char numFramesReceived[4]; + volatile u_char numReceiveFramesLost[4]; + volatile u_char numRXBufferOverflows[4]; + volatile u_char numFramesDiscardedAddrMismatch[4]; + volatile u_char numFramesDiscardedSIDMismatch[4]; + volatile u_char numPollsTransmistted[4]; + volatile u_char numPollAcknowledges[4]; + volatile u_char numStatusTimeouts[4]; + volatile u_char numNACKReceived[4]; + + volatile u_char _19[0x86]; + + volatile u_char txBuffer[0x800]; + volatile u_char rxBuffer[0x800]; + + volatile u_char _20[0x800]; + volatile u_char _21[0x3fb]; + volatile u_char configStatus; + volatile u_char _22; + volatile u_char progIOCtrl; + volatile u_char shareMBase; + volatile u_char controlRegister; +}; + +struct arlan_conf_stru { + int spreadingCode; + int channelSet; + int channelNumber; + int scramblingDisable; + int txAttenuation; + int systemId; + int maxDatagramSize; + int maxFrameSize; + int maxRetries; + int receiveMode; + int priority; + int rootOrRepeater; + int SID; + int radioNodeId; + int registrationMode; + int registrationFill; + int localTalkAddress; + int codeFormat; + int numChannels; + int channel1; + int channel2; + int channel3; + int channel4; + int txClear; + int txRetries; + int txRouting; + int txScrambled; + int rxParameter; + int txTimeoutMs; + int txAckTimeoutMs; + int waitCardTimeout; + int waitTime; + int lParameter; + int _15; + int headerSize; + int async; + int retries; + int tx_delay_ms; + int waitReTransmitPacketMaxSize; + int ReTransmitPacketMaxSize; + int fastReTransCount; + int driverRetransmissions; + int registrationInterrupts; + int hardwareType; + int radioType; + int writeRadioType; + int writeEEPROM; + char siteName[17]; + int measure_rate; + int in_speed; + int out_speed; + int in_speed10; + int out_speed10; + int in_speed_max; + int out_speed_max; + int pre_Command_Wait; + int rx_tweak1; + int rx_tweak2; + int tx_queue_len; +}; + +struct arlan_conf_stru arlan_conf[MAX_ARLANS]; + +struct TxParam +{ + volatile short offset; + volatile short length; + volatile u_char dest[6]; + volatile unsigned char clear; + volatile unsigned char retries; + volatile unsigned char routing; + volatile unsigned char scrambled; +}; + +struct TxRingPoint { + struct TxParam txParam; + + +}; + +#define TX_RING_SIZE 2 +/* Information that need to be kept for each board. */ +struct arlan_private { + struct enet_statistics stats; + long open_time; /* Useless example local info. */ + struct arlan_shmem * card; + struct arlan_shmem * conf; + struct TxParam txParam; + int multicastLength; + char multicastList[ARLAN_MAX_MULTICAST_ADDRS][6]; + int promiscModeEnabled; + struct arlan_conf_stru * Conf; + int bad; + int reset; + long long lastReset; + struct timer_list timer; + struct timer_list tx_delay_timer; + struct timer_list tx_retry_timer; + struct timer_list rx_check_timer; + struct semaphore card_lock; + atomic_t card_users; + atomic_t delay_on; + atomic_t retr_on; + int registrationLostCount; + int reRegisterExp; + int nof_tx; + int nof_tx_ack; + int last_nof_tx; + int last_nof_tx_ack; + int irq_test_done; + int last_command_was_rx; + struct TxParam txRing[TX_RING_SIZE]; + char reTransmitBuff[0x800]; + volatile int txLast; + volatile int txNew; + volatile int txOffset; + volatile char ReTransmitRequested; + volatile long long tx_done_delayed; + volatile long long registrationLastSeen; + volatile char under_command; + volatile char under_toggle; + volatile long long tx_last_sent; + volatile long long tx_last_cleared; + volatile u_char under_tx; + volatile int retransmissions; + volatile int tx_chain_active; + volatile int timer_chain_active; + volatile int interrupt_ack_requested; + volatile int command_lock; + volatile int rx_command_needed; + volatile int tx_command_needed; + volatile int waiting_command_mask; + volatile int card_polling_interval; + volatile int last_command_buff_free_time; + volatile int numResets; + volatile int under_reset; + volatile int under_config; + volatile int rx_command_given; + volatile int tx_command_given; + volatile int interrupt_processing_active; + volatile long long last_tx_time; + volatile long long last_rx_time; + volatile long long last_rx_int_ack_time; + int in_bytes; + int out_bytes; + int in_time; + int out_time; + int in_time10; + int out_time10; + int in_bytes10; + int out_bytes10; +}; + + + +#define ARLAN_CLEAR 0x00 +#define ARLAN_RESET 0x01 +#define ARLAN_CHANNEL_ATTENTION 0x02 +#define ARLAN_INTERRUPT_ENABLE 0x04 +#define ARLAN_CLEAR_INTERRUPT 0x08 +#define ARLAN_POWER 0x40 +#define ARLAN_ACCESS 0x80 + +#define ARLAN_COM_CONF 0x01 +#define ARLAN_COM_RX_ENABLE 0x03 +#define ARLAN_COM_RX_ABORT 0x04 +#define ARLAN_COM_TX_ENABLE 0x05 +#define ARLAN_COM_TX_ABORT 0x06 +#define ARLAN_COM_NOP 0x07 +#define ARLAN_COM_STANDBY 0x08 +#define ARLAN_COM_ACTIVATE 0x09 +#define ARLAN_COM_GOTO_SLOW_POLL 0x0a +#define ARLAN_COM_INT 0x80 + + +#define TXLAST(dev) (((struct arlan_private *)dev->priv)->txRing[((struct arlan_private *)dev->priv)->txLast]) +#define TXHEAD(dev) (((struct arlan_private *)dev->priv)->txRing[0]) +#define TXTAIL(dev) (((struct arlan_private *)dev->priv)->txRing[1]) + +#define TXBuffStart(dev) \ + ((int)(((struct arlan_private *)dev->priv)->card)->txBuffer) - ((int)(((struct arlan_private *)dev->priv)->card) ) +#define TXBuffEnd(dev) \ + ((int)(((struct arlan_private *)dev->priv)->card)->rxBuffer) - ((int)(((struct arlan_private *)dev->priv)->card) + +#define READSHM(to,from,atype) {\ + atype tmp;\ + memcpy_fromio(&(tmp),&(from),sizeof(atype));\ + to = tmp;\ + } + +#define READSHMEM(from,atype)\ + atype from; \ + READSHM(from, arlan->from, atype); + +#define WRITESHM(to,from,atype) \ + { atype tmpSHM = from;\ + memcpy_toio(&(to),&tmpSHM,sizeof(atype));\ + } + +#define DEBUGSHM(levelSHM,stringSHM,stuff,atype) \ + { atype tmpSHM; \ + memcpy_fromio(&tmpSHM,&(stuff),sizeof(atype));\ + IFDEBUG(levelSHM) printk(stringSHM,tmpSHM);\ + } + +#define WRITESHMB(to, val) \ + writeb(val,&(to)) +#define READSHMB(to) \ + readb(&(to)) +#define WRITESHMS(to, val) \ + writew(val,&(to)) +#define READSHMS(to) \ + readw(&(to)) +#define WRITESHMI(to, val) \ + writel(val,&(to)) +#define READSHMI(to) \ + readl(&(to)) + + + + + +#define registrationBad(dev)\ + ( ( READSHMB(((struct arlan_private *)dev->priv)->card->registrationMode) > 0) && \ + ( READSHMB(((struct arlan_private *)dev->priv)->card->registrationStatus) == 0) ) + + +#define readControlRegister(dev)\ + READSHMB(((struct arlan_private *)dev->priv)->card->cntrlRegImage) + +#define writeControlRegister(dev, v){\ + WRITESHMB(((struct arlan_private *)dev->priv)->card->cntrlRegImage ,((v) &0xF) );\ + WRITESHMB(((struct arlan_private *)dev->priv)->card->controlRegister ,(v) );} + + +#define arlan_interrupt_lancpu(dev) {\ + int cr; \ + \ + priv->under_toggle++; \ + cr = readControlRegister(dev);\ + if (cr & ARLAN_CHANNEL_ATTENTION){ \ + writeControlRegister(dev, (cr & ~ARLAN_CHANNEL_ATTENTION));\ + }else \ + writeControlRegister(dev, (cr | ARLAN_CHANNEL_ATTENTION));\ + priv->under_toggle=0; \ +} + +#define clearChannelAttention(dev){ \ + writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_CHANNEL_ATTENTION);} +#define setHardwareReset(dev) {\ + writeControlRegister(dev,readControlRegister(dev) | ARLAN_RESET);} +#define clearHardwareReset(dev) {\ + writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_RESET);} +#define setInterruptEnable(dev){\ + writeControlRegister(dev,readControlRegister(dev) | ARLAN_INTERRUPT_ENABLE) ;} +#define clearInterruptEnable(dev){\ + writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_INTERRUPT_ENABLE) ;} +#define setClearInterrupt(dev){\ + writeControlRegister(dev,readControlRegister(dev) | ARLAN_CLEAR_INTERRUPT) ;} +#define clearClearInterrupt(dev){\ + writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_CLEAR_INTERRUPT);} +#define setPowerOff(dev){\ + writeControlRegister(dev,readControlRegister(dev) | (ARLAN_POWER && ARLAN_ACCESS));\ + writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_ACCESS);} +#define setPowerOn(dev){\ + writeControlRegister(dev,readControlRegister(dev) & ~(ARLAN_POWER)); } +#define arlan_lock_card_access(dev){\ + writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_ACCESS);} +#define arlan_unlock_card_access(dev){\ + writeControlRegister(dev,readControlRegister(dev) | ARLAN_ACCESS ); } + + + + +#define ARLAN_COMMAND_RX 0x00001 +#define ARLAN_COMMAND_NOOP 0x00002 +#define ARLAN_COMMAND_NOOPINT 0x00004 +#define ARLAN_COMMAND_TX 0x00008 +#define ARLAN_COMMAND_CONF 0x00010 +#define ARLAN_COMMAND_RESET 0x00020 +#define ARLAN_COMMAND_TX_ABORT 0x00040 +#define ARLAN_COMMAND_RX_ABORT 0x00080 +#define ARLAN_COMMAND_POWERDOWN 0x00100 +#define ARLAN_COMMAND_POWERUP 0x00200 +#define ARLAN_COMMAND_SLOW_POLL 0x00400 +#define ARLAN_COMMAND_ACTIVATE 0x00800 +#define ARLAN_COMMAND_INT_ACK 0x01000 +#define ARLAN_COMMAND_INT_ENABLE 0x02000 +#define ARLAN_COMMAND_WAIT_NOW 0x04000 +#define ARLAN_COMMAND_LONG_WAIT_NOW 0x08000 +#define ARLAN_COMMAND_STANDBY 0x10000 +#define ARLAN_COMMAND_INT_RACK 0x20000 +#define ARLAN_COMMAND_INT_RENABLE 0x40000 +#define ARLAN_COMMAND_CONF_WAIT 0x80000 +#define ARLAN_COMMAND_CLEAN_AND_CONF (ARLAN_COMMAND_TX_ABORT\ + | ARLAN_COMMAND_RX_ABORT\ + | ARLAN_COMMAND_CONF) +#define ARLAN_COMMAND_CLEAN_AND_RESET (ARLAN_COMMAND_TX_ABORT\ + | ARLAN_COMMAND_RX_ABORT\ + | ARLAN_COMMAND_RESET) + + + +#define ARLAN_DEBUG_CHAIN_LOCKS 0x00001 +#define ARLAN_DEBUG_RESET 0x00002 +#define ARLAN_DEBUG_TIMING 0x00004 +#define ARLAN_DEBUG_CARD_STATE 0x00008 +#define ARLAN_DEBUG_TX_CHAIN 0x00010 +#define ARLAN_DEBUG_MULTICAST 0x00020 +#define ARLAN_DEBUG_HEADER_DUMP 0x00040 +#define ARLAN_DEBUG_INTERRUPT 0x00080 +#define ARLAN_DEBUG_STARTUP 0x00100 +#define ARLAN_DEBUG_SHUTDOWN 0x00200 + \ No newline at end of file diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/bagetlance.c linux.pre11.3/drivers/net/bagetlance.c --- linux.vanilla/drivers/net/bagetlance.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/net/bagetlance.c Mon Jul 19 23:27:35 1999 @@ -0,0 +1,1363 @@ +/* $Id$ + * vmelance.c: Ethernet driver for VME Lance cards on Baget/MIPS + * This code stolen and adopted from linux/drivers/net/atarilance.c + * See that for author info + * + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + */ + +/* + * Driver code for Baget/Lance taken from atarilance.c, which also + * works well in case of Besta. Most significant changes made here + * related with 16BIT-only access to A24 space. + */ + +static char *version = "bagetlance.c: v1.1 11/10/98\n"; + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#define BAGET_LANCE_IRQ BAGET_IRQ_MASK(0xdf) + +/* + * Define following if you don't need 16BIT-only access to Lance memory + * (Normally BAGET needs it) + */ +#undef NORMAL_MEM_ACCESS + +/* Debug level: + * 0 = silent, print only serious errors + * 1 = normal, print error messages + * 2 = debug, print debug infos + * 3 = debug, print even more debug infos (packet data) + */ + +#define LANCE_DEBUG 1 + +#ifdef LANCE_DEBUG +static int lance_debug = LANCE_DEBUG; +#else +static int lance_debug = 1; +#endif +MODULE_PARM(lance_debug, "i"); + +/* Print debug messages on probing? */ +#undef LANCE_DEBUG_PROBE + +#define DPRINTK(n,a) \ + do { \ + if (lance_debug >= n) \ + printk a; \ + } while( 0 ) + +#ifdef LANCE_DEBUG_PROBE +# define PROBE_PRINT(a) printk a +#else +# define PROBE_PRINT(a) +#endif + +/* These define the number of Rx and Tx buffers as log2. (Only powers + * of two are valid) + * Much more rx buffers (32) are reserved than tx buffers (8), since receiving + * is more time critical then sending and packets may have to remain in the + * board's memory when main memory is low. + */ + +/* Baget Lance has 64K on-board memory, so it looks we can't increase + buffer quantity (40*1.5K is about 64K) */ + +#define TX_LOG_RING_SIZE 3 +#define RX_LOG_RING_SIZE 5 + +/* These are the derived values */ + +#define TX_RING_SIZE (1 << TX_LOG_RING_SIZE) +#define TX_RING_LEN_BITS (TX_LOG_RING_SIZE << 5) +#define TX_RING_MOD_MASK (TX_RING_SIZE - 1) + +#define RX_RING_SIZE (1 << RX_LOG_RING_SIZE) +#define RX_RING_LEN_BITS (RX_LOG_RING_SIZE << 5) +#define RX_RING_MOD_MASK (RX_RING_SIZE - 1) + +/* The LANCE Rx and Tx ring descriptors. */ +struct lance_rx_head { + volatile unsigned short base; /* Low word of base addr */ +#ifdef NORMAL_MEM_ACCESS + /* Following two fields are joined into one short to guarantee + 16BIT access to Baget lance registers */ + volatile unsigned char flag; + unsigned char base_hi; /* High word of base addr (unused) */ +#else +/* Following macros are used as replecements to 8BIT fields */ +#define GET_FLAG(h) (((h)->flag_base_hi >> 8) & 0xff) +#define SET_FLAG(h,f) (h)->flag_base_hi = ((h)->flag_base_hi & 0xff) | \ + (((unsigned)(f)) << 8) + volatile unsigned short flag_base_hi; +#endif + volatile short buf_length; /* This length is 2s complement! */ + volatile short msg_length; /* This length is "normal". */ +}; + + +struct lance_tx_head { + volatile unsigned short base; /* Low word of base addr */ +#ifdef NORMAL_MEM_ACCESS +/* See comments above about 8BIT-access Baget A24-space problems */ + volatile unsigned char flag; + unsigned char base_hi; /* High word of base addr (unused) */ +#else + volatile unsigned short flag_base_hi; +#endif + volatile short length; /* Length is 2s complement! */ + volatile short misc; +}; + +struct ringdesc { + volatile unsigned short adr_lo; /* Low 16 bits of address */ +#ifdef NORMAL_MEM_ACCESS +/* See comments above about 8BIT-access Bage A24-space problems */ + unsigned char len; /* Length bits */ + unsigned char adr_hi; /* High 8 bits of address (unused) */ +#else + volatile unsigned short len_adr_hi; +#endif +}; + +/* The LANCE initialization block, described in databook. */ +struct lance_init_block { + unsigned short mode; /* Pre-set mode */ + unsigned char hwaddr[6]; /* Physical ethernet address */ + unsigned filter[2]; /* Multicast filter (unused). */ + /* Receive and transmit ring base, along with length bits. */ + struct ringdesc rx_ring; + struct ringdesc tx_ring; +}; + +/* The whole layout of the Lance shared memory */ +struct lance_memory { + struct lance_init_block init; + struct lance_tx_head tx_head[TX_RING_SIZE]; + struct lance_rx_head rx_head[RX_RING_SIZE]; + char packet_area[0]; /* packet data follow after the + * init block and the ring + * descriptors and are located + * at runtime */ +}; + +/* RieblCard specifics: + * The original TOS driver for these cards reserves the area from offset + * 0xee70 to 0xeebb for storing configuration data. Of interest to us is the + * Ethernet address there, and the magic for verifying the data's validity. + * The reserved area isn't touch by packet buffers. Furthermore, offset 0xfffe + * is reserved for the interrupt vector number. + */ +#define RIEBL_RSVD_START 0xee70 +#define RIEBL_RSVD_END 0xeec0 +#define RIEBL_MAGIC 0x09051990 +#define RIEBL_MAGIC_ADDR ((unsigned long *)(((char *)MEM) + 0xee8a)) +#define RIEBL_HWADDR_ADDR ((unsigned char *)(((char *)MEM) + 0xee8e)) +#define RIEBL_IVEC_ADDR ((unsigned short *)(((char *)MEM) + 0xfffe)) + +/* This is a default address for the old RieblCards without a battery + * that have no ethernet address at boot time. 00:00:36:04 is the + * prefix for Riebl cards, the 00:00 at the end is arbitrary. + */ + +static unsigned char OldRieblDefHwaddr[6] = { + 0x00, 0x00, 0x36, 0x04, 0x00, 0x00 +}; + +/* I/O registers of the Lance chip */ + +struct lance_ioreg { +/* base+0x0 */ volatile unsigned short data; +/* base+0x2 */ volatile unsigned short addr; + unsigned char _dummy1[3]; +/* base+0x7 */ volatile unsigned char ivec; + unsigned char _dummy2[5]; +/* base+0xd */ volatile unsigned char eeprom; + unsigned char _dummy3; +/* base+0xf */ volatile unsigned char mem; +}; + +/* Types of boards this driver supports */ + +enum lance_type { + OLD_RIEBL, /* old Riebl card without battery */ + NEW_RIEBL, /* new Riebl card with battery */ + PAM_CARD /* PAM card with EEPROM */ +}; + +static char *lance_names[] = { + "Riebl-Card (without battery)", + "Riebl-Card (with battery)", + "PAM intern card" +}; + +/* The driver's private device structure */ + +struct lance_private { + enum lance_type cardtype; + struct lance_ioreg *iobase; + struct lance_memory *mem; + int cur_rx, cur_tx; /* The next free ring entry */ + int dirty_tx; /* Ring entries to be freed. */ + /* copy function */ + void *(*memcpy_f)( void *, const void *, size_t ); + struct net_device_stats stats; +/* These two must be ints for set_bit() */ + int tx_full; + int lock; +}; + +/* I/O register access macros */ + +#define MEM lp->mem +#define DREG IO->data +#define AREG IO->addr +#define REGA(a) ( AREG = (a), DREG ) + +/* Definitions for packet buffer access: */ +#define PKT_BUF_SZ 1544 +/* Get the address of a packet buffer corresponding to a given buffer head */ +#define PKTBUF_ADDR(head) (((unsigned char *)(MEM)) + (head)->base) + +/* Possible memory/IO addresses for probing */ + +struct lance_addr { + unsigned long memaddr; + unsigned long ioaddr; + int slow_flag; +} lance_addr_list[] = { + { BAGET_LANCE_MEM_BASE, BAGET_LANCE_IO_BASE, 1 } /* Baget Lance */ +}; + +#define N_LANCE_ADDR (sizeof(lance_addr_list)/sizeof(*lance_addr_list)) + + +#define LANCE_HI_BASE (0xff & (BAGET_LANCE_MEM_BASE >> 16)) + +/* Definitions for the Lance */ + +/* tx_head flags */ +#define TMD1_ENP 0x01 /* end of packet */ +#define TMD1_STP 0x02 /* start of packet */ +#define TMD1_DEF 0x04 /* deferred */ +#define TMD1_ONE 0x08 /* one retry needed */ +#define TMD1_MORE 0x10 /* more than one retry needed */ +#define TMD1_ERR 0x40 /* error summary */ +#define TMD1_OWN 0x80 /* ownership (set: chip owns) */ + +#define TMD1_OWN_CHIP TMD1_OWN +#define TMD1_OWN_HOST 0 + +/* tx_head misc field */ +#define TMD3_TDR 0x03FF /* Time Domain Reflectometry counter */ +#define TMD3_RTRY 0x0400 /* failed after 16 retries */ +#define TMD3_LCAR 0x0800 /* carrier lost */ +#define TMD3_LCOL 0x1000 /* late collision */ +#define TMD3_UFLO 0x4000 /* underflow (late memory) */ +#define TMD3_BUFF 0x8000 /* buffering error (no ENP) */ + +/* rx_head flags */ +#define RMD1_ENP 0x01 /* end of packet */ +#define RMD1_STP 0x02 /* start of packet */ +#define RMD1_BUFF 0x04 /* buffer error */ +#define RMD1_CRC 0x08 /* CRC error */ +#define RMD1_OFLO 0x10 /* overflow */ +#define RMD1_FRAM 0x20 /* framing error */ +#define RMD1_ERR 0x40 /* error summary */ +#define RMD1_OWN 0x80 /* ownership (set: ship owns) */ + +#define RMD1_OWN_CHIP RMD1_OWN +#define RMD1_OWN_HOST 0 + +/* register names */ +#define CSR0 0 /* mode/status */ +#define CSR1 1 /* init block addr (low) */ +#define CSR2 2 /* init block addr (high) */ +#define CSR3 3 /* misc */ +#define CSR8 8 /* address filter */ +#define CSR15 15 /* promiscuous mode */ + +/* CSR0 */ +/* (R=readable, W=writeable, S=set on write, C=clear on write) */ +#define CSR0_INIT 0x0001 /* initialize (RS) */ +#define CSR0_STRT 0x0002 /* start (RS) */ +#define CSR0_STOP 0x0004 /* stop (RS) */ +#define CSR0_TDMD 0x0008 /* transmit demand (RS) */ +#define CSR0_TXON 0x0010 /* transmitter on (R) */ +#define CSR0_RXON 0x0020 /* receiver on (R) */ +#define CSR0_INEA 0x0040 /* interrupt enable (RW) */ +#define CSR0_INTR 0x0080 /* interrupt active (R) */ +#define CSR0_IDON 0x0100 /* initialization done (RC) */ +#define CSR0_TINT 0x0200 /* transmitter interrupt (RC) */ +#define CSR0_RINT 0x0400 /* receiver interrupt (RC) */ +#define CSR0_MERR 0x0800 /* memory error (RC) */ +#define CSR0_MISS 0x1000 /* missed frame (RC) */ +#define CSR0_CERR 0x2000 /* carrier error (no heartbeat :-) (RC) */ +#define CSR0_BABL 0x4000 /* babble: tx-ed too many bits (RC) */ +#define CSR0_ERR 0x8000 /* error (RC) */ + +/* CSR3 */ +#define CSR3_BCON 0x0001 /* byte control */ +#define CSR3_ACON 0 // fixme: 0x0002 /* ALE control */ +#define CSR3_BSWP 0x0004 /* byte swap (1=big endian) */ + + + +/***************************** Prototypes *****************************/ + +static int addr_accessible( volatile void *regp, int wordflag, int + writeflag ); +static unsigned long lance_probe1( struct device *dev, struct lance_addr + *init_rec ); +static int lance_open( struct device *dev ); +static void lance_init_ring( struct device *dev ); +static int lance_start_xmit( struct sk_buff *skb, struct device *dev ); +static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp ); +static int lance_rx( struct device *dev ); +static int lance_close( struct device *dev ); +static struct net_device_stats *lance_get_stats( struct device *dev ); +static void set_multicast_list( struct device *dev ); +static int lance_set_mac_address( struct device *dev, void *addr ); + +/************************* End of Prototypes **************************/ + +/* Network traffic statistic (bytes) */ + +int lance_stat = 0; + +static void update_lance_stat (int len) { + lance_stat += len; +} + +/* + This function is used to access Baget/Lance memory to avoid + 8/32BIT access to VAC A24 space + ALL memcpy calls was chenged to this function to avoid dbe problems + Don't confuse with function name -- it stays from original code +*/ + +void *slow_memcpy( void *dst, const void *src, size_t len ) + +{ + unsigned long to = (unsigned long)dst; + unsigned long from = (unsigned long)src; + unsigned long to_end = to +len; + + /* Unaligned flags */ + + int odd_from = from & 1; + int odd_to = to & 1; + int odd_to_end = to_end & 1; + + /* Align for 16BIT-access first */ + + register unsigned short *from_a = (unsigned short*) (from & ~1); + register unsigned short *to_a = (unsigned short*) (to & ~1); + register unsigned short *to_end_a = (unsigned short*) (to_end & ~1); + + /* Caching values -- not in loop invariant */ + + register unsigned short from_v; + register unsigned short to_v; + + /* Invariant is: from_a and to_a are pointers before or exactly to + currently copying byte */ + + if (odd_to) { + /* First byte unaligned case */ + from_v = *from_a; + to_v = *to_a; + + to_v &= ~0xff; + to_v |= 0xff & (from_v >> (odd_from ? 0 : 8)); + *to_a++ = to_v; + + if (odd_from) from_a++; + } + if (odd_from == odd_to) { + /* Same parity */ + while (to_a + 7 < to_end_a) { + unsigned long dummy1, dummy2; + unsigned long reg1, reg2, reg3, reg4; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "lh\t%2,0(%1)\n\t" + "nop\n\t" + "lh\t%3,2(%1)\n\t" + "sh\t%2,0(%0)\n\t" + "lh\t%4,4(%1)\n\t" + "sh\t%3,2(%0)\n\t" + "lh\t%5,6(%1)\n\t" + "sh\t%4,4(%0)\n\t" + "lh\t%2,8(%1)\n\t" + "sh\t%5,6(%0)\n\t" + "lh\t%3,10(%1)\n\t" + "sh\t%2,8(%0)\n\t" + "lh\t%4,12(%1)\n\t" + "sh\t%3,10(%0)\n\t" + "lh\t%5,14(%1)\n\t" + "sh\t%4,12(%0)\n\t" + "nop\n\t" + "sh\t%5,14(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (dummy1), "=r" (dummy2), + "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) + :"0" (to_a), "1" (from_a) + :"memory"); + + to_a += 8; + from_a += 8; + + } + while (to_a < to_end_a) { + *to_a++ = *from_a++; + } + } else { + /* Different parity */ + from_v = *from_a; + while (to_a < to_end_a) { + unsigned short from_v_next; + from_v_next = *++from_a; + *to_a++ = ((from_v & 0xff)<<8) | ((from_v_next>>8) & 0xff); + from_v = from_v_next; + } + + } + if (odd_to_end) { + /* Last byte unaligned case */ + to_v = *to_a; + from_v = *from_a; + + to_v &= ~0xff00; + if (odd_from == odd_to) { + to_v |= from_v & 0xff00; + } else { + to_v |= (from_v<<8) & 0xff00; + } + + *to_a = to_v; + } + + update_lance_stat( len ); + + return( dst ); +} + + +__initfunc(int bagetlance_probe( struct device *dev )) + +{ int i; + static int found = 0; + + if (found) + /* Assume there's only one board possible... That seems true, since + * the Riebl/PAM board's address cannot be changed. */ + return( ENODEV ); + + for( i = 0; i < N_LANCE_ADDR; ++i ) { + if (lance_probe1( dev, &lance_addr_list[i] )) { + found = 1; + return( 0 ); + } + } + + return( ENODEV ); +} + + + +/* Derived from hwreg_present() in vme/config.c: */ + +__initfunc(static int addr_accessible( volatile void *regp, + int wordflag, + int writeflag )) +{ + /* We have a fine function to do it */ + extern int try_read(unsigned long, int); + return try_read((unsigned long)regp, sizeof(short)) != -1; +} + + + +/* Original atari driver uses it */ +#define IRQ_TYPE_PRIO SA_INTERRUPT +#define IRQ_SOURCE_TO_VECTOR(x) (x) + +__initfunc(static unsigned long lance_probe1( struct device *dev, + struct lance_addr *init_rec )) + +{ volatile unsigned short *memaddr = + (volatile unsigned short *)init_rec->memaddr; + volatile unsigned short *ioaddr = + (volatile unsigned short *)init_rec->ioaddr; + struct lance_private *lp; + struct lance_ioreg *IO; + int i; + static int did_version = 0; + unsigned short save1, save2; + + PROBE_PRINT(( "Probing for Lance card at mem %#lx io %#lx\n", + (long)memaddr, (long)ioaddr )); + + /* Test whether memory readable and writable */ + PROBE_PRINT(( "lance_probe1: testing memory to be accessible\n" )); + if (!addr_accessible( memaddr, 1, 1 )) goto probe_fail; + + if ((unsigned long)memaddr >= KSEG2) { + extern int kseg2_alloc_io (unsigned long addr, unsigned long size); + if (kseg2_alloc_io((unsigned long)memaddr, BAGET_LANCE_MEM_SIZE)) { + printk("bagetlance: unable map lance memory\n"); + goto probe_fail; + } + } + + /* Written values should come back... */ + PROBE_PRINT(( "lance_probe1: testing memory to be writable (1)\n" )); + save1 = *memaddr; + *memaddr = 0x0001; + if (*memaddr != 0x0001) goto probe_fail; + PROBE_PRINT(( "lance_probe1: testing memory to be writable (2)\n" )); + *memaddr = 0x0000; + if (*memaddr != 0x0000) goto probe_fail; + *memaddr = save1; + + /* First port should be readable and writable */ + PROBE_PRINT(( "lance_probe1: testing ioport to be accessible\n" )); + if (!addr_accessible( ioaddr, 1, 1 )) goto probe_fail; + + /* and written values should be readable */ + PROBE_PRINT(( "lance_probe1: testing ioport to be writeable\n" )); + save2 = ioaddr[1]; + ioaddr[1] = 0x0001; + if (ioaddr[1] != 0x0001) goto probe_fail; + + /* The CSR0_INIT bit should not be readable */ + PROBE_PRINT(( "lance_probe1: testing CSR0 register function (1)\n" )); + save1 = ioaddr[0]; + ioaddr[1] = CSR0; + ioaddr[0] = CSR0_INIT | CSR0_STOP; + if (ioaddr[0] != CSR0_STOP) { + ioaddr[0] = save1; + ioaddr[1] = save2; + goto probe_fail; + } + PROBE_PRINT(( "lance_probe1: testing CSR0 register function (2)\n" )); + ioaddr[0] = CSR0_STOP; + if (ioaddr[0] != CSR0_STOP) { + ioaddr[0] = save1; + ioaddr[1] = save2; + goto probe_fail; + } + + /* Now ok... */ + PROBE_PRINT(( "lance_probe1: Lance card detected\n" )); + goto probe_ok; + + probe_fail: + return( 0 ); + + probe_ok: + init_etherdev( dev, sizeof(struct lance_private) ); + if (!dev->priv) + dev->priv = kmalloc( sizeof(struct lance_private), GFP_KERNEL ); + lp = (struct lance_private *)dev->priv; + MEM = (struct lance_memory *)memaddr; + IO = lp->iobase = (struct lance_ioreg *)ioaddr; + dev->base_addr = (unsigned long)ioaddr; /* informational only */ + lp->memcpy_f = init_rec->slow_flag ? slow_memcpy : memcpy; + + REGA( CSR0 ) = CSR0_STOP; + + /* Now test for type: If the eeprom I/O port is readable, it is a + * PAM card */ + if (addr_accessible( &(IO->eeprom), 0, 0 )) { + /* Switch back to Ram */ + i = IO->mem; + lp->cardtype = PAM_CARD; + } +#ifdef NORMAL_MEM_ACCESS + else if (*RIEBL_MAGIC_ADDR == RIEBL_MAGIC) { +#else + else if (({ + unsigned short *a = (unsigned short*)RIEBL_MAGIC_ADDR; + (((int)a[0]) << 16) + ((int)a[1]) == RIEBL_MAGIC; + })) { +#endif + lp->cardtype = NEW_RIEBL; + } + else + lp->cardtype = OLD_RIEBL; + + if (lp->cardtype == PAM_CARD || + memaddr == (unsigned short *)0xffe00000) { + /* PAMs card and Riebl on ST use level 5 autovector */ + request_irq(BAGET_LANCE_IRQ, lance_interrupt, IRQ_TYPE_PRIO, + "PAM/Riebl-ST Ethernet", dev); + dev->irq = (unsigned short)BAGET_LANCE_IRQ; + } + else { + /* For VME-RieblCards, request a free VME int; + * (This must be unsigned long, since dev->irq is short and the + * IRQ_MACHSPEC bit would be cut off...) + */ + unsigned long irq = BAGET_LANCE_IRQ; + if (!irq) { + printk( "Lance: request for VME interrupt failed\n" ); + return( 0 ); + } + request_irq(irq, lance_interrupt, IRQ_TYPE_PRIO, + "Riebl-VME Ethernet", dev); + dev->irq = irq; + } + + printk("%s: %s at io %#lx, mem %#lx, irq %d%s, hwaddr ", + dev->name, lance_names[lp->cardtype], + (unsigned long)ioaddr, + (unsigned long)memaddr, + dev->irq, + init_rec->slow_flag ? " (slow memcpy)" : "" ); + + /* Get the ethernet address */ + switch( lp->cardtype ) { + case OLD_RIEBL: + /* No ethernet address! (Set some default address) */ + slow_memcpy( dev->dev_addr, OldRieblDefHwaddr, 6 ); + break; + case NEW_RIEBL: + lp->memcpy_f( dev->dev_addr, RIEBL_HWADDR_ADDR, 6 ); + break; + case PAM_CARD: + i = IO->eeprom; + for( i = 0; i < 6; ++i ) + dev->dev_addr[i] = + ((((unsigned short *)MEM)[i*2] & 0x0f) << 4) | + ((((unsigned short *)MEM)[i*2+1] & 0x0f)); + i = IO->mem; + break; + } + for( i = 0; i < 6; ++i ) + printk( "%02x%s", dev->dev_addr[i], (i < 5) ? ":" : "\n" ); + if (lp->cardtype == OLD_RIEBL) { + printk( "%s: Warning: This is a default ethernet address!\n", + dev->name ); + printk( " Use \"ifconfig hw ether ...\" to set the address.\n" ); + } + + MEM->init.mode = 0x0000; /* Disable Rx and Tx. */ + + { + unsigned char hwaddr[6]; + for( i = 0; i < 6; i++ ) + hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */ + slow_memcpy(MEM->init.hwaddr, hwaddr, sizeof(hwaddr)); + } + + MEM->init.filter[0] = 0x00000000; + MEM->init.filter[1] = 0x00000000; + MEM->init.rx_ring.adr_lo = offsetof( struct lance_memory, rx_head ); + +#ifdef NORMAL_MEM_ACCESS + MEM->init.rx_ring.adr_hi = LANCE_HI_BASE; + MEM->init.rx_ring.len = RX_RING_LEN_BITS; +#else + MEM->init.rx_ring.len_adr_hi = + ((unsigned)RX_RING_LEN_BITS << 8) | LANCE_HI_BASE; +#endif + + + MEM->init.tx_ring.adr_lo = offsetof( struct lance_memory, tx_head ); + +#ifdef NORMAL_MEM_ACCESS + MEM->init.tx_ring.adr_hi = LANCE_HI_BASE; + MEM->init.tx_ring.len = TX_RING_LEN_BITS; +#else + MEM->init.tx_ring.len_adr_hi = + ((unsigned)TX_RING_LEN_BITS<<8) | LANCE_HI_BASE; +#endif + + if (lp->cardtype == PAM_CARD) + IO->ivec = IRQ_SOURCE_TO_VECTOR(dev->irq); + else + *RIEBL_IVEC_ADDR = IRQ_SOURCE_TO_VECTOR(dev->irq); + + if (did_version++ == 0) + DPRINTK( 1, ( version )); + + /* The LANCE-specific entries in the device structure. */ + dev->open = &lance_open; + dev->hard_start_xmit = &lance_start_xmit; + dev->stop = &lance_close; + dev->get_stats = &lance_get_stats; + dev->set_multicast_list = &set_multicast_list; + dev->set_mac_address = &lance_set_mac_address; + dev->start = 0; + + memset( &lp->stats, 0, sizeof(lp->stats) ); + + return( 1 ); +} + + +static int lance_open( struct device *dev ) + +{ struct lance_private *lp = (struct lance_private *)dev->priv; + struct lance_ioreg *IO = lp->iobase; + int i; + + DPRINTK( 2, ( "%s: lance_open()\n", dev->name )); + + lance_init_ring(dev); + /* Re-initialize the LANCE, and start it when done. */ + + REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0); + REGA( CSR2 ) = 0; + REGA( CSR1 ) = 0; + REGA( CSR0 ) = CSR0_INIT; + /* From now on, AREG is kept to point to CSR0 */ + + i = 1000000; + while (--i > 0) + if (DREG & CSR0_IDON) + break; + if (i < 0 || (DREG & CSR0_ERR)) { + DPRINTK( 2, ( "lance_open(): opening %s failed, i=%d, csr0=%04x\n", + dev->name, i, DREG )); + DREG = CSR0_STOP; + return( -EIO ); + } + DREG = CSR0_IDON; + DREG = CSR0_STRT; + DREG = CSR0_INEA; + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG )); + MOD_INC_USE_COUNT; + + return( 0 ); +} + + +/* Initialize the LANCE Rx and Tx rings. */ + +static void lance_init_ring( struct device *dev ) + +{ struct lance_private *lp = (struct lance_private *)dev->priv; + int i; + unsigned offset; + + lp->lock = 0; + lp->tx_full = 0; + lp->cur_rx = lp->cur_tx = 0; + lp->dirty_tx = 0; + + offset = offsetof( struct lance_memory, packet_area ); + +/* If the packet buffer at offset 'o' would conflict with the reserved area + * of RieblCards, advance it */ +#define CHECK_OFFSET(o) \ + do { \ + if (lp->cardtype == OLD_RIEBL || lp->cardtype == NEW_RIEBL) { \ + if (((o) < RIEBL_RSVD_START) ? (o)+PKT_BUF_SZ > RIEBL_RSVD_START \ + : (o) < RIEBL_RSVD_END) \ + (o) = RIEBL_RSVD_END; \ + } \ + } while(0) + + for( i = 0; i < TX_RING_SIZE; i++ ) { + CHECK_OFFSET(offset); + MEM->tx_head[i].base = offset; +#ifdef NORMAL_MEM_ACCESS + MEM->tx_head[i].flag = TMD1_OWN_HOST; + MEM->tx_head[i].base_hi = LANCE_HI_BASE; +#else + MEM->tx_head[i].flag_base_hi = + (TMD1_OWN_HOST<<8) | LANCE_HI_BASE; +#endif + MEM->tx_head[i].length = 0; + MEM->tx_head[i].misc = 0; + offset += PKT_BUF_SZ; + } + + for( i = 0; i < RX_RING_SIZE; i++ ) { + CHECK_OFFSET(offset); + MEM->rx_head[i].base = offset; +#ifdef NORMAL_MEM_ACCESS + MEM->rx_head[i].flag = TMD1_OWN_CHIP; + MEM->rx_head[i].base_hi = LANCE_HI_BASE; +#else + MEM->rx_head[i].flag_base_hi = + (TMD1_OWN_CHIP<<8) | LANCE_HI_BASE; +#endif + MEM->rx_head[i].buf_length = -PKT_BUF_SZ; + MEM->rx_head[i].msg_length = 0; + offset += PKT_BUF_SZ; + } +} + + +static int lance_start_xmit( struct sk_buff *skb, struct device *dev ) + +{ struct lance_private *lp = (struct lance_private *)dev->priv; + struct lance_ioreg *IO = lp->iobase; + int entry, len; + struct lance_tx_head *head; + unsigned long flags; + + /* Transmitter timeout, serious problems. */ + if (dev->tbusy) { + int tickssofar = jiffies - dev->trans_start; + if (tickssofar < 20) + return( 1 ); + AREG = CSR0; + DPRINTK( 1, ( "%s: transmit timed out, status %04x, resetting.\n", + dev->name, DREG )); + DREG = CSR0_STOP; + /* + * Always set BSWP after a STOP as STOP puts it back into + * little endian mode. + */ + REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0); + lp->stats.tx_errors++; +#ifndef final_version + { int i; + DPRINTK( 2, ( "Ring data: dirty_tx %d cur_tx %d%s cur_rx %d\n", + lp->dirty_tx, lp->cur_tx, + lp->tx_full ? " (full)" : "", + lp->cur_rx )); + for( i = 0 ; i < RX_RING_SIZE; i++ ) + DPRINTK( 2, ( "rx #%d: base=%04x blen=%04x mlen=%04x\n", + i, MEM->rx_head[i].base, + -MEM->rx_head[i].buf_length, + MEM->rx_head[i].msg_length )); + for( i = 0 ; i < TX_RING_SIZE; i++ ) + DPRINTK( 2, ( "tx #%d: base=%04x len=%04x misc=%04x\n", + i, MEM->tx_head[i].base, + -MEM->tx_head[i].length, + MEM->tx_head[i].misc )); + } +#endif + lance_init_ring(dev); + REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT; + + dev->tbusy = 0; + dev->trans_start = jiffies; + + return( 0 ); + } + + DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n", + dev->name, DREG )); + + /* Block a timer-based transmit from overlapping. This could better be + done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ + if (test_and_set_bit( 0, (void*)&dev->tbusy ) != 0) { + DPRINTK( 0, ( "%s: Transmitter access conflict.\n", dev->name )); + return 1; + } + + if (test_and_set_bit( 0, (void*)&lp->lock ) != 0) { + DPRINTK( 0, ( "%s: tx queue lock!.\n", dev->name )); + /* don't clear dev->tbusy flag. */ + return 1; + } + + /* Fill in a Tx ring entry */ + if (lance_debug >= 3) { + u_char *p; + int i; + printk( "%s: TX pkt type 0x%04x from ", dev->name, + ((u_short *)skb->data)[6]); + for( p = &((u_char *)skb->data)[6], i = 0; i < 6; i++ ) + printk("%02x%s", *p++, i != 5 ? ":" : "" ); + printk(" to "); + for( p = (u_char *)skb->data, i = 0; i < 6; i++ ) + printk("%02x%s", *p++, i != 5 ? ":" : "" ); + printk(" data at 0x%08x len %d\n", (int)skb->data, + (int)skb->len ); + } + + /* We're not prepared for the int until the last flags are set/reset. And + * the int may happen already after setting the OWN_CHIP... */ + save_flags(flags); + cli(); + + /* Mask to ring buffer boundary. */ + entry = lp->cur_tx & TX_RING_MOD_MASK; + head = &(MEM->tx_head[entry]); + + /* Caution: the write order is important here, set the "ownership" bits + * last. + */ + + /* The old LANCE chips doesn't automatically pad buffers to min. size. */ + len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; + /* PAM-Card has a bug: Can only send packets with even number of bytes! */ + if (lp->cardtype == PAM_CARD && (len & 1)) + ++len; + + head->length = -len; + head->misc = 0; + lp->memcpy_f( PKTBUF_ADDR(head), (void *)skb->data, skb->len ); +#ifdef NORMAL_MEM_ACCESS + head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP; +#else + SET_FLAG(head,(TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP)); +#endif + dev_kfree_skb( skb ); + lp->cur_tx++; + lp->stats.tx_bytes += skb->len; + while( lp->cur_tx >= TX_RING_SIZE && lp->dirty_tx >= TX_RING_SIZE ) { + lp->cur_tx -= TX_RING_SIZE; + lp->dirty_tx -= TX_RING_SIZE; + } + + /* Trigger an immediate send poll. */ + DREG = CSR0_INEA | CSR0_TDMD; + dev->trans_start = jiffies; + + lp->lock = 0; +#ifdef NORMAL_MEM_ACCESS + if ((MEM->tx_head[(entry+1) & TX_RING_MOD_MASK].flag & TMD1_OWN) == +#else + if ((GET_FLAG(&MEM->tx_head[(entry+1) & TX_RING_MOD_MASK]) & TMD1_OWN) == +#endif + TMD1_OWN_HOST) + dev->tbusy = 0; + else + lp->tx_full = 1; + restore_flags(flags); + + return 0; +} + +/* The LANCE interrupt handler. */ + +static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp) +{ + struct device *dev = dev_id; + struct lance_private *lp; + struct lance_ioreg *IO; + int csr0, boguscnt = 10; + + if (dev == NULL) { + DPRINTK( 1, ( "lance_interrupt(): interrupt for unknown device.\n" )); + return; + } + + lp = (struct lance_private *)dev->priv; + IO = lp->iobase; + AREG = CSR0; + + if (dev->interrupt) { + DPRINTK( 1, ( "Re-entering CAUSE=%08x STATUS=%08x\n", + read_32bit_cp0_register(CP0_CAUSE), + read_32bit_cp0_register(CP0_STATUS) )); + panic("lance: interrupt handler reentered !"); + } + + dev->interrupt = 1; + + while( ((csr0 = DREG) & (CSR0_ERR | CSR0_TINT | CSR0_RINT)) && + --boguscnt >= 0) { + /* Acknowledge all of the current interrupt sources ASAP. */ + DREG = csr0 & ~(CSR0_INIT | CSR0_STRT | CSR0_STOP | + CSR0_TDMD | CSR0_INEA); + + DPRINTK( 2, ( "%s: interrupt csr0=%04x new csr=%04x.\n", + dev->name, csr0, DREG )); + + if (csr0 & CSR0_RINT) /* Rx interrupt */ + lance_rx( dev ); + + if (csr0 & CSR0_TINT) { /* Tx-done interrupt */ + int dirty_tx = lp->dirty_tx; + + while( dirty_tx < lp->cur_tx) { + int entry = dirty_tx & TX_RING_MOD_MASK; +#ifdef NORMAL_MEM_ACCESS + int status = MEM->tx_head[entry].flag; +#else + int status = GET_FLAG(&MEM->tx_head[entry]); +#endif + if (status & TMD1_OWN_CHIP) + break; /* It still hasn't been Txed */ + +#ifdef NORMAL_MEM_ACCESS + MEM->tx_head[entry].flag = 0; +#else + SET_FLAG(&MEM->tx_head[entry],0); +#endif + + if (status & TMD1_ERR) { + /* There was an major error, log it. */ + int err_status = MEM->tx_head[entry].misc; + lp->stats.tx_errors++; + if (err_status & TMD3_RTRY) lp->stats.tx_aborted_errors++; + if (err_status & TMD3_LCAR) lp->stats.tx_carrier_errors++; + if (err_status & TMD3_LCOL) lp->stats.tx_window_errors++; + if (err_status & TMD3_UFLO) { + /* Ackk! On FIFO errors the Tx unit is turned off! */ + lp->stats.tx_fifo_errors++; + /* Remove this verbosity later! */ + DPRINTK( 1, ( "%s: Tx FIFO error! Status %04x\n", + dev->name, csr0 )); + /* Restart the chip. */ + DREG = CSR0_STRT; + } + } else { + if (status & (TMD1_MORE | TMD1_ONE | TMD1_DEF)) + lp->stats.collisions++; + lp->stats.tx_packets++; + } + dirty_tx++; + } + +#ifndef final_version + if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) { + DPRINTK( 0, ( "out-of-sync dirty pointer," + " %d vs. %d, full=%d.\n", + dirty_tx, lp->cur_tx, lp->tx_full )); + dirty_tx += TX_RING_SIZE; + } +#endif + + if (lp->tx_full && dev->tbusy + && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { + /* The ring is no longer full, clear tbusy. */ + lp->tx_full = 0; + dev->tbusy = 0; + mark_bh( NET_BH ); + } + + lp->dirty_tx = dirty_tx; + } + + /* Log misc errors. */ + if (csr0 & CSR0_BABL) lp->stats.tx_errors++; /* Tx babble. */ + if (csr0 & CSR0_MISS) lp->stats.rx_errors++; /* Missed a Rx frame. */ + if (csr0 & CSR0_MERR) { + DPRINTK( 1, ( "%s: Bus master arbitration failure (?!?), " + "status %04x.\n", dev->name, csr0 )); + /* Restart the chip. */ + DREG = CSR0_STRT; + } + } + + /* Clear any other interrupt, and set interrupt enable. */ + DREG = CSR0_BABL | CSR0_CERR | CSR0_MISS | CSR0_MERR | + CSR0_IDON | CSR0_INEA; + + DPRINTK( 2, ( "%s: exiting interrupt, csr0=%#04x.\n", + dev->name, DREG )); + dev->interrupt = 0; + return; +} + + +static int lance_rx( struct device *dev ) + +{ struct lance_private *lp = (struct lance_private *)dev->priv; + int entry = lp->cur_rx & RX_RING_MOD_MASK; + int i; + +#ifdef NORMAL_MEM_ACCESS + DPRINTK( 2, ( "%s: rx int, flag=%04x\n", dev->name, + MEM->rx_head[entry].flag )); +#else + DPRINTK( 2, ( "%s: rx int, flag=%04x\n", dev->name, + GET_FLAG(&MEM->rx_head[entry]) )); +#endif + + /* If we own the next entry, it's a new packet. Send it up. */ +#ifdef NORMAL_MEM_ACCESS + while( (MEM->rx_head[entry].flag & RMD1_OWN) == RMD1_OWN_HOST ) { +#else + while( (GET_FLAG(&MEM->rx_head[entry]) & RMD1_OWN) == RMD1_OWN_HOST ) { +#endif + struct lance_rx_head *head = &(MEM->rx_head[entry]); +#ifdef NORMAL_MEM_ACCESS + int status = head->flag; +#else + int status = GET_FLAG(head); +#endif + + if (status != (RMD1_ENP|RMD1_STP)) { /* There was an error. */ + /* There is a tricky error noted by John Murphy, + to Russ Nelson: Even with full-sized + buffers it's possible for a jabber packet to use two + buffers, with only the last correctly noting the error. */ + if (status & RMD1_ENP) /* Only count a general error at the */ + lp->stats.rx_errors++; /* end of a packet.*/ + if (status & RMD1_FRAM) lp->stats.rx_frame_errors++; + if (status & RMD1_OFLO) lp->stats.rx_over_errors++; + if (status & RMD1_CRC) lp->stats.rx_crc_errors++; + if (status & RMD1_BUFF) lp->stats.rx_fifo_errors++; +#ifdef NORMAL_MEM_ACCESS + head->flag &= (RMD1_ENP|RMD1_STP); +#else + SET_FLAG(head,GET_FLAG(head) & (RMD1_ENP|RMD1_STP)); +#endif + } else { + /* Malloc up new buffer, compatible with net-3. */ + short pkt_len = head->msg_length & 0xfff; + struct sk_buff *skb; + + if (pkt_len < 60) { + printk( "%s: Runt packet!\n", dev->name ); + lp->stats.rx_errors++; + } + else { + skb = dev_alloc_skb( pkt_len+2 ); + if (skb == NULL) { + DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n", + dev->name )); + for( i = 0; i < RX_RING_SIZE; i++ ) +#ifdef NORMAL_MEM_ACCESS + if (MEM->rx_head[(entry+i) & RX_RING_MOD_MASK].flag & +#else + if (GET_FLAG(&MEM->rx_head[(entry+i) & \ + RX_RING_MOD_MASK]) & +#endif + RMD1_OWN_CHIP) + break; + + if (i > RX_RING_SIZE - 2) { + lp->stats.rx_dropped++; +#ifdef NORMAL_MEM_ACCESS + head->flag |= RMD1_OWN_CHIP; +#else + SET_FLAG(head,GET_FLAG(head) | RMD1_OWN_CHIP); +#endif + lp->cur_rx++; + } + break; + } + + if (lance_debug >= 3) { + u_char *data = PKTBUF_ADDR(head), *p; + printk( "%s: RX pkt type 0x%04x from ", dev->name, + ((u_short *)data)[6]); + for( p = &data[6], i = 0; i < 6; i++ ) + printk("%02x%s", *p++, i != 5 ? ":" : "" ); + printk(" to "); + for( p = data, i = 0; i < 6; i++ ) + printk("%02x%s", *p++, i != 5 ? ":" : "" ); + printk(" data %02x %02x %02x %02x %02x %02x %02x %02x " + "len %d\n", + data[15], data[16], data[17], data[18], + data[19], data[20], data[21], data[22], + pkt_len ); + } + + skb->dev = dev; + skb_reserve( skb, 2 ); /* 16 byte align */ + skb_put( skb, pkt_len ); /* Make room */ + lp->memcpy_f( skb->data, PKTBUF_ADDR(head), pkt_len ); + skb->protocol = eth_type_trans( skb, dev ); + netif_rx( skb ); + lp->stats.rx_packets++; + lp->stats.rx_bytes += skb->len; + } + } + +#ifdef NORMAL_MEM_ACCESS + head->flag |= RMD1_OWN_CHIP; +#else + SET_FLAG(head,GET_FLAG(head) | RMD1_OWN_CHIP); +#endif + entry = (++lp->cur_rx) & RX_RING_MOD_MASK; + } + lp->cur_rx &= RX_RING_MOD_MASK; + + /* From lance.c (Donald Becker): */ + /* We should check that at least two ring entries are free. If not, + we should free one and mark stats->rx_dropped++. */ + + return 0; +} + + +static int lance_close( struct device *dev ) + +{ struct lance_private *lp = (struct lance_private *)dev->priv; + struct lance_ioreg *IO = lp->iobase; + + dev->start = 0; + dev->tbusy = 1; + + AREG = CSR0; + + DPRINTK( 2, ( "%s: Shutting down ethercard, status was %2.2x.\n", + dev->name, DREG )); + + /* We stop the LANCE here -- it occasionally polls + memory if we don't. */ + DREG = CSR0_STOP; + + MOD_DEC_USE_COUNT; + return 0; +} + + +static struct net_device_stats *lance_get_stats( struct device *dev ) + +{ + struct lance_private *lp = (struct lance_private *)dev->priv; + return &lp->stats; +} + + +/* Set or clear the multicast filter for this adaptor. + num_addrs == -1 Promiscuous mode, receive all packets + num_addrs == 0 Normal mode, clear multicast list + num_addrs > 0 Multicast mode, receive normal and MC packets, and do + best-effort filtering. + */ + +static void set_multicast_list( struct device *dev ) + +{ struct lance_private *lp = (struct lance_private *)dev->priv; + struct lance_ioreg *IO = lp->iobase; + + if (!dev->start) + /* Only possible if board is already started */ + return; + + /* We take the simple way out and always enable promiscuous mode. */ + DREG = CSR0_STOP; /* Temporarily stop the lance. */ + + if (dev->flags & IFF_PROMISC) { + /* Log any net taps. */ + DPRINTK( 1, ( "%s: Promiscuous mode enabled.\n", dev->name )); + REGA( CSR15 ) = 0x8000; /* Set promiscuous mode */ + } else { + short multicast_table[4]; + int num_addrs = dev->mc_count; + int i; + /* We don't use the multicast table, but rely on upper-layer + * filtering. */ + memset( multicast_table, (num_addrs == 0) ? 0 : -1, + sizeof(multicast_table) ); + for( i = 0; i < 4; i++ ) + REGA( CSR8+i ) = multicast_table[i]; + REGA( CSR15 ) = 0; /* Unset promiscuous mode */ + } + + /* + * Always set BSWP after a STOP as STOP puts it back into + * little endian mode. + */ + REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0); + + /* Resume normal operation and reset AREG to CSR0 */ + REGA( CSR0 ) = CSR0_IDON | CSR0_INEA | CSR0_STRT; +} + + +/* This is needed for old RieblCards and possible for new RieblCards */ + +static int lance_set_mac_address( struct device *dev, void *addr ) + +{ struct lance_private *lp = (struct lance_private *)dev->priv; + struct sockaddr *saddr = addr; + int i; + + if (lp->cardtype != OLD_RIEBL && lp->cardtype != NEW_RIEBL) + return( -EOPNOTSUPP ); + + if (dev->start) { + /* Only possible while card isn't started */ + DPRINTK( 1, ( "%s: hwaddr can be set only while card isn't open.\n", + dev->name )); + return( -EIO ); + } + + slow_memcpy( dev->dev_addr, saddr->sa_data, dev->addr_len ); + + { + unsigned char hwaddr[6]; + for( i = 0; i < 6; i++ ) + hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */ + slow_memcpy(MEM->init.hwaddr, hwaddr, sizeof(hwaddr)); + } + + lp->memcpy_f( RIEBL_HWADDR_ADDR, dev->dev_addr, 6 ); + /* set also the magic for future sessions */ +#ifdef NORMAL_MEM_ACCESS + *RIEBL_MAGIC_ADDR = RIEBL_MAGIC; +#else + { + unsigned long magic = RIEBL_MAGIC; + slow_memcpy(RIEBL_MAGIC_ADDR, &magic, sizeof(*RIEBL_MAGIC_ADDR)); + } +#endif + return( 0 ); +} + + +#ifdef MODULE +static char devicename[9] = { 0, }; + +static struct device bagetlance_dev = +{ + devicename, /* filled in by register_netdev() */ + 0, 0, 0, 0, /* memory */ + 0, 0, /* base, irq */ + 0, 0, 0, NULL, bagetlance_probe, +}; + +int init_module(void) + +{ int err; + + if ((err = register_netdev( &bagetlance_dev ))) { + if (err == -EIO) { + printk( "No Vme Lance board found. Module not loaded.\n"); + } + return( err ); + } + return( 0 ); +} + +void cleanup_module(void) + +{ + unregister_netdev( &bagetlance_dev ); +} + +#endif /* MODULE */ + +/* + * Local variables: + * c-indent-level: 4 + * tab-width: 4 + * End: + */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/com90xx.c linux.pre11.3/drivers/net/com90xx.c --- linux.vanilla/drivers/net/com90xx.c Sun Nov 8 15:07:30 1998 +++ linux.pre11.3/drivers/net/com90xx.c Mon Jul 19 23:27:30 1999 @@ -399,7 +399,7 @@ */ airqmask = probe_irq_on(); AINTMASK(NORXflag); - udelay(1); + mdelay(1); AINTMASK(0); airq = probe_irq_off(airqmask); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/de4x5.c linux.pre11.3/drivers/net/de4x5.c --- linux.vanilla/drivers/net/de4x5.c Thu May 27 22:11:54 1999 +++ linux.pre11.3/drivers/net/de4x5.c Mon Jul 19 23:59:55 1999 @@ -5559,17 +5559,15 @@ switch(ioc->cmd) { case DE4X5_GET_HWADDR: /* Get the hardware address */ ioc->len = ETH_ALEN; - if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT; for (i=0; idev_addr[i]; } - copy_to_user(ioc->data, tmp.addr, ioc->len); + if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT; break; case DE4X5_SET_HWADDR: /* Set the hardware address */ if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (verify_area(VERIFY_READ, ioc->data, ETH_ALEN)) return -EFAULT; - copy_from_user(tmp.addr, ioc->data, ETH_ALEN); + if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN)) return -EFAULT; for (i=0; idev_addr[i] = tmp.addr[i]; } @@ -5612,9 +5610,8 @@ case DE4X5_GET_STATS: /* Get the driver statistics */ ioc->len = sizeof(lp->pktStats); - if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT; spin_lock_irqsave(&lp->lock, flags); - copy_to_user(ioc->data, &lp->pktStats, ioc->len); + if (copy_to_user(ioc->data, &lp->pktStats, ioc->len)) return -EFAULT; spin_unlock_irqrestore(&lp->lock, flags); break; @@ -5627,14 +5624,12 @@ case DE4X5_GET_OMR: /* Get the OMR Register contents */ tmp.addr[0] = inl(DE4X5_OMR); - if (verify_area(VERIFY_WRITE, ioc->data, 1)) return -EFAULT; - copy_to_user(ioc->data, tmp.addr, 1); + if (copy_to_user(ioc->data, tmp.addr, 1)) return -EFAULT; break; case DE4X5_SET_OMR: /* Set the OMR Register contents */ if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (verify_area(VERIFY_READ, ioc->data, 1)) return -EFAULT; - copy_from_user(tmp.addr, ioc->data, 1); + if (copy_from_user(tmp.addr, ioc->data, 1)) return -EFAULT; outl(tmp.addr[0], DE4X5_OMR); break; @@ -5649,8 +5644,7 @@ tmp.lval[6] = inl(DE4X5_STRR); j+=4; tmp.lval[7] = inl(DE4X5_SIGR); j+=4; ioc->len = j; - if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT; - copy_to_user(ioc->data, tmp.addr, ioc->len); + if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT; break; #define DE4X5_DUMP 0x0f /* Dump the DE4X5 Status */ @@ -5739,8 +5733,7 @@ tmp.addr[j++] = dev->tbusy; ioc->len = j; - if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT; - copy_to_user(ioc->data, tmp.addr, ioc->len); + if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT; break; */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/declance.c linux.pre11.3/drivers/net/declance.c --- linux.vanilla/drivers/net/declance.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/net/declance.c Mon Jul 19 23:27:35 1999 @@ -0,0 +1,1259 @@ +/* + * Lance ethernet driver for the MIPS processor based + * DECstation family + * + * + * adopted from sunlance.c by Richard van den Berg + * + * additional sources: + * - PMAD-AA TURBOchannel Ethernet Module Functional Specification, + * Revision 1.2 + * + * History: + * + * v0.001: The kernel accepts the code and it shows the hardware address. + * + * v0.002: Removed most sparc stuff, left only some module and dma stuff. + * + * v0.003: Enhanced base address calculation from proposals by + * Harald Koerfgen and Thomas Riemer. + * + * v0.004: lance-regs is pointing at the right addresses, added prom + * check. First start of address mapping and DMA. + * + * v0.005: started to play around with LANCE-DMA. This driver will not work + * for non IOASIC lances. HK + * + * v0.006: added pointer arrays to lance_private and setup routine for them + * in dec_lance_init. HK + * + * v0.007: Big shit. The LANCE seems to use a different DMA mechanism to access + * the init block. This looks like one (short) word at a time, but the smallest + * amount the IOASIC can transfer is a (long) word. So we have a 2-2 padding here. + * Changed lance_init_block accordingly. The 16-16 padding for the buffers + * seems to be correct. HK + * + * v0.008 - mods to make PMAX_LANCE work. 01/09/1999 triemer + */ + +#undef DEBUG_DRIVER + +static char *version = +"declance.c: v0.008 by Linux Mips DECstation task force\n"; + +static char *lancestr = "LANCE"; + +/* + * card types + */ +#define ASIC_LANCE 1 +#define PMAD_LANCE 2 +#define PMAX_LANCE 3 + +#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 + +#ifndef CONFIG_TC +unsigned long system_base = 0; +unsigned long dmaptr; +#endif +static int type; + +#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ +#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ + +#define LE_CSR0 0 +#define LE_CSR1 1 +#define LE_CSR2 2 +#define LE_CSR3 3 + +#define LE_MO_PROM 0x8000 /* Enable promiscuous mode */ + +#define LE_C0_ERR 0x8000 /* Error: set if BAB, SQE, MISS or ME is set */ +#define LE_C0_BABL 0x4000 /* BAB: Babble: tx timeout. */ +#define LE_C0_CERR 0x2000 /* SQE: Signal quality error */ +#define LE_C0_MISS 0x1000 /* MISS: Missed a packet */ +#define LE_C0_MERR 0x0800 /* ME: Memory error */ +#define LE_C0_RINT 0x0400 /* Received interrupt */ +#define LE_C0_TINT 0x0200 /* Transmitter Interrupt */ +#define LE_C0_IDON 0x0100 /* IFIN: Init finished. */ +#define LE_C0_INTR 0x0080 /* Interrupt or error */ +#define LE_C0_INEA 0x0040 /* Interrupt enable */ +#define LE_C0_RXON 0x0020 /* Receiver on */ +#define LE_C0_TXON 0x0010 /* Transmitter on */ +#define LE_C0_TDMD 0x0008 /* Transmitter demand */ +#define LE_C0_STOP 0x0004 /* Stop the card */ +#define LE_C0_STRT 0x0002 /* Start the card */ +#define LE_C0_INIT 0x0001 /* Init the card */ + +#define LE_C3_BSWP 0x4 /* SWAP */ +#define LE_C3_ACON 0x2 /* ALE Control */ +#define LE_C3_BCON 0x1 /* Byte control */ + +/* Receive message descriptor 1 */ +#define LE_R1_OWN 0x80 /* Who owns the entry */ +#define LE_R1_ERR 0x40 /* Error: if FRA, OFL, CRC or BUF is set */ +#define LE_R1_FRA 0x20 /* FRA: Frame error */ +#define LE_R1_OFL 0x10 /* OFL: Frame overflow */ +#define LE_R1_CRC 0x08 /* CRC error */ +#define LE_R1_BUF 0x04 /* BUF: Buffer error */ +#define LE_R1_SOP 0x02 /* Start of packet */ +#define LE_R1_EOP 0x01 /* End of packet */ +#define LE_R1_POK 0x03 /* Packet is complete: SOP + EOP */ + +#define LE_T1_OWN 0x80 /* Lance owns the packet */ +#define LE_T1_ERR 0x40 /* Error summary */ +#define LE_T1_EMORE 0x10 /* Error: more than one retry needed */ +#define LE_T1_EONE 0x08 /* Error: one retry needed */ +#define LE_T1_EDEF 0x04 /* Error: deferred */ +#define LE_T1_SOP 0x02 /* Start of packet */ +#define LE_T1_EOP 0x01 /* End of packet */ +#define LE_T1_POK 0x03 /* Packet is complete: SOP + EOP */ + +#define LE_T3_BUF 0x8000 /* Buffer error */ +#define LE_T3_UFL 0x4000 /* Error underflow */ +#define LE_T3_LCOL 0x1000 /* Error late collision */ +#define LE_T3_CLOS 0x0800 /* Error carrier loss */ +#define LE_T3_RTY 0x0400 /* Error retry */ +#define LE_T3_TDR 0x03ff /* Time Domain Reflectometry counter */ + +/* Define: 2^4 Tx buffers and 2^4 Rx buffers */ + +#ifndef LANCE_LOG_TX_BUFFERS +#define LANCE_LOG_TX_BUFFERS 4 +#define LANCE_LOG_RX_BUFFERS 4 +#endif + +#define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS)) +#define TX_RING_MOD_MASK (TX_RING_SIZE - 1) + +#define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS)) +#define RX_RING_MOD_MASK (RX_RING_SIZE - 1) + +#define PKT_BUF_SZ 1536 +#define RX_BUFF_SIZE PKT_BUF_SZ +#define TX_BUFF_SIZE PKT_BUF_SZ + +#undef TEST_HITS +#define DEBUG_DRIVER 1 + +#define ZERO 0 + +/* The DS2000/3000 have a linear 64 KB buffer. + + * The PMAD-AA has 128 kb buffer on-board. + * + * The IOASIC LANCE devices use a shared memory region. This region as seen + * from the CPU is (max) 128 KB long and has to be on an 128 KB boundary. + * The LANCE sees this as a 64 KB long continuous memory region. + * + * The LANCE's DMA address is used as an index in this buffer and DMA takes + * place in bursts of eight 16-Bit words which are packed into four 32-Bit words + * by the IOASIC. This leads to a strange padding: 16 bytes of valid data followed + * by a 16 byte gap :-(. + */ + +struct lance_rx_desc { + unsigned short rmd0; /* low address of packet */ + short gap0; + unsigned char rmd1_hadr; /* high address of packet */ + unsigned char rmd1_bits; /* descriptor bits */ + short gap1; + short length; /* This length is 2s complement (negative)! + * Buffer length + */ + short gap2; + unsigned short mblength; /* This is the actual number of bytes received */ + short gap3; +}; + +struct lance_tx_desc { + unsigned short tmd0; /* low address of packet */ + short gap0; + unsigned char tmd1_hadr; /* high address of packet */ + unsigned char tmd1_bits; /* descriptor bits */ + short gap1; + short length; /* Length is 2s complement (negative)! */ + short gap2; + unsigned short misc; + short gap3; +}; + + +/* First part of the LANCE initialization block, described in databook. */ +struct lance_init_block { + unsigned short mode; /* Pre-set mode (reg. 15) */ + short gap0; + + unsigned char phys_addr[12]; /* Physical ethernet address + * only 0, 1, 4, 5, 8, 9 are valid + * 2, 3, 6, 7, 10, 11 are gaps + */ + unsigned short filter[8]; /* Multicast filter. + * only 0, 2, 4, 6 are valid + * 1, 3, 5, 7 are gaps + */ + + /* Receive and transmit ring base, along with extra bits. */ + unsigned short rx_ptr; /* receive descriptor addr */ + short gap1; + unsigned short rx_len; /* receive len and high addr */ + short gap2; + unsigned short tx_ptr; /* transmit descriptor addr */ + short gap3; + unsigned short tx_len; /* transmit len and high addr */ + short gap4; + char gap5[16]; + + /* The buffer descriptors */ + struct lance_rx_desc brx_ring[RX_RING_SIZE]; + struct lance_tx_desc btx_ring[TX_RING_SIZE]; +}; + +#define BUF_OFFSET_CPU sizeof(struct lance_init_block) +#define BUF_OFFSET_LNC (sizeof(struct lance_init_block)>>1) + +#define libdesc_offset(rt, elem) \ +((__u32)(((unsigned long)(&(((struct lance_init_block *)0)->rt[elem]))))) + +/* + * This works *only* for the ring descriptors + */ +#define LANCE_ADDR(x) (PHYSADDR(x) >> 1) + +struct lance_private { + char *name; + volatile struct lance_regs *ll; + volatile struct lance_init_block *init_block; + volatile unsigned long *dma_ptr_reg; + + int rx_new, tx_new; + int rx_old, tx_old; + + struct net_device_stats stats; + + unsigned short busmaster_regval; + + struct device *dev; /* Backpointer */ + struct lance_private *next_module; + + /* Pointers to the ring buffers as seen from the CPU */ + char *rx_buf_ptr_cpu[RX_RING_SIZE]; + char *tx_buf_ptr_cpu[TX_RING_SIZE]; + + /* Pointers to the ring buffers as seen from the LANCE */ + char *rx_buf_ptr_lnc[RX_RING_SIZE]; + char *tx_buf_ptr_lnc[TX_RING_SIZE]; +}; + +#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\ + lp->tx_old+TX_RING_MOD_MASK-lp->tx_new:\ + lp->tx_old - lp->tx_new-1) + +/* The lance control ports are at an absolute address, machine and tc-slot + * dependant. + * DECstations do only 32-bit access and the LANCE uses 16 bit addresses, + * so we have to give the structure an extra member making rap pointing + * at the right address + */ +struct lance_regs { + volatile unsigned short rdp; /* register data port */ + unsigned short pad; + volatile unsigned short rap; /* register address port */ +}; + +int dec_lance_debug = 2; + +/* + #ifdef MODULE + static struct lance_private *root_lance_dev = NULL; + #endif + */ + +static inline void writereg(volatile unsigned short *regptr, short value) +{ + *regptr = value; +} + +/* Load the CSR registers */ +static void load_csrs(struct lance_private *lp) +{ + volatile struct lance_regs *ll = lp->ll; + int leptr; + + /* The address space as seen from the LANCE + * begins at address 0. HK + */ + leptr = 0; + + writereg(&ll->rap, LE_CSR1); + writereg(&ll->rdp, (leptr & 0xFFFF)); + writereg(&ll->rap, LE_CSR2); + writereg(&ll->rdp, leptr >> 16); + writereg(&ll->rap, LE_CSR3); + writereg(&ll->rdp, lp->busmaster_regval); + + /* Point back to csr0 */ + writereg(&ll->rap, LE_CSR0); +} + +/* + * Our specialized copy routines + * + */ +void cp_to_buf(void *to, const void *from, __kernel_size_t len) +{ + unsigned short *tp, *fp, clen; + unsigned char *rtp, *rfp; + + if (type == PMAX_LANCE) { + clen = len >> 1; + tp = (unsigned short *) to; + fp = (unsigned short *) from; + + while (clen--) { + *tp++ = *fp++; + tp++; + } + + clen = len & 1; + rtp = (unsigned char *) tp; + rfp = (unsigned char *) fp; + while (clen--) { + *rtp++ = *rfp++; + } + } else { + /* + * copy 16 Byte chunks + */ + clen = len >> 4; + tp = (unsigned short *) to; + fp = (unsigned short *) from; + while (clen--) { + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + tp += 8; + } + + /* + * do the rest, if any. + */ + clen = len & 15; + rtp = (unsigned char *) tp; + rfp = (unsigned char *) fp; + while (clen--) { + *rtp++ = *rfp++; + } + } + +} + +void cp_from_buf(void *to, unsigned char *from, int len) +{ + unsigned short *tp, *fp, clen; + unsigned char *rtp, *rfp; + + if (type == PMAX_LANCE) { + clen = len >> 1; + tp = (unsigned short *) to; + fp = (unsigned short *) from; + while (clen--) { + *tp++ = *fp++; + fp++; + } + + clen = len & 1; + + rtp = (unsigned char *) tp; + rfp = (unsigned char *) fp; + + while (clen--) { + *rtp++ = *rfp++; + } + } else { + + /* + * copy 16 Byte chunks + */ + clen = len >> 4; + tp = (unsigned short *) to; + fp = (unsigned short *) from; + while (clen--) { + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + *tp++ = *fp++; + fp += 8; + } + + /* + * do the rest, if any. + */ + clen = len & 15; + rtp = (unsigned char *) tp; + rfp = (unsigned char *) fp; + while (clen--) { + *rtp++ = *rfp++; + } + + + } + +} + +/* Setup the Lance Rx and Tx rings */ +/* Sets dev->tbusy */ +static void lance_init_ring(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_init_block *ib; + int leptr; + int i; + + ib = (struct lance_init_block *) (dev->mem_start); + + /* Lock out other processes while setting up hardware */ + dev->tbusy = 1; + lp->rx_new = lp->tx_new = 0; + lp->rx_old = lp->tx_old = 0; + + ib->mode = 0; + + /* Copy the ethernet address to the lance init block. + * XXX bit 0 of the physical address registers has to be zero + */ + ib->phys_addr[0] = dev->dev_addr[0]; + ib->phys_addr[1] = dev->dev_addr[1]; + ib->phys_addr[4] = dev->dev_addr[2]; + ib->phys_addr[5] = dev->dev_addr[3]; + ib->phys_addr[8] = dev->dev_addr[4]; + ib->phys_addr[9] = dev->dev_addr[5]; + /* Setup the initialization block */ + + /* Setup rx descriptor pointer */ + leptr = LANCE_ADDR(libdesc_offset(brx_ring, 0)); + ib->rx_len = (LANCE_LOG_RX_BUFFERS << 13) | (leptr >> 16); + ib->rx_ptr = leptr; + if (ZERO) + printk("RX ptr: %8.8x(%8.8x)\n", leptr, libdesc_offset(brx_ring, 0)); + + /* Setup tx descriptor pointer */ + leptr = LANCE_ADDR(libdesc_offset(btx_ring, 0)); + ib->tx_len = (LANCE_LOG_TX_BUFFERS << 13) | (leptr >> 16); + ib->tx_ptr = leptr; + if (ZERO) + printk("TX ptr: %8.8x(%8.8x)\n", leptr, libdesc_offset(btx_ring, 0)); + + /* Clear the multicast filter */ + ib->filter[0] = 0; + ib->filter[2] = 0; + ib->filter[4] = 0; + ib->filter[6] = 0; + if (ZERO) + printk("TX rings:\n"); + + /* Setup the Tx ring entries */ + for (i = 0; i < TX_RING_SIZE; i++) { + leptr = (int) lp->tx_buf_ptr_lnc[i]; + ib->btx_ring[i].tmd0 = leptr; + ib->btx_ring[i].tmd1_hadr = leptr >> 16; + ib->btx_ring[i].tmd1_bits = 0; + ib->btx_ring[i].length = 0xf000; /* The ones required by tmd2 */ + ib->btx_ring[i].misc = 0; + if (i < 3 && ZERO) + printk("%d: 0x%8.8x(0x%8.8x)\n", i, leptr, (int) lp->tx_buf_ptr_cpu[i]); + } + + /* Setup the Rx ring entries */ + if (ZERO) + printk("RX rings:\n"); + for (i = 0; i < RX_RING_SIZE; i++) { + leptr = (int) lp->rx_buf_ptr_lnc[i]; + ib->brx_ring[i].rmd0 = leptr; + ib->brx_ring[i].rmd1_hadr = leptr >> 16; + ib->brx_ring[i].rmd1_bits = LE_R1_OWN; + ib->brx_ring[i].length = -RX_BUFF_SIZE | 0xf000; + ib->brx_ring[i].mblength = 0; + if (i < 3 && ZERO) + printk("%d: 0x%8.8x(0x%8.8x)\n", i, leptr, (int) lp->rx_buf_ptr_cpu[i]); + } +} + +static int init_restart_lance(struct lance_private *lp) +{ + volatile struct lance_regs *ll = lp->ll; + int i; + + writereg(&ll->rap, LE_CSR0); + writereg(&ll->rdp, LE_C0_INIT); + + /* Wait for the lance to complete initialization */ + for (i = 0; (i < 100) && !(ll->rdp & LE_C0_IDON); i++) { + udelay(10); + } + if ((i == 100) || (ll->rdp & LE_C0_ERR)) { + printk("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, ll->rdp); + return -1; + } + if ((ll->rdp & LE_C0_ERR)) { + printk("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, ll->rdp); + return -1; + } + writereg(&ll->rdp, LE_C0_IDON); + writereg(&ll->rdp, LE_C0_STRT); + writereg(&ll->rdp, LE_C0_INEA); + + return 0; +} + +static int lance_rx(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_init_block *ib; + volatile struct lance_rx_desc *rd = 0; + unsigned char bits; + int len = 0; + struct sk_buff *skb = 0; + ib = (struct lance_init_block *) (dev->mem_start); + +#ifdef TEST_HITS + int i; + + printk("["); + for (i = 0; i < RX_RING_SIZE; i++) { + if (i == lp->rx_new) + printk("%s", + ib->brx_ring[i].rmd1_bits & LE_R1_OWN ? "_" : "X"); + else + printk("%s", + ib->brx_ring[i].rmd1_bits & LE_R1_OWN ? "." : "1"); + } + printk("]"); +#endif + + for (rd = &ib->brx_ring[lp->rx_new]; + !((bits = rd->rmd1_bits) & LE_R1_OWN); + rd = &ib->brx_ring[lp->rx_new]) { + + /* We got an incomplete frame? */ + if ((bits & LE_R1_POK) != LE_R1_POK) { + lp->stats.rx_over_errors++; + lp->stats.rx_errors++; + } else if (bits & LE_R1_ERR) { + /* Count only the end frame as a rx error, + * not the beginning + */ + if (bits & LE_R1_BUF) + lp->stats.rx_fifo_errors++; + if (bits & LE_R1_CRC) + lp->stats.rx_crc_errors++; + if (bits & LE_R1_OFL) + lp->stats.rx_over_errors++; + if (bits & LE_R1_FRA) + lp->stats.rx_frame_errors++; + if (bits & LE_R1_EOP) + lp->stats.rx_errors++; + } else { + len = (rd->mblength & 0xfff) - 4; + skb = dev_alloc_skb(len + 2); + + if (skb == 0) { + printk("%s: Memory squeeze, deferring packet.\n", + dev->name); + lp->stats.rx_dropped++; + rd->mblength = 0; + rd->rmd1_bits = LE_R1_OWN; + lp->rx_new = (lp->rx_new + 1) & RX_RING_MOD_MASK; + return 0; + } + lp->stats.rx_bytes += len; + + skb->dev = dev; + skb_reserve(skb, 2); /* 16 byte align */ + skb_put(skb, len); /* make room */ + cp_from_buf(skb->data, + (char *) lp->rx_buf_ptr_cpu[lp->rx_new], + len); + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + lp->stats.rx_packets++; + } + + /* Return the packet to the pool */ + rd->mblength = 0; + rd->length = -RX_BUFF_SIZE | 0xf000; + rd->rmd1_bits = LE_R1_OWN; + lp->rx_new = (lp->rx_new + 1) & RX_RING_MOD_MASK; + } + return 0; +} + +static int lance_tx(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_init_block *ib; + volatile struct lance_regs *ll = lp->ll; + volatile struct lance_tx_desc *td; + int i, j; + int status; + ib = (struct lance_init_block *) (dev->mem_start); + j = lp->tx_old; + + for (i = j; i != lp->tx_new; i = j) { + td = &ib->btx_ring[i]; + /* If we hit a packet not owned by us, stop */ + if (td->tmd1_bits & LE_T1_OWN) + break; + + if (td->tmd1_bits & LE_T1_ERR) { + status = td->misc; + + lp->stats.tx_errors++; + if (status & LE_T3_RTY) + lp->stats.tx_aborted_errors++; + if (status & LE_T3_LCOL) + lp->stats.tx_window_errors++; + + if (status & LE_T3_CLOS) { + lp->stats.tx_carrier_errors++; + printk("%s: Carrier Lost", dev->name); + /* Stop the lance */ + writereg(&ll->rap, LE_CSR0); + writereg(&ll->rdp, LE_C0_STOP); + lance_init_ring(dev); + load_csrs(lp); + init_restart_lance(lp); + return 0; + } + /* Buffer errors and underflows turn off the + * transmitter, restart the adapter. + */ + if (status & (LE_T3_BUF | LE_T3_UFL)) { + lp->stats.tx_fifo_errors++; + + printk("%s: Tx: ERR_BUF|ERR_UFL, restarting\n", + dev->name); + /* Stop the lance */ + writereg(&ll->rap, LE_CSR0); + writereg(&ll->rdp, LE_C0_STOP); + lance_init_ring(dev); + load_csrs(lp); + init_restart_lance(lp); + return 0; + } + } else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) { + /* + * So we don't count the packet more than once. + */ + td->tmd1_bits &= ~(LE_T1_POK); + + /* One collision before packet was sent. */ + if (td->tmd1_bits & LE_T1_EONE) + lp->stats.collisions++; + + /* More than one collision, be optimistic. */ + if (td->tmd1_bits & LE_T1_EMORE) + lp->stats.collisions += 2; + + lp->stats.tx_packets++; + } + j = (j + 1) & TX_RING_MOD_MASK; + } + lp->tx_old = j; + return 0; +} + +static void lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs) +{ + struct device *dev = (struct device *) dev_id; + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_regs *ll = lp->ll; + int csr0; + + if (dev->interrupt) + printk("%s: again\n", dev->name); + + dev->interrupt = 1; + + writereg(&ll->rap, LE_CSR0); + csr0 = ll->rdp; + + /* Acknowledge all the interrupt sources ASAP */ + writereg(&ll->rdp, csr0 & (LE_C0_INTR | LE_C0_TINT | LE_C0_RINT)); + + if ((csr0 & LE_C0_ERR)) { + /* Clear the error condition */ + writereg(&ll->rdp, LE_C0_BABL | LE_C0_ERR | LE_C0_MISS | + LE_C0_CERR | LE_C0_MERR); + } + if (csr0 & LE_C0_RINT) + lance_rx(dev); + + if (csr0 & LE_C0_TINT) + lance_tx(dev); + + if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) { + dev->tbusy = 0; + mark_bh(NET_BH); + } + if (csr0 & LE_C0_BABL) + lp->stats.tx_errors++; + + if (csr0 & LE_C0_MISS) + lp->stats.rx_errors++; + + if (csr0 & LE_C0_MERR) { + volatile unsigned long int_stat = *(unsigned long *) (system_base + IOCTL + SIR); + + printk("%s: Memory error, status %04x", dev->name, csr0); + + if (int_stat & LANCE_DMA_MEMRDERR) { + printk("%s: DMA error\n", dev->name); + int_stat |= LANCE_DMA_MEMRDERR; + /* + * re-enable LANCE DMA + */ + *(unsigned long *) (system_base + IOCTL + SSR) |= (1 << 16); + } + writereg(&ll->rdp, LE_C0_STOP); + + lance_init_ring(dev); + load_csrs(lp); + init_restart_lance(lp); + dev->tbusy = 0; + } + writereg(&ll->rdp, LE_C0_INEA); + writereg(&ll->rdp, LE_C0_INEA); + dev->interrupt = 0; +} + +struct device *last_dev = 0; + +static int lance_open(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_regs *ll = lp->ll; + int status = 0; + + last_dev = dev; + + /* Associate IRQ with lance_interrupt */ + if (request_irq(dev->irq, &lance_interrupt, 0, lp->name, dev)) { + printk("Lance: Can't get irq %d\n", dev->irq); + return -EAGAIN; + } + /* Stop the Lance */ + writereg(&ll->rap, LE_CSR0); + writereg(&ll->rdp, LE_C0_STOP); + + lance_init_ring(dev); + load_csrs(lp); + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + status = init_restart_lance(lp); + + /* + * if (!status) + * MOD_INC_USE_COUNT; + */ + + return status; +} + +static int lance_close(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_regs *ll = lp->ll; + + dev->start = 0; + dev->tbusy = 1; + + /* Stop the card */ + writereg(&ll->rap, LE_CSR0); + writereg(&ll->rdp, LE_C0_STOP); + + free_irq(dev->irq, (void *) dev); + /* + MOD_DEC_USE_COUNT; + */ + return 0; +} + +static inline int lance_reset(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_regs *ll = lp->ll; + int status; + + /* Stop the lance */ + writereg(&ll->rap, LE_CSR0); + writereg(&ll->rdp, LE_C0_STOP); + + lance_init_ring(dev); + load_csrs(lp); + dev->trans_start = jiffies; + dev->interrupt = 0; + dev->start = 1; + dev->tbusy = 0; + status = init_restart_lance(lp); +#ifdef DEBUG_DRIVER + printk("Lance restart=%d\n", status); +#endif + return status; +} + +static int lance_start_xmit(struct sk_buff *skb, struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_regs *ll = lp->ll; + volatile struct lance_init_block *ib; + unsigned long flags; + int entry, skblen, len; + int status = 0; + static int outs; + ib = (struct lance_init_block *) (dev->mem_start); + + /* Transmitter timeout, serious problems */ + if (dev->tbusy) { + int tickssofar = jiffies - dev->trans_start; + + if (tickssofar < 100) { + status = -1; + } else { + printk("%s: transmit timed out, status %04x, reset\n", + dev->name, ll->rdp); + lance_reset(dev); + } + return status; + } + /* Block a timer-based transmit from overlapping. */ + if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) { + printk("Transmitter access conflict.\n"); + return -1; + } + skblen = skb->len; + save_and_cli(flags); + if (!TX_BUFFS_AVAIL) { + restore_flags(flags); + return -1; + } + len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen; + + lp->stats.tx_bytes += len; + + entry = lp->tx_new & TX_RING_MOD_MASK; + ib->btx_ring[entry].length = (-len); + ib->btx_ring[entry].misc = 0; + + cp_to_buf((char *) lp->tx_buf_ptr_cpu[entry], skb->data, skblen); + + /* Clear the slack of the packet, do I need this? */ + /* For a firewall its a good idea - AC */ +/* + if (len != skblen) + memset ((char *) &ib->tx_buf [entry][skblen], 0, (len - skblen) << 1); + */ + + /* Now, give the packet to the lance */ + ib->btx_ring[entry].tmd1_bits = (LE_T1_POK | LE_T1_OWN); + lp->tx_new = (lp->tx_new + 1) & TX_RING_MOD_MASK; + + outs++; + /* Kick the lance: transmit now */ + writereg(&ll->rdp, LE_C0_INEA | LE_C0_TDMD); + dev->trans_start = jiffies; + dev_kfree_skb(skb); + + if (TX_BUFFS_AVAIL) + dev->tbusy = 0; + + restore_flags(flags); + return status; +} + +static struct net_device_stats *lance_get_stats(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + + return &lp->stats; +} + +static void lance_load_multicast(struct device *dev) +{ + volatile struct lance_init_block *ib = (struct lance_init_block *) (dev->mem_start); + volatile u16 *mcast_table = (u16 *) & ib->filter; + struct dev_mc_list *dmi = dev->mc_list; + char *addrs; + int i, j, bit, byte; + u32 crc, poly = CRC_POLYNOMIAL_BE; + + /* set all multicast bits */ + if (dev->flags & IFF_ALLMULTI) { + ib->filter[0] = 0xffff; + ib->filter[2] = 0xffff; + ib->filter[4] = 0xffff; + ib->filter[6] = 0xffff; + return; + } + /* clear the multicast filter */ + ib->filter[0] = 0; + ib->filter[2] = 0; + ib->filter[4] = 0; + ib->filter[6] = 0; + + /* Add addresses */ + for (i = 0; i < dev->mc_count; i++) { + addrs = dmi->dmi_addr; + dmi = dmi->next; + + /* multicast address? */ + if (!(*addrs & 1)) + continue; + + crc = 0xffffffff; + for (byte = 0; byte < 6; byte++) + for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { + int test; + + test = ((bit ^ crc) & 0x01); + crc >>= 1; + + if (test) { + crc = crc ^ poly; + } + } + + crc = crc >> 26; + mcast_table[crc >> 3] |= 1 << (crc & 0xf); + } + return; +} + +static void lance_set_multicast(struct device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_init_block *ib; + volatile struct lance_regs *ll = lp->ll; + + ib = (struct lance_init_block *) (dev->mem_start); + + while (dev->tbusy) + schedule(); + set_bit(0, (void *) &dev->tbusy); + while (lp->tx_old != lp->tx_new) + schedule(); + + writereg(&ll->rap, LE_CSR0); + writereg(&ll->rdp, LE_C0_STOP); + + lance_init_ring(dev); + + if (dev->flags & IFF_PROMISC) { + ib->mode |= LE_MO_PROM; + } else { + ib->mode &= ~LE_MO_PROM; + lance_load_multicast(dev); + } + load_csrs(lp); + init_restart_lance(lp); + dev->tbusy = 0; +} + +__initfunc(static int dec_lance_init(struct device *dev, const int type)) +{ + static unsigned version_printed = 0; + struct lance_private *lp; + volatile struct lance_regs *ll; + int i; + unsigned long esar_base; + unsigned char *esar; + +#ifndef CONFIG_TC + system_base = KN01_LANCE_BASE; +#else + int slot; +#endif + + if (dec_lance_debug && version_printed++ == 0) + printk(version); + + if (dev == NULL) { + dev = init_etherdev(0, sizeof(struct lance_private) + 8); + } else { + dev->priv = kmalloc(sizeof(struct lance_private) + 8, + GFP_KERNEL); + if (dev->priv == NULL) + return -ENOMEM; + memset(dev->priv, 0, sizeof(struct lance_private) + 8); + + } + + /* Make certain the data structures used by the LANCE are aligned. */ + dev->priv = (void *) (((unsigned long) dev->priv + 7) & ~7); + lp = (struct lance_private *) dev->priv; + + switch (type) { +#ifdef CONFIG_TC + case ASIC_LANCE: + dev->base_addr = system_base + LANCE; + + /* buffer space for the on-board LANCE shared memory */ + /* + * FIXME: ugly hack! + */ + dev->mem_start = KSEG1ADDR(0x0020000); + dev->mem_end = dev->mem_start + 0x00020000; + dev->irq = ETHER; + esar_base = system_base + ESAR; + + /* + * setup the pointer arrays, this sucks [tm] :-( + */ + for (i = 0; i < RX_RING_SIZE; i++) { + lp->rx_buf_ptr_cpu[i] = (char *) (dev->mem_start + BUF_OFFSET_CPU + + 2 * i * RX_BUFF_SIZE); + lp->rx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC + + i * RX_BUFF_SIZE); + } + for (i = 0; i < TX_RING_SIZE; i++) { + lp->tx_buf_ptr_cpu[i] = (char *) (dev->mem_start + BUF_OFFSET_CPU + + 2 * RX_RING_SIZE * RX_BUFF_SIZE + + 2 * i * TX_BUFF_SIZE); + lp->tx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC + + RX_RING_SIZE * RX_BUFF_SIZE + + i * TX_BUFF_SIZE); + } + + /* + * setup and enable IOASIC LANCE DMA + */ + lp->dma_ptr_reg = (unsigned long *) (system_base + IOCTL + LANCE_DMA_P); + *(lp->dma_ptr_reg) = PHYSADDR(dev->mem_start) << 3; + *(unsigned long *) (system_base + IOCTL + SSR) |= (1 << 16); + + break; + case PMAD_LANCE: + slot = search_tc_card("PMAD-AA"); + claim_tc_card(slot); + + dev->mem_start = get_tc_base_addr(slot); + dev->base_addr = dev->mem_start + 0x100000; + dev->irq = get_tc_irq_nr(slot); + esar_base = dev->mem_start + 0x1c0002; + break; +#endif + case PMAX_LANCE: + dev->irq = ETHER; + dev->base_addr = KN01_LANCE_BASE; + dev->mem_start = KN01_LANCE_BASE + 0x01000000; + esar_base = KN01_RTC_BASE + 1; + /* + * setup the pointer arrays, this sucks [tm] :-( + */ + for (i = 0; i < RX_RING_SIZE; i++) { + lp->rx_buf_ptr_cpu[i] = + (char *) (dev->mem_start + BUF_OFFSET_CPU + + 2 * i * RX_BUFF_SIZE); + + lp->rx_buf_ptr_lnc[i] = + (char *) (BUF_OFFSET_LNC + + i * RX_BUFF_SIZE); + + } + for (i = 0; i < TX_RING_SIZE; i++) { + lp->tx_buf_ptr_cpu[i] = + (char *) (dev->mem_start + BUF_OFFSET_CPU + + 2 * RX_RING_SIZE * RX_BUFF_SIZE + + 2 * i * TX_BUFF_SIZE); + lp->tx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC + + RX_RING_SIZE * RX_BUFF_SIZE + + i * TX_BUFF_SIZE); + + } + break; + default: + printk("declance_init called with unknown type\n"); + return -ENODEV; + break; + } + + ll = (struct lance_regs *) dev->base_addr; + esar = (unsigned char *) esar_base; + + /* prom checks */ + /* First, check for test pattern */ + if (esar[0x60] != 0xff && esar[0x64] != 0x00 && + esar[0x68] != 0x55 && esar[0x6c] != 0xaa) { + printk("Ethernet station address prom not found!\n"); + return -ENODEV; + } + /* Check the prom contents */ + for (i = 0; i < 8; i++) { + if (esar[i * 4] != esar[0x3c - i * 4] && + esar[i * 4] != esar[0x40 + i * 4] && + esar[0x3c - i * 4] != esar[0x40 + i * 4]) { + printk("Something is wrong with the ethernet " + "station address prom!\n"); + return -ENODEV; + } + } + + /* Copy the ethernet address to the device structure, later to the + * lance initialization block so the lance gets it every time it's + * (re)initialized. + */ + switch (type) { + case ASIC_LANCE: + printk("%s: IOASIC onboard LANCE, addr = ", dev->name); + break; + case PMAD_LANCE: + printk("%s: PMAD-AA, addr = ", dev->name); + break; + case PMAX_LANCE: + printk("%s: PMAX onboard LANCE, addr = ", dev->name); + break; + } + for (i = 0; i < 6; i++) { + dev->dev_addr[i] = esar[i * 4]; + printk("%2.2x%c", dev->dev_addr[i], i == 5 ? ',' : ':'); + } + + printk(" irq = %d\n", dev->irq); + + /* Fill the dev fields */ + + dev->open = lance_open; + dev->stop = lance_close; + dev->hard_start_xmit = lance_start_xmit; + dev->get_stats = lance_get_stats; + dev->set_multicast_list = lance_set_multicast; + dev->dma = 0; + + /* lp->ll is the location of the registers for lance card */ + lp->ll = ll; + + lp->name = lancestr; + + /* busmaster_regval (CSR3) should be zero according to the PMAD-AA + * specification. + */ + lp->busmaster_regval = 0; + lp->dev = dev; + + ether_setup(dev); +/* + #ifdef MODULE + dev->ifindex = dev_new_index(); + lp->next_module = root_lance_dev; + root_lance_dev = lp; + #endif + */ + return 0; +} + + +/* Find all the lance cards on the system and initialize them */ +__initfunc(int dec_lance_probe(struct device *dev)) +{ + static int called = 0; + +#ifdef CONFIG_TC + int slot = -1; + + if (TURBOCHANNEL) { + if (IOASIC && !called) { + called = 1; + type = ASIC_LANCE; + } else { + if ((slot = search_tc_card("PMAD-AA")) >= 0) { + type = PMAD_LANCE; + } else { + return -ENODEV; + } + } + } else { + if (!called) { + called = 1; + type = PMAX_LANCE; + } else { + return -ENODEV; + } + } +#else + if (!called && !TURBOCHANNEL) { + called = 1; + type = PMAX_LANCE; + } else { + return -ENODEV; + } +#endif + + return dec_lance_init(dev, type); +} + +/* + #ifdef MODULE + + int + init_module(void) + { + root_lance_dev = NULL; + return dec_lance_probe(NULL); + } + + void + cleanup_module(void) + { + struct lance_private *lp; + + while (root_lance_dev) { + lp = root_lance_dev->next_module; + + unregister_netdev(root_lance_dev->dev); + kfree(root_lance_dev->dev); + root_lance_dev = lp; + } + } + + #endif -* MODULE */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/depca.c linux.pre11.3/drivers/net/depca.c --- linux.vanilla/drivers/net/depca.c Thu Dec 3 13:48:35 1998 +++ linux.pre11.3/drivers/net/depca.c Mon Jul 19 23:59:56 1999 @@ -221,11 +221,13 @@ by 0.451 5-Nov-98 Fixed mca stuff cuz I'm a dummy. 0.5 14-Nov-98 Re-spin for 2.1.x kernels. + 0.51 27-Jun-99 Correct received packet length for CRC from + report by ========================================================================= */ -static const char *version = "depca.c:v0.5 1998/11/14 davies@maniac.ultranet.com\n"; +static const char *version = "depca.c:v0.51 1999/6/27 davies@maniac.ultranet.com\n"; #include #include @@ -947,7 +949,7 @@ if (status & R_CRC) lp->stats.rx_crc_errors++; if (status & R_BUFF) lp->stats.rx_fifo_errors++; } else { - short len, pkt_len = readw(&lp->rx_ring[entry].msg_length); + short len, pkt_len = readw(&lp->rx_ring[entry].msg_length) - 4; struct sk_buff *skb; skb = dev_alloc_skb(pkt_len+2); @@ -1898,14 +1900,12 @@ tmp.addr[i] = dev->dev_addr[i]; } ioc->len = ETH_ALEN; - if (verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len)) return -EFAULT; - copy_to_user(ioc->data, tmp.addr, ioc->len); + if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT; break; case DEPCA_SET_HWADDR: /* Set the hardware address */ if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN)) return -EFAULT; - copy_from_user(tmp.addr,ioc->data,ETH_ALEN); + if (copy_from_user(tmp.addr,ioc->data,ETH_ALEN)) return -EFAULT; for (i=0; idev_addr[i] = tmp.addr[i]; } @@ -1956,14 +1956,12 @@ case DEPCA_GET_MCA: /* Get the multicast address table */ ioc->len = (HASH_TABLE_LEN >> 3); - if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT; - copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len); + if (copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len)) return -EFAULT; break; case DEPCA_SET_MCA: /* Set a multicast address */ if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (verify_area(VERIFY_READ, ioc->data, ETH_ALEN*ioc->len)) return -EFAULT; - copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len); + if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len)) return -EFAULT; set_multicast_list(dev); break; @@ -1980,11 +1978,8 @@ case DEPCA_GET_STATS: /* Get the driver statistics */ cli(); ioc->len = sizeof(lp->pktStats); - if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) { - status = -EFAULT; - } else { - copy_to_user(ioc->data, &lp->pktStats, ioc->len); - } + if (copy_to_user(ioc->data, &lp->pktStats, ioc->len)) + status = -EFAULT; sti(); break; @@ -2002,8 +1997,7 @@ tmp.sval[i++] = inw(DEPCA_DATA); memcpy(&tmp.sval[i], &lp->init_block, sizeof(struct depca_init)); ioc->len = i+sizeof(struct depca_init); - if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT; - copy_to_user(ioc->data, tmp.addr, ioc->len); + if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT; break; default: diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/eepro100.c linux.pre11.3/drivers/net/eepro100.c --- linux.vanilla/drivers/net/eepro100.c Tue Feb 23 14:21:33 1999 +++ linux.pre11.3/drivers/net/eepro100.c Mon Jul 19 23:27:30 1999 @@ -343,7 +343,8 @@ const char *product_name; struct device *next_module; spinlock_t lock; - struct TxFD tx_ring[TX_RING_SIZE]; /* Commands (usually CmdTxPacket). */ + struct TxFD tx_ring[TX_RING_SIZE] /* Commands (usually CmdTxPacket). */ + __attribute__ ((aligned (L1_CACHE_BYTES)));; /* The saved address of a sent-in-place packet/buffer, for skfree(). */ struct sk_buff* tx_skbuff[TX_RING_SIZE]; struct descriptor *last_cmd; /* Last command sent. */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/eql.c linux.pre11.3/drivers/net/eql.c --- linux.vanilla/drivers/net/eql.c Thu May 27 22:11:54 1999 +++ linux.pre11.3/drivers/net/eql.c Mon Jul 19 23:59:56 1999 @@ -411,16 +411,15 @@ slaving_request_t srq; int err; - err = verify_area(VERIFY_READ, (void *)srqp, sizeof (slaving_request_t)); + err = copy_from_user(&srq, srqp, sizeof (slaving_request_t)); if (err) { #ifdef EQL_DEBUG if (eql_debug >= 20) - printk ("EQL enslave: error detected by verify_area\n"); + printk ("EQL enslave: error detected by copy_from_user\n"); #endif return err; } - copy_from_user (&srq, srqp, sizeof (slaving_request_t)); #ifdef EQL_DEBUG if (eql_debug >= 20) @@ -473,11 +472,10 @@ slaving_request_t srq; int err; - err = verify_area(VERIFY_READ, (void *)srqp, sizeof (slaving_request_t)); + err = copy_from_user(&srq, srqp, sizeof (slaving_request_t)); if (err) return err; - copy_from_user (&srq, srqp, sizeof (slaving_request_t)); #ifdef EQL_DEBUG if (eql_debug >= 20) printk ("%s: emancipate `%s`\n", dev->name, srq.slave_name); @@ -504,11 +502,10 @@ slave_config_t sc; int err; - err = verify_area(VERIFY_READ, (void *)scp, sizeof (slave_config_t)); + err = copy_from_user (&sc, scp, sizeof (slave_config_t)); if (err) return err; - copy_from_user (&sc, scp, sizeof (slave_config_t)); #ifdef EQL_DEBUG if (eql_debug >= 20) printk ("%s: get config for slave `%s'\n", dev->name, sc.slave_name); @@ -541,7 +538,7 @@ slave_config_t sc; int err; - err = verify_area(VERIFY_READ, (void *)scp, sizeof (slave_config_t)); + err = copy_from_user (&sc, scp, sizeof (slave_config_t)); if (err) return err; @@ -550,7 +547,6 @@ printk ("%s: set config for slave `%s'\n", dev->name, sc.slave_name); #endif - copy_from_user (&sc, scp, sizeof (slave_config_t)); eql = (equalizer_t *) dev->priv; slave_dev = dev_get (sc.slave_name); @@ -583,13 +579,12 @@ if ( eql_is_master (dev) ) { int err; - err = verify_area(VERIFY_WRITE, (void *)mcp, sizeof (master_config_t)); - if (err) - return err; eql = (equalizer_t *) dev->priv; mc.max_slaves = eql->max_slaves; mc.min_slaves = eql->min_slaves; - copy_to_user (mcp, &mc, sizeof (master_config_t)); + err = copy_to_user (mcp, &mc, sizeof (master_config_t)); + if (err) + return err; return 0; } return -EINVAL; @@ -602,14 +597,13 @@ master_config_t mc; int err; - err = verify_area(VERIFY_READ, (void *)mcp, sizeof (master_config_t)); + err = copy_from_user (&mc, mcp, sizeof (master_config_t)); if (err) return err; #if EQL_DEBUG if (eql_debug >= 20) printk ("%s: set master config\n", dev->name); #endif - copy_from_user (&mc, mcp, sizeof (master_config_t)); if ( eql_is_master (dev) ) { eql = (equalizer_t *) dev->priv; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/ewrk3.c linux.pre11.3/drivers/net/ewrk3.c --- linux.vanilla/drivers/net/ewrk3.c Sun Nov 8 15:07:23 1998 +++ linux.pre11.3/drivers/net/ewrk3.c Mon Jul 19 23:59:56 1999 @@ -1679,18 +1679,20 @@ tmp.addr[i] = dev->dev_addr[i]; } ioc->len = ETH_ALEN; - if (!(status = verify_area(VERIFY_WRITE, (void *) ioc->data, ioc->len))) { - copy_to_user(ioc->data, tmp.addr, ioc->len); + if (copy_to_user(ioc->data, tmp.addr, ioc->len)) { + status = -EFAULT; + break; } - break; case EWRK3_SET_HWADDR: /* Set the hardware address */ if (capable(CAP_NET_ADMIN)) { - if (!(status = verify_area(VERIFY_READ, (void *) ioc->data, ETH_ALEN))) { csr = inb(EWRK3_CSR); csr |= (CSR_TXD | CSR_RXD); outb(csr, EWRK3_CSR); /* Disable the TX and RX */ - copy_from_user(tmp.addr, ioc->data, ETH_ALEN); + if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN)) { + status = -EFAULT; + break; + } for (i = 0; i < ETH_ALEN; i++) { dev->dev_addr[i] = tmp.addr[i]; outb(tmp.addr[i], EWRK3_PAR0 + i); @@ -1698,7 +1700,6 @@ csr &= ~(CSR_TXD | CSR_RXD); /* Enable the TX and RX */ outb(csr, EWRK3_CSR); - } } else { status = -EPERM; } @@ -1730,7 +1731,6 @@ break; case EWRK3_GET_MCA: /* Get the multicast address table */ - if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { while (test_and_set_bit(0, (void *) &lp->lock) != 0); /* Wait for lock to free */ if (lp->shmem_length == IO_ONLY) { outb(0, EWRK3_IOPR); @@ -1743,17 +1743,21 @@ memcpy_fromio(tmp.addr, (char *) (lp->shmem_base + PAGE0_HTE), (HASH_TABLE_LEN >> 3)); } ioc->len = (HASH_TABLE_LEN >> 3); - copy_to_user(ioc->data, tmp.addr, ioc->len); - } + if (copy_to_user(ioc->data, tmp.addr, ioc->len)) { + status = -EFAULT; + break; + } + lp->lock = 0; /* Unlock the page register */ break; case EWRK3_SET_MCA: /* Set a multicast address */ if (capable(CAP_NET_ADMIN)) { - if (!(status = verify_area(VERIFY_READ, ioc->data, ETH_ALEN * ioc->len))) { - copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len); - set_multicast_list(dev); + if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len)) { + status = -EFAULT; + break; } + set_multicast_list(dev); } else { status = -EPERM; } @@ -1781,9 +1785,8 @@ case EWRK3_GET_STATS: /* Get the driver statistics */ cli(); ioc->len = sizeof(lp->pktStats); - if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { - copy_to_user(ioc->data, &lp->pktStats, ioc->len); - } + if (copy_to_user(ioc->data, &lp->pktStats, ioc->len)) + status = -EFAULT; sti(); break; @@ -1800,16 +1803,16 @@ case EWRK3_GET_CSR: /* Get the CSR Register contents */ tmp.addr[0] = inb(EWRK3_CSR); ioc->len = 1; - if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { - copy_to_user(ioc->data, tmp.addr, ioc->len); - } + if (copy_to_user(ioc->data, tmp.addr, ioc->len)) + status = -EFAULT; break; case EWRK3_SET_CSR: /* Set the CSR Register contents */ if (capable(CAP_NET_ADMIN)) { - if (!(status = verify_area(VERIFY_READ, ioc->data, 1))) { - copy_from_user(tmp.addr, ioc->data, 1); - outb(tmp.addr[0], EWRK3_CSR); + if (copy_from_user(tmp.addr, ioc->data, 1)) { + status = -EFAULT; + break; } + outb(tmp.addr[0], EWRK3_CSR); } else { status = -EPERM; } @@ -1826,9 +1829,8 @@ tmp.addr[i++] = inb(EWRK3_PAR0 + j); } ioc->len = EEPROM_MAX + 1 + ETH_ALEN; - if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { - copy_to_user(ioc->data, tmp.addr, ioc->len); - } + if (copy_to_user(ioc->data, tmp.addr, ioc->len)) + status = -EFAULT; } else { status = -EPERM; } @@ -1836,11 +1838,12 @@ break; case EWRK3_SET_EEPROM: /* Set the EEPROM contents */ if (capable(CAP_NET_ADMIN)) { - if (!(status = verify_area(VERIFY_READ, ioc->data, EEPROM_MAX))) { - copy_from_user(tmp.addr, ioc->data, EEPROM_MAX); - for (i = 0; i < (EEPROM_MAX >> 1); i++) { - Write_EEPROM(tmp.val[i], iobase, i); - } + if (copy_from_user(tmp.addr, ioc->data, EEPROM_MAX)) { + status = -EFAULT; + break; + } + for (i = 0; i < (EEPROM_MAX >> 1); i++) { + Write_EEPROM(tmp.val[i], iobase, i); } } else { status = -EPERM; @@ -1850,9 +1853,8 @@ case EWRK3_GET_CMR: /* Get the CMR Register contents */ tmp.addr[0] = inb(EWRK3_CMR); ioc->len = 1; - if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) { - copy_to_user(ioc->data, tmp.addr, ioc->len); - } + if (copy_to_user(ioc->data, tmp.addr, ioc->len)) + status = -EFAULT; break; case EWRK3_SET_TX_CUT_THRU: /* Set TX cut through mode */ if (suser()) { diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/hamradio/Config.in linux.pre11.3/drivers/net/hamradio/Config.in --- linux.vanilla/drivers/net/hamradio/Config.in Thu Dec 31 18:10:42 1998 +++ linux.pre11.3/drivers/net/hamradio/Config.in Tue Jul 20 00:29:25 1999 @@ -28,3 +28,5 @@ bool ' soundmodem support for 4800 baud PSK modulation' CONFIG_SOUNDMODEM_PSK4800 bool ' soundmodem support for 9600 baud FSK G3RUH modulation' CONFIG_SOUNDMODEM_FSK9600 fi + +tristate 'YAM driver for AX.25' CONFIG_YAM diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/hamradio/Makefile linux.pre11.3/drivers/net/hamradio/Makefile --- linux.vanilla/drivers/net/hamradio/Makefile Sun Nov 8 15:07:26 1998 +++ linux.pre11.3/drivers/net/hamradio/Makefile Tue Jul 20 00:29:25 1999 @@ -53,6 +53,14 @@ endif endif +ifeq ($(CONFIG_YAM),y) +L_OBJS += yam.o +else + ifeq ($(CONFIG_YAM),m) + M_OBJS += yam.o + endif +endif + ifeq ($(CONFIG_PI),y) L_OBJS += pi2.o else diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/hamradio/hdlcdrv.c linux.pre11.3/drivers/net/hamradio/hdlcdrv.c --- linux.vanilla/drivers/net/hamradio/hdlcdrv.c Thu Dec 31 18:10:42 1998 +++ linux.pre11.3/drivers/net/hamradio/hdlcdrv.c Tue Jul 20 00:29:25 1999 @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/hamradio/soundmodem/sm.h linux.pre11.3/drivers/net/hamradio/soundmodem/sm.h --- linux.vanilla/drivers/net/hamradio/soundmodem/sm.h Sun Nov 8 15:07:27 1998 +++ linux.pre11.3/drivers/net/hamradio/soundmodem/sm.h Tue Jul 20 00:29:25 1999 @@ -296,8 +296,6 @@ #ifdef __i386__ -#include - #define HAS_RDTSC (current_cpu_data.x86_capability & X86_FEATURE_TSC) /* diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/hamradio/yam.c linux.pre11.3/drivers/net/hamradio/yam.c --- linux.vanilla/drivers/net/hamradio/yam.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/net/hamradio/yam.c Tue Jul 20 00:29:25 1999 @@ -0,0 +1,1297 @@ +/*****************************************************************************/ + +/* + * yam.c -- YAM radio modem driver. + * + * Copyright (C) 1998 Frederic Rible F1OAT (frible@teaser.fr) + * Adapted from baycom.c driver written by Thomas Sailer (sailer@ife.ee.ethz.ch) + * + * This program is free software; you can redistribute 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. + * + * Please note that the GPL allows you to use the driver, NOT the radio. + * In order to use the radio, you need a license from the communications + * authority of your country. + * + * + * History: + * 0.0 F1OAT 06.06.98 Begin of work with baycom.c source code V 0.3 + * 0.1 F1OAT 07.06.98 Add timer polling routine for channel arbitration + * 0.2 F6FBB 08.06.98 Added delay after FPGA programming + * 0.3 F6FBB 29.07.98 Delayed PTT implementation for dupmode=2 + * 0.4 F6FBB 30.07.98 Added TxTail, Slottime and Persistance + * 0.5 F6FBB 01.08.98 Shared IRQs, /proc/net and network statistics + * 0.6 F6FBB 25.08.98 Added 1200Bds format + * 0.7 F6FBB 12.09.98 Added to the kernel configuration + * 0.8 F6FBB 14.10.98 Fixed slottime/persistance timing bug + */ + +/*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) +/* prototypes for ax25_encapsulate and ax25_rebuild_header */ +#include +#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */ + +/* make genksyms happy */ +#include +#include +#include + +#include +#include + +#include +#include "yam9600.h" +#include "yam1200.h" + +/* --------------------------------------------------------------------- */ + +/* + * currently this module is supposed to support both module styles, i.e. + * the old one present up to about 2.1.9, and the new one functioning + * starting with 2.1.21. The reason is I have a kit allowing to compile + * this module also under 2.0.x which was requested by several people. + * This will go in 2.2 + */ +#include + +#if LINUX_VERSION_CODE >= 0x20100 +#include +#else +#include +#include + +#undef put_user +#undef get_user + +#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) +#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) + +extern inline int copy_from_user(void *to, const void *from, unsigned long n) +{ + int i = verify_area(VERIFY_READ, from, n); + if (i) + return i; + memcpy_fromfs(to, from, n); + return 0; +} + +extern inline int copy_to_user(void *to, const void *from, unsigned long n) +{ + int i = verify_area(VERIFY_WRITE, to, n); + if (i) + return i; + memcpy_tofs(to, from, n); + return 0; +} +#endif + +#if LINUX_VERSION_CODE < 0x20115 +extern __inline__ void dev_init_buffers(struct device *dev) +{ + int i; + for (i = 0; i < DEV_NUMBUFFS; i++) { + skb_queue_head_init(&dev->buffs[i]); + } +} +#endif + +#if LINUX_VERSION_CODE >= 0x20123 +#include +#else +#define __init +#define __initdata +#define __initfunc(x) x +#endif + +/* --------------------------------------------------------------------- */ + +static const char yam_drvname[] = "yam"; +static const char yam_drvinfo[] = KERN_INFO "YAM driver version 0.8 by F1OAT/F6FBB\n"; + +/* --------------------------------------------------------------------- */ + +#define YAM_9600 1 +#define YAM_1200 2 + +#define NR_PORTS 4 +#define YAM_MAGIC 0xF10A7654 + +/* Transmitter states */ + +#define TX_OFF 0 +#define TX_HEAD 1 +#define TX_DATA 2 +#define TX_CRC1 3 +#define TX_CRC2 4 +#define TX_TAIL 5 + +#define YAM_MAX_FRAME 1024 + +#define DEFAULT_BITRATE 9600 /* bps */ +#define DEFAULT_HOLDD 10 /* sec */ +#define DEFAULT_TXD 300 /* ms */ +#define DEFAULT_TXTAIL 10 /* ms */ +#define DEFAULT_SLOT 100 /* ms */ +#define DEFAULT_PERS 64 /* 0->255 */ + +struct yam_port { + int magic; + int bitrate; + int baudrate; + int iobase; + int irq; + int dupmode; + char name[16]; + + struct device dev; + + /* Stats section */ + +#if LINUX_VERSION_CODE < 0x20119 + struct enet_statistics stats; +#else + struct net_device_stats stats; +#endif + int nb_rxint; + int nb_mdint; + + /* Parameters section */ + + int txd; /* tx delay */ + int holdd; /* duplex ptt delay */ + int txtail; /* txtail delay */ + int slot; /* slottime */ + int pers; /* persistence */ + + /* Tx section */ + + int tx_state; + int tx_count; + int slotcnt; + unsigned char tx_buf[YAM_MAX_FRAME]; + int tx_len; + int tx_crcl, tx_crch; + struct sk_buff_head send_queue; /* Packets awaiting transmission */ + + /* Rx section */ + + int dcd; + unsigned char rx_buf[YAM_MAX_FRAME]; + int rx_len; + int rx_crcl, rx_crch; +}; + +struct yam_mcs { + unsigned char bits[YAM_FPGA_SIZE]; + int bitrate; + struct yam_mcs *next; +}; + +static struct yam_port yam_ports[NR_PORTS]; + +static struct yam_mcs *yam_data = NULL; + +static unsigned irqs[16]; + +static char ax25_bcast[7] = +{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1}; +static char ax25_test[7] = +{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1}; + +static struct timer_list yam_timer; + +/* --------------------------------------------------------------------- */ + +#define RBR(iobase) (iobase+0) +#define THR(iobase) (iobase+0) +#define IER(iobase) (iobase+1) +#define IIR(iobase) (iobase+2) +#define FCR(iobase) (iobase+2) +#define LCR(iobase) (iobase+3) +#define MCR(iobase) (iobase+4) +#define LSR(iobase) (iobase+5) +#define MSR(iobase) (iobase+6) +#define SCR(iobase) (iobase+7) +#define DLL(iobase) (iobase+0) +#define DLM(iobase) (iobase+1) + +#define YAM_EXTENT 8 + +/* Interrupt Identification Register Bit Masks */ +#define IIR_NOPEND 1 +#define IIR_MSR 0 +#define IIR_TX 2 +#define IIR_RX 4 +#define IIR_LSR 6 +#define IIR_TIMEOUT 12 /* Fifo mode only */ + +#define IIR_MASK 0x0F + +/* Interrupt Enable Register Bit Masks */ +#define IER_RX 1 /* enable rx interrupt */ +#define IER_TX 2 /* enable tx interrupt */ +#define IER_LSR 4 /* enable line status interrupts */ +#define IER_MSR 8 /* enable modem status interrupts */ + +/* Modem Control Register Bit Masks */ +#define MCR_DTR 0x01 /* DTR output */ +#define MCR_RTS 0x02 /* RTS output */ +#define MCR_OUT1 0x04 /* OUT1 output (not accessible in RS232) */ +#define MCR_OUT2 0x08 /* Master Interrupt enable (must be set on PCs) */ +#define MCR_LOOP 0x10 /* Loopback enable */ + +/* Modem Status Register Bit Masks */ +#define MSR_DCTS 0x01 /* Delta CTS input */ +#define MSR_DDSR 0x02 /* Delta DSR */ +#define MSR_DRIN 0x04 /* Delta RI */ +#define MSR_DDCD 0x08 /* Delta DCD */ +#define MSR_CTS 0x10 /* CTS input */ +#define MSR_DSR 0x20 /* DSR input */ +#define MSR_RING 0x40 /* RI input */ +#define MSR_DCD 0x80 /* DCD input */ + +/* line status register bit mask */ +#define LSR_RXC 0x01 +#define LSR_OE 0x02 +#define LSR_PE 0x04 +#define LSR_FE 0x08 +#define LSR_BREAK 0x10 +#define LSR_THRE 0x20 +#define LSR_TSRE 0x40 + +/* Line Control Register Bit Masks */ +#define LCR_DLAB 0x80 +#define LCR_BREAK 0x40 +#define LCR_PZERO 0x28 +#define LCR_PEVEN 0x18 +#define LCR_PODD 0x08 +#define LCR_STOP1 0x00 +#define LCR_STOP2 0x04 +#define LCR_BIT5 0x00 +#define LCR_BIT6 0x02 +#define LCR_BIT7 0x01 +#define LCR_BIT8 0x03 + +/* YAM Modem <-> UART Port mapping */ + +#define TX_RDY MSR_DCTS /* transmitter ready to send */ +#define RX_DCD MSR_DCD /* carrier detect */ +#define RX_FLAG MSR_RING /* hdlc flag received */ +#define FPGA_DONE MSR_DSR /* FPGA is configured */ +#define PTT_ON (MCR_RTS|MCR_OUT2) /* activate PTT */ +#define PTT_OFF (MCR_DTR|MCR_OUT2) /* release PTT */ + +#define ENABLE_RXINT IER_RX /* enable uart rx interrupt during rx */ +#define ENABLE_TXINT IER_MSR /* enable uart ms interrupt during tx */ +#define ENABLE_RTXINT (IER_RX|IER_MSR) /* full duplex operations */ + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +/************************************************************************* +* CRC Tables +************************************************************************/ + +static const unsigned char chktabl[256] = +{0x00, 0x89, 0x12, 0x9b, 0x24, 0xad, 0x36, 0xbf, 0x48, 0xc1, 0x5a, 0xd3, 0x6c, 0xe5, 0x7e, + 0xf7, 0x81, 0x08, 0x93, 0x1a, 0xa5, 0x2c, 0xb7, 0x3e, 0xc9, 0x40, 0xdb, 0x52, 0xed, 0x64, + 0xff, 0x76, 0x02, 0x8b, 0x10, 0x99, 0x26, 0xaf, 0x34, 0xbd, 0x4a, 0xc3, 0x58, 0xd1, 0x6e, + 0xe7, 0x7c, 0xf5, 0x83, 0x0a, 0x91, 0x18, 0xa7, 0x2e, 0xb5, 0x3c, 0xcb, 0x42, 0xd9, 0x50, + 0xef, 0x66, 0xfd, 0x74, 0x04, 0x8d, 0x16, 0x9f, 0x20, 0xa9, 0x32, 0xbb, 0x4c, 0xc5, 0x5e, + 0xd7, 0x68, 0xe1, 0x7a, 0xf3, 0x85, 0x0c, 0x97, 0x1e, 0xa1, 0x28, 0xb3, 0x3a, 0xcd, 0x44, + 0xdf, 0x56, 0xe9, 0x60, 0xfb, 0x72, 0x06, 0x8f, 0x14, 0x9d, 0x22, 0xab, 0x30, 0xb9, 0x4e, + 0xc7, 0x5c, 0xd5, 0x6a, 0xe3, 0x78, 0xf1, 0x87, 0x0e, 0x95, 0x1c, 0xa3, 0x2a, 0xb1, 0x38, + 0xcf, 0x46, 0xdd, 0x54, 0xeb, 0x62, 0xf9, 0x70, 0x08, 0x81, 0x1a, 0x93, 0x2c, 0xa5, 0x3e, + 0xb7, 0x40, 0xc9, 0x52, 0xdb, 0x64, 0xed, 0x76, 0xff, 0x89, 0x00, 0x9b, 0x12, 0xad, 0x24, + 0xbf, 0x36, 0xc1, 0x48, 0xd3, 0x5a, 0xe5, 0x6c, 0xf7, 0x7e, 0x0a, 0x83, 0x18, 0x91, 0x2e, + 0xa7, 0x3c, 0xb5, 0x42, 0xcb, 0x50, 0xd9, 0x66, 0xef, 0x74, 0xfd, 0x8b, 0x02, 0x99, 0x10, + 0xaf, 0x26, 0xbd, 0x34, 0xc3, 0x4a, 0xd1, 0x58, 0xe7, 0x6e, 0xf5, 0x7c, 0x0c, 0x85, 0x1e, + 0x97, 0x28, 0xa1, 0x3a, 0xb3, 0x44, 0xcd, 0x56, 0xdf, 0x60, 0xe9, 0x72, 0xfb, 0x8d, 0x04, + 0x9f, 0x16, 0xa9, 0x20, 0xbb, 0x32, 0xc5, 0x4c, 0xd7, 0x5e, 0xe1, 0x68, 0xf3, 0x7a, 0x0e, + 0x87, 0x1c, 0x95, 0x2a, 0xa3, 0x38, 0xb1, 0x46, 0xcf, 0x54, 0xdd, 0x62, 0xeb, 0x70, 0xf9, + 0x8f, 0x06, 0x9d, 0x14, 0xab, 0x22, 0xb9, 0x30, 0xc7, 0x4e, 0xd5, 0x5c, 0xe3, 0x6a, 0xf1, + 0x78}; +static const unsigned char chktabh[256] = +{0x00, 0x11, 0x23, 0x32, 0x46, 0x57, 0x65, 0x74, 0x8c, 0x9d, 0xaf, 0xbe, 0xca, 0xdb, 0xe9, + 0xf8, 0x10, 0x01, 0x33, 0x22, 0x56, 0x47, 0x75, 0x64, 0x9c, 0x8d, 0xbf, 0xae, 0xda, 0xcb, + 0xf9, 0xe8, 0x21, 0x30, 0x02, 0x13, 0x67, 0x76, 0x44, 0x55, 0xad, 0xbc, 0x8e, 0x9f, 0xeb, + 0xfa, 0xc8, 0xd9, 0x31, 0x20, 0x12, 0x03, 0x77, 0x66, 0x54, 0x45, 0xbd, 0xac, 0x9e, 0x8f, + 0xfb, 0xea, 0xd8, 0xc9, 0x42, 0x53, 0x61, 0x70, 0x04, 0x15, 0x27, 0x36, 0xce, 0xdf, 0xed, + 0xfc, 0x88, 0x99, 0xab, 0xba, 0x52, 0x43, 0x71, 0x60, 0x14, 0x05, 0x37, 0x26, 0xde, 0xcf, + 0xfd, 0xec, 0x98, 0x89, 0xbb, 0xaa, 0x63, 0x72, 0x40, 0x51, 0x25, 0x34, 0x06, 0x17, 0xef, + 0xfe, 0xcc, 0xdd, 0xa9, 0xb8, 0x8a, 0x9b, 0x73, 0x62, 0x50, 0x41, 0x35, 0x24, 0x16, 0x07, + 0xff, 0xee, 0xdc, 0xcd, 0xb9, 0xa8, 0x9a, 0x8b, 0x84, 0x95, 0xa7, 0xb6, 0xc2, 0xd3, 0xe1, + 0xf0, 0x08, 0x19, 0x2b, 0x3a, 0x4e, 0x5f, 0x6d, 0x7c, 0x94, 0x85, 0xb7, 0xa6, 0xd2, 0xc3, + 0xf1, 0xe0, 0x18, 0x09, 0x3b, 0x2a, 0x5e, 0x4f, 0x7d, 0x6c, 0xa5, 0xb4, 0x86, 0x97, 0xe3, + 0xf2, 0xc0, 0xd1, 0x29, 0x38, 0x0a, 0x1b, 0x6f, 0x7e, 0x4c, 0x5d, 0xb5, 0xa4, 0x96, 0x87, + 0xf3, 0xe2, 0xd0, 0xc1, 0x39, 0x28, 0x1a, 0x0b, 0x7f, 0x6e, 0x5c, 0x4d, 0xc6, 0xd7, 0xe5, + 0xf4, 0x80, 0x91, 0xa3, 0xb2, 0x4a, 0x5b, 0x69, 0x78, 0x0c, 0x1d, 0x2f, 0x3e, 0xd6, 0xc7, + 0xf5, 0xe4, 0x90, 0x81, 0xb3, 0xa2, 0x5a, 0x4b, 0x79, 0x68, 0x1c, 0x0d, 0x3f, 0x2e, 0xe7, + 0xf6, 0xc4, 0xd5, 0xa1, 0xb0, 0x82, 0x93, 0x6b, 0x7a, 0x48, 0x59, 0x2d, 0x3c, 0x0e, 0x1f, + 0xf7, 0xe6, 0xd4, 0xc5, 0xb1, 0xa0, 0x92, 0x83, 0x7b, 0x6a, 0x58, 0x49, 0x3d, 0x2c, 0x1e, + 0x0f}; + +/************************************************************************* +* FPGA functions +************************************************************************/ + +static void delay(int ms) +{ + unsigned long timeout = jiffies + ((ms * HZ) / 1000); + while (jiffies < timeout); +} + +/* + * reset FPGA + */ + +static void fpga_reset(int iobase) +{ + outb(0, IER(iobase)); + outb(LCR_DLAB | LCR_BIT5, LCR(iobase)); + outb(1, DLL(iobase)); + outb(0, DLM(iobase)); + + outb(LCR_BIT5, LCR(iobase)); + inb(LSR(iobase)); + inb(MSR(iobase)); + /* turn off FPGA supply voltage */ + outb(MCR_OUT1 | MCR_OUT2, MCR(iobase)); + delay(100); + /* turn on FPGA supply voltage again */ + outb(MCR_DTR | MCR_RTS | MCR_OUT1 | MCR_OUT2, MCR(iobase)); + delay(100); +} + +/* + * send one byte to FPGA + */ + +static int fpga_write(int iobase, unsigned char wrd) +{ + unsigned char bit; + int k; + unsigned long timeout = jiffies + HZ / 10; + + for (k = 0; k < 8; k++) { + bit = (wrd & 0x80) ? (MCR_RTS | MCR_DTR) : MCR_DTR; + outb(bit | MCR_OUT1 | MCR_OUT2, MCR(iobase)); + wrd <<= 1; + outb(0xfc, THR(iobase)); + while ((inb(LSR(iobase)) & LSR_TSRE) == 0) + if (jiffies > timeout) + return -1; + } + + return 0; +} + +#ifdef MODULE +static void free_mcs(void) +{ + struct yam_mcs *p; + + while (yam_data) { + p = yam_data; + yam_data = yam_data->next; + kfree(p); + } +} +#endif + +static unsigned char * + add_mcs(unsigned char *bits, int bitrate) +{ + struct yam_mcs *p; + + /* If it already exists, replace the bit data */ + p = yam_data; + while (p) { + if (p->bitrate == bitrate) { + memcpy(p->bits, bits, YAM_FPGA_SIZE); + return p->bits; + } + p = p->next; + } + + /* Allocate a new mcs */ + p = kmalloc(sizeof(struct yam_mcs), GFP_ATOMIC); + if (p == NULL) { + printk(KERN_WARNING "YAM: no memory to allocate mcs\n"); + return NULL; + } + memcpy(p->bits, bits, YAM_FPGA_SIZE); + p->bitrate = bitrate; + p->next = yam_data; + yam_data = p; + + return p->bits; +} + +static unsigned char *get_mcs(int bitrate) +{ + struct yam_mcs *p; + + p = yam_data; + while (p) { + if (p->bitrate == bitrate) + return p->bits; + p = p->next; + } + + /* Load predefined mcs data */ + switch (bitrate) { + case 1200: + return add_mcs(bits_1200, bitrate); + default: + return add_mcs(bits_9600, bitrate); + } +} + +/* + * download bitstream to FPGA + * data is contained in bits[] array in fpgaconf.h + */ + +static int fpga_download(int iobase, int bitrate) +{ + int i, rc; + unsigned char *pbits; + + pbits = get_mcs(bitrate); + if (pbits == NULL) + return -1; + + fpga_reset(iobase); + for (i = 0; i < YAM_FPGA_SIZE; i++) { + if (fpga_write(iobase, pbits[i])) { + printk("yam: error in write cycle\n"); + return -1; /* write... */ + } + } + + fpga_write(iobase, 0xFF); + rc = inb(MSR(iobase)); /* check DONE signal */ + + /* Needed for some hardwares */ + delay(50); + + return (rc & MSR_DSR) ? 0 : -1; +} + + +/************************************************************************ +* Serial port init +************************************************************************/ + +static void yam_set_uart(struct device *dev) +{ + struct yam_port *yp = (struct yam_port *) dev->priv; + int divisor = 115200 / yp->baudrate; + + outb(0, IER(dev->base_addr)); + outb(LCR_DLAB | LCR_BIT8, LCR(dev->base_addr)); + outb(divisor, DLL(dev->base_addr)); + outb(0, DLM(dev->base_addr)); + outb(LCR_BIT8, LCR(dev->base_addr)); + outb(PTT_OFF, MCR(dev->base_addr)); + outb(0x00, FCR(dev->base_addr)); + + /* Flush pending irq */ + + inb(RBR(dev->base_addr)); + inb(MSR(dev->base_addr)); + + /* Enable rx irq */ + + outb(ENABLE_RTXINT, IER(dev->base_addr)); +} + + +/* --------------------------------------------------------------------- */ + +enum uart { + c_uart_unknown, c_uart_8250, + c_uart_16450, c_uart_16550, c_uart_16550A +}; + +static const char *uart_str[] = +{"unknown", "8250", "16450", "16550", "16550A"}; + +static enum uart yam_check_uart(unsigned int iobase) +{ + unsigned char b1, b2, b3; + enum uart u; + enum uart uart_tab[] = + {c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A}; + + b1 = inb(MCR(iobase)); + outb(b1 | 0x10, MCR(iobase)); /* loopback mode */ + b2 = inb(MSR(iobase)); + outb(0x1a, MCR(iobase)); + b3 = inb(MSR(iobase)) & 0xf0; + outb(b1, MCR(iobase)); /* restore old values */ + outb(b2, MSR(iobase)); + if (b3 != 0x90) + return c_uart_unknown; + inb(RBR(iobase)); + inb(RBR(iobase)); + outb(0x01, FCR(iobase)); /* enable FIFOs */ + u = uart_tab[(inb(IIR(iobase)) >> 6) & 3]; + if (u == c_uart_16450) { + outb(0x5a, SCR(iobase)); + b1 = inb(SCR(iobase)); + outb(0xa5, SCR(iobase)); + b2 = inb(SCR(iobase)); + if ((b1 != 0x5a) || (b2 != 0xa5)) + u = c_uart_8250; + } + return u; +} + +/****************************************************************************** +* Rx Section +******************************************************************************/ +static void inline + yam_rx_flag(struct device *dev, struct yam_port *yp) +{ + if (yp->dcd && yp->rx_len >= 3 && yp->rx_len < YAM_MAX_FRAME) { + int pkt_len = yp->rx_len - 2 + 1; /* -CRC + kiss */ + struct sk_buff *skb; + + if ((yp->rx_crch & yp->rx_crcl) != 0xFF) { + /* Bad crc */ + } else { + if (!(skb = dev_alloc_skb(pkt_len))) { + printk("%s: memory squeeze, dropping packet\n", dev->name); + ++yp->stats.rx_dropped; + } else { + unsigned char *cp; + skb->dev = dev; + cp = skb_put(skb, pkt_len); + *cp++ = 0; /* KISS kludge */ + memcpy(cp, yp->rx_buf, pkt_len - 1); + skb->protocol = htons(ETH_P_AX25); + skb->mac.raw = skb->data; + netif_rx(skb); + ++yp->stats.rx_packets; + } + } + } + yp->rx_len = 0; + yp->rx_crcl = 0x21; + yp->rx_crch = 0xf3; +} + +static void inline + yam_rx_byte(struct device *dev, struct yam_port *yp, unsigned char rxb) +{ + if (yp->rx_len < YAM_MAX_FRAME) { + unsigned char c = yp->rx_crcl; + yp->rx_crcl = (chktabl[c] ^ yp->rx_crch); + yp->rx_crch = (chktabh[c] ^ rxb); + yp->rx_buf[yp->rx_len++] = rxb; + } +} + +/******************************************************************************** +* TX Section +********************************************************************************/ + +static void ptt_on(struct device *dev) +{ + outb(PTT_ON, MCR(dev->base_addr)); +} + +static void ptt_off(struct device *dev) +{ + outb(PTT_OFF, MCR(dev->base_addr)); +} + +static int yam_send_packet(struct sk_buff *skb, struct device *dev) +{ + struct yam_port *yp = dev->priv; + + if (skb == NULL) { + return 0; + } + skb_queue_tail(&yp->send_queue, skb); + dev->trans_start = jiffies; + return 0; +} + +static void yam_start_tx(struct device *dev, struct yam_port *yp) +{ + if ((yp->tx_state == TX_TAIL) || (yp->txd == 0)) + yp->tx_count = 1; + else + yp->tx_count = (yp->bitrate * yp->txd) / 8000; + yp->tx_state = TX_HEAD; + ptt_on(dev); +} + +static unsigned short random_seed; + +static inline unsigned short random_num(void) +{ + random_seed = 28629 * random_seed + 157; + return random_seed; +} + +static void yam_arbitrate(struct device *dev) +{ + struct yam_port *yp = dev->priv; + + if (!yp || yp->magic != YAM_MAGIC + || yp->tx_state != TX_OFF || skb_queue_empty(&yp->send_queue)) { + return; + } + /* tx_state is TX_OFF and there is data to send */ + + if (yp->dupmode) { + /* Full duplex mode, don't wait */ + yam_start_tx(dev, yp); + return; + } + if (yp->dcd) { + /* DCD on, wait slotime ... */ + yp->slotcnt = yp->slot / 10; + return; + } + /* Is slottime passed ? */ + if ((--yp->slotcnt) > 0) + return; + + yp->slotcnt = yp->slot / 10; + + /* is random > persist ? */ + if ((random_num() % 256) > yp->pers) + return; + + yam_start_tx(dev, yp); +} + +static void yam_dotimer(unsigned long dummy) +{ + int i; + + for (i = 0; i < NR_PORTS; i++) { + struct device *dev = &yam_ports[i].dev; + if (dev->start) + yam_arbitrate(dev); + } + yam_timer.expires = jiffies + HZ / 100; + add_timer(&yam_timer); +} + +static void yam_tx_byte(struct device *dev, struct yam_port *yp) +{ + struct sk_buff *skb; + unsigned char b, temp; + + switch (yp->tx_state) { + case TX_OFF: + break; + case TX_HEAD: + if (--yp->tx_count <= 0) { + if (!(skb = skb_dequeue(&yp->send_queue))) { + ptt_off(dev); + yp->tx_state = TX_OFF; + break; + } + yp->tx_state = TX_DATA; + if (skb->data[0] != 0) { +/* do_kiss_params(s, skb->data, skb->len); */ + dev_kfree_skb(skb); + break; + } + yp->tx_len = skb->len - 1; /* strip KISS byte */ + if (yp->tx_len >= YAM_MAX_FRAME || yp->tx_len < 2) { + dev_kfree_skb(skb); + break; + } + memcpy(yp->tx_buf, skb->data + 1, yp->tx_len); + dev_kfree_skb(skb); + yp->tx_count = 0; + yp->tx_crcl = 0x21; + yp->tx_crch = 0xf3; + yp->tx_state = TX_DATA; + } + break; + case TX_DATA: + b = yp->tx_buf[yp->tx_count++]; + outb(b, THR(dev->base_addr)); + temp = yp->tx_crcl; + yp->tx_crcl = chktabl[temp] ^ yp->tx_crch; + yp->tx_crch = chktabh[temp] ^ b; + if (yp->tx_count >= yp->tx_len) { + yp->tx_state = TX_CRC1; + } + break; + case TX_CRC1: + yp->tx_crch = chktabl[yp->tx_crcl] ^ yp->tx_crch; + yp->tx_crcl = chktabh[yp->tx_crcl] ^ chktabl[yp->tx_crch] ^ 0xff; + outb(yp->tx_crcl, THR(dev->base_addr)); + yp->tx_state = TX_CRC2; + break; + case TX_CRC2: + outb(chktabh[yp->tx_crch] ^ 0xFF, THR(dev->base_addr)); + if (skb_queue_empty(&yp->send_queue)) { + yp->tx_count = (yp->bitrate * yp->txtail) / 8000; + if (yp->dupmode == 2) + yp->tx_count += (yp->bitrate * yp->holdd) / 8; + if (yp->tx_count == 0) + yp->tx_count = 1; + yp->tx_state = TX_TAIL; + } else { + yp->tx_count = 1; + yp->tx_state = TX_HEAD; + } + ++yp->stats.tx_packets; + break; + case TX_TAIL: + if (--yp->tx_count <= 0) { + yp->tx_state = TX_OFF; + ptt_off(dev); + } + break; + } +} + +/*********************************************************************************** +* ISR routine +************************************************************************************/ + +static void yam_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct device *dev; + struct yam_port *yp; + unsigned char iir; + int counter = 100; + int i; + + sti(); + + for (i = 0; i < NR_PORTS; i++) { + yp = &yam_ports[i]; + dev = &yp->dev; + + if (!dev->start) + continue; + + while ((iir = IIR_MASK & inb(IIR(dev->base_addr))) != IIR_NOPEND) { + unsigned char msr = inb(MSR(dev->base_addr)); + unsigned char lsr = inb(LSR(dev->base_addr)); + unsigned char rxb; + + if (lsr & LSR_OE) + ++yp->stats.rx_fifo_errors; + + yp->dcd = (msr & RX_DCD) ? 1 : 0; + + if (--counter <= 0) { + printk("%s: too many irq iir=%d\n", dev->name, iir); + return; + } + if (msr & TX_RDY) { + ++yp->nb_mdint; + yam_tx_byte(dev, yp); + } + if (lsr & LSR_RXC) { + ++yp->nb_rxint; + rxb = inb(RBR(dev->base_addr)); + if (msr & RX_FLAG) + yam_rx_flag(dev, yp); + else + yam_rx_byte(dev, yp, rxb); + } + } + } +} + +static int yam_net_get_info(char *buffer, char **start, off_t offset, int length, int dummy) +{ + int len = 0; + int i; + off_t pos = 0; + off_t begin = 0; + + cli(); + + for (i = 0; i < NR_PORTS; i++) { + if (yam_ports[i].iobase == 0 || yam_ports[i].irq == 0) + continue; + len += sprintf(buffer + len, "Device %s\n", yam_ports[i].name); + len += sprintf(buffer + len, " Up %d\n", yam_ports[i].dev.start); + len += sprintf(buffer + len, " Speed %u\n", yam_ports[i].bitrate); + len += sprintf(buffer + len, " IoBase 0x%x\n", yam_ports[i].iobase); + len += sprintf(buffer + len, " BaudRate %u\n", yam_ports[i].baudrate); + len += sprintf(buffer + len, " IRQ %u\n", yam_ports[i].irq); + len += sprintf(buffer + len, " TxState %u\n", yam_ports[i].tx_state); + len += sprintf(buffer + len, " Duplex %u\n", yam_ports[i].dupmode); + len += sprintf(buffer + len, " HoldDly %u\n", yam_ports[i].holdd); + len += sprintf(buffer + len, " TxDelay %u\n", yam_ports[i].txd); + len += sprintf(buffer + len, " TxTail %u\n", yam_ports[i].txtail); + len += sprintf(buffer + len, " SlotTime %u\n", yam_ports[i].slot); + len += sprintf(buffer + len, " Persist %u\n", yam_ports[i].pers); + len += sprintf(buffer + len, " TxFrames %lu\n", yam_ports[i].stats.tx_packets); + len += sprintf(buffer + len, " RxFrames %lu\n", yam_ports[i].stats.rx_packets); + len += sprintf(buffer + len, " TxInt %u\n", yam_ports[i].nb_mdint); + len += sprintf(buffer + len, " RxInt %u\n", yam_ports[i].nb_rxint); + len += sprintf(buffer + len, " RxOver %lu\n", yam_ports[i].stats.rx_fifo_errors); + len += sprintf(buffer + len, "\n"); + + pos = begin + len; + + if (pos < offset) { + len = 0; + begin = pos; + } + if (pos > offset + length) + break; + } + + sti(); + + *start = buffer + (offset - begin); + len -= (offset - begin); + + if (len > length) + len = length; + + return len; +} + +#ifdef CONFIG_INET +#ifndef PROC_NET_YAM +#define PROC_NET_YAM (PROC_NET_LAST+10) /* Sorry again... */ +#endif + +struct proc_dir_entry yam_proc_dir_entry = +{ + PROC_NET_YAM, 3, "yam", S_IFREG | S_IRUGO, 1, 0, 0, 0, + &proc_net_inode_operations, yam_net_get_info +}; + +#define yam_net_procfs_init() proc_net_register(&yam_proc_dir_entry); +#define yam_net_procfs_remove() proc_net_unregister(PROC_NET_YAM); +#else +#define yam_net_procfs_init() +#define yam_net_procfs_remove() +#endif + +/* --------------------------------------------------------------------- */ + +#if LINUX_VERSION_CODE >= 0x20119 +static struct net_device_stats * + yam_get_stats(struct device *dev) +#else +static struct enet_statistics * + yam_get_stats(struct device *dev) +#endif +{ + struct yam_port *yp; + + if (!dev || !dev->priv) + return NULL; + + yp = (struct yam_port *) dev->priv; + if (yp->magic != YAM_MAGIC) + return NULL; + + /* + * Get the current statistics. This may be called with the + * card open or closed. + */ + return &yp->stats; +} + +/* --------------------------------------------------------------------- */ + +static int yam_open(struct device *dev) +{ + struct yam_port *yp = (struct yam_port *) dev->priv; + enum uart u; + int i; + + printk(KERN_INFO "Trying %s at iobase 0x%lx irq %u\n", dev->name, dev->base_addr, dev->irq); + + if (!dev || !yp || !yp->bitrate) + return -ENXIO; + if (!dev->base_addr || dev->base_addr > 0x1000 - YAM_EXTENT || + dev->irq < 2 || dev->irq > 15) { + return -ENXIO; + } + if (check_region(dev->base_addr, YAM_EXTENT)) { + printk("%s: cannot 0x%lx busy\n", dev->name, dev->base_addr); + return -EACCES; + } + if ((u = yam_check_uart(dev->base_addr)) == c_uart_unknown) { + printk("%s: cannot find uart type\n", dev->name); + return -EIO; + } + if (fpga_download(dev->base_addr, yp->bitrate)) { + printk("%s: cannot init FPGA\n", dev->name); + return -EIO; + } + outb(0, IER(dev->base_addr)); + if (request_irq(dev->irq, yam_interrupt, SA_INTERRUPT | SA_SHIRQ, dev->name, NULL)) { + printk("%s: irq %d busy\n", dev->name, dev->irq); + return -EBUSY; + } + request_region(dev->base_addr, YAM_EXTENT, dev->name); + + yam_set_uart(dev); + dev->start = 1; + yp->slotcnt = yp->slot / 10; + + /* Reset overruns for all ports - FPGA programming makes overruns */ + for (i = 0; i < NR_PORTS; i++) { + inb(LSR(yam_ports[i].dev.base_addr)); + yam_ports[i].stats.rx_fifo_errors = 0; + } + + printk(KERN_INFO "%s at iobase 0x%lx irq %u uart %s\n", dev->name, dev->base_addr, dev->irq, + uart_str[u]); + MOD_INC_USE_COUNT; + return 0; +} + +/* --------------------------------------------------------------------- */ + +static int yam_close(struct device *dev) +{ + struct sk_buff *skb; + struct yam_port *yp = (struct yam_port *) dev->priv; + + if (!dev || !yp) + return -EINVAL; + /* + * disable interrupts + */ + outb(0, IER(dev->base_addr)); + outb(1, MCR(dev->base_addr)); + /* Remove IRQ handler if last */ + free_irq(dev->irq, NULL); + release_region(dev->base_addr, YAM_EXTENT); + dev->start = 0; + dev->tbusy = 1; + while ((skb = skb_dequeue(&yp->send_queue))) + dev_kfree_skb(skb); + + printk(KERN_INFO "%s: close yam at iobase 0x%lx irq %u\n", + yam_drvname, dev->base_addr, dev->irq); + MOD_DEC_USE_COUNT; + return 0; +} + +/* --------------------------------------------------------------------- */ + +static int yam_ioctl(struct device *dev, struct ifreq *ifr, int cmd) +{ + struct yam_port *yp = (struct yam_port *) dev->priv; + struct yamdrv_ioctl_cfg yi; + struct yamdrv_ioctl_mcs *ym; + int ioctl_cmd; + + if (copy_from_user(&ioctl_cmd, ifr->ifr_data, sizeof(int))) + return -EFAULT; + + if (yp == NULL || yp->magic != YAM_MAGIC) + return -EINVAL; + + if (!suser()) + return -EPERM; + + if (cmd != SIOCDEVPRIVATE) + return -EINVAL; + + switch (ioctl_cmd) { + + case SIOCYAMRESERVED: + return -EINVAL; /* unused */ + + case SIOCYAMSMCS: + if (dev->start) + return -EINVAL; /* Cannot change this parameter when up */ + ym = kmalloc(sizeof(struct yamdrv_ioctl_mcs), GFP_ATOMIC); + ym->bitrate = 9600; + if (copy_from_user(ym, ifr->ifr_data, sizeof(struct yamdrv_ioctl_mcs))) + return -EFAULT; + if (ym->bitrate > YAM_MAXBITRATE) + return -EINVAL; + add_mcs(ym->bits, ym->bitrate); + kfree(ym); + break; + + case SIOCYAMSCFG: + if (copy_from_user(&yi, ifr->ifr_data, sizeof(struct yamdrv_ioctl_cfg))) + return -EFAULT; + + if ((yi.cfg.mask & YAM_IOBASE) && dev->start) + return -EINVAL; /* Cannot change this parameter when up */ + if ((yi.cfg.mask & YAM_IRQ) && dev->start) + return -EINVAL; /* Cannot change this parameter when up */ + if ((yi.cfg.mask & YAM_BITRATE) && dev->start) + return -EINVAL; /* Cannot change this parameter when up */ + if ((yi.cfg.mask & YAM_BAUDRATE) && dev->start) + return -EINVAL; /* Cannot change this parameter when up */ + + if (yi.cfg.mask & YAM_IOBASE) { + yp->iobase = yi.cfg.iobase; + dev->base_addr = yi.cfg.iobase; + } + if (yi.cfg.mask & YAM_IRQ) { + if (yi.cfg.irq > 15) + return -EINVAL; + yp->irq = yi.cfg.irq; + dev->irq = yi.cfg.irq; + } + if (yi.cfg.mask & YAM_BITRATE) { + if (yi.cfg.bitrate > YAM_MAXBITRATE) + return -EINVAL; + yp->bitrate = yi.cfg.bitrate; + } + if (yi.cfg.mask & YAM_BAUDRATE) { + if (yi.cfg.baudrate > YAM_MAXBAUDRATE) + return -EINVAL; + yp->baudrate = yi.cfg.baudrate; + } + if (yi.cfg.mask & YAM_MODE) { + if (yi.cfg.mode > YAM_MAXMODE) + return -EINVAL; + yp->dupmode = yi.cfg.mode; + } + if (yi.cfg.mask & YAM_HOLDDLY) { + if (yi.cfg.holddly > YAM_MAXHOLDDLY) + return -EINVAL; + yp->holdd = yi.cfg.holddly; + } + if (yi.cfg.mask & YAM_TXDELAY) { + if (yi.cfg.txdelay > YAM_MAXTXDELAY) + return -EINVAL; + yp->txd = yi.cfg.txdelay; + } + if (yi.cfg.mask & YAM_TXTAIL) { + if (yi.cfg.txtail > YAM_MAXTXTAIL) + return -EINVAL; + yp->txtail = yi.cfg.txtail; + } + if (yi.cfg.mask & YAM_PERSIST) { + if (yi.cfg.persist > YAM_MAXPERSIST) + return -EINVAL; + yp->pers = yi.cfg.persist; + } + if (yi.cfg.mask & YAM_SLOTTIME) { + if (yi.cfg.slottime > YAM_MAXSLOTTIME) + return -EINVAL; + yp->slot = yi.cfg.slottime; + yp->slotcnt = yp->slot / 10; + } + break; + + case SIOCYAMGCFG: + yi.cfg.mask = 0xffffffff; + yi.cfg.iobase = yp->iobase; + yi.cfg.irq = yp->irq; + yi.cfg.bitrate = yp->bitrate; + yi.cfg.baudrate = yp->baudrate; + yi.cfg.mode = yp->dupmode; + yi.cfg.txdelay = yp->txd; + yi.cfg.holddly = yp->holdd; + yi.cfg.txtail = yp->txtail; + yi.cfg.persist = yp->pers; + yi.cfg.slottime = yp->slot; + if (copy_to_user(ifr->ifr_data, &yi, sizeof(struct yamdrv_ioctl_cfg))) + return -EFAULT; + break; + + default: + return -EINVAL; + + } + + return 0; +} + +/* --------------------------------------------------------------------- */ + +static int yam_set_mac_address(struct device *dev, void *addr) +{ + struct sockaddr *sa = (struct sockaddr *) addr; + + /* addr is an AX.25 shifted ASCII mac address */ + memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); + return 0; +} + +/* --------------------------------------------------------------------- */ + +static int yam_probe(struct device *dev) +{ + struct yam_port *yp; + + if (!dev) + return -ENXIO; + + yp = (struct yam_port *) dev->priv; + + dev->open = yam_open; + dev->stop = yam_close; + dev->do_ioctl = yam_ioctl; + dev->hard_start_xmit = yam_send_packet; + dev->get_stats = yam_get_stats; + + dev_init_buffers(dev); + skb_queue_head_init(&yp->send_queue); + +#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) + dev->hard_header = ax25_encapsulate; + dev->rebuild_header = ax25_rebuild_header; +#else /* CONFIG_AX25 || CONFIG_AX25_MODULE */ + dev->hard_header = NULL; + dev->rebuild_header = NULL; +#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */ + + dev->set_mac_address = yam_set_mac_address; + + dev->type = ARPHRD_AX25; /* AF_AX25 device */ + dev->hard_header_len = 73; /* We do digipeaters now */ + dev->mtu = 256; /* AX25 is the default */ + dev->addr_len = 7; /* sizeof an ax.25 address */ + memcpy(dev->broadcast, ax25_bcast, 7); + memcpy(dev->dev_addr, ax25_test, 7); + + /* New style flags */ + dev->flags = 0; + + return 0; +} + +/* --------------------------------------------------------------------- */ + +__initfunc(int yam_init(struct device *dev)) +{ + int i; + + printk(yam_drvinfo); + + /* Clears the IRQ table */ + memset(irqs, 0, sizeof(irqs)); + memset(yam_ports, 0, sizeof(yam_ports)); + + for (i = 0; i < NR_PORTS; i++) { + sprintf(yam_ports[i].name, "yam%d", i); + yam_ports[i].magic = YAM_MAGIC; + yam_ports[i].bitrate = DEFAULT_BITRATE; + yam_ports[i].baudrate = DEFAULT_BITRATE * 2; + yam_ports[i].iobase = 0; + yam_ports[i].irq = 0; + yam_ports[i].dupmode = 0; + yam_ports[i].holdd = DEFAULT_HOLDD; + yam_ports[i].txd = DEFAULT_TXD; + yam_ports[i].txtail = DEFAULT_TXTAIL; + yam_ports[i].slot = DEFAULT_SLOT; + yam_ports[i].pers = DEFAULT_PERS; + + dev = &yam_ports[i].dev; + + dev->priv = &yam_ports[i]; + dev->name = yam_ports[i].name; + dev->base_addr = yam_ports[i].iobase; + dev->irq = yam_ports[i].irq; + dev->init = yam_probe; + dev->if_port = 0; + dev->start = 0; + dev->tbusy = 1; + + if (register_netdev(dev)) { + printk(KERN_WARNING "yam: cannot register net device %s\n", dev->name); + return -ENXIO; + } + } + + yam_timer.function = yam_dotimer; + yam_timer.expires = jiffies + HZ / 100; + add_timer(&yam_timer); + + yam_net_procfs_init(); + + /* do not keep this device */ + return 1; +} + +/* --------------------------------------------------------------------- */ + +#ifdef MODULE + +/* + * command line settable parameters + */ + +#if LINUX_VERSION_CODE >= 0x20115 + +MODULE_AUTHOR("Frederic Rible F1OAT frible@teaser.fr"); +MODULE_DESCRIPTION("Yam amateur radio modem driver"); + +#endif + +__initfunc(int init_module(void)) +{ + int ret = yam_init(NULL); + + return (ret == 1) ? 0 : ret; +} + +/* --------------------------------------------------------------------- */ + +void cleanup_module(void) +{ + int i; + + del_timer(&yam_timer); + for (i = 0; i < NR_PORTS; i++) { + struct device *dev = &yam_ports[i].dev; + if (!dev->priv) + continue; + if (dev->start) + yam_close(dev); + unregister_netdev(dev); + } + free_mcs(); + yam_net_procfs_remove(); +} + +#endif /* MODULE */ +/* --------------------------------------------------------------------- */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/hamradio/yam1200.h linux.pre11.3/drivers/net/hamradio/yam1200.h --- linux.vanilla/drivers/net/hamradio/yam1200.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/net/hamradio/yam1200.h Tue Jul 20 00:29:25 1999 @@ -0,0 +1,343 @@ +/* + * + * File yam1k2b5.mcs converted to h format by mcs2h + * + * (C) F6FBB 1998 + * + * Tue Aug 25 20:24:08 1998 + * + */ + +static unsigned char bits_1200[]= { +0xff,0xf2,0x00,0xa5,0xad,0xff,0xfe,0x9f,0xff,0xef,0xf3,0xcb,0xff,0xdb,0xfc,0xf2, +0xff,0xf6,0xff,0x3c,0xbf,0xfd,0xbf,0xdf,0x6e,0x3f,0x6f,0xf1,0x7d,0xb4,0xfd,0xbf, +0xdf,0x6f,0x3f,0x6f,0xf7,0x0b,0xff,0xdb,0xfd,0xf2,0xff,0xf6,0xff,0xff,0xff,0xff, +0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xdf,0xff,0xff,0xff,0xef,0xff,0xff,0xff, +0xfd,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xbf, +0xff,0xff,0xf7,0xff,0xff,0xfb,0xff,0xff,0xff,0xfc,0xff,0xfe,0xff,0xff,0xff,0xf0, +0x5f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,0xf1,0xff,0xff,0xfe,0x7f,0xbf,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xfb,0xff,0xff,0xff,0xf0,0x9f, +0xff,0xff,0xff,0xfe,0xff,0xfd,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xf7,0xff, +0xff,0xff,0xfb,0xff,0xfb,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xf7,0xff,0xff,0xfb,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xef,0xff,0xf0,0x5f,0xff, +0xff,0xff,0xfe,0xff,0xff,0xef,0xff,0xff,0xfb,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xbf,0xff,0xff,0xdf,0xf7,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xfb,0xfe,0xff,0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff, +0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xeb, +0xff,0xff,0xff,0xfd,0xff,0xbf,0xf1,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xfb, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x6f,0xff,0xff,0xff, +0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xf7,0xff,0xff,0xf1,0xff,0xff,0xf7,0xbf,0xe7,0xff,0xff,0xff,0xff,0xfb, +0xff,0xff,0xff,0xff,0xff,0xff,0x77,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xdb, +0xff,0xff,0xf5,0xa5,0xfd,0x4b,0x6e,0xef,0x33,0x32,0xdd,0xd3,0x4a,0xd6,0x92,0xfe, +0xb3,0x3f,0xbd,0xf1,0xfa,0xdb,0xfe,0xf7,0xf6,0x96,0xbd,0xbd,0xff,0xbd,0xff,0xed, +0x7f,0x6b,0x7f,0xfb,0xdf,0xfe,0xfb,0xfe,0x90,0xcf,0xff,0xff,0xff,0xfe,0xbe,0xef, +0xff,0xff,0xdb,0x5f,0xf6,0xff,0xf6,0x8f,0xfd,0xa5,0xdd,0xff,0xff,0xff,0xff,0x6f, +0x7f,0xdb,0xf1,0xfc,0xbf,0xff,0x6f,0xff,0xef,0xfc,0x5b,0x5d,0xda,0xdf,0xf4,0xff, +0xf2,0xff,0xfd,0xbf,0xff,0xff,0xff,0xd0,0x1f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff, +0xff,0xfb,0xef,0xb7,0xfc,0x33,0xff,0xfb,0xff,0x04,0x6a,0xf3,0x3c,0x36,0xff,0xf0, +0x0f,0xf1,0x0f,0xff,0xff,0xff,0xf3,0x15,0x72,0x0f,0xf1,0x6f,0xff,0xfe,0x94,0x3f, +0xff,0xff,0xff,0x7b,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf0, +0xf7,0xef,0xb7,0xfc,0x33,0xff,0xff,0xff,0x04,0x6a,0xf3,0x3c,0x36,0xff,0xf0,0x0f, +0xf1,0x0f,0xff,0xff,0xff,0xf3,0x15,0x73,0x8f,0xf2,0x6f,0xff,0xfe,0x94,0x3f,0xff, +0xff,0xff,0x7d,0x9f,0xff,0xf0,0x0f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0x9e, +0xff,0xfc,0xef,0xd3,0xfb,0xff,0x7f,0xf5,0x5f,0xfe,0x59,0xff,0xff,0xff,0xfc,0xf1, +0xfe,0x7f,0xff,0xff,0xfa,0x17,0xff,0xe7,0xef,0xef,0xff,0xff,0x3f,0xf1,0xff,0xff, +0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xf5,0xff,0xbf,0xff,0xfc,0xea, +0xff,0xf0,0xff,0xff,0xbf,0xf9,0x3f,0xb1,0xef,0xff,0xd7,0xff,0xfb,0xff,0xf0,0xff, +0xff,0xf3,0xff,0xdf,0xff,0x7b,0xff,0xfd,0xff,0xf6,0xff,0xbf,0xff,0xff,0xbf,0xff, +0xff,0xff,0xda,0xf0,0xff,0xff,0xff,0xff,0xfe,0xf2,0xc0,0x01,0x00,0x00,0x02,0x02, +0x02,0x02,0x00,0x40,0x40,0x40,0x10,0x00,0x00,0x00,0x20,0x00,0x00,0x01,0x00,0x00, +0x00,0x00,0x00,0x00,0x19,0x00,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10, +0x00,0x3c,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xfb,0xff,0xfd,0xff, +0xff,0x7f,0xff,0xff,0xbf,0xff,0xef,0xff,0xff,0xfd,0xff,0xff,0xf1,0xff,0xdf,0xff, +0xff,0xff,0xff,0xff,0xff,0xbf,0xfe,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xdf, +0xdb,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xf0,0xbf,0xdf,0xff,0x7f,0xff,0xff,0xff,0xff, +0xdf,0xdf,0xff,0xef,0xff,0x9e,0xef,0xff,0xff,0x7f,0xff,0xf1,0xef,0xff,0xff,0xff, +0xf7,0xfa,0xbf,0xff,0xff,0xfe,0x47,0xef,0xff,0xbd,0xf6,0xff,0xff,0xdf,0xf5,0xf0, +0xf0,0xef,0xff,0xff,0xff,0xfe,0xf8,0x30,0x00,0x00,0x00,0x04,0x00,0x01,0x02,0x08, +0x16,0x00,0x00,0x00,0x80,0x00,0x01,0x02,0x00,0x80,0x01,0x0c,0x02,0x00,0x00,0x01, +0x00,0x00,0x20,0x00,0x00,0x06,0x00,0x20,0x00,0x10,0x00,0x14,0x00,0x04,0xc1,0xf0, +0x2f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xff,0x7f, +0xec,0xff,0xff,0xfa,0xff,0xbf,0xff,0x6f,0xff,0xe1,0xff,0xff,0xff,0xff,0xbd,0xfe, +0x46,0xff,0xef,0x7f,0xcd,0xdf,0xff,0xff,0xfd,0xff,0xbd,0xff,0x7f,0x7f,0xf0,0x4f, +0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff, +0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0xa4,0xbc,0xcd,0x6d,0x6b,0x6f,0x5b,0xdc,0x33, +0x5a,0xf6,0xf7,0xf6,0xb3,0x3f,0xbd,0xc1,0xfa,0x5a,0xf6,0xf6,0xb6,0xf7,0xff,0xbd, +0xbb,0x3c,0xce,0xcf,0x34,0xef,0x33,0xbb,0xcc,0xff,0xff,0xff,0xf0,0x4f,0xff,0xff, +0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,0xf6,0xd6,0xff,0xfd,0xfd,0xbf,0xff,0xad, +0xbf,0xf9,0x7f,0x6f,0xfc,0xdb,0xf1,0xfd,0xbf,0xff,0x6f,0xff,0xff,0xda,0xdb,0xfc, +0xdb,0xff,0x76,0x8f,0xf6,0xff,0xcd,0xab,0xfe,0xfb,0xff,0xd0,0xff,0xff,0xff,0xff, +0xfe,0xff,0x9f,0xff,0xf4,0x20,0xaf,0x6d,0x0b,0xc1,0x7b,0xff,0xff,0xff,0xcb,0xff, +0x3f,0xf0,0xef,0x7f,0x0f,0xf1,0xc3,0x3c,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x0b, +0x1d,0x6a,0x64,0x05,0x6b,0x99,0x01,0xff,0xfd,0xef,0xf0,0x2f,0xff,0xff,0xff,0xfe, +0xff,0xff,0xff,0xf4,0x00,0x2f,0xcc,0x0b,0xc3,0x7f,0xff,0xff,0xff,0x0a,0xdf,0xbf, +0xfd,0x7f,0xff,0xff,0xf1,0xc3,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x4a,0x0e, +0x96,0x64,0x02,0x97,0x99,0x10,0xff,0xff,0xff,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff, +0xff,0xff,0xfe,0x84,0xf9,0xd5,0x27,0xf1,0x7f,0xff,0xf8,0xeb,0xdf,0xf3,0xcf,0x3f, +0x1f,0xff,0xf7,0x11,0xff,0xcf,0xff,0xfe,0x67,0xff,0xff,0xff,0xff,0xc4,0xff,0xff, +0xb3,0xa1,0xff,0xf9,0xe0,0xff,0xff,0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xf5,0xff, +0xff,0xfb,0x7f,0xe0,0xff,0xc7,0xfe,0x7f,0x3f,0xff,0xfd,0x77,0x8d,0x7f,0x0f,0xff, +0xc3,0xff,0xf1,0xbf,0x8f,0xcf,0xff,0xff,0xdd,0x7b,0xff,0xf6,0xfa,0xf7,0xff,0x40, +0x9f,0xf9,0x7f,0xd8,0xff,0xff,0xfa,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xf1,0xc0,0x00, +0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x10,0x00,0x00,0x10, +0x00,0x01,0x00,0x10,0x20,0x20,0x00,0x00,0x10,0x00,0x04,0x01,0x05,0x00,0x00,0x00, +0x00,0x40,0x40,0x00,0x00,0x3c,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff, +0xff,0xff,0xfe,0x7f,0x7f,0xff,0xef,0xff,0xff,0xdf,0xff,0xff,0xdf,0xff,0xef,0xf7, +0xf1,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xf7,0xff,0xff,0xff,0xfc,0xfd,0xff,0x7f, +0x7e,0xff,0xff,0xff,0xdb,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xf0,0xbb,0xff,0xff,0xff, +0xff,0xff,0xfe,0xeb,0xfd,0x6f,0xff,0xf7,0xfe,0xf5,0x7f,0xff,0xff,0x7f,0xbf,0xb1, +0xff,0xff,0x9f,0xbf,0xfb,0xff,0xfe,0xff,0xfe,0xff,0xf7,0xeb,0xdf,0xbf,0x5f,0xdd, +0xff,0xdb,0xfd,0xd0,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xf8,0x30,0x20,0x00,0x42,0x00, +0x00,0x00,0x30,0x18,0x04,0x08,0x09,0x21,0x82,0x80,0x02,0x00,0x08,0x00,0x01,0x00, +0x00,0x00,0x0c,0x20,0x10,0x00,0x11,0x00,0x44,0x84,0x00,0x20,0x20,0x84,0x80,0x00, +0x00,0x00,0xc1,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xf7,0xff,0xfb,0xdd,0xf9,0xff, +0xda,0xff,0xdc,0xdd,0xfc,0xfb,0xff,0xbf,0xfb,0x3e,0xd7,0x96,0xfe,0x61,0xf7,0xff, +0x7f,0xff,0x3f,0xfd,0xff,0xdf,0xcf,0xf7,0xdf,0xf7,0xbf,0xfd,0xff,0xfe,0xef,0xef, +0xfe,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf3,0xbd,0xfd,0x4b,0x74,0xcf, +0x73,0x5b,0xcb,0x3b,0xdf,0xfe,0xf7,0xfe,0xd3,0x75,0xac,0xa1,0xfb,0xdf,0xfe,0xf7, +0x76,0x96,0xb5,0x24,0xbd,0xa5,0xad,0x49,0x2f,0x69,0x2b,0x52,0x5b,0xbd,0xff,0xff, +0xf0,0xcf,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,0xf6,0xfe,0xff,0xcc, +0xa7,0xfb,0xad,0xff,0x7f,0x6f,0xff,0x6d,0x7f,0xdb,0xf1,0xfd,0xbf,0xff,0x6f,0xff, +0x6f,0xff,0xdb,0xff,0xdb,0xff,0xf6,0x97,0xf6,0xff,0xb5,0xb5,0xff,0xff,0xff,0xd0, +0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0xa5,0xbc,0x43,0xfc,0x7c,0x03,0xe7, +0xff,0xff,0x20,0xff,0xff,0xff,0xcc,0xfd,0x7d,0xf1,0xff,0xff,0xff,0xff,0xd5,0x59, +0xba,0x56,0x66,0x6a,0xad,0x9a,0xa9,0x9a,0x97,0xa5,0xaa,0xbb,0xff,0xff,0xf0,0x0f, +0xff,0xff,0xff,0xfe,0xfe,0xfb,0xff,0xfd,0xf7,0xfd,0x43,0xff,0xfd,0x6b,0xe7,0xff, +0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0x3f,0xf1,0xff,0xff,0xff,0xff,0xd5,0x59,0xb5, +0xa6,0x66,0x6a,0xad,0x9a,0xa9,0x99,0x6b,0x5a,0xaa,0xff,0xff,0xb7,0xf0,0x3f,0xff, +0xff,0xff,0xfe,0xff,0xff,0xff,0xfe,0x9c,0xf7,0xfd,0xd2,0x41,0xff,0xff,0xf2,0x7f, +0x8f,0xff,0xff,0x3d,0xf3,0xff,0x17,0xf1,0xff,0xff,0xff,0xff,0xff,0x7f,0xdf,0xfc, +0x8f,0x38,0xff,0xef,0x23,0xff,0xfb,0xf7,0xc8,0xff,0xff,0xff,0xf0,0x9f,0xff,0xff, +0xff,0xfe,0xf5,0x7f,0xff,0xfd,0xff,0xe4,0xff,0xeb,0xff,0xcf,0xbf,0xfa,0xff,0xab, +0xef,0xff,0xfb,0xff,0xf3,0xfd,0x61,0xff,0xff,0xff,0xff,0xfa,0xff,0xfb,0xfd,0x0d, +0xff,0xfe,0xff,0x43,0x7f,0xfe,0xbf,0xd0,0xfd,0xff,0xfa,0xf0,0x3f,0xff,0xff,0xff, +0xfe,0xf3,0xc0,0x00,0x00,0x00,0x02,0x00,0x02,0x01,0x00,0x60,0xc0,0x40,0x00,0x00, +0x00,0x00,0x34,0x04,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x88,0x00, +0x00,0x03,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x3c,0xf0,0x3f,0xff,0xff,0xff,0xfe, +0xfd,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x7f,0xbf,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xf7,0xf1,0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,0xfd,0xff, +0xff,0xff,0xff,0xfe,0xfe,0x5f,0xff,0xff,0xcb,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xf0, +0xff,0xff,0xfd,0xff,0xef,0xe3,0xde,0xee,0xd9,0xc5,0x93,0xff,0xff,0xfe,0xfe,0xff, +0xfb,0xee,0xfe,0xf1,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xbf,0xf7,0xff,0xff,0x7f, +0xaf,0xbd,0xdf,0xdf,0xfb,0xf3,0xf3,0xf0,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xf8,0x34, +0x00,0x06,0x61,0x00,0x18,0x01,0xa0,0x05,0x17,0x00,0x20,0x05,0x28,0x20,0x00,0x00, +0x05,0x00,0x41,0x00,0x00,0x40,0x00,0x09,0x00,0x01,0x20,0x86,0x82,0x08,0x40,0x03, +0x80,0x30,0x70,0x08,0x14,0x02,0xc1,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff, +0xff,0xff,0xbd,0xef,0xfb,0xff,0xff,0xfb,0x9c,0x7f,0xef,0xdf,0xff,0xbf,0xeb,0xde, +0xff,0xc1,0x7f,0xff,0xfb,0x7f,0xff,0xff,0xff,0x5f,0xff,0xff,0xff,0xdf,0xbf,0xef, +0x3f,0xf7,0x8f,0xef,0x7f,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xbd, +0xdf,0xef,0x7d,0x6d,0x2b,0x5a,0x5d,0xd2,0xdf,0xf6,0x92,0xb6,0xb2,0xb3,0xac,0xa1, +0xfb,0xdf,0xfe,0xf1,0xee,0xf5,0xf6,0xbc,0x6b,0xbd,0x7d,0xaf,0x1a,0xef,0x5f,0x6b, +0xc6,0xff,0xff,0xff,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff, +0xf6,0xff,0xf6,0xb7,0xfd,0xad,0xfd,0xbf,0xf3,0x6f,0xff,0x6f,0xff,0xdb,0xd1,0xfd, +0xbf,0xff,0x6f,0xf5,0x6b,0xbc,0x5b,0x3c,0xda,0xef,0x16,0xaf,0x16,0xff,0xcd,0xab, +0xff,0x6f,0xff,0xd0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfc,0xbf,0xff,0xff, +0xff,0x6c,0x03,0x10,0xc1,0xf3,0xff,0xf3,0x3a,0xf3,0xca,0xff,0xaf,0xf1,0xff,0xff, +0xff,0xff,0xd9,0x96,0xa6,0x65,0xa6,0x66,0x6a,0x95,0x69,0x69,0x6a,0x5a,0x5a,0xff, +0xff,0x5f,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff, +0xea,0x0f,0x50,0xc3,0xf3,0x7f,0xff,0xf3,0xf3,0xc3,0xff,0xaf,0xf1,0xff,0xff,0xff, +0xff,0xd9,0x96,0xa6,0x65,0xa6,0x66,0x6a,0x95,0x69,0x69,0x6a,0x5a,0x5a,0xff,0xff, +0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xd7,0xff,0xff,0x5f,0xc1, +0x3f,0xf7,0x5e,0xf5,0xce,0x9e,0x5f,0x3f,0x17,0xff,0xf3,0xe1,0xff,0xff,0xff,0xff, +0xd8,0xff,0xfa,0xfe,0x67,0xff,0xfe,0xbf,0x5a,0xff,0xff,0xaf,0xf5,0xff,0xff,0xff, +0xf0,0x2f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xfd,0xff,0xf7,0xff,0xfd,0x4e,0x3d, +0x3f,0xe7,0x0b,0xbf,0x8f,0xf9,0xff,0xeb,0xe3,0xff,0xe1,0xff,0xff,0xfc,0xff,0xc7, +0x9f,0xff,0x3e,0x39,0xe5,0xff,0xcf,0x9b,0xf9,0xff,0xff,0xc5,0xff,0xff,0xfa,0xf0, +0x5f,0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00, +0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x20,0x00,0x20, +0x00,0x01,0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0xf0,0x4f, +0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xbf, +0x3f,0xff,0xff,0xbf,0xff,0xff,0xff,0xfb,0xf1,0xff,0xff,0xff,0xff,0xf7,0xff,0xf7, +0xff,0xed,0xff,0xfb,0xfe,0xff,0x7f,0xff,0x7f,0xdf,0xff,0xff,0xdd,0xf0,0x3f,0xff, +0xff,0xff,0xfe,0xf0,0xff,0xff,0xf3,0xff,0xf7,0xff,0xfe,0x5f,0xff,0xf7,0xff,0xff, +0xdf,0xff,0xff,0xff,0xf7,0xfe,0x7b,0xf1,0xff,0xfd,0xfd,0xff,0xdf,0xdf,0xff,0x7d, +0x73,0xf9,0xff,0xc3,0x7e,0xfe,0xff,0xef,0xd7,0xff,0xcf,0xd0,0xf0,0x6f,0xff,0xff, +0xff,0xfe,0xf8,0x30,0x00,0x00,0x40,0x04,0x00,0x01,0x41,0x20,0x00,0x04,0x00,0x02, +0xd5,0x09,0x00,0x02,0x80,0x02,0x01,0x00,0x00,0x00,0x0a,0x04,0x00,0x07,0x00,0x01, +0x50,0x01,0x80,0x02,0x61,0x40,0x41,0x0c,0x14,0x08,0xc1,0xf0,0x9f,0xff,0xff,0xff, +0xfe,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfe,0xdf,0xcb,0x5f,0xfe,0xef,0xff,0xfe, +0xff,0x3f,0xff,0x7f,0xfd,0xc1,0xff,0xff,0x7f,0xff,0xdf,0xfd,0xfc,0xfd,0xf7,0xee, +0xff,0xff,0x4e,0xff,0xdf,0xcf,0xdb,0xeb,0xff,0xff,0xf0,0x1f,0xff,0xff,0xff,0xfe, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff,0xfe,0x7f, +0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff, +0xf7,0xfb,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0x7f,0xff,0xff,0xff,0x7f,0xff,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xdd,0xff, +0xff,0xff,0xa5,0xff,0x6f,0x6b,0xe9,0x6f,0xda,0xca,0xfb,0xdd,0xee,0xf7,0xf6,0xb2, +0xb3,0xa4,0xa1,0x5b,0x5b,0xf6,0xd7,0xf4,0xf7,0x7b,0xbd,0xbd,0xad,0xcf,0xef,0x7f, +0x6b,0x7f,0x3b,0xdf,0xdb,0xff,0xff,0x30,0xcf,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff, +0xff,0xff,0xff,0xf6,0xfe,0x96,0xff,0xfd,0xb5,0xfd,0xbf,0xad,0x7f,0xff,0x6f,0xff, +0xde,0xd1,0xad,0xad,0xe9,0xff,0xf1,0xec,0xef,0xde,0x3f,0xcb,0xff,0xf6,0xff,0x32, +0xff,0xc5,0xbd,0xff,0xff,0xff,0xd0,0xbf,0xff,0xff,0xff,0xfe,0xfe,0xfb,0xff,0xf4, +0x28,0xbf,0xff,0xfd,0xfb,0xd3,0xff,0xff,0x42,0xff,0xff,0xff,0xea,0xb3,0xfc,0xc3, +0xc1,0xff,0x33,0xff,0xc0,0x15,0x6b,0x70,0xff,0xf0,0xf2,0x4f,0xff,0xfc,0x3e,0x97, +0x3c,0xff,0xff,0xfd,0xef,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfe,0x78, +0xbf,0xff,0xfd,0xf3,0xef,0x55,0xff,0x7e,0xff,0xff,0xff,0xea,0xb3,0xfc,0xc3,0xc1, +0xff,0x33,0xff,0xc0,0x15,0x6f,0xff,0x0f,0xf0,0xf0,0x0f,0xff,0xfc,0x3d,0x6b,0xc3, +0xff,0xff,0xfe,0xf7,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfc,0xff, +0xff,0x23,0xf8,0x7f,0xff,0x4e,0xff,0xff,0xff,0xfb,0xf9,0x17,0xff,0xf6,0xf1,0xff, +0xcf,0xef,0xff,0xff,0x13,0xdf,0xe6,0x2f,0xc7,0xff,0xff,0xe7,0xc1,0xfd,0xff,0xfe, +0xff,0xff,0xff,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xff,0xfe,0xae,0xff, +0xff,0x7f,0x3b,0x3f,0xfc,0x7f,0xfc,0xef,0xff,0xfc,0xe2,0x7b,0xff,0xf1,0xfd,0xed, +0xef,0xff,0xff,0x35,0x73,0xff,0xff,0xfe,0xfa,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff, +0xff,0xfa,0xf0,0x8f,0xff,0xff,0xff,0xfe,0xf1,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x80,0x00,0x00,0x40,0x00,0x00,0x00,0x0c,0x04,0x01,0x40,0x40,0x00, +0x00,0x30,0x28,0x04,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00, +0x38,0xf0,0x0f,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xfb,0xff,0x7f, +0xff,0xff,0x9f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xdf,0xdf,0xff, +0xff,0xff,0xff,0xed,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xbf,0xbf,0xff,0xff,0xc3, +0xf0,0x3f,0xff,0xff,0xff,0xfe,0xf0,0xbf,0xfd,0xff,0xbf,0xff,0xff,0xfd,0xff,0xff, +0xff,0xff,0xff,0xfd,0x7b,0xff,0x7f,0xff,0xbd,0xff,0xf1,0xef,0xff,0xff,0xfd,0xdf, +0xfd,0xfb,0xff,0xff,0xbf,0xbe,0xff,0xcd,0x7f,0xfc,0xf7,0xf7,0x6f,0xbf,0xd8,0xf0, +0xef,0xff,0xff,0xff,0xfe,0xf8,0x30,0x00,0x00,0x00,0x04,0x00,0x00,0xa0,0x00,0x00, +0xc0,0x00,0x00,0x20,0x34,0x00,0x00,0x00,0x0c,0x81,0x00,0x20,0xa4,0x20,0x00,0x10, +0x08,0x04,0x48,0x08,0x00,0x40,0x93,0x00,0x10,0x00,0x38,0x18,0x20,0xc1,0xf0,0x3f, +0xff,0xff,0xff,0xfe,0xff,0xfb,0xff,0xff,0xb9,0xdf,0xfe,0xb3,0xff,0xff,0xe7,0xfd, +0xff,0xff,0x3b,0xff,0x7f,0xff,0xbf,0xff,0xc1,0xff,0xfc,0xff,0xff,0x3f,0x77,0xfe, +0xfe,0xcf,0xff,0xbf,0xfd,0xbf,0xff,0xfe,0xed,0xf2,0xfd,0xf7,0xff,0xf0,0x2f,0xff, +0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xbf,0xff,0xff, +0xff,0xfe,0xff,0xff,0xff,0xf3,0xad,0xcf,0xef,0x70,0xc9,0x73,0x3b,0xdf,0x5b,0x4a, +0xf6,0xb7,0xfe,0xd7,0xf5,0xbc,0xc1,0x33,0xca,0xd6,0xb7,0x6e,0xf7,0xfb,0xbd,0xc5, +0x24,0xcf,0x6f,0x2f,0x4d,0x2b,0xba,0x5a,0xff,0xff,0xff,0xf0,0xaf,0xff,0xff,0xff, +0xfe,0xbf,0xff,0xff,0xff,0xff,0xf6,0xf6,0xd7,0xff,0xff,0xad,0xbd,0xff,0xff,0xff, +0xef,0xf7,0x7f,0xfc,0x5b,0xb1,0xfd,0xbd,0x75,0x6f,0xef,0x6a,0xfd,0x5b,0xfb,0xdb, +0x3a,0xbf,0x8e,0x9f,0xff,0xbf,0xfd,0xff,0x6f,0xff,0xd0,0x6f,0xff,0xff,0xff,0xfe, +0xff,0xbb,0xff,0xf0,0x3f,0xff,0xff,0xfd,0xfb,0x7f,0xde,0xff,0xff,0x5a,0xd6,0xbf, +0xd8,0x2a,0xbf,0xbf,0xf1,0xe5,0xff,0xcc,0xc0,0xa9,0x70,0xff,0xf3,0x3c,0x3c,0xfd, +0x57,0xfd,0x98,0x03,0x00,0xc3,0xff,0xff,0xff,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xff, +0xff,0xff,0xff,0x3d,0xbf,0xff,0xfd,0xfb,0xff,0xdb,0xff,0xff,0x0f,0xfc,0x3f,0xd8, +0x2a,0xbf,0xbf,0xf1,0xef,0xff,0xcc,0xc0,0x96,0xbe,0xff,0xf3,0x3f,0xff,0xfd,0x57, +0xfd,0x99,0x0f,0xff,0xc3,0xff,0xff,0xff,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xff,0xff, +0xff,0xf1,0xe7,0xff,0xff,0xf3,0x8e,0x7b,0xff,0xa8,0xff,0xdf,0x7f,0x8e,0x78,0x73, +0xff,0xf1,0x51,0x62,0xff,0xfc,0x4b,0xff,0xf3,0xff,0x7e,0xcf,0xf9,0xff,0xfd,0xff, +0xff,0x7f,0xff,0xe0,0xff,0xff,0xff,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff, +0xfb,0xfd,0xae,0xff,0xfc,0xfe,0x6f,0x3f,0xf8,0xfd,0x77,0xaf,0xfe,0x37,0xfe,0x7b, +0xff,0xb1,0x8c,0xff,0xef,0xfd,0xf8,0xe7,0xbf,0xff,0xf1,0xfe,0x3e,0xf7,0xfe,0x95, +0x3e,0xbf,0xff,0xff,0xff,0xfa,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xf1,0xc0,0x00,0x00, +0x01,0x04,0x00,0x00,0x00,0x00,0x80,0x02,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x08, +0x41,0x80,0x10,0x00,0x00,0x08,0x10,0x84,0x00,0x0c,0x04,0x02,0x61,0x00,0x00,0x81, +0x00,0x00,0x00,0x00,0x3d,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff, +0xff,0xff,0x7f,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1, +0x7f,0xbf,0xf7,0x7f,0xef,0xff,0xef,0xff,0xf7,0xfd,0xff,0xff,0xfd,0x7f,0xff,0xbe, +0xdf,0xff,0xff,0xd9,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xf0,0xbb,0xff,0x7f,0xfb,0xff, +0xfb,0xff,0xbf,0xff,0xf3,0x7f,0xfb,0xfd,0xeb,0x7f,0xdf,0xfa,0xff,0xde,0xf0,0xed, +0xff,0xb1,0xf7,0xf9,0x1f,0xb5,0x5b,0xfe,0x7e,0xf7,0xbe,0xfd,0x7f,0x5f,0xb5,0xf7, +0xff,0xff,0xd0,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf8,0x30,0x01,0x00,0x07,0x42,0x01, +0x00,0x6a,0x18,0x50,0x80,0x00,0x00,0x02,0x40,0x01,0x01,0x20,0x01,0x01,0x24,0x14, +0x21,0x10,0x02,0x08,0x07,0x08,0x00,0x40,0x10,0x80,0x58,0x00,0x84,0x80,0x18,0x10, +0x40,0xc1,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf7,0xff,0xdb,0xb7,0xf3, +0xdf,0x7c,0xf8,0x74,0xff,0xff,0x6f,0x7d,0x3f,0x7e,0xec,0x7f,0xc1,0xf5,0xff,0xcf, +0x6f,0x9f,0xf9,0xdf,0xbe,0xe5,0xe7,0xff,0xd7,0xf3,0xdd,0xfb,0xff,0xfc,0xff,0xbf, +0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xf0,0x2f,0xff,0xff,0xff,0xfe,0xd7,0xff,0xff,0xff,0xb4,0xcf,0xef,0x77,0x6f,0x73, +0x3a,0x4a,0x3a,0xcb,0xd4,0xf7,0x2e,0xd6,0xbd,0xbd,0xa1,0x3b,0xdf,0xd6,0xf7,0xee, +0xd3,0x35,0xbd,0xfb,0xbd,0xce,0xeb,0x2b,0x4d,0x2f,0xbb,0xda,0xff,0xff,0xfe,0xb0, +0x5f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdf,0x5f,0x36,0xaf,0x3f,0xed,0xb7, +0xf5,0xfd,0xf3,0x2b,0xef,0x77,0xff,0xfb,0xda,0xb1,0xbd,0xa3,0x77,0x69,0x7f,0x4f, +0xff,0xdb,0xfa,0x5b,0xff,0xf2,0xfe,0xff,0x96,0xff,0xff,0xfe,0xdf,0xff,0xd0,0xaf, +0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0x8f,0xfd,0x40,0x6f,0x9e,0x83,0x5a,0x0f, +0xfa,0xc3,0xff,0xff,0xfc,0xe9,0x7f,0xf3,0x01,0xd0,0x00,0xfe,0xbf,0xcd,0x3f,0xf0, +0xef,0xfc,0xc5,0x0c,0x3f,0xfd,0x68,0x0b,0xff,0xff,0xff,0xfe,0xdf,0xf0,0xff,0xff, +0xff,0xff,0xfe,0xff,0xbb,0xff,0xfd,0x85,0xff,0xd4,0x6f,0x9f,0xc3,0x5a,0x0f,0xff, +0xff,0xff,0xff,0xfc,0xe9,0x7f,0xf3,0x01,0xf0,0xfb,0xc2,0xbf,0xfc,0x00,0x37,0xef, +0xfc,0xcd,0xbc,0x3f,0xff,0x0c,0xbf,0xff,0xff,0xff,0xff,0xff,0xf0,0x5f,0xff,0xff, +0xff,0xfe,0xff,0xff,0xff,0xff,0xd9,0xf7,0xd1,0xb7,0x7e,0x7f,0xf1,0xe4,0xfd,0xff, +0xfb,0xfb,0xff,0x5f,0xff,0x7f,0xb1,0xbc,0x0f,0x67,0xeb,0xb8,0x3f,0xff,0xe2,0xff, +0xe9,0xff,0xfd,0xe3,0xff,0x3f,0x9f,0xc2,0xff,0xff,0xff,0xf0,0x9f,0xff,0xff,0xff, +0xfe,0xf5,0x7f,0xff,0xf0,0x3f,0xbc,0xff,0xd5,0xf5,0xce,0x3f,0xfe,0xff,0xfe,0x6d, +0xff,0xf1,0xbf,0x7b,0xff,0xf1,0xfd,0xff,0x4f,0xff,0x87,0xff,0xae,0xff,0xb1,0xf8, +0xfe,0xff,0xff,0x78,0x01,0xb9,0xff,0xff,0xff,0xfa,0xf0,0x2f,0xff,0xff,0xff,0xfe, +0xf3,0xc0,0x00,0x00,0x00,0x04,0x02,0x13,0x02,0x00,0x80,0x40,0x00,0x90,0x10,0x00, +0x10,0x00,0x02,0x00,0x01,0x20,0x80,0x12,0x10,0x00,0x40,0x08,0x00,0x04,0x00,0x00, +0x02,0x00,0x01,0x40,0x00,0x80,0x00,0x00,0x3c,0xf0,0xef,0xff,0xff,0xff,0xfe,0xfd, +0x1f,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x7f,0xff,0x7f,0xf7,0xdf,0xf7,0xff, +0xf7,0xfb,0xeb,0xd1,0xff,0xff,0xff,0xff,0xef,0xf7,0xff,0xff,0xfb,0xff,0xfe,0xff, +0xff,0x7e,0xff,0xfb,0xff,0xff,0xff,0xdb,0xf0,0xff,0xff,0xff,0xff,0xfe,0xf0,0xff, +0xff,0xb7,0xeb,0xf7,0xdf,0xff,0xfe,0xf5,0x6b,0xe7,0xed,0xf7,0x3e,0xec,0xff,0x54, +0xef,0x6f,0xf1,0xf5,0xaf,0x6f,0xf6,0xfd,0xff,0xdd,0x7b,0xff,0xef,0xbf,0x7f,0xff, +0xff,0xf7,0xff,0xf3,0x5f,0xf7,0xd0,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xf8,0x30,0x00, +0x80,0x40,0x04,0x00,0x81,0x2c,0x04,0x24,0x00,0x02,0x01,0xc8,0x02,0x00,0x02,0x24, +0x00,0x01,0xb4,0x42,0xdc,0x44,0x02,0x15,0x90,0x02,0x03,0x48,0x39,0x10,0x02,0x24, +0xa0,0xba,0x00,0x00,0x40,0xc1,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff, +0xfe,0xfc,0xf7,0xf0,0xee,0xb6,0x5d,0xfd,0xf5,0xff,0xdb,0xf7,0x7f,0x7f,0xbe,0xff, +0xc1,0xfe,0xbf,0xfa,0xfa,0x5f,0xff,0xad,0xff,0xef,0xff,0x7f,0xdf,0x7f,0xfe,0xbf, +0xb7,0x94,0xbf,0xff,0xff,0xf0,0x9f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xf0,0x8f,0xff,0xff,0xff,0xfe,0xd7,0xff,0xff,0xfb,0xb5,0xff, +0xef,0x7c,0xeb,0x2b,0x52,0x5b,0x3b,0xda,0xd4,0xf3,0x36,0x96,0xb5,0xbd,0xf1,0xfb, +0xda,0xee,0xf6,0xfe,0xd3,0x35,0xbd,0xdf,0xad,0xcf,0xef,0x7e,0xcd,0x6b,0xbb,0xdf, +0xff,0xff,0xfd,0xb0,0xef,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xd3,0x5f,0xf6, +0xff,0xf6,0xff,0xfd,0xad,0xfd,0xff,0x7f,0xef,0xff,0x6f,0x7f,0xdb,0xf1,0xa5,0xa3, +0x7f,0x6f,0x6b,0x4f,0xff,0xdb,0xfb,0xcb,0xff,0xf6,0xff,0xf4,0xd7,0xfd,0xbf,0xfe, +0xdf,0xff,0xd0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf7,0xdf,0xff,0xff,0xff, +0x3f,0x7f,0xfc,0xe5,0xff,0x20,0xfe,0xff,0xff,0xdf,0x7f,0xff,0xf1,0x7f,0xff,0xfe, +0xff,0xf0,0x7c,0x3d,0x4f,0xf3,0xc3,0x3f,0xff,0xff,0x6f,0xc3,0xff,0x0f,0xff,0xff, +0xaf,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xff,0xff,0xfb,0xb7,0xe0,0x0f,0xff,0xff,0x2b, +0xff,0x7d,0xbf,0xff,0xdf,0xff,0xff,0xf8,0x9f,0x7f,0xff,0xf1,0x55,0xff,0xff,0xff, +0xfd,0x7c,0x3c,0xff,0xf3,0xc3,0x3f,0xff,0xff,0xef,0xc3,0xff,0xdf,0xff,0xff,0xff, +0xf0,0x9f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xef,0xff,0xff,0x9f,0xbf,0x7f, +0xf9,0x19,0x47,0x8e,0xe7,0x9f,0x3f,0x17,0xff,0xfc,0x81,0xc1,0x7e,0xf3,0xd9,0xf9, +0x73,0xdf,0xf4,0x7f,0xfa,0xff,0xff,0xff,0xfb,0x7f,0x77,0xc7,0xff,0xff,0xff,0xf0, +0x2f,0xff,0xff,0xff,0xfe,0xf5,0xf7,0xff,0xfb,0xff,0xf7,0x3f,0xfc,0xbf,0x3e,0x3f, +0xec,0xff,0x81,0xaf,0xfe,0x4f,0xf3,0xbb,0xff,0xf0,0x7e,0xff,0x6f,0xff,0x87,0xff, +0xbb,0xff,0xd5,0xfc,0xff,0x7f,0xfc,0x6f,0xff,0xef,0xe7,0xff,0xff,0xfa,0xf0,0x3f, +0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80, +0x00,0x30,0x10,0x60,0x20,0x00,0x08,0x00,0x01,0x20,0x80,0x00,0x10,0x00,0x04,0x00, +0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x80,0x40,0x00,0x08,0x20,0x3c,0xf0,0x6f,0xff, +0xff,0xff,0xfe,0xf5,0xbf,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0x7f,0xfe,0x3f,0xff, +0xff,0xff,0xff,0xff,0xef,0xff,0xff,0xf1,0xdf,0xdf,0xff,0xff,0xff,0x7f,0xdf,0xff, +0xfd,0xbd,0xff,0xff,0xff,0xfb,0xdf,0xff,0xff,0xff,0xff,0x5b,0xf0,0xff,0xff,0xff, +0xff,0xfe,0xf0,0xbf,0xbf,0xbf,0xff,0xf7,0xfb,0xff,0xfe,0xee,0xfa,0xff,0xff,0xff, +0x3d,0x3b,0xff,0xff,0xfe,0xfb,0xf1,0xff,0xbf,0x7b,0xff,0xff,0xef,0xff,0xbf,0xff, +0xff,0xff,0xff,0xff,0xfe,0xff,0xf7,0xef,0xff,0xfb,0xd0,0xf0,0xdf,0xff,0xff,0xff, +0xfe,0xf8,0x30,0x00,0x00,0x00,0x00,0x00,0x0b,0x10,0x05,0x01,0x00,0x08,0x00,0x02, +0x01,0x01,0x00,0x00,0x10,0x01,0xc8,0x08,0x00,0x00,0x00,0x00,0x42,0x02,0x00,0x00, +0x00,0x80,0x02,0x00,0x00,0x40,0x24,0x80,0x00,0xc1,0xf0,0x3f,0xff,0xff,0xff,0xfe, +0xff,0xff,0xff,0xff,0xf7,0xfd,0xf7,0xfa,0xef,0xee,0xf9,0xfd,0xff,0xf7,0xfe,0xbf, +0x1f,0xfd,0x9e,0xfd,0xd1,0xef,0xff,0xf7,0x7f,0x9f,0xff,0xef,0xff,0xf6,0xff,0xfe, +0xfe,0x7b,0xff,0xbd,0xff,0x7e,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xff,0xff, +0xff,0xf7,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xdf,0xfd,0xff,0xff,0xdf,0xff, +0xff,0x5f,0xf1,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xef,0xff, +0xf7,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xfb,0xff,0xff,0xef,0xfb,0xfd, +0xff,0xf1,0xff,0xff,0xfb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xf7,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xe7,0xff, +0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xcf,0xff,0xfb,0xff,0xfb,0xf1, +0xff,0xff,0xfb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7b,0xff,0xff,0xff,0x7f,0xff,0xf1,0xff, +0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xef,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0x57,0xff,0xfe,0xbf,0xfb,0xf1,0xff,0xff, +0xfd,0xf7,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xd7,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf7,0xdb,0xff,0xdb,0xfd, +0xf6,0xff,0xf6,0xff,0x3c,0xbc,0xbc,0xbf,0xdf,0x6f,0xef,0x2f,0xf1,0x3c,0xbf,0xbc, +0xbf,0xdf,0x6f,0xff,0x6f,0xf7,0xdb,0xff,0xdb,0xfd,0xf6,0xff,0xf6,0xff,0xff,0xff, +0x01,0xe2,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff }; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/hamradio/yam9600.h linux.pre11.3/drivers/net/hamradio/yam9600.h --- linux.vanilla/drivers/net/hamradio/yam9600.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/net/hamradio/yam9600.h Tue Jul 20 00:29:25 1999 @@ -0,0 +1,343 @@ +/* + * + * File yam111.mcs converted to h format by mcs2h + * + * (C) F6FBB 1998 + * + * Tue Aug 25 20:23:03 1998 + * + */ + +static unsigned char bits_9600[]= { +0xff,0xf2,0x00,0xa5,0xad,0xff,0xfe,0x9f,0xff,0xef,0xfb,0xcb,0xff,0xdb,0xfe,0xf2, +0xff,0xf6,0xff,0x9c,0xbf,0xfd,0xbf,0xef,0x2e,0x3f,0x6f,0xf1,0xfd,0xb4,0xfd,0xbf, +0xff,0x6f,0xff,0x6f,0xff,0x0b,0xff,0xdb,0xff,0xf2,0xff,0xf6,0xff,0xff,0xff,0xff, +0xf0,0x6f,0xff,0xff,0xff,0xfe,0xff,0xfd,0xdf,0xff,0xff,0xff,0xf7,0xff,0xff,0xff, +0xfb,0xff,0xff,0xf7,0xff,0xff,0xff,0xfe,0xff,0x7f,0xf1,0xff,0xfe,0xff,0xbf,0xbf, +0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,0xfe,0xff,0xfe,0xff,0xff,0xff,0xf0, +0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xf7, +0xff,0xff,0xf7,0xef,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0x7e,0xff,0xff, +0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xf0,0xdf, +0xff,0xff,0xff,0xfe,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xef,0xff,0xf3,0xfb,0xfe,0xff,0xf1,0xff,0xfd,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xdf,0xff,0xf0,0x7f,0xff, +0xff,0xff,0xfe,0xff,0xff,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xdf,0xff,0xff,0xff,0xf7,0xf1,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff, +0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf5, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff, +0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xff,0xff,0xef,0xff,0x7f,0xff,0xef, +0xff,0xef,0xff,0x7f,0xef,0xf1,0xff,0xef,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xf0,0x9f,0xff,0xff,0xff,0xfe, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xff, +0xff,0xff,0xff,0xbd,0xff,0xef,0x7f,0xef,0x7f,0xfb,0xdf,0xd3,0x5a,0xfe,0xd7,0xd6, +0xf7,0x7f,0xbd,0xf1,0xbb,0x5d,0xd6,0xf7,0xfe,0x96,0xff,0xbd,0xaf,0xad,0xbf,0xef, +0x7f,0x6b,0x7f,0xfb,0xd6,0xfe,0xf7,0xff,0x10,0xef,0xff,0xff,0xff,0xfe,0xbe,0xef, +0xff,0xff,0xdb,0xff,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xfd,0xbf,0xff,0x7f,0xff,0x7f, +0xdf,0xdb,0xf1,0xfd,0x35,0xff,0x6f,0xff,0x6f,0xff,0xdb,0xff,0xcb,0xff,0xf6,0xff, +0xf2,0xfd,0xfd,0xbf,0xff,0xff,0xff,0xd0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0xff,0xcc,0xc0,0x3f,0xff, +0xff,0xf1,0x24,0xf0,0xff,0xff,0xcf,0xef,0x3f,0xff,0xf0,0xff,0xff,0xff,0xfc,0x3f, +0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0xff,0xcc,0xc0,0x3f,0xff,0xff, +0xf1,0x00,0xf0,0xff,0xff,0xcf,0xdf,0xff,0xff,0xf0,0xff,0xff,0xff,0xfc,0x3f,0xff, +0xff,0xff,0x7d,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xfe,0x7f,0xdf,0xff,0xff,0xff,0xf1, +0xff,0xcf,0xff,0xf3,0xff,0x97,0xff,0xff,0x8f,0xe7,0xff,0xff,0xfc,0x71,0xff,0xff, +0xff,0xff,0xff,0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xf5,0xff,0xbf,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xe3,0xf7,0xef,0xff,0xff,0xfc,0x7b,0xff,0xf1,0x3f, +0xff,0xef,0xff,0xcf,0xe3,0xe3,0xff,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0xbf,0xff, +0xbf,0xff,0xda,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xf2,0xc0,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00, +0x01,0x3c,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xdb,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0x9f,0xff, +0xff,0xff,0xf7,0xff,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xdb,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xf0,0xbb,0xdf,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xdf,0xbf,0xf1,0xfe,0xfd,0xf7,0xff, +0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x77,0xfd,0xf2, +0xf0,0x1f,0xff,0xff,0xff,0xfe,0xf8,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03, +0x00,0x00,0x00,0x02,0x00,0x90,0x00,0x00,0x00,0x0c,0x01,0x00,0x00,0x04,0x24,0x00, +0x40,0x01,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x01,0xc0,0xf0, +0x4f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xbf,0xff,0xff,0x6f,0xff,0xdf,0xff,0xd1,0xff,0xfe,0xff,0xff,0xff,0xff, +0xff,0xff,0xdf,0xff,0xfb,0xff,0xfb,0xef,0xff,0xff,0xee,0xff,0xff,0x7f,0xf0,0xdf, +0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x8f,0xff, +0xff,0xff,0xfe,0xff,0xff,0xff,0xf5,0xad,0xff,0x69,0x2a,0xed,0x6b,0xfb,0xdf,0x3a, +0xdc,0xf4,0x96,0xee,0xb3,0x3d,0x35,0xc1,0xbb,0xdd,0xfe,0xf6,0xfe,0xd6,0xb5,0xad, +0xbf,0xa5,0xad,0x49,0x2f,0x4f,0x2b,0xda,0x5f,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff, +0xff,0xfe,0xbf,0xff,0xff,0xfb,0x5b,0xf7,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xfd,0xa5, +0xf3,0x6f,0xf3,0x6e,0xfa,0x7b,0xd1,0xfd,0xb5,0x77,0x6f,0xe9,0x6f,0xff,0xdb,0xfb, +0xdb,0xdf,0xf6,0xff,0xf6,0xff,0xfd,0x3f,0xfe,0xf7,0xff,0xd0,0x4f,0xff,0xff,0xff, +0xfe,0xff,0x9f,0xff,0xff,0x0f,0xff,0xc0,0x3f,0x9c,0x03,0xff,0xff,0x8b,0xa5,0xfe, +0x80,0x3e,0xc2,0xbf,0xac,0xb1,0x24,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0xff,0xa3, +0xff,0xfd,0x6b,0xff,0xff,0xf0,0xa5,0xff,0xff,0xff,0xf0,0xaf,0xff,0xff,0xff,0xfe, +0xff,0xff,0xff,0xff,0x0f,0xff,0xc0,0x3f,0xd4,0x6b,0xff,0xff,0xdb,0xff,0xfe,0x86, +0xbf,0xc2,0xbf,0x30,0xa1,0x24,0xff,0xff,0xff,0xff,0xcc,0xff,0x0f,0xff,0xa3,0xff, +0x05,0x6b,0xff,0xff,0xf0,0xa5,0xff,0xff,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff, +0xff,0xff,0xfb,0xc7,0xff,0xc4,0xff,0xff,0x7f,0xff,0xec,0xfe,0x7f,0xdf,0xd8,0xb9, +0x47,0xfc,0x36,0xc1,0xdf,0xff,0xff,0xf9,0xff,0xf3,0xff,0xf7,0xff,0xfc,0xff,0xfd, +0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xf5,0xff, +0xff,0xff,0xff,0xfe,0xff,0xff,0x7e,0xbd,0x3f,0xff,0x2b,0xfe,0x2f,0xf5,0xa3,0xfc, +0x5b,0xfe,0x61,0x9f,0x7f,0xef,0xff,0xff,0xa7,0xfb,0xff,0xff,0xfa,0xfe,0xff,0x33, +0xf1,0xff,0xbf,0xff,0xff,0xff,0xfa,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xf1,0xc0,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x30,0x24,0x04, +0x00,0x01,0x00,0x80,0x40,0x00,0x08,0x00,0x00,0x00,0x02,0x01,0x01,0x00,0x02,0x00, +0x00,0x00,0x00,0x00,0x01,0x3d,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xfd,0xbd,0xff,0xfd, +0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xff,0x7f,0xf6,0xef,0xbf,0xf7,0xff,0x73,0xeb, +0xf1,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xf9,0xff,0xfd,0xfe,0xff,0xff, +0xff,0xff,0xff,0xff,0xd9,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xf0,0xbf,0x7f,0xff,0xff, +0xff,0x7f,0xff,0xff,0xde,0xff,0xff,0xef,0xdd,0xde,0x77,0xf2,0xfb,0xed,0xe7,0xf1, +0x73,0xfd,0xfd,0xdf,0xff,0x7d,0xbe,0xdf,0xff,0xfb,0xff,0xef,0xff,0xef,0xff,0xff, +0xff,0xff,0xff,0xd0,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xf8,0x30,0x20,0x02,0x00,0x22, +0x40,0xc0,0x00,0x00,0x00,0x08,0x00,0x02,0x41,0x02,0x12,0x00,0x21,0x87,0x81,0x00, +0x00,0x80,0x04,0x0b,0x28,0x01,0xb0,0x00,0x82,0x00,0x40,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xc1,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xfd,0xff, +0xf7,0xff,0xfe,0x7f,0xed,0x79,0xff,0xde,0xeb,0x7f,0x74,0xf7,0xf7,0xe1,0xf9,0xff, +0xf6,0x5f,0x7f,0xff,0xff,0xff,0xd7,0xdb,0xef,0xff,0xbb,0xff,0xff,0xff,0xcc,0xff, +0xff,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xf0,0x0f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0x3d,0xcd,0x49,0x7f,0x6f, +0x2b,0xba,0x5c,0xd2,0xda,0xf6,0xf3,0x3e,0xf7,0xff,0xbd,0xf1,0xfa,0xdf,0xfe,0xf7, +0xcc,0xf6,0xbb,0xa5,0xb3,0xad,0xbf,0x6f,0x7d,0x6f,0x6b,0xdb,0xdf,0xbd,0xff,0xfe, +0xb0,0x5f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xfb,0xdb,0x57,0xf6,0xfe,0x9f,0xd5, +0xb7,0xff,0xaf,0xe5,0x3f,0xff,0xff,0x6f,0xff,0xdb,0xf1,0xfd,0xbf,0xff,0x6f,0x69, +0x6c,0xdf,0xda,0xdf,0xcb,0xff,0xf6,0xff,0x76,0xfd,0xfd,0xbf,0xff,0xff,0xff,0xd0, +0x3f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfd,0xbd,0x08,0x03,0x89,0x4f,0x5a, +0x0f,0xf0,0xff,0xf8,0xbf,0xff,0xff,0xff,0xff,0xf1,0x5a,0xff,0xff,0xff,0xff,0xf3, +0xfa,0xa0,0xf0,0xf2,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xff, +0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfc,0xfd,0x00,0x6b,0xff,0xff,0x5a,0x0f, +0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0x5a,0xff,0xff,0xff,0xff,0xb3,0xf5, +0x50,0xf0,0xf0,0xff,0xff,0xff,0xd7,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x7f,0xff, +0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0xbc,0xff,0xe4,0xe7,0x71,0xff,0xf9,0xc4,0xf4, +0x7f,0x7f,0xcf,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xfb,0xf7,0x73,0xbf,0x14, +0xff,0xe6,0xff,0xff,0xe1,0x7d,0xff,0xff,0xe7,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff, +0xff,0xfe,0xf5,0xff,0xff,0xfe,0xd2,0xfa,0xff,0xc4,0xf4,0x5c,0xbf,0xfa,0xff,0xff, +0xec,0x7e,0xbf,0xff,0xff,0xff,0xf1,0xff,0xff,0xef,0xff,0xff,0x6b,0xdb,0xff,0xdf, +0xf9,0xfb,0xbf,0xff,0xf1,0xff,0xbf,0xff,0xff,0xff,0xfb,0xf0,0xbf,0xff,0xff,0xff, +0xfe,0xf3,0xc0,0x00,0x02,0x00,0x00,0x00,0x00,0x82,0x00,0x00,0x00,0x00,0x80,0x00, +0x00,0x00,0x00,0x40,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x20,0x00,0x00,0x00,0x00, +0x01,0x00,0x01,0x00,0x00,0x80,0x02,0x00,0x01,0x3c,0xf0,0x5f,0xff,0xff,0xff,0xfe, +0xfd,0xbf,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0x7f,0xff,0xdf,0xff,0xef,0xff, +0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xfb,0xff,0xfd,0xff, +0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xc3,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xf0, +0xff,0xdf,0xff,0xff,0xf7,0x23,0xff,0xff,0xfd,0xff,0xef,0xff,0xfe,0x7f,0x7d,0xf7, +0xfe,0xff,0x7f,0x71,0xff,0xfb,0x7f,0xff,0xff,0xff,0x6e,0xfd,0xf7,0xfd,0xff,0xbf, +0xff,0xbf,0xf9,0xfd,0xff,0xdf,0xef,0xf0,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xf8,0x30, +0x40,0x01,0x00,0x83,0x00,0x00,0x00,0x0c,0x06,0x08,0x04,0x26,0x26,0x00,0x00,0x06, +0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x04,0x00,0x70,0x08,0x80,0x00,0x20,0x01,0x20, +0x00,0x02,0x00,0x30,0x00,0x00,0xc1,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff, +0xff,0xff,0x7b,0x3f,0xf7,0xff,0xd7,0xfe,0xfe,0xfb,0xfe,0x3b,0xfe,0xbd,0xff,0x2f, +0xff,0x71,0xff,0xfb,0x7f,0xe7,0xff,0xf9,0xef,0xff,0xd7,0xfa,0xff,0xb7,0xbb,0xfe, +0xff,0xff,0x74,0xff,0xf7,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xf0,0x8f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xb5, +0xbd,0x6f,0x7c,0xeb,0x7f,0xfb,0xdb,0xd3,0x4b,0xee,0xd6,0xf6,0xb7,0xfd,0xac,0xa1, +0xfb,0xdf,0xfe,0xf7,0xf4,0x96,0xbd,0xb4,0xc5,0xa5,0xaf,0x6f,0x69,0x4f,0x7f,0xba, +0xdb,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff, +0xf6,0xff,0xf6,0xff,0xbd,0xbf,0xa5,0xbf,0xff,0x7d,0x7f,0xef,0xff,0xfb,0xf1,0xfd, +0xbf,0xff,0x6f,0xff,0x6b,0x7a,0xdb,0xff,0xdb,0xdf,0xf6,0xfe,0xb6,0xfd,0xfd,0xbf, +0xfe,0xf7,0xff,0xd0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xf4,0x2f,0xff, +0xfc,0x43,0x6b,0xff,0xff,0xff,0x0d,0xff,0xfc,0x33,0x3f,0xf0,0x5f,0xf1,0xff,0xff, +0xff,0xff,0xf9,0xde,0xf0,0x4c,0xfe,0x77,0xaf,0xff,0xff,0xef,0xff,0xf0,0xff,0xdb, +0xff,0x5f,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff,0xfe,0xf7,0xff,0xf0,0x2f,0xff,0xfd, +0x43,0x7f,0xff,0xff,0xf1,0x0f,0xff,0xfc,0x33,0x3f,0xff,0xaf,0xf1,0xff,0xff,0xff, +0xff,0xf6,0xd7,0xff,0xbc,0xfd,0xbd,0xff,0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff, +0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfc,0xff,0xff,0xfb,0xf1, +0xbf,0xff,0xf9,0xfd,0xcf,0xf2,0x70,0xff,0x1f,0x9f,0xf3,0xf1,0xff,0xff,0xff,0xff, +0xfc,0xf7,0xff,0x13,0x9f,0xfc,0xff,0xff,0x84,0xf7,0xff,0xff,0x47,0xff,0xff,0xff, +0xf0,0xbf,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xff,0xf1,0xfc,0xff,0xfe,0xfe,0x79, +0x3f,0xff,0x1d,0x46,0xcf,0xff,0xcf,0xfc,0x7b,0xff,0xf1,0xff,0xff,0xff,0xff,0xed, +0xf3,0xab,0xff,0xcb,0xff,0xf8,0xff,0xfc,0xf5,0xff,0xbf,0xff,0xff,0xff,0xfa,0xf0, +0x8f,0xff,0xff,0xff,0xfe,0xf3,0xc2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, +0x00,0x00,0x20,0x00,0x20,0x00,0x00,0x04,0x08,0x01,0x00,0x00,0x00,0x00,0x00,0x20, +0x0c,0x00,0x00,0x04,0x01,0x00,0x01,0x00,0x00,0x80,0x00,0x00,0x01,0x3c,0xf0,0x7f, +0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xfd,0xfe,0xff,0xff,0xff,0xff,0xfe,0xff, +0xdf,0xff,0xff,0xf7,0xff,0xff,0xff,0xef,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xeb, +0xff,0xdf,0xff,0xff,0xfb,0xf7,0x7f,0xff,0xfe,0xff,0xff,0xbf,0xdb,0xf0,0xff,0xff, +0xff,0xff,0xfe,0xf0,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0x7f,0xf7,0xff, +0xbf,0xbf,0xcf,0xff,0xff,0xff,0x3e,0xf1,0x7f,0xff,0xff,0xef,0xff,0xff,0xff,0xfe, +0xff,0xfd,0xff,0xbf,0xbd,0xfe,0xff,0xfb,0xf7,0xdf,0xfb,0xd0,0xf0,0x9f,0xff,0xff, +0xff,0xfe,0xf8,0x30,0x20,0x00,0x40,0x01,0x80,0xc0,0x30,0x00,0x00,0x20,0x00,0x10, +0x50,0x88,0x20,0x00,0x00,0x13,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00, +0x00,0x00,0x01,0x80,0x08,0x00,0x00,0xa0,0x00,0x10,0xc1,0xf0,0xef,0xff,0xff,0xff, +0xfe,0xfd,0xef,0x7f,0xff,0xff,0xbf,0xff,0xf7,0xff,0xef,0xfb,0xfd,0x77,0xef,0xbf, +0xf7,0x7f,0xff,0xff,0xbf,0xd1,0x7f,0xff,0xff,0xf7,0xff,0xff,0xff,0xff,0xaf,0xff, +0xdf,0xf7,0xfb,0xff,0xfd,0xff,0xfc,0xff,0xfd,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff, +0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x3f,0xff,0xff,0xff,0xfe,0xdd,0xff, +0xff,0xff,0xa5,0xfd,0x6f,0x7d,0x6d,0x7f,0x52,0xdf,0x5a,0x4b,0xee,0xb6,0xee,0xf2, +0xbb,0xac,0xa1,0x5b,0x4d,0xd6,0xf7,0xfe,0xb2,0xbd,0x35,0xb5,0xb5,0xdd,0x6f,0x7f, +0xe9,0x5f,0x52,0xdf,0xbd,0xff,0xff,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff, +0xff,0xdb,0xfe,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xfd,0xb5,0xbf,0xf9,0x7f,0x6f,0xff, +0xdb,0xf1,0xfd,0xbf,0xff,0x6f,0xff,0x69,0x7f,0xdb,0xff,0xd3,0xff,0xf6,0xfe,0xf2, +0xff,0xad,0xbf,0xff,0xff,0xff,0xd0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf5, +0x30,0x0f,0xff,0xff,0xfd,0x6b,0xca,0xff,0xf0,0x0f,0xd6,0xbf,0xcf,0x3f,0xff,0xff, +0xf1,0xff,0xff,0xff,0xca,0xfe,0xbf,0xff,0xf0,0x05,0xaf,0x0f,0xff,0xfc,0xf0,0xcf, +0xf0,0xff,0xff,0xff,0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf5,0x30, +0x0f,0xff,0xff,0xfc,0x3f,0xca,0xff,0x0f,0x0f,0xd6,0xbf,0xff,0xff,0xf5,0x5f,0xf1, +0xff,0x8b,0xff,0xc3,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0xff,0xfc,0xf0,0xcf,0xf0, +0xff,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xcf,0xff, +0xff,0xbf,0x9f,0x3f,0xfe,0xfc,0xff,0x4f,0xff,0xff,0xff,0xff,0xff,0xf7,0xf1,0xff, +0xdf,0xfe,0x7e,0x3f,0x9f,0xf4,0xfc,0x7f,0xfc,0xff,0xff,0x3f,0xff,0x3f,0xfe,0x3f, +0xff,0xff,0xff,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xfb,0xff,0xfe,0xff, +0xff,0xff,0xff,0xbf,0xfb,0xff,0xf8,0xed,0xff,0x8f,0xff,0xbb,0xff,0xb1,0xf3,0xef, +0x8f,0xf7,0xff,0xff,0xdb,0xff,0xff,0xff,0xef,0xbf,0xfd,0x79,0xbf,0xbf,0xff,0xff, +0xff,0xfb,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00,0x00,0x04,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x04,0x08,0x08,0x01,0x01,0x00,0x90, +0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0x00,0x01, +0x3c,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0x9f,0xff,0xaf,0xdf,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff, +0xbf,0xef,0xff,0xff,0xff,0xed,0xff,0xff,0xff,0xef,0xff,0xbf,0xff,0xff,0xff,0xc3, +0xf0,0x3f,0xff,0xff,0xff,0xfe,0xf0,0xff,0xfd,0xff,0xff,0xff,0xfb,0xff,0xbb,0xff, +0xff,0xff,0x7f,0xf6,0xff,0x7f,0xfb,0xfd,0xed,0xff,0xf1,0xff,0xfe,0x7f,0xff,0xff, +0xff,0x5f,0xff,0xf7,0xff,0x7e,0xff,0xfd,0xff,0xef,0xff,0xff,0xff,0xef,0xf0,0xf0, +0x8f,0xff,0xff,0xff,0xfe,0xf8,0x30,0x80,0x00,0x04,0x00,0x00,0x40,0x02,0x00,0x03, +0x00,0x05,0x04,0x20,0x00,0x00,0x01,0xd0,0x00,0x81,0x00,0x20,0x04,0x04,0x00,0x00, +0x81,0x04,0x08,0x80,0x10,0x00,0xc0,0x00,0x00,0x00,0x20,0x00,0x08,0xc1,0xf0,0x6f, +0xff,0xff,0xff,0xfe,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xf3,0xfd,0xff,0xed,0xfc, +0xff,0xff,0x9f,0xfb,0xfd,0xff,0xff,0xff,0xf1,0xff,0xff,0x7f,0xfb,0x3e,0xff,0x9f, +0xff,0xff,0xff,0xff,0xfd,0xf9,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xf0,0x6f,0xff, +0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xcf,0xff,0xff, +0xff,0xfe,0xff,0xff,0xff,0xfd,0xbd,0xff,0xef,0x7c,0xeb,0x7f,0xfb,0xdb,0xfa,0xdc, +0xee,0xf7,0xf6,0xd7,0xf5,0x2d,0xa1,0xbb,0xdd,0xee,0xf7,0x54,0xf7,0xfb,0x2c,0xb5, +0xb4,0xbd,0x6b,0x6f,0xef,0x6f,0xbb,0xdf,0xff,0xff,0xff,0xf0,0x1f,0xff,0xff,0xff, +0xfe,0xbf,0xff,0xff,0xff,0xfb,0xff,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xff,0xbf,0xef, +0x6f,0xff,0x6f,0xfa,0xdb,0xf1,0xc5,0xbd,0xf5,0x6f,0xff,0x6f,0xca,0xdb,0xff,0xdb, +0xfb,0xf6,0x97,0xf6,0xff,0xfd,0xbf,0xfe,0xf7,0xff,0xd0,0x9f,0xff,0xff,0xff,0xfe, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x8b,0x7f,0xff,0xff,0xe7,0x63,0xff,0xff, +0xff,0xfc,0x77,0xdf,0xf1,0xdb,0xff,0xd6,0xa8,0x3f,0xff,0xff,0x08,0x2f,0xf0,0xff, +0xc3,0xff,0xeb,0xff,0xff,0xff,0xff,0xff,0x5f,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x8b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xfc,0xff,0xcf,0xf1,0xdb,0xff,0xd6,0xa8,0x3f,0xff,0xff,0x08,0x2f,0xf0,0xff,0xc3, +0xff,0xeb,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xf5,0xbf,0xff,0xca,0xff,0x9f,0xff,0xfa,0xb9,0xe7, +0x9f,0xf3,0x81,0xff,0xff,0xfc,0x73,0xd7,0xff,0xff,0x77,0xff,0xfd,0xff,0xfc,0xff, +0xff,0xff,0xff,0xcf,0xff,0xff,0xff,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff, +0xff,0xf7,0xde,0xff,0xfe,0x7e,0xff,0xbf,0xff,0xbf,0xf1,0xb3,0xff,0xff,0xe3,0xfb, +0xff,0xe1,0x1f,0x7f,0xff,0xf8,0x78,0xff,0xfb,0x1e,0xff,0xf7,0xfe,0xe7,0xff,0xff, +0xff,0xbf,0xff,0xff,0xff,0xfa,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x04,0x00, +0x01,0x80,0x40,0x40,0x20,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00, +0x80,0x00,0x00,0x01,0x3c,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xfb,0xff, +0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xf7,0xf1, +0xfd,0xff,0xff,0xff,0xdf,0xff,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff, +0xff,0xff,0xff,0xdb,0xf0,0x8f,0xff,0xff,0xff,0xfe,0xf0,0xff,0xdf,0xff,0xff,0x7f, +0xff,0xff,0xff,0xbe,0xd7,0xff,0xed,0xbd,0x7e,0xbf,0xfe,0xf6,0x7f,0xbf,0x71,0xff, +0xff,0xda,0xff,0xf9,0xff,0xbf,0x7f,0xfe,0xff,0x6f,0x7f,0xff,0xff,0xff,0xff,0xff, +0x7f,0xff,0xd0,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xf8,0x30,0x42,0x00,0x00,0x00,0x00, +0x80,0xc1,0x00,0x00,0x90,0x00,0xc4,0x00,0x00,0x12,0x20,0x43,0x22,0x81,0x84,0x00, +0x00,0x14,0x00,0x01,0x00,0x08,0x80,0x00,0x02,0x00,0x02,0x00,0x04,0x02,0x00,0x00, +0x10,0xc1,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xff,0xff,0xfd,0xff,0xff,0xdd,0xfe,0xff, +0xb6,0x76,0xe5,0xbc,0xf9,0xf7,0xaf,0x5f,0xbf,0xfc,0xdf,0xcf,0xf1,0xff,0xef,0x79, +0xff,0xbd,0xff,0xef,0xff,0xff,0xf7,0x6f,0x5f,0xff,0xff,0xfd,0xef,0xef,0xbf,0xff, +0xff,0xf0,0x9f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xf0,0xff,0xff,0xff,0xff,0xfe,0xdb,0xff,0xff,0xfd,0x2d,0xff,0x69,0x2a,0xef,0x77, +0xbb,0xdd,0x5a,0xdf,0xf6,0xf6,0xd6,0xf7,0x7d,0xbd,0xd1,0xb2,0x4a,0xd6,0xb2,0xbe, +0x97,0xf5,0xbd,0xb3,0xad,0xff,0xef,0x7f,0x69,0x6b,0xfb,0xdf,0xff,0xff,0xff,0xf0, +0x2f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,0xf6,0xfe,0x9f,0xd4,0xbf, +0xed,0xaf,0xff,0x6b,0x6f,0xf7,0xff,0xdd,0xdb,0x31,0xfd,0xbf,0xff,0x6f,0x7f,0xff, +0xff,0xdb,0xff,0xcb,0xdf,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xfe,0xf7,0xff,0xd0,0x8f, +0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0x1f,0xff,0x46,0x2f,0x9f,0xff,0xff,0xff, +0xa5,0xff,0xff,0xff,0xdf,0xb7,0xff,0xff,0xf1,0xff,0xff,0xff,0xf7,0xe9,0x6a,0xbf, +0xff,0xff,0xfd,0xff,0xff,0xfd,0x55,0x57,0xff,0xff,0xff,0xff,0xaf,0xf0,0x4f,0xff, +0xff,0xff,0xfe,0xfe,0xdf,0xff,0xfd,0x1f,0xff,0x46,0x2f,0x9f,0xff,0xff,0xff,0xa5, +0xff,0xff,0xff,0xc0,0x37,0xff,0xff,0xf1,0x99,0x8e,0xdc,0x7f,0xe9,0x6a,0xbf,0xff, +0xf0,0x0f,0xff,0xff,0xfd,0x55,0x57,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff, +0xff,0xfe,0xff,0xff,0xff,0xff,0x07,0xff,0xc0,0xbe,0xff,0xff,0xcf,0xef,0x9f,0xff, +0xff,0xfb,0xff,0xe7,0xff,0xff,0xa1,0xe3,0xce,0x3c,0x58,0x3f,0xf3,0xff,0xfd,0xef, +0xf9,0xff,0xff,0xf7,0xf1,0x7f,0xff,0xcb,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff, +0xfe,0xf5,0x7f,0xff,0xf0,0xff,0xfe,0xff,0xc4,0x75,0xe7,0xb9,0xff,0xff,0xff,0xef, +0xff,0xc7,0x37,0x3b,0xff,0xf0,0x13,0x9e,0x0f,0xf4,0xff,0xfe,0xfb,0xff,0xff,0xf9, +0xfc,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xfa,0xf0,0xef,0xff,0xff,0xff,0xfe, +0xf3,0xc0,0x01,0x00,0x00,0x02,0x00,0x02,0x22,0x00,0x00,0xc0,0x40,0x00,0x40,0x00, +0x04,0x08,0x04,0x0a,0x01,0x01,0x10,0x20,0x20,0x00,0x00,0x04,0x08,0x08,0x04,0x00, +0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x3c,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xfd, +0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0x7f,0xff,0x7f,0xff,0xcf,0x9d,0xff, +0xff,0xf7,0xfd,0xf1,0xff,0xff,0xff,0xee,0xbf,0xff,0xff,0xff,0xff,0xfe,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xf0,0xff, +0xff,0xff,0xf7,0xf7,0xff,0xff,0xfe,0xbf,0xf7,0xff,0xff,0x5b,0xff,0xbf,0xf7,0xff, +0xfd,0x7f,0x71,0xfd,0xff,0xed,0xf7,0xfe,0xef,0xff,0xff,0x7f,0xff,0xff,0xff,0xff, +0xff,0xff,0xef,0xff,0x7f,0xff,0xd0,0xf0,0xff,0xff,0xff,0xff,0xfe,0xf8,0x30,0x11, +0x00,0x48,0x60,0x40,0x82,0x60,0x24,0x60,0x00,0xcc,0x00,0x80,0x04,0x01,0x00,0x00, +0x14,0x01,0x0c,0x04,0x00,0x30,0x00,0x00,0x00,0x08,0x08,0x00,0x01,0x00,0xc2,0x00, +0x00,0x02,0x00,0x80,0x00,0xc1,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff, +0xf7,0x7b,0xff,0xf3,0xeb,0xbf,0xff,0xf7,0xff,0xff,0xff,0xe7,0x5d,0x3f,0xff,0xf6, +0xd1,0xfd,0xff,0xeb,0xf7,0x3d,0xff,0xff,0xff,0x5f,0xff,0x7f,0x7f,0xf3,0xff,0xff, +0xef,0xfd,0xbf,0xff,0xff,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf5,0xb5,0xdf, +0x6f,0x7d,0x69,0x7f,0xfb,0xdf,0x52,0x5f,0xf6,0xf7,0xfe,0xf6,0xf3,0xbd,0xb1,0xda, +0xcd,0xfe,0xf6,0xee,0xd2,0xbd,0xa5,0xaf,0xbd,0xff,0x6f,0x7c,0xeb,0x2b,0xfa,0xda, +0xff,0xfe,0xdf,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,0xf6, +0xff,0xf6,0xff,0xbd,0xbf,0xcd,0xbf,0xeb,0x6f,0xf7,0x6f,0xdf,0xdb,0x51,0xfd,0xbd, +0xff,0x6f,0xff,0x6f,0xfb,0x5b,0xff,0xdb,0xff,0xf6,0xfe,0xf6,0xfd,0xfd,0xbf,0xfe, +0xf7,0xff,0xd0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfa,0x50,0xff,0xff,0xff, +0xf0,0x6f,0xff,0xff,0xf0,0x96,0xff,0xff,0xc6,0x2b,0xff,0xff,0xf1,0xfc,0xff,0xff, +0xf7,0xdb,0xc3,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xc1,0x4f,0xc3,0xff,0xff,0xff, +0xaf,0xf0,0x9f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf5,0xa0,0xff,0xff,0xff,0xf0, +0x6f,0xff,0xff,0xf0,0x96,0xff,0xff,0xc6,0x2b,0xff,0xff,0xf1,0x5a,0xff,0xff,0xff, +0xf3,0xc3,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xc1,0x4f,0xc3,0xff,0xff,0xff,0xff, +0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfc,0xff,0xff,0x9f,0xf0,0x7f, +0xff,0xf9,0xfc,0x4f,0xf3,0xff,0x27,0xeb,0xff,0xfc,0x81,0xfc,0x7f,0xfe,0x7b,0xff, +0xf7,0xff,0x12,0x7f,0xff,0xff,0xff,0xff,0x18,0xff,0xff,0xff,0xff,0xff,0xff,0xf0, +0x7f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xff,0xdf,0xfe,0xff,0xfc,0x7e,0x7f,0xbf, +0xff,0xff,0xaf,0xef,0xff,0xdf,0xdf,0xfb,0xff,0xf1,0xc3,0xfe,0x6f,0xf1,0xcf,0x3f, +0xfb,0xff,0xff,0xcf,0xfe,0xff,0xff,0xfe,0x7f,0xbf,0xff,0xff,0xbf,0xfa,0xf0,0xdf, +0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00, +0x20,0x00,0x01,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x02,0x00,0x00,0x80,0x00,0x02,0x80,0x00,0x02,0x3c,0xf0,0x2f,0xff, +0xff,0xff,0xfe,0xfd,0xbf,0xff,0xfb,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xf5,0xf1,0xff,0x7f,0xff,0xff,0xff,0xff,0xef,0xff, +0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xf0,0x2f,0xff,0xff, +0xff,0xfe,0xf0,0xff,0xff,0xff,0xfb,0xff,0xbf,0xff,0xff,0xff,0xff,0xf7,0xbf,0xfb, +0xff,0xff,0xff,0xdf,0xf7,0xff,0xf1,0xf7,0xbf,0xfb,0xff,0xff,0xff,0x7f,0xde,0xff, +0xff,0xff,0xff,0xff,0xff,0xed,0xf7,0xff,0xff,0x7f,0xd0,0xf0,0x3f,0xff,0xff,0xff, +0xfe,0xf8,0x30,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x80, +0x20,0x01,0x01,0x92,0x00,0x01,0x01,0x00,0xe0,0x1c,0x60,0x20,0x30,0x08,0x08,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xc1,0xf0,0x6f,0xff,0xff,0xff,0xfe, +0xff,0xff,0xff,0xff,0xff,0xdb,0xfe,0xff,0xff,0xdf,0xff,0xfc,0x7f,0xfb,0xbf,0xff, +0xff,0xff,0xff,0xff,0xf1,0xf6,0xff,0xf7,0x7e,0x3f,0xff,0x7f,0xff,0xff,0xff,0xf7, +0xff,0xff,0xff,0xed,0xff,0xdf,0xff,0xb7,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff, +0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xbf,0xff,0xdf, +0x57,0xef,0xf1,0xfd,0xfe,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xfb,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff, +0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xdf,0xff, +0xff,0xf1,0xfd,0xff,0x7f,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xfe,0xff,0xff,0xff,0xff,0xf0,0x9f,0xff,0xff,0xff,0xfe,0xf7,0xfd,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xff,0xff, +0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1, +0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xfb,0xff,0xff,0xff,0xfe,0xff,0xff,0xfb,0x6f,0xff,0xfe,0xbf,0xff,0xf1,0xff, +0xf7,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd, +0xff,0xff,0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xfb,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0x57,0xff,0xfd,0xbf,0xff,0xf1,0xff,0xef, +0xfe,0xff,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff, +0xde,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf7,0xdb,0xff,0xdb,0xfd, +0xf6,0xff,0xf6,0xff,0x3c,0xbc,0xbc,0xbf,0xdf,0x6f,0xe7,0x2f,0xf1,0x3c,0xbf,0xfd, +0xbf,0xdf,0x6f,0xff,0x6f,0xf7,0xdb,0xff,0xdb,0xfd,0xf6,0xff,0xf6,0xff,0xff,0xff, +0x02,0x01,0xdf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff }; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/hostess_sv11.c linux.pre11.3/drivers/net/hostess_sv11.c --- linux.vanilla/drivers/net/hostess_sv11.c Tue Feb 23 14:21:33 1999 +++ linux.pre11.3/drivers/net/hostess_sv11.c Mon Jul 19 23:27:33 1999 @@ -389,7 +389,8 @@ free_irq(dev->sync.irq, dev); if(dma) { - free_dma(dev->sync.chanA.rxdma); + if(dma==1) + free_dma(dev->sync.chanA.rxdma); free_dma(dev->sync.chanA.txdma); } release_region(dev->sync.chanA.ctrlio-1, 8); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/irda/toshoboe.c linux.pre11.3/drivers/net/irda/toshoboe.c --- linux.vanilla/drivers/net/irda/toshoboe.c Tue Jun 15 16:49:49 1999 +++ linux.pre11.3/drivers/net/irda/toshoboe.c Mon Jul 19 23:27:34 1999 @@ -568,11 +568,11 @@ self->rxs = inb_p (OBOE_RCVT); self->txs = inb_p (OBOE_XMTT) - OBOE_XMTT_OFFSET; -#ifdef 0 +#if 0 self->rxs = 0; self->txs = 0; #endif -#ifdef 0 +#if 0 self->rxs = RX_SLOTS - 1; self->txs = 0; #endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/jazzsonic.c linux.pre11.3/drivers/net/jazzsonic.c --- linux.vanilla/drivers/net/jazzsonic.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/net/jazzsonic.c Mon Jul 19 23:27:35 1999 @@ -0,0 +1,266 @@ +/* + * sonic.c + * + * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de) + * + * This driver is based on work from Andreas Busse, but most of + * the code is rewritten. + * + * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de) + * + * A driver for the onboard Sonic ethernet controller on Mips Jazz + * systems (Acer Pica-61, Mips Magnum 4000, Olivetti M700 and + * perhaps others, too) + */ + +#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 + +#define SREGS_PAD(n) u16 n; + +#include "sonic.h" + +/* + * Macros to access SONIC registers + */ +#define SONIC_READ(reg) \ + *((volatile unsigned int *)base_addr+reg) + +#define SONIC_WRITE(reg,val) \ + *((volatile unsigned int *)base_addr+reg) = val + + +/* use 0 for production, 1 for verification, >2 for debug */ +#ifdef SONIC_DEBUG +static unsigned int sonic_debug = SONIC_DEBUG; +#else +static unsigned int sonic_debug = 1; +#endif + +/* + * Base address and interupt of the SONIC controller on JAZZ boards + */ +static struct { + unsigned int port; + unsigned int irq; +} sonic_portlist[] = { {JAZZ_ETHERNET_BASE, JAZZ_ETHERNET_IRQ}, {0, 0}}; + +/* + * We cannot use station (ethernet) address prefixes to detect the + * sonic controller since these are board manufacturer depended. + * So we check for known Silicon Revision IDs instead. + */ +static unsigned short known_revisions[] = +{ + 0x04, /* Mips Magnum 4000 */ + 0xffff /* end of list */ +}; + +/* Index to functions, as function prototypes. */ + +extern int sonic_probe(struct device *dev); +static int sonic_probe1(struct device *dev, unsigned int base_addr, unsigned int irq); + + +/* + * Probe for a SONIC ethernet controller on a Mips Jazz board. + * Actually probing is superfluous but we're paranoid. + */ +__initfunc(int sonic_probe(struct device *dev)) +{ + unsigned int base_addr = dev ? dev->base_addr : 0; + int i; + + /* + * Don't probe if we're not running on a Jazz board. + */ + if (mips_machgroup != MACH_GROUP_JAZZ) + return -ENODEV; + if (base_addr >= KSEG0) /* Check a single specified location. */ + return sonic_probe1(dev, base_addr, dev->irq); + else if (base_addr != 0) /* Don't probe at all. */ + return -ENXIO; + + for (i = 0; sonic_portlist[i].port; i++) { + int base_addr = sonic_portlist[i].port; + if (check_region(base_addr, 0x100)) + continue; + if (sonic_probe1(dev, base_addr, sonic_portlist[i].irq) == 0) + return 0; + } + return -ENODEV; +} + +__initfunc(static int sonic_probe1(struct device *dev, + unsigned int base_addr, unsigned int irq)) +{ + static unsigned version_printed = 0; + unsigned int silicon_revision; + unsigned int val; + struct sonic_local *lp; + int i; + + /* + * get the Silicon Revision ID. If this is one of the known + * one assume that we found a SONIC ethernet controller at + * the expected location. + */ + silicon_revision = SONIC_READ(SONIC_SR); + if (sonic_debug > 1) + printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision); + + i = 0; + while ((known_revisions[i] != 0xffff) && + (known_revisions[i] != silicon_revision)) + i++; + + if (known_revisions[i] == 0xffff) { + printk("SONIC ethernet controller not found (0x%4x)\n", + silicon_revision); + return -ENODEV; + } + + request_region(base_addr, 0x100, "SONIC"); + + /* Allocate a new 'dev' if needed. */ + if (dev == NULL) + dev = init_etherdev(0, sizeof(struct sonic_local)); + + if (sonic_debug && version_printed++ == 0) + printk(version); + + printk("%s: %s found at 0x%08x, ", + dev->name, "SONIC ethernet", base_addr); + + /* Fill in the 'dev' fields. */ + dev->base_addr = base_addr; + dev->irq = irq; + + /* + * Put the sonic into software reset, then + * retrieve and print the ethernet address. + */ + SONIC_WRITE(SONIC_CMD,SONIC_CR_RST); + SONIC_WRITE(SONIC_CEP,0); + for (i=0; i<3; i++) { + val = SONIC_READ(SONIC_CAP0-i); + dev->dev_addr[i*2] = val; + dev->dev_addr[i*2+1] = val >> 8; + } + + printk("HW Address "); + for (i = 0; i < 6; i++) { + printk("%2.2x", dev->dev_addr[i]); + if (i<5) + printk(":"); + } + + printk(" IRQ %d\n", irq); + + /* Initialize the device structure. */ + if (dev->priv == NULL) { + /* + * the memory be located in the same 64kb segment + */ + lp = NULL; + i = 0; + do { + lp = (struct sonic_local *)kmalloc(sizeof(*lp), GFP_KERNEL); + if ((unsigned long)lp >> 16 != ((unsigned long)lp + sizeof(*lp) ) >> 16) { + /* FIXME, free the memory later */ + kfree (lp); + lp = NULL; + } + } while (lp == NULL && i++ < 20); + + if (lp == NULL) { + printk ("%s: couldn't allocate memory for descriptors\n", + dev->name); + return -ENOMEM; + } + + memset(lp, 0, sizeof(struct sonic_local)); + + /* get the virtual dma address */ + lp->cda_laddr = vdma_alloc(PHYSADDR(lp),sizeof(*lp)); + if (lp->cda_laddr == ~0UL) { + printk ("%s: couldn't get DMA page entry for descriptors\n", + dev->name); + return -ENOMEM; + } + + lp->tda_laddr = lp->cda_laddr + sizeof (lp->cda); + lp->rra_laddr = lp->tda_laddr + sizeof (lp->tda); + lp->rda_laddr = lp->rra_laddr + sizeof (lp->rra); + + /* allocate receive buffer area */ + /* FIXME, maybe we should use skbs */ + if ((lp->rba = (char *)kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL)) == NULL) { + printk ("%s: couldn't allocate receive buffers\n",dev->name); + return -ENOMEM; + } + + /* get virtual dma address */ + if ((lp->rba_laddr = vdma_alloc(PHYSADDR(lp->rba),SONIC_NUM_RRS * SONIC_RBSIZE)) == ~0UL) { + printk ("%s: couldn't get DMA page entry for receive buffers\n",dev->name); + return -ENOMEM; + } + + /* now convert pointer to KSEG1 pointer */ + lp->rba = (char *)KSEG1ADDR(lp->rba); + flush_cache_all(); + dev->priv = (struct sonic_local *)KSEG1ADDR(lp); + } + + lp = (struct sonic_local *)dev->priv; + dev->open = sonic_open; + dev->stop = sonic_close; + dev->hard_start_xmit = sonic_send_packet; + dev->get_stats = sonic_get_stats; + dev->set_multicast_list = &sonic_multicast_list; + + /* + * clear tally counter + */ + SONIC_WRITE(SONIC_CRCT,0xffff); + SONIC_WRITE(SONIC_FAET,0xffff); + SONIC_WRITE(SONIC_MPT,0xffff); + + /* Fill in the fields of the device structure with ethernet values. */ + ether_setup(dev); + return 0; +} + +/* + * SONIC uses a normal IRQ + */ +#define sonic_request_irq request_irq +#define sonic_free_irq free_irq + +#define sonic_chiptomem(x) KSEG1ADDR(vdma_log2phys(x)) + +#include "sonic.c" diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/lance.c linux.pre11.3/drivers/net/lance.c --- linux.vanilla/drivers/net/lance.c Mon Dec 28 23:09:43 1998 +++ linux.pre11.3/drivers/net/lance.c Tue Jul 20 00:00:12 1999 @@ -499,6 +499,8 @@ lp = (struct lance_private *)(((unsigned long)kmalloc(sizeof(*lp)+7, GFP_DMA | GFP_KERNEL)+7) & ~7); + if(lp==NULL) + return -ENODEV; if (lance_debug > 6) printk(" (#0x%05lx)", (unsigned long)lp); memset(lp, 0, sizeof(*lp)); dev->priv = lp; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/ne2k-pci.c linux.pre11.3/drivers/net/ne2k-pci.c --- linux.vanilla/drivers/net/ne2k-pci.c Tue Jan 26 09:44:21 1999 +++ linux.pre11.3/drivers/net/ne2k-pci.c Mon Jul 19 23:27:32 1999 @@ -24,11 +24,8 @@ /* Our copyright info must remain in the binary. */ static const char *version = -"ne2k-pci.c:v0.99L 2/7/98 D. Becker/P. Gortmaker http://cesdis.gsfc.nasa.gov/linux/drivers/ne2k-pci.html\n"; +"ne2k-pci.c:vpre-1.00e 5/27/99 D. Becker/P. Gortmaker http://cesdis.gsfc.nasa.gov/linux/drivers/ne2k-pci.html\n"; -#ifdef MODVERSIONS -#include -#endif #include #include #include @@ -44,6 +41,13 @@ #include #include "8390.h" +#if defined(__powerpc__) +#define inl_le(addr) le32_to_cpu(inl(addr)) +#define inw_le(addr) le16_to_cpu(inw(addr)) +#define insl insl_ns +#define outsl outsl_ns +#endif + /* Set statically or when loading the driver module. */ static int debug = 1; @@ -58,19 +62,34 @@ /* Do we have a non std. amount of memory? (in units of 256 byte pages) */ /* #define PACKETBUF_MEMSIZE 0x40 */ +#define ne2k_flags reg0 /* Rename an existing field to store flags! */ + +/* Only the low 8 bits are usable for non-init-time flags! */ +enum { + HOLTEK_FDX=1, /* Full duplex -> set 0x80 at offset 0x20. */ + ONLY_16BIT_IO=2, ONLY_32BIT_IO=4, /* Chip can do only 16/32-bit xfers. */ + STOP_PG_0x60=0x100, +}; + +/* This will eventually be converted to the standard PCI probe table. */ + static struct { unsigned short vendor, dev_id; char *name; + int flags; } pci_clone_list[] __initdata = { - {0x10ec, 0x8029, "RealTek RTL-8029"}, - {0x1050, 0x0940, "Winbond 89C940"}, - {0x11f6, 0x1401, "Compex RL2000"}, - {0x8e2e, 0x3000, "KTI ET32P2"}, - {0x4a14, 0x5000, "NetVin NV5000SC"}, - {0x1106, 0x0926, "Via 82C926"}, - {0x10bd, 0x0e34, "SureCom NE34"}, - {0x1050, 0x5a5a, "Winbond"}, + {0x10ec, 0x8029, "RealTek RTL-8029", 0}, + {0x1050, 0x0940, "Winbond 89C940", 0}, + {0x11f6, 0x1401, "Compex RL2000", 0}, + {0x8e2e, 0x3000, "KTI ET32P2", 0}, + {0x4a14, 0x5000, "NetVin NV5000SC", 0}, + {0x1106, 0x0926, "Via 86C926", ONLY_16BIT_IO}, + {0x10bd, 0x0e34, "SureCom NE34", 0}, + {0x1050, 0x5a5a, "Winbond", 0}, + {0x12c3, 0x0058, "Holtek HT80232", ONLY_16BIT_IO | HOLTEK_FDX}, + {0x12c3, 0x5598, "Holtek HT80229", + ONLY_32BIT_IO | HOLTEK_FDX | STOP_PG_0x60 }, {0,} }; @@ -86,7 +105,8 @@ #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ int ne2k_pci_probe(struct device *dev); -static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq); +static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq, + int chip_idx); static int ne2k_pci_open(struct device *dev); static int ne2k_pci_close(struct device *dev); @@ -115,17 +135,13 @@ int init_module(void) { - int retval; - /* We must emit version information. */ if (debug) printk(KERN_INFO "%s", version); - retval = ne2k_pci_probe(0); - - if (retval) { - printk(KERN_NOTICE "ne2k-pci.c: no (useable) cards found, driver NOT installed.\n"); - return retval; + if (ne2k_pci_probe(0)) { + printk(KERN_NOTICE "ne2k-pci.c: No useable cards found, driver NOT installed.\n"); + return -ENODEV; } lock_8390_module(); return 0; @@ -225,7 +241,7 @@ printk("ne2k-pci.c: PCI NE2000 clone '%s' at I/O %#x, IRQ %d.\n", pci_clone_list[i].name, pci_ioaddr, pci_irq_line); - dev = ne2k_pci_probe1(dev, pci_ioaddr, pci_irq_line); + dev = ne2k_pci_probe1(dev, pci_ioaddr, pci_irq_line, i); if (dev == 0) { /* Should not happen. */ printk(KERN_ERR "ne2k-pci: Probe of PCI card at %#x failed.\n", @@ -247,11 +263,11 @@ return cards_found ? 0 : -ENODEV; } -__initfunc (static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq)) +__initfunc (static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq, + int chip_idx)) { int i; unsigned char SA_prom[32]; - const char *name = NULL; int start_page, stop_page; int reg0 = inb(ioaddr); @@ -273,6 +289,8 @@ } } + dev = init_etherdev(dev, 0); + /* Reset card. Who knows what dain-bramaged state it was left in. */ { unsigned long reset_start_time = jiffies; @@ -321,59 +339,47 @@ } -#ifdef notdef - /* Some broken PCI cards don't respect the byte-wide - request in program_seq above, and hence don't have doubled up values. - */ - for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) { - SA_prom[i] = inb(ioaddr + NE_DATAPORT); - SA_prom[i+1] = inb(ioaddr + NE_DATAPORT); - if (SA_prom[i] != SA_prom[i+1]) - sa_prom_doubled = 0; - } - - if (sa_prom_doubled) - for (i = 0; i < 16; i++) - SA_prom[i] = SA_prom[i+i]; -#else - for(i = 0; i < 32 /*sizeof(SA_prom)*/; i++) - SA_prom[i] = inb(ioaddr + NE_DATAPORT); + /* Note: all PCI cards have at least 16 bit access, so we don't have + to check for 8 bit cards. Most cards permit 32 bit access. */ -#endif + if (pci_clone_list[chip_idx].flags & ONLY_32BIT_IO) { + for (i = 0; i < 4 ; i++) + ((u32 *)SA_prom)[i] = le32_to_cpu(inl(ioaddr + NE_DATAPORT)); + } else + for(i = 0; i < 32 /*sizeof(SA_prom)*/; i++) + SA_prom[i] = inb(ioaddr + NE_DATAPORT); /* We always set the 8390 registers for word mode. */ outb(0x49, ioaddr + EN0_DCFG); start_page = NESM_START_PG; - stop_page = NESM_STOP_PG; - /* Set up the rest of the parameters. */ - name = "PCI NE2000"; - - dev = init_etherdev(dev, 0); + stop_page = + pci_clone_list[chip_idx].flags&STOP_PG_0x60 ? 0x60 : NESM_STOP_PG; + /* Set up the rest of the parameters. */ dev->irq = irq; dev->base_addr = ioaddr; /* Allocate dev->priv and fill in 8390 specific dev fields. */ if (ethdev_init(dev)) { printk ("%s: unable to get memory for dev->priv.\n", dev->name); - kfree(dev); return 0; } request_region(ioaddr, NE_IO_EXTENT, dev->name); printk("%s: %s found at %#x, IRQ %d, ", - dev->name, name, ioaddr, dev->irq); + dev->name, pci_clone_list[chip_idx].name, ioaddr, dev->irq); for(i = 0; i < 6; i++) { printk("%2.2X%s", SA_prom[i], i == 5 ? ".\n": ":"); dev->dev_addr[i] = SA_prom[i]; } - ei_status.name = name; + ei_status.name = pci_clone_list[chip_idx].name; ei_status.tx_start_page = start_page; ei_status.stop_page = stop_page; ei_status.word16 = 1; + ei_status.ne2k_flags = pci_clone_list[chip_idx].flags; ei_status.rx_start_page = start_page + TX_PAGES; #ifdef PACKETBUF_MEMSIZE @@ -447,9 +453,9 @@ /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { printk("%s: DMAing conflict in ne2k_pci_get_8390_hdr " - "[DMAstat:%d][irqlock:%d][intr:%ld].\n", + "[DMAstat:%d][irqlock:%d][intr:%d].\n", dev->name, ei_status.dmaing, ei_status.irqlock, - dev->interrupt); + (int)dev->interrupt); return; } @@ -461,11 +467,12 @@ outb(ring_page, nic_base + EN0_RSARHI); outb(E8390_RREAD+E8390_START, nic_base + NE_CMD); -#if defined(USE_LONGIO) - *(u32*)hdr = inl(NE_BASE + NE_DATAPORT); -#else - insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1); -#endif + if (ei_status.ne2k_flags & ONLY_16BIT_IO) { + insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1); + } else { + *(u32*)hdr = le32_to_cpu(inl(NE_BASE + NE_DATAPORT)); + le16_to_cpus(&hdr->count); + } outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ ei_status.dmaing &= ~0x01; @@ -485,12 +492,14 @@ /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { printk("%s: DMAing conflict in ne2k_pci_block_input " - "[DMAstat:%d][irqlock:%d][intr:%ld].\n", + "[DMAstat:%d][irqlock:%d][intr:%d].\n", dev->name, ei_status.dmaing, ei_status.irqlock, - dev->interrupt); + (int)dev->interrupt); return; } ei_status.dmaing |= 0x01; + if (ei_status.ne2k_flags & ONLY_32BIT_IO) + count = (count + 3) & 0xFFFC; outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); outb(count & 0xff, nic_base + EN0_RCNTLO); outb(count >> 8, nic_base + EN0_RCNTHI); @@ -498,21 +507,21 @@ outb(ring_offset >> 8, nic_base + EN0_RSARHI); outb(E8390_RREAD+E8390_START, nic_base + NE_CMD); -#if defined(USE_LONGIO) - insl(NE_BASE + NE_DATAPORT, buf, count>>2); - if (count & 3) { - buf += count & ~3; - if (count & 2) - *((u16*)buf)++ = inw(NE_BASE + NE_DATAPORT); - if (count & 1) - *buf = inb(NE_BASE + NE_DATAPORT); - } -#else - insw(NE_BASE + NE_DATAPORT,buf,count>>1); - if (count & 0x01) { - buf[count-1] = inb(NE_BASE + NE_DATAPORT); + if (ei_status.ne2k_flags & ONLY_16BIT_IO) { + insw(NE_BASE + NE_DATAPORT,buf,count>>1); + if (count & 0x01) { + buf[count-1] = inb(NE_BASE + NE_DATAPORT); + } + } else { + insl(NE_BASE + NE_DATAPORT, buf, count>>2); + if (count & 3) { + buf += count & ~3; + if (count & 2) + *((u16*)buf)++ = le16_to_cpu(inw(NE_BASE + NE_DATAPORT)); + if (count & 1) + *buf = inb(NE_BASE + NE_DATAPORT); + } } -#endif outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ ei_status.dmaing &= ~0x01; @@ -527,15 +536,18 @@ /* On little-endian it's always safe to round the count up for word writes. */ - if (count & 0x01) - count++; + if (ei_status.ne2k_flags & ONLY_32BIT_IO) + count = (count + 3) & 0xFFFC; + else + if (count & 0x01) + count++; /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { printk("%s: DMAing conflict in ne2k_pci_block_output." - "[DMAstat:%d][irqlock:%d][intr:%ld]\n", + "[DMAstat:%d][irqlock:%d][intr:%d]\n", dev->name, ei_status.dmaing, ei_status.irqlock, - dev->interrupt); + (int)dev->interrupt); return; } ei_status.dmaing |= 0x01; @@ -561,16 +573,16 @@ outb(0x00, nic_base + EN0_RSARLO); outb(start_page, nic_base + EN0_RSARHI); outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD); -#if defined(USE_LONGIO) - outsl(NE_BASE + NE_DATAPORT, buf, count>>2); - if (count & 3) { - buf += count & ~3; - if (count & 2) - outw(*((u16*)buf)++, NE_BASE + NE_DATAPORT); + if (ei_status.ne2k_flags & ONLY_16BIT_IO) { + outsw(NE_BASE + NE_DATAPORT, buf, count>>1); + } else { + outsl(NE_BASE + NE_DATAPORT, buf, count>>2); + if (count & 3) { + buf += count & ~3; + if (count & 2) + outw(cpu_to_le16(*((u16*)buf)++), NE_BASE + NE_DATAPORT); + } } -#else - outsw(NE_BASE + NE_DATAPORT, buf, count>>1); -#endif dma_start = jiffies; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/net_init.c linux.pre11.3/drivers/net/net_init.c --- linux.vanilla/drivers/net/net_init.c Wed Apr 28 19:14:27 1999 +++ linux.pre11.3/drivers/net/net_init.c Tue Jul 20 00:00:21 1999 @@ -107,6 +107,8 @@ alloc_size &= ~3; /* Round to dword boundary. */ dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL); + if(dev==NULL) + return NULL; memset(dev, 0, alloc_size); if (sizeof_priv) dev->priv = (void *) (dev + 1); @@ -225,6 +227,8 @@ alloc_size &= ~3; /* Round to dword boundary. */ dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL); + if(dev==NULL) + return NULL; memset(dev, 0, alloc_size); if (sizeof_priv) dev->priv = (void *) (dev + 1); @@ -551,6 +555,8 @@ alloc_size &= ~3; /* Round to dword boundary. */ dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL); + if(dev==NULL) + return NULL; memset(dev, 0, alloc_size); if (sizeof_priv) dev->priv = (void *) (dev + 1); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/olympic.c linux.pre11.3/drivers/net/olympic.c --- linux.vanilla/drivers/net/olympic.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/net/olympic.c Tue Jul 20 00:00:32 1999 @@ -0,0 +1,1661 @@ +/* + * olympic.c (c) 1999 Peter De Schrijver All Rights Reserved + * 1999 Mike Phillips (phillim@amtrak.com) + * + * Linux driver for IBM PCI tokenring cards based on the Pit/Pit-Phy/Olympic + * chipset. + * + * Base Driver Skeleton: + * Written 1993-94 by Donald Becker. + * + * Copyright 1993 United States Government as represented by the + * Director, National Security Agency. + * + * Thanks to Erik De Cock, Adrian Bridgett and Frank Fiene for their + * assistance and perserverance with the testing of this driver. + * + * This software may be used and distributed according to the terms + * of the GNU Public License, incorporated herein by reference. + * + * 4/27/99 - Alpha Release 0.1.0 + * First release to the public + * + * 6/8/99 - Official Release 0.2.0 + * Merged into the kernel code + * + * To Do: + * + * Sanitize for smp + * + * If Problems do Occur + * Most problems can be rectified by either closing and opening the interface + * (ifconfig down and up) or rmmod and insmod'ing the driver (a bit difficult + * if compiled into the kernel). + */ + +/* Change OLYMPIC_DEBUG to 1 to get verbose, and I mean really verbose, messages */ + +#define OLYMPIC_DEBUG 0 + +/* Change OLYMPIC_NETWORK_MONITOR to receive mac frames through the arb channel. + * Will also create a /proc/net/olympic_tr entry if proc_fs is compiled into the + * kernel. + * Intended to be used to create a ring-error reporting network module + * i.e. it will give you the source address of beaconers on the ring + */ + +#define OLYMPIC_NETWORK_MONITOR 0 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "olympic.h" + +/* I've got to put some intelligence into the version number so that Peter and I know + * which version of the code somebody has got. + * Version Number = a.b.c.d where a.b.c is the level of code and d is the latest author. + * So 0.0.1.pds = Peter, 0.0.1.mlp = Mike + * + * Official releases will only have an a.b.c version number format. + */ + +static char *version = +"Olympic.c v0.2.0 6/8/99 - Peter De Schrijver & Mike Phillips" ; + +static char *open_maj_error[] = {"No error", "Lobe Media Test", "Physical Insertion", + "Address Verification", "Neighbor Notification (Ring Poll)", + "Request Parameters","FDX Registration Request", + "FDX Duplicate Address Check", "Station registration Query Wait", + "Unknown stage"}; + +static char *open_min_error[] = {"No error", "Function Failure", "Signal Lost", "Wire Fault", + "Ring Speed Mismatch", "Timeout","Ring Failure","Ring Beaconing", + "Duplicate Node Address","Request Parameters","Remove Received", + "Reserved", "Reserved", "No Monitor Detected for RPL", + "Monitor Contention failer for RPL", "FDX Protocol Error"}; + +/* Module paramters */ + +/* Ring Speed 0,4,16,100 + * 0 = Autosense + * 4,16 = Selected speed only, no autosense + * This allows the card to be the first on the ring + * and become the active monitor. + * 100 = Nothing at present, 100mbps is autodetected + * if FDX is turned on. May be implemented in the future to + * fail if 100mpbs is not detected. + * + * WARNING: Some hubs will allow you to insert + * at the wrong speed + */ + +static int ringspeed[OLYMPIC_MAX_ADAPTERS] = {0,} ; + +MODULE_PARM(ringspeed, "1-" __MODULE_STRING(OLYMPIC_MAX_ADAPTERS) "i"); + +/* Packet buffer size */ + +static int pkt_buf_sz[OLYMPIC_MAX_ADAPTERS] = {0,} ; + +MODULE_PARM(pkt_buf_sz, "1-" __MODULE_STRING(OLYMPIC_MAX_ADAPTERS) "i") ; + +/* Message Level */ + +static int message_level[OLYMPIC_MAX_ADAPTERS] = {0,} ; + +MODULE_PARM(message_level, "1-" __MODULE_STRING(OLYMPIC_MAX_ADAPTERS) "i") ; + +static int olympic_scan(struct device *dev); +static int olympic_init(struct device *dev); +static int olympic_open(struct device *dev); +static int olympic_xmit(struct sk_buff *skb, struct device *dev); +static int olympic_close(struct device *dev); +static void olympic_set_rx_mode(struct device *dev); +static void olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static struct net_device_stats * olympic_get_stats(struct device *dev); +static int olympic_set_mac_address(struct device *dev, void *addr) ; +static void olympic_arb_cmd(struct device *dev); +static int olympic_change_mtu(struct device *dev, int mtu); +static void olympic_srb_bh(struct device *dev) ; +static void olympic_asb_bh(struct device *dev) ; +#if OLYMPIC_NETWORK_MONITOR +#ifdef CONFIG_PROC_FS +static int sprintf_info(char *buffer, struct device *dev) ; +#endif +#endif + +__initfunc(int olympic_probe(struct device *dev)) +{ + int cards_found; + + cards_found=olympic_scan(dev); + return cards_found ? 0 : -ENODEV; +} + +__initfunc(static int olympic_scan(struct device *dev)) +{ + struct pci_dev *pci_device = NULL ; + struct olympic_private *olympic_priv; + int card_no = 0 ; + if (pci_present()) { + + while((pci_device=pci_find_device(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_TR_WAKE, pci_device))) { + + pci_set_master(pci_device); + + /* Check to see if io has been allocated, if so, we've already done this card, + so continue on the card discovery loop */ + + if (check_region(pci_device->base_address[0] & (~3), OLYMPIC_IO_SPACE)) { + card_no++ ; + continue ; + } + + olympic_priv=kmalloc(sizeof (struct olympic_private), GFP_KERNEL); + memset(olympic_priv, 0, sizeof(struct olympic_private)); +#ifndef MODULE + dev=init_trdev(dev, 0); +#endif + dev->priv=(void *)olympic_priv; +#if OLYMPIC_DEBUG + printk("pci_device: %p, dev:%p, dev->priv: %p\n", pci_device, dev, dev->priv); +#endif + dev->irq=pci_device->irq; + dev->base_addr=pci_device->base_address[0] & (~3); + dev->init=&olympic_init; + olympic_priv->olympic_mmio=ioremap(pci_device->base_address[1],256); + olympic_priv->olympic_lap=ioremap(pci_device->base_address[2],2048); + + if ((pkt_buf_sz[card_no] < 100) || (pkt_buf_sz[card_no] > 18000) ) + olympic_priv->pkt_buf_sz = PKT_BUF_SZ ; + else + olympic_priv->pkt_buf_sz = pkt_buf_sz[card_no] ; + + olympic_priv->olympic_ring_speed = ringspeed[card_no] ; + olympic_priv->olympic_message_level = message_level[card_no] ; + olympic_priv->olympic_multicast_set = 0 ; + + if(olympic_init(dev)==-1) { + unregister_netdevice(dev); + kfree(dev->priv); + return 0; + } + + dev->open=&olympic_open; + dev->hard_start_xmit=&olympic_xmit; + dev->change_mtu=&olympic_change_mtu; + + dev->stop=&olympic_close; + dev->do_ioctl=NULL; + dev->set_multicast_list=&olympic_set_rx_mode; + dev->get_stats=&olympic_get_stats ; + dev->set_mac_address=&olympic_set_mac_address ; + return 1; + } + } + return 0 ; +} + + +__initfunc(static int olympic_init(struct device *dev)) +{ + struct olympic_private *olympic_priv; + __u8 *olympic_mmio, *init_srb,*adapter_addr; + unsigned long t; + unsigned int uaa_addr; + + olympic_priv=(struct olympic_private *)dev->priv; + olympic_mmio=olympic_priv->olympic_mmio; + + printk("%s \n", version); + printk("%s: IBM PCI tokenring card. I/O at %hx, MMIO at %p, LAP at %p, using irq %d\n",dev->name, (unsigned int) dev->base_addr,olympic_priv->olympic_mmio, olympic_priv->olympic_lap, dev->irq); + + request_region(dev->base_addr, OLYMPIC_IO_SPACE, "olympic"); + writel(readl(olympic_mmio+BCTL) | BCTL_SOFTRESET,olympic_mmio+BCTL); + t=jiffies; + while((readl(olympic_priv->olympic_mmio+BCTL)) & BCTL_SOFTRESET) { + schedule(); + if(jiffies-t > 40*HZ) { + printk(KERN_ERR "IBM PCI tokenring card not responding.\n"); + release_region(dev->base_addr, OLYMPIC_IO_SPACE) ; + return -1; + } + } + +#if OLYMPIC_DEBUG + printk("BCTL: %x\n",readl(olympic_mmio+BCTL)); + printk("GPR: %x\n",readw(olympic_mmio+GPR)); + printk("SISRMASK: %x\n",readl(olympic_mmio+SISR_MASK)); +#endif + /* Aaaahhh, You have got to be real careful setting GPR, the card + holds the previous values from flash memory, including autosense + and ring speed */ + + writel(readl(olympic_mmio+BCTL)|BCTL_MIMREB,olympic_mmio+BCTL); + + if (olympic_priv->olympic_ring_speed == 0) { /* Autosense */ + writel(readl(olympic_mmio+GPR)|GPR_AUTOSENSE,olympic_mmio+GPR); + if (olympic_priv->olympic_message_level) + printk(KERN_INFO "%s: Ringspeed autosense mode on\n",dev->name); + } else if (olympic_priv->olympic_ring_speed == 16) { + if (olympic_priv->olympic_message_level) + printk(KERN_INFO "%s: Trying to open at 16 Mbps as requested\n", dev->name); + writel(GPR_16MBPS, olympic_mmio+GPR); + } else if (olympic_priv->olympic_ring_speed == 4) { + if (olympic_priv->olympic_message_level) + printk(KERN_INFO "%s: Trying to open at 4 Mbps as requested\n", dev->name) ; + writel(0, olympic_mmio+GPR); + } + + writel(readl(olympic_mmio+GPR)|GPR_NEPTUNE_BF,olympic_mmio+GPR); + +#if OLYMPIC_DEBUG + printk("GPR = %x\n",readw(olympic_mmio + GPR) ) ; +#endif + /* start solo init */ + writel((1<<15),olympic_mmio+SISR_MASK_SUM); + + t=jiffies; + while(!((readl(olympic_mmio+SISR_RR)) & SISR_SRB_REPLY)) { + schedule(); + if(jiffies-t > 40*HZ) { + printk(KERN_ERR "IBM PCI tokenring card not responding.\n"); + release_region(dev->base_addr, OLYMPIC_IO_SPACE); + return -1; + } + } + + writel(readl(olympic_mmio+LAPWWO),olympic_mmio+LAPA); + +#if OLYMPIC_DEBUG + printk("LAPWWO: %x, LAPA: %x\n",readl(olympic_mmio+LAPWWO), readl(olympic_mmio+LAPA)); +#endif + + init_srb=olympic_priv->olympic_lap + ((readl(olympic_mmio+LAPWWO)) & (~0xf800)); + +#if OLYMPIC_DEBUG +{ + int i; + printk("init_srb(%p): ",init_srb); + for(i=0;i<20;i++) + printk("%x ",readb(init_srb+i)); + printk("\n"); +} +#endif + if(readw(init_srb+6)) { + printk(KERN_INFO "tokenring card intialization failed. errorcode : %x\n",readw(init_srb+6)); + release_region(dev->base_addr, OLYMPIC_IO_SPACE); + return -1; + } + + uaa_addr=ntohs(readw(init_srb+8)); + +#if OLYMPIC_DEBUG + printk("UAA resides at %x\n",uaa_addr); +#endif + + writel(uaa_addr,olympic_mmio+LAPA); + adapter_addr=olympic_priv->olympic_lap + (uaa_addr & (~0xf800)); + +#if OLYMPIC_DEBUG + printk("adapter address: %02x:%02x:%02x:%02x:%02x:%02x\n", + readb(adapter_addr), readb(adapter_addr+1),readb(adapter_addr+2), + readb(adapter_addr+3),readb(adapter_addr+4),readb(adapter_addr+5)); +#endif + + memcpy_fromio(&dev->dev_addr[0], adapter_addr,6); + + olympic_priv->olympic_addr_table_addr = ntohs(readw(init_srb + 12)) ; + olympic_priv->olympic_parms_addr = ntohs(readw(init_srb + 14)) ; + + return 0; + +} + +static int olympic_open(struct device *dev) +{ + struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; + __u8 *olympic_mmio=olympic_priv->olympic_mmio,*init_srb; + unsigned long flags; + char open_error[255] ; + int i, open_finished = 1 ; + +#if OLYMPIC_NETWORK_MONITOR + __u8 *oat ; + __u8 *opt ; +#endif + + if(request_irq(dev->irq, &olympic_interrupt, SA_SHIRQ , "olympic", dev)) { + return -EAGAIN; + } + +#if OLYMPIC_DEBUG + printk("BMCTL: %x\n",readl(olympic_mmio+BMCTL_SUM)); + printk("pending ints: %x\n",readl(olympic_mmio+SISR_RR)); +#endif + + writel(SISR_MI,olympic_mmio+SISR_MASK_SUM); + + writel(SISR_MI | SISR_SRB_REPLY, olympic_mmio+SISR_MASK); /* more ints later, doesn't stop arb cmd interrupt */ + + writel(LISR_LIE,olympic_mmio+LISR); /* more ints later */ + + /* adapter is closed, so SRB is pointed to by LAPWWO */ + + writel(readl(olympic_mmio+LAPWWO),olympic_mmio+LAPA); + init_srb=olympic_priv->olympic_lap + ((readl(olympic_mmio+LAPWWO)) & (~0xf800)); + +#if OLYMPIC_DEBUG + printk("LAPWWO: %x, LAPA: %x\n",readl(olympic_mmio+LAPWWO), readl(olympic_mmio+LAPA)); + printk("SISR Mask = %04x\n", readl(olympic_mmio+SISR_MASK)); + printk("Before the open command \n"); +#endif + do { + int i; + + save_flags(flags); + cli(); + for(i=0;iolympic_laa[0]) { + writeb(olympic_priv->olympic_laa[0],init_srb+12); + writeb(olympic_priv->olympic_laa[1],init_srb+13); + writeb(olympic_priv->olympic_laa[2],init_srb+14); + writeb(olympic_priv->olympic_laa[3],init_srb+15); + writeb(olympic_priv->olympic_laa[4],init_srb+16); + writeb(olympic_priv->olympic_laa[5],init_srb+17); + memcpy(dev->dev_addr,olympic_priv->olympic_laa,dev->addr_len) ; + } + writeb(1,init_srb+30); + + olympic_priv->srb_queued=1; + + writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); + + while(olympic_priv->srb_queued) { + interruptible_sleep_on_timeout(&olympic_priv->srb_wait, 60*HZ); + if(signal_pending(current)) { + printk(KERN_WARNING "%s: SRB timed out.\n", + dev->name); + printk(KERN_WARNING "SISR=%x MISR=%x\n", + readl(olympic_mmio+SISR), + readl(olympic_mmio+LISR)); + olympic_priv->srb_queued=0; + break; + } + } + restore_flags(flags); +#if OLYMPIC_DEBUG + printk("init_srb(%p): ",init_srb); + for(i=0;i<20;i++) + printk("%x ",readb(init_srb+i)); + printk("\n"); +#endif + + /* If we get the same return response as we set, the interrupt wasn't raised and the open + * timed out. + */ + + if(readb(init_srb+2)== OLYMPIC_CLEAR_RET_CODE) { + printk(KERN_WARNING "%s: Adapter Open time out or error.\n", dev->name) ; + return -EIO ; + } + + if(readb(init_srb+2)!=0) { + if (readb(init_srb+2) == 0x07) { + if (!olympic_priv->olympic_ring_speed && open_finished) { /* Autosense , first time around */ + printk(KERN_WARNING "%s: Retrying at different ring speed \n", dev->name); + open_finished = 0 ; + } else { + + strcpy(open_error, open_maj_error[(readb(init_srb+7) & 0xf0) >> 4]) ; + strcat(open_error," - ") ; + strcat(open_error, open_min_error[(readb(init_srb+7) & 0x0f)]) ; + + if (!olympic_priv->olympic_ring_speed && ((readb(init_srb+7) & 0x0f) == 0x0d)) { + printk(KERN_WARNING "%s: Tried to autosense ring speed with no monitors present\n",dev->name); + printk(KERN_WARNING "%s: Please try again with a specified ring speed \n",dev->name); + free_irq(dev->irq, dev); + return -EIO ; + } + + printk(KERN_WARNING "%s: %s\n",dev->name,open_error); + free_irq(dev->irq,dev) ; + return -EIO ; + + } /* if autosense && open_finished */ + } else { + printk(KERN_WARNING "%s: Bad OPEN response: %x\n", dev->name,init_srb[2]); + free_irq(dev->irq, dev); + return -EIO; + } + } else + open_finished = 1 ; + } while (!(open_finished)) ; /* Will only loop if ring speed mismatch re-open attempted && autosense is on */ + + if (readb(init_srb+18) & (1<<3)) + if (olympic_priv->olympic_message_level) + printk(KERN_INFO "%s: Opened in FDX Mode\n",dev->name); + + if (readb(init_srb+18) & (1<<1)) + olympic_priv->olympic_ring_speed = 100 ; + else if (readb(init_srb+18) & 1) + olympic_priv->olympic_ring_speed = 16 ; + else + olympic_priv->olympic_ring_speed = 4 ; + + if (olympic_priv->olympic_message_level) + printk(KERN_INFO "%s: Opened in %d Mbps mode\n",dev->name, olympic_priv->olympic_ring_speed); + + olympic_priv->asb=ntohs(readw(init_srb+8)); + olympic_priv->srb=ntohs(readw(init_srb+10)); + olympic_priv->arb=ntohs(readw(init_srb+12)); + olympic_priv->trb=ntohs(readw(init_srb+16)); + + olympic_priv->olympic_receive_options = 0x01 ; + olympic_priv->olympic_copy_all_options = 0 ; + + /* setup rx ring */ + + writel((3<<16),olympic_mmio+BMCTL_RWM); /* Ensure end of frame generated interrupts */ + + writel(BMCTL_RX_DIS|3,olympic_mmio+BMCTL_RWM); /* Yes, this the enables RX channel */ + + for(i=0;ipkt_buf_sz); + if(skb == NULL) + break; + + skb->dev = dev; + + olympic_priv->olympic_rx_ring[i].buffer=virt_to_bus(skb->data); + olympic_priv->olympic_rx_ring[i].res_length = olympic_priv->pkt_buf_sz ; + olympic_priv->rx_ring_skb[i]=skb; + } + + if (i==0) { + printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers. Adapter disabled\n",dev->name); + free_irq(dev->irq, dev); + return -EIO; + } + + writel(virt_to_bus(&olympic_priv->olympic_rx_ring[0]),olympic_mmio+RXDESCQ); + writel(virt_to_bus(&olympic_priv->olympic_rx_ring[0]),olympic_mmio+RXCDA); + writew(i,olympic_mmio+RXDESCQCNT); + + writel(virt_to_bus(&olympic_priv->olympic_rx_status_ring[0]),olympic_mmio+RXSTATQ); + writel(virt_to_bus(&olympic_priv->olympic_rx_status_ring[0]),olympic_mmio+RXCSA); + + olympic_priv->rx_ring_last_received=OLYMPIC_RX_RING_SIZE-1; /* last processed rx status */ + olympic_priv->rx_status_last_received = OLYMPIC_RX_RING_SIZE-1; + + writew(i,olympic_mmio+RXSTATQCNT); + +#if OLYMPIC_DEBUG + printk("# of rx buffers: %d, RXENQ: %x\n",i, readw(olympic_mmio+RXENQ)); + printk("RXCSA: %x, rx_status_ring[0]: %p\n",bus_to_virt(readl(olympic_mmio+RXCSA)),&olympic_priv->olympic_rx_status_ring[0]); + printk(" stat_ring[1]: %p, stat_ring[2]: %p, stat_ring[3]: %p\n", &(olympic_priv->olympic_rx_status_ring[1]), &(olympic_priv->olympic_rx_status_ring[2]), &(olympic_priv->olympic_rx_status_ring[3]) ); + printk(" stat_ring[4]: %p, stat_ring[5]: %p, stat_ring[6]: %p\n", &(olympic_priv->olympic_rx_status_ring[4]), &(olympic_priv->olympic_rx_status_ring[5]), &(olympic_priv->olympic_rx_status_ring[6]) ); + printk(" stat_ring[7]: %p\n", &(olympic_priv->olympic_rx_status_ring[7]) ); + + printk("RXCDA: %x, rx_ring[0]: %p\n",bus_to_virt(readl(olympic_mmio+RXCDA)),&olympic_priv->olympic_rx_ring[0]); +#endif + + writew((((readw(olympic_mmio+RXENQ)) & 0x8000) ^ 0x8000) | i,olympic_mmio+RXENQ); + +#if OLYMPIC_DEBUG + printk("# of rx buffers: %d, RXENQ: %x\n",i, readw(olympic_mmio+RXENQ)); + printk("RXCSA: %x, rx_ring[0]: %p\n",bus_to_virt(readl(olympic_mmio+RXCSA)),&olympic_priv->olympic_rx_status_ring[0]); + printk("RXCDA: %x, rx_ring[0]: %p\n",bus_to_virt(readl(olympic_mmio+RXCDA)),&olympic_priv->olympic_rx_ring[0]); +#endif + + writel(SISR_RX_STATUS | SISR_RX_NOBUF,olympic_mmio+SISR_MASK_SUM); + + /* setup tx ring */ + + writel(BMCTL_TX1_DIS,olympic_mmio+BMCTL_RWM); /* Yes, this enables TX channel 1 */ + for(i=0;iolympic_tx_ring[i].buffer=0xdeadbeef; + + olympic_priv->free_tx_ring_entries=OLYMPIC_TX_RING_SIZE; + writel(virt_to_bus(&olympic_priv->olympic_tx_ring[0]),olympic_mmio+TXDESCQ_1); + writel(virt_to_bus(&olympic_priv->olympic_tx_ring[0]),olympic_mmio+TXCDA_1); + writew(OLYMPIC_TX_RING_SIZE,olympic_mmio+TXDESCQCNT_1); + + writel(virt_to_bus(&olympic_priv->olympic_tx_status_ring[0]),olympic_mmio+TXSTATQ_1); + writel(virt_to_bus(&olympic_priv->olympic_tx_status_ring[0]),olympic_mmio+TXCSA_1); + writew(OLYMPIC_TX_RING_SIZE,olympic_mmio+TXSTATQCNT_1); + + olympic_priv->tx_ring_free=0; /* next entry in tx ring to use */ + olympic_priv->tx_ring_last_status=OLYMPIC_TX_RING_SIZE-1; /* last processed tx status */ + + writel(SISR_TX1_EOF | SISR_ADAPTER_CHECK | SISR_ARB_CMD | SISR_TRB_REPLY | SISR_ASB_FREE,olympic_mmio+SISR_MASK_SUM); + +#if OLYMPIC_DEBUG + printk("BMCTL: %x\n",readl(olympic_mmio+BMCTL_SUM)); + printk("SISR MASK: %x\n",readl(olympic_mmio+SISR_MASK)); +#endif + +#if OLYMPIC_NETWORK_MONITOR + oat = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; + opt = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; + + printk("%s: Node Address: %02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, + readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)), + readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+1), + readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+2), + readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+3), + readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+4), + readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+5)); + printk("%s: Functional Address: %02x:%02x:%02x:%02x\n",dev->name, + readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)), + readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+1), + readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+2), + readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+3)); + + printk("%s: NAUN Address: %02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, + readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)), + readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+1), + readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+2), + readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+3), + readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+4), + readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+5)); + + +#endif + + dev->start = 1; + dev->interrupt=0; + dev->tbusy=0; + + MOD_INC_USE_COUNT ; + return 0; + +} + +/* + * When we enter the rx routine we do not know how many frames have been + * queued on the rx channel. Therefore we start at the next rx status + * position and travel around the receive ring until we have completed + * all the frames. + * + * This means that we may process the frame before we receive the end + * of frame interrupt. This is why we always test the status instead + * of blindly processing the next frame. + * + */ +static void olympic_rx(struct device *dev) +{ + struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; + __u8 *olympic_mmio=olympic_priv->olympic_mmio; + struct olympic_rx_status *rx_status; + struct olympic_rx_desc *rx_desc ; + int rx_ring_last_received,length, buffer_cnt, cpy_length, frag_len; + struct sk_buff *skb, *skb2; + int i; + + rx_status=&(olympic_priv->olympic_rx_status_ring[(olympic_priv->rx_status_last_received + 1) & (OLYMPIC_RX_RING_SIZE - 1)]) ; + + while (rx_status->status_buffercnt) { + + olympic_priv->rx_status_last_received++ ; + olympic_priv->rx_status_last_received &= (OLYMPIC_RX_RING_SIZE -1); +#if OLYMPIC_DEBUG + printk(" stat_ring addr: %x \n", &(olympic_priv->olympic_rx_status_ring[olympic_priv->rx_status_last_received]) ); + printk("rx status: %x rx len: %x \n",rx_status->status_buffercnt,rx_status->fragmentcnt_framelen); +#endif + length=rx_status->fragmentcnt_framelen & 0xffff; + buffer_cnt = rx_status->status_buffercnt & 0xffff ; + i = buffer_cnt ; /* Need buffer_cnt later for rxenq update */ + frag_len = rx_status->fragmentcnt_framelen >> 16 ; + +#if OLYMPIC_DEBUG + printk("length: %x, frag_len: %x, buffer_cnt: %x\n",length,frag_len,buffer_cnt); +#endif + + if(rx_status->status_buffercnt & 0xC0000000) { + if (rx_status->status_buffercnt & 0x3B000000) { + if (olympic_priv->olympic_message_level) { + if (rx_status->status_buffercnt & (1<<29)) /* Rx Frame Truncated */ + printk(KERN_WARNING "%s: Rx Frame Truncated \n",dev->name); + if (rx_status->status_buffercnt & (1<<28)) /*Rx receive overrun */ + printk(KERN_WARNING "%s: Rx Frame Receive overrun \n",dev->name); + if (rx_status->status_buffercnt & (1<<27)) /* No receive buffers */ + printk(KERN_WARNING "%s: No receive buffers \n",dev->name); + if (rx_status->status_buffercnt & (1<<25)) /* Receive frame error detect */ + printk(KERN_WARNING "%s: Receive frame error detect \n",dev->name); + if (rx_status->status_buffercnt & (1<<24)) /* Received Error Detect */ + printk(KERN_WARNING "%s: Received Error Detect \n",dev->name); + } + olympic_priv->rx_ring_last_received += i ; + olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1) ; + olympic_priv->olympic_stats.rx_errors++; + } else { + + if (buffer_cnt == 1) { + skb = dev_alloc_skb(olympic_priv->pkt_buf_sz) ; + } else { + skb = dev_alloc_skb(length) ; + } + + if (skb == NULL) { + printk(KERN_WARNING "%s: Not enough memory to copy packet to upper layers. \n",dev->name) ; + olympic_priv->olympic_stats.rx_dropped++ ; + /* Update counters even though we don't transfer the frame */ + olympic_priv->rx_ring_last_received += i ; + olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1) ; + } else { + skb->dev = dev ; + + /* Optimise based upon number of buffers used. + If only one buffer is used we can simply swap the buffers around. + If more than one then we must use the new buffer and copy the information + first. Ideally all frames would be in a single buffer, this can be tuned by + altering the buffer size. */ + + if (buffer_cnt==1) { + olympic_priv->rx_ring_last_received++ ; + olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1); + rx_ring_last_received = olympic_priv->rx_ring_last_received ; + skb2=olympic_priv->rx_ring_skb[rx_ring_last_received] ; + skb_put(skb2,length); + skb2->protocol = tr_type_trans(skb2,dev); + olympic_priv->olympic_rx_ring[rx_ring_last_received].buffer=virt_to_bus(skb->data); + olympic_priv->olympic_rx_ring[rx_ring_last_received].res_length = olympic_priv->pkt_buf_sz ; + olympic_priv->rx_ring_skb[rx_ring_last_received] = skb ; + netif_rx(skb2) ; + } else { + do { /* Walk the buffers */ + olympic_priv->rx_ring_last_received++ ; + olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1); + rx_ring_last_received = olympic_priv->rx_ring_last_received ; + rx_desc = &(olympic_priv->olympic_rx_ring[rx_ring_last_received]); + cpy_length = (i == 1 ? frag_len : rx_desc->res_length); + memcpy(skb_put(skb, cpy_length), bus_to_virt(rx_desc->buffer), cpy_length) ; + } while (--i) ; + + skb->protocol = tr_type_trans(skb,dev); + netif_rx(skb) ; + } + olympic_priv->olympic_stats.rx_packets++ ; + olympic_priv->olympic_stats.rx_bytes += length ; + } /* if skb == null */ + } /* If status & 0x3b */ + + } else { /*if buffercnt & 0xC */ + olympic_priv->rx_ring_last_received += i ; + olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE - 1) ; + } + + rx_status->fragmentcnt_framelen = 0 ; + rx_status->status_buffercnt = 0 ; + rx_status = &(olympic_priv->olympic_rx_status_ring[(olympic_priv->rx_status_last_received+1) & (OLYMPIC_RX_RING_SIZE -1) ]); + + writew((((readw(olympic_mmio+RXENQ)) & 0x8000) ^ 0x8000) | buffer_cnt , olympic_mmio+RXENQ); + } /* while */ + +} + +static void olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct device *dev= (struct device *)dev_id; + struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; + __u8 *olympic_mmio=olympic_priv->olympic_mmio; + __u32 sisr; + __u8 *adapter_check_area ; + + sisr=readl(olympic_mmio+SISR_RR) ; /* Reset sisr */ + + if (!(sisr & SISR_MI)) /* Interrupt isn't for us */ + return ; + + if (dev->interrupt) + printk(KERN_WARNING "%s: Re-entering interrupt \n",dev->name) ; + + dev->interrupt = 1 ; + + if (sisr & (SISR_SRB_REPLY | SISR_TX1_EOF | SISR_RX_STATUS | SISR_ADAPTER_CHECK | + SISR_ASB_FREE | SISR_ARB_CMD | SISR_TRB_REPLY | SISR_RX_NOBUF)) { + + if(sisr & SISR_SRB_REPLY) { + if(olympic_priv->srb_queued==1) { + wake_up_interruptible(&olympic_priv->srb_wait); + } else if (olympic_priv->srb_queued==2) { + olympic_srb_bh(dev) ; + } + olympic_priv->srb_queued=0; + } /* SISR_SRB_REPLY */ + + if (sisr & SISR_TX1_EOF) { + olympic_priv->tx_ring_last_status++; + olympic_priv->tx_ring_last_status &= (OLYMPIC_TX_RING_SIZE-1); + olympic_priv->free_tx_ring_entries++; + olympic_priv->olympic_stats.tx_bytes += olympic_priv->tx_ring_skb[olympic_priv->tx_ring_last_status]->len; + olympic_priv->olympic_stats.tx_packets++ ; + dev_kfree_skb(olympic_priv->tx_ring_skb[olympic_priv->tx_ring_last_status]); + olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_last_status].buffer=0xdeadbeef; + olympic_priv->olympic_tx_status_ring[olympic_priv->tx_ring_last_status].status=0; + + if(dev->tbusy) { + dev->tbusy=0; + mark_bh(NET_BH); + } + } /* SISR_TX1_EOF */ + + if (sisr & SISR_RX_STATUS) { + olympic_rx(dev); + } /* SISR_RX_STATUS */ + + if (sisr & SISR_ADAPTER_CHECK) { + printk(KERN_WARNING "%s: Adapter Check Interrupt Raised, 8 bytes of information follow:\n", dev->name); + writel(readl(olympic_mmio+LAPWWO),olympic_mmio+LAPA); + adapter_check_area = (__u8 *)(olympic_mmio+LAPWWO) ; + printk(KERN_WARNING "%s: Bytes %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, readb(adapter_check_area+0), readb(adapter_check_area+1), readb(adapter_check_area+2), readb(adapter_check_area+3), readb(adapter_check_area+4), readb(adapter_check_area+5), readb(adapter_check_area+6), readb(adapter_check_area+7)) ; + dev->interrupt = 0 ; + free_irq(dev->irq, dev) ; + + } /* SISR_ADAPTER_CHECK */ + + if (sisr & SISR_ASB_FREE) { + /* Wake up anything that is waiting for the asb response */ + if (olympic_priv->asb_queued) { + olympic_asb_bh(dev) ; + } + } /* SISR_ASB_FREE */ + + if (sisr & SISR_ARB_CMD) { + olympic_arb_cmd(dev) ; + } /* SISR_ARB_CMD */ + + if (sisr & SISR_TRB_REPLY) { + /* Wake up anything that is waiting for the trb response */ + if (olympic_priv->trb_queued) { + wake_up_interruptible(&olympic_priv->trb_wait); + } + olympic_priv->trb_queued = 0 ; + } /* SISR_TRB_REPLY */ + + if (sisr & SISR_RX_NOBUF) { + /* According to the documentation, we don't have to do anything, but trapping it keeps it out of + /var/log/messages. */ + } /* SISR_RX_NOBUF */ + } else { + printk(KERN_WARNING "%s: Unexpected interrupt: %x\n",dev->name, sisr); + printk(KERN_WARNING "%s: SISR_MASK: %x\n",dev->name, readl(olympic_mmio+SISR_MASK)) ; + } /* One if the interrupts we want */ + + dev->interrupt = 0 ; + + writel(SISR_MI,olympic_mmio+SISR_MASK_SUM); + +} + +static int olympic_xmit(struct sk_buff *skb, struct device *dev) +{ + struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; + __u8 *olympic_mmio=olympic_priv->olympic_mmio; + + if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { + return 1; + } + + if(olympic_priv->free_tx_ring_entries) { + olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].buffer=virt_to_bus(skb->data); + olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].status_length=skb->len | (0x80000000); + olympic_priv->tx_ring_skb[olympic_priv->tx_ring_free]=skb; + olympic_priv->free_tx_ring_entries--; + + olympic_priv->tx_ring_free++; + olympic_priv->tx_ring_free &= (OLYMPIC_TX_RING_SIZE-1); + + + writew((((readw(olympic_mmio+TXENQ_1)) & 0x8000) ^ 0x8000) | 1,olympic_mmio+TXENQ_1); + + dev->tbusy=0; + + return 0; + } else + return 1; + +} + + +static int olympic_close(struct device *dev) +{ + struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; + __u8 *olympic_mmio=olympic_priv->olympic_mmio,*srb; + unsigned long flags; + int i; + + writel(olympic_priv->srb,olympic_mmio+LAPA); + srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800)); + + writeb(SRB_CLOSE_ADAPTER,srb+0); + writeb(0,srb+1); + writeb(OLYMPIC_CLEAR_RET_CODE,srb+2); + + save_flags(flags); + cli(); + + olympic_priv->srb_queued=1; + + writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); + + while(olympic_priv->srb_queued) { + interruptible_sleep_on_timeout(&olympic_priv->srb_wait, jiffies+60*HZ); + if(signal_pending(current)) { + printk(KERN_WARNING "%s: SRB timed out.\n", + dev->name); + printk(KERN_WARNING "SISR=%x MISR=%x\n", + readl(olympic_mmio+SISR), + readl(olympic_mmio+LISR)); + olympic_priv->srb_queued=0; + break; + } + } + + restore_flags(flags) ; + olympic_priv->rx_status_last_received++; + olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1; + + for(i=0;irx_ring_skb[olympic_priv->rx_status_last_received]); + olympic_priv->rx_status_last_received++; + olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1; + } + + /* reset tx/rx fifo's and busmaster logic */ + + writel(readl(olympic_mmio+BCTL)|(3<<13),olympic_mmio+BCTL); + udelay(1); + writel(readl(olympic_mmio+BCTL)&~(3<<13),olympic_mmio+BCTL); + +#if OLYMPIC_DEBUG + printk("srb(%p): ",srb); + for(i=0;i<4;i++) + printk("%x ",readb(srb+i)); + printk("\n"); +#endif + dev->start = 0; + free_irq(dev->irq,dev); + + MOD_DEC_USE_COUNT ; + return 0; + +} + +static void olympic_set_rx_mode(struct device *dev) +{ + struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; + __u8 *olympic_mmio = olympic_priv->olympic_mmio ; + __u8 options = 0, set_mc_list = 0 ; + __u8 *srb, *ata ; + struct dev_mc_list *dmi ; + + writel(olympic_priv->srb,olympic_mmio+LAPA); + srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800)); + options = olympic_priv->olympic_copy_all_options; + + if (dev->flags&IFF_PROMISC) + options |= (3<<5) ; /* All LLC and MAC frames, all through the main rx channel */ + else + options &= ~(3<<5) ; + + if (dev->mc_count) { + set_mc_list = 1 ; + } + + /* Only issue the srb if there is a change in options */ + + if ((options ^ olympic_priv->olympic_copy_all_options)) { + + /* Now to issue the srb command to alter the copy.all.options */ + + writeb(SRB_MODIFY_RECEIVE_OPTIONS,srb); + writeb(0,srb+1); + writeb(OLYMPIC_CLEAR_RET_CODE,srb+2); + writeb(0,srb+3); + writeb(olympic_priv->olympic_receive_options,srb+4); + writeb(options,srb+5); + + olympic_priv->srb_queued=2; /* Can't sleep, use srb_bh */ + + writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); + + olympic_priv->olympic_copy_all_options = options ; + + return ; + } + + if (set_mc_list ^ olympic_priv->olympic_multicast_set) { /* Multicast options have changed */ + + dmi = dev->mc_list ; + + if (set_mc_list) { /* Turn multicast on */ + + /* RFC 1469 Says we must support using the functional address C0 00 00 04 00 00 + * We do this with a set functional address mask. + */ + + ata=olympic_priv->olympic_lap + (olympic_priv->olympic_addr_table_addr) ; + if (!(readb(ata+11) & 0x04)) { /* Hmmm, need to set the functional mask */ + writeb(SRB_SET_FUNC_ADDRESS,srb+0); + writeb(0,srb+1); + writeb(OLYMPIC_CLEAR_RET_CODE,srb+2); + writeb(0,srb+3); + writeb(0,srb+4); + writeb(0,srb+5); + writeb(readb(ata+10),srb+6); + writeb(readb(ata+11)|4,srb+7); + writeb(readb(ata+12),srb+8); + writeb(readb(ata+13),srb+9); + + olympic_priv->srb_queued = 2 ; + writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); + + olympic_priv->olympic_multicast_set = 1 ; + } + + + } else { /* Turn multicast off */ + + ata=olympic_priv->olympic_lap + (olympic_priv->olympic_addr_table_addr) ; + if ((readb(ata+11) & 0x04)) { /* Hmmm, need to reset the functional mask */ + writeb(SRB_SET_FUNC_ADDRESS,srb+0); + writeb(0,srb+1); + writeb(OLYMPIC_CLEAR_RET_CODE,srb+2); + writeb(0,srb+3); + writeb(0,srb+4); + writeb(0,srb+5); + writeb(readb(ata+10),srb+6); + writeb(readb(ata+11) & ~4,srb+7); + writeb(readb(ata+12),srb+8); + writeb(readb(ata+13),srb+9); + + olympic_priv->srb_queued = 2 ; + writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); + + olympic_priv->olympic_multicast_set = 0 ; + } + } + + } + + +} + +static void olympic_srb_bh(struct device *dev) +{ + struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; + __u8 *olympic_mmio = olympic_priv->olympic_mmio ; + __u8 *srb; + + writel(olympic_priv->srb,olympic_mmio+LAPA); + srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800)); + + switch (readb(srb)) { + + /* SRB_MODIFY_RECEIVE_OPTIONS i.e. set_multicast_list options (promiscuous) + * At some point we should do something if we get an error, such as + * resetting the IFF_PROMISC flag in dev + */ + + case SRB_MODIFY_RECEIVE_OPTIONS: + switch (readb(srb+2)) { + case 0x01: + printk(KERN_WARNING "%s: Unrecognized srb command\n",dev->name) ; + break ; + case 0x04: + printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name); + break ; + default: + if (olympic_priv->olympic_message_level) + printk(KERN_WARNING "%s: Receive Options Modified to %x,%x\n",dev->name,olympic_priv->olympic_copy_all_options, olympic_priv->olympic_receive_options) ; + break ; + } /* switch srb[2] */ + break ; + + /* SRB_SET_GROUP_ADDRESS - Multicast group setting + */ + + case SRB_SET_GROUP_ADDRESS: + switch (readb(srb+2)) { + case 0x00: + olympic_priv->olympic_multicast_set = 1 ; + break ; + case 0x01: + printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; + break ; + case 0x04: + printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name); + break ; + case 0x3c: + printk(KERN_WARNING "%s: Group/Functional address indicator bits not set correctly\n",dev->name) ; + break ; + case 0x3e: /* If we ever implement individual multicast addresses, will need to deal with this */ + printk(KERN_WARNING "%s: Group address registers full\n",dev->name) ; + break ; + case 0x55: + printk(KERN_INFO "%s: Group Address already set.\n",dev->name) ; + break ; + default: + break ; + } /* switch srb[2] */ + break ; + + /* SRB_RESET_GROUP_ADDRESS - Remove a multicast address from group list + */ + + case SRB_RESET_GROUP_ADDRESS: + switch (readb(srb+2)) { + case 0x00: + olympic_priv->olympic_multicast_set = 0 ; + break ; + case 0x01: + printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; + break ; + case 0x04: + printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ; + break ; + case 0x39: /* Must deal with this if individual multicast addresses used */ + printk(KERN_INFO "%s: Group address not found \n",dev->name); + break ; + default: + break ; + } /* switch srb[2] */ + break ; + + + /* SRB_SET_FUNC_ADDRESS - Called by the set_rx_mode + */ + + case SRB_SET_FUNC_ADDRESS: + switch (readb(srb+2)) { + case 0x00: + if (olympic_priv->olympic_message_level) + printk(KERN_INFO "%s: Functional Address Mask Set \n",dev->name) ; + break ; + case 0x01: + printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; + break ; + case 0x04: + printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ; + break ; + default: + break ; + } /* switch srb[2] */ + break ; + + /* SRB_READ_LOG - Read and reset the adapter error counters + */ + + case SRB_READ_LOG: + switch (readb(srb+2)) { + case 0x00: + if (olympic_priv->olympic_message_level) + printk(KERN_INFO "%s: Read Log issued\n",dev->name) ; + break ; + case 0x01: + printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; + break ; + case 0x04: + printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ; + break ; + + } /* switch srb[2] */ + break ; + + /* SRB_READ_SR_COUNTERS - Read and reset the source routing bridge related counters */ + + case SRB_READ_SR_COUNTERS: + switch (readb(srb+2)) { + case 0x00: + if (olympic_priv->olympic_message_level) + printk(KERN_INFO "%s: Read Source Routing Counters issued\n",dev->name) ; + break ; + case 0x01: + printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; + break ; + case 0x04: + printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ; + break ; + default: + break ; + } /* switch srb[2] */ + break ; + + default: + printk(KERN_WARNING "%s: Unrecognized srb bh return value.\n",dev->name); + break ; + } /* switch srb[0] */ + +} + +static struct net_device_stats * olympic_get_stats(struct device *dev) +{ + struct olympic_private *olympic_priv ; + olympic_priv=(struct olympic_private *) dev->priv; + return (struct net_device_stats *) &olympic_priv->olympic_stats; +} + +static int olympic_set_mac_address (struct device *dev, void *addr) +{ + struct sockaddr *saddr = addr ; + struct olympic_private *olympic_priv = (struct olympic_private *)dev->priv ; + + if (dev->start) { + printk(KERN_WARNING "%s: Cannot set mac/laa address while card is open\n", dev->name) ; + return -EIO ; + } + + memcpy(olympic_priv->olympic_laa, saddr->sa_data,dev->addr_len) ; + + if (olympic_priv->olympic_message_level) { + printk(KERN_INFO "%s: MAC/LAA Set to = %x.%x.%x.%x.%x.%x\n",dev->name, olympic_priv->olympic_laa[0], + olympic_priv->olympic_laa[1], olympic_priv->olympic_laa[2], + olympic_priv->olympic_laa[3], olympic_priv->olympic_laa[4], + olympic_priv->olympic_laa[5]); + } + + return 0 ; +} + +static void olympic_arb_cmd(struct device *dev) +{ + struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv; + __u8 *olympic_mmio=olympic_priv->olympic_mmio; + __u8 *arb_block, *asb_block, *srb ; + __u8 header_len ; + __u16 frame_len, buffer_len ; + struct sk_buff *mac_frame ; + __u8 *buf_ptr ; + __u8 *frame_data ; + __u16 buff_off ; + __u16 lan_status = 0, lan_status_diff ; /* Initialize to stop compiler warning */ + __u8 fdx_prot_error ; + __u16 next_ptr; + +#if OLYMPIC_NETWORK_MONITOR + struct trh_hdr *mac_hdr ; +#endif + + arb_block = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ; + asb_block = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ; + srb = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->srb) ; + writel(readl(olympic_mmio+LAPA),olympic_mmio+LAPWWO); + + if (readb(arb_block+0) == ARB_RECEIVE_DATA) { /* Receive.data, MAC frames */ + + header_len = readb(arb_block+8) ; /* 802.5 Token-Ring Header Length */ + frame_len = ntohs(readw(arb_block + 10)) ; + + buff_off = ntohs(readw(arb_block + 6)) ; + + buf_ptr = olympic_priv->olympic_lap + buff_off ; + +#if OLYMPIC_DEBUG +{ + int i; + frame_data = buf_ptr+offsetof(struct mac_receive_buffer,frame_data) ; + + for (i=0 ; i < 14 ; i++) { + printk("Loc %d = %02x\n",i,readb(frame_data + i)); + } + + printk("next %04x, fs %02x, len %04x \n",readw(buf_ptr+offsetof(struct mac_receive_buffer,next)), readb(buf_ptr+offsetof(struct mac_receive_buffer,frame_status)), readw(buf_ptr+offsetof(struct mac_receive_buffer,buffer_length))); +} +#endif + mac_frame = dev_alloc_skb(frame_len) ; + + /* Walk the buffer chain, creating the frame */ + + do { + frame_data = buf_ptr+offsetof(struct mac_receive_buffer,frame_data) ; + buffer_len = ntohs(readw(buf_ptr+offsetof(struct mac_receive_buffer,buffer_length))); + memcpy_fromio(skb_put(mac_frame, buffer_len), frame_data , buffer_len ) ; + next_ptr=readw(buf_ptr+offsetof(struct mac_receive_buffer,next)); + + } while (next_ptr && (buf_ptr=olympic_priv->olympic_lap + ntohs(next_ptr))); + +#if OLYMPIC_NETWORK_MONITOR + printk(KERN_WARNING "%s: Received MAC Frame, details: \n",dev->name) ; + mac_hdr = (struct trh_hdr *)mac_frame->data ; + printk(KERN_WARNING "%s: MAC Frame Dest. Addr: %02x:%02x:%02x:%02x:%02x:%02x \n", dev->name , mac_hdr->daddr[0], mac_hdr->daddr[1], mac_hdr->daddr[2], mac_hdr->daddr[3], mac_hdr->daddr[4], mac_hdr->daddr[5]) ; + printk(KERN_WARNING "%s: MAC Frame Srce. Addr: %02x:%02x:%02x:%02x:%02x:%02x \n", dev->name , mac_hdr->saddr[0], mac_hdr->saddr[1], mac_hdr->saddr[2], mac_hdr->saddr[3], mac_hdr->saddr[4], mac_hdr->saddr[5]) ; +#endif + mac_frame->dev = dev ; + mac_frame->protocol = tr_type_trans(mac_frame,dev); + netif_rx(mac_frame) ; + + /* Now tell the card we have dealt with the received frame */ + + /* Set LISR Bit 1 */ + writel(LISR_ARB_FREE,olympic_priv->olympic_lap + LISR_SUM); + + /* Is the ASB free ? */ + + if (!(readl(olympic_priv->olympic_mmio + SISR) & SISR_ASB_FREE)) { + olympic_priv->asb_queued = 1 ; + writel(LISR_ASB_FREE_REQ,olympic_priv->olympic_mmio+LISR_SUM); + return ; + /* Drop out and wait for the bottom half to be run */ + } + + writeb(ASB_RECEIVE_DATA,asb_block); /* Receive data */ + writeb(OLYMPIC_CLEAR_RET_CODE,asb_block+2); /* Necessary ?? */ + writeb(readb(arb_block+6),asb_block+6); /* Must send the address back to the adapter */ + writeb(readb(arb_block+7),asb_block+7); /* To let it know we have dealt with the data */ + + writel(LISR_ASB_REPLY | LISR_ASB_FREE_REQ,olympic_priv->olympic_mmio+LISR_SUM); + + olympic_priv->asb_queued = 2 ; + + return ; + + } else if (readb(arb_block) == ARB_LAN_CHANGE_STATUS) { /* Lan.change.status */ + lan_status = readw(arb_block+6); + fdx_prot_error = readb(arb_block+8) ; + + /* Issue ARB Free */ + writel(LISR_ARB_FREE,olympic_priv->olympic_mmio+LISR_SUM); + + lan_status_diff = olympic_priv->olympic_lan_status ^ lan_status ; + + if (lan_status_diff & (LSC_LWF | LSC_ARW | LSC_FPE | LSC_RR) ) { + if (lan_status_diff & LSC_LWF) + printk(KERN_WARNING "%s: Short circuit detected on the lobe\n",dev->name); + if (lan_status_diff & LSC_ARW) + printk(KERN_WARNING "%s: Auto removal error\n",dev->name); + if (lan_status_diff & LSC_FPE) + printk(KERN_WARNING "%s: FDX Protocol Error\n",dev->name); + if (lan_status_diff & LSC_RR) + printk(KERN_WARNING "%s: Force remove MAC frame received\n",dev->name); + + /* Adapter has been closed by the hardware */ + + /* reset tx/rx fifo's and busmaster logic */ + + writel(readl(olympic_mmio+BCTL)|(3<<13),olympic_mmio+BCTL); + udelay(1); + writel(readl(olympic_mmio+BCTL)&~(3<<13),olympic_mmio+BCTL); + dev->tbusy = 1 ; + dev->interrupt = 1 ; + dev->start = 0 ; + olympic_priv->srb = readw(olympic_priv->olympic_lap + LAPWWO) ; + free_irq(dev->irq,dev); + + printk(KERN_WARNING "%s: Adapter has been closed \n", dev->name) ; + + } /* If serious error */ + + if (olympic_priv->olympic_message_level) { + if (lan_status_diff & LSC_SIG_LOSS) + printk(KERN_WARNING "%s: No receive signal detected \n", dev->name) ; + if (lan_status_diff & LSC_HARD_ERR) + printk(KERN_INFO "%s: Beaconing \n",dev->name); + if (lan_status_diff & LSC_SOFT_ERR) + printk(KERN_WARNING "%s: Adapter transmitted Soft Error Report Mac Frame \n",dev->name); + if (lan_status_diff & LSC_TRAN_BCN) + printk(KERN_INFO "%s: We are tranmitting the beacon, aaah\n",dev->name); + if (lan_status_diff & LSC_SS) + printk(KERN_INFO "%s: Single Station on the ring \n", dev->name); + if (lan_status_diff & LSC_RING_REC) + printk(KERN_INFO "%s: Ring recovery ongoing\n",dev->name); + if (lan_status_diff & LSC_FDX_MODE) + printk(KERN_INFO "%s: Operating in FDX mode\n",dev->name); + } + + if (lan_status_diff & LSC_CO) { + + if (olympic_priv->olympic_message_level) + printk(KERN_INFO "%s: Counter Overflow \n", dev->name); + + /* Issue READ.LOG command */ + + writeb(SRB_READ_LOG, srb); + writeb(0,srb+1); + writeb(OLYMPIC_CLEAR_RET_CODE,srb+2); + writeb(0,srb+3); + writeb(0,srb+4); + writeb(0,srb+5); + + olympic_priv->srb_queued=2; /* Can't sleep, use srb_bh */ + + writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); + + } + + if (lan_status_diff & LSC_SR_CO) { + + if (olympic_priv->olympic_message_level) + printk(KERN_INFO "%s: Source routing counters overflow\n", dev->name); + + /* Issue a READ.SR.COUNTERS */ + + writeb(SRB_READ_SR_COUNTERS,srb); + writeb(0,srb+1); + writeb(OLYMPIC_CLEAR_RET_CODE,srb+2); + writeb(0,srb+3); + + olympic_priv->srb_queued=2; /* Can't sleep, use srb_bh */ + + writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); + + } + + olympic_priv->olympic_lan_status = lan_status ; + + } /* Lan.change.status */ + else + printk(KERN_WARNING "%s: Unknown arb command \n", dev->name); +} + +static void olympic_asb_bh(struct device *dev) +{ + struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; + __u8 *arb_block, *asb_block ; + + arb_block = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ; + asb_block = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ; + + if (olympic_priv->asb_queued == 1) { /* Dropped through the first time */ + + writeb(ASB_RECEIVE_DATA,asb_block); /* Receive data */ + writeb(OLYMPIC_CLEAR_RET_CODE,asb_block+2); /* Necessary ?? */ + writeb(readb(arb_block+6),asb_block+6); /* Must send the address back to the adapter */ + writeb(readb(arb_block+7),asb_block+7); /* To let it know we have dealt with the data */ + + writel(LISR_ASB_REPLY | LISR_ASB_FREE_REQ,olympic_priv->olympic_mmio+LISR_SUM); + olympic_priv->asb_queued = 2 ; + + return ; + } + + if (olympic_priv->asb_queued == 2) { + switch (readb(asb_block+2)) { + case 0x01: + printk(KERN_WARNING "%s: Unrecognized command code \n", dev->name); + break ; + case 0x26: + printk(KERN_WARNING "%s: Unrecognized buffer address \n", dev->name); + break ; + case 0xFF: + /* Valid response, everything should be ok again */ + break ; + default: + printk(KERN_WARNING "%s: Invalid return code in asb\n",dev->name); + break ; + } + } + olympic_priv->asb_queued = 0 ; +} + +static int olympic_change_mtu(struct device *dev, int mtu) +{ + struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv; + __u16 max_mtu ; + + if (olympic_priv->olympic_ring_speed == 4) + max_mtu = 4500 ; + else + max_mtu = 18000 ; + + if (mtu > max_mtu) + return -EINVAL ; + if (mtu < 100) + return -EINVAL ; + + dev->mtu = mtu ; + olympic_priv->pkt_buf_sz = mtu + TR_HLEN ; + + return 0 ; +} + +#if OLYMPIC_NETWORK_MONITOR +#ifdef CONFIG_PROC_FS +static int olympic_proc_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data) +{ + struct pci_dev *pci_device = NULL ; + int len=0; + off_t begin=0; + off_t pos=0; + int size; + + struct device *dev; + + + size = sprintf(buffer, + "IBM Pit/Pit-Phy/Olympic Chipset Token Ring Adapters\n"); + + pos+=size; + len+=size; + + + while((pci_device=pci_find_device(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_TR_WAKE, pci_device))) { + + for (dev = dev_base; dev != NULL; dev = dev->next) + { + if (dev->base_addr == (pci_device->base_address[0] & (~3)) ) { /* Yep, an Olympic device */ + size = sprintf_info(buffer+len, dev); + len+=size; + pos=begin+len; + + if(posoffset+length) + break; + } /* if */ + } /* for */ + } /* While */ + + *start=buffer+(offset-begin); /* Start of wanted data */ + len-=(offset-begin); /* Start slop */ + if(len>length) + len=length; /* Ending slop */ + return len; +} + +static int sprintf_info(char *buffer, struct device *dev) +{ + struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; + __u8 *oat = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; + __u8 *opt = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; + int size = 0 ; + + size = sprintf(buffer, "\n%6s: Adapter Address : Node Address : Functional Addr\n", + dev->name); + + size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x\n", + dev->name, + dev->dev_addr[0], + dev->dev_addr[1], + dev->dev_addr[2], + dev->dev_addr[3], + dev->dev_addr[4], + dev->dev_addr[5], + readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)), + readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+1), + readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+2), + readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+3), + readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+4), + readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+5), + readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)), + readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+1), + readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+2), + readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+3)); + + size += sprintf(buffer+size, "\n%6s: Token Ring Parameters Table:\n", dev->name); + + size += sprintf(buffer+size, "%6s: Physical Addr : Up Node Address : Poll Address : AccPri : Auth Src : Att Code :\n", + dev->name) ; + + size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x:%02x:%02x : %04x : %04x : %04x :\n", + dev->name, + readb(opt+offsetof(struct olympic_parameters_table, phys_addr)), + readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+1), + readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+2), + readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+3), + readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)), + readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+1), + readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+2), + readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+3), + readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+4), + readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+5), + readb(opt+offsetof(struct olympic_parameters_table, poll_addr)), + readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+1), + readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+2), + readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+3), + readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+4), + readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+5), + ntohs(readw(opt+offsetof(struct olympic_parameters_table, acc_priority))), + ntohs(readw(opt+offsetof(struct olympic_parameters_table, auth_source_class))), + ntohs(readw(opt+offsetof(struct olympic_parameters_table, att_code)))); + + size += sprintf(buffer+size, "%6s: Source Address : Bcn T : Maj. V : Lan St : Lcl Rg : Mon Err : Frame Correl : \n", + dev->name) ; + + size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x:%02x:%02x : %04x : %04x : %04x : %04x : %04x : %04x : \n", + dev->name, + readb(opt+offsetof(struct olympic_parameters_table, source_addr)), + readb(opt+offsetof(struct olympic_parameters_table, source_addr)+1), + readb(opt+offsetof(struct olympic_parameters_table, source_addr)+2), + readb(opt+offsetof(struct olympic_parameters_table, source_addr)+3), + readb(opt+offsetof(struct olympic_parameters_table, source_addr)+4), + readb(opt+offsetof(struct olympic_parameters_table, source_addr)+5), + ntohs(readw(opt+offsetof(struct olympic_parameters_table, beacon_type))), + ntohs(readw(opt+offsetof(struct olympic_parameters_table, major_vector))), + ntohs(readw(opt+offsetof(struct olympic_parameters_table, lan_status))), + ntohs(readw(opt+offsetof(struct olympic_parameters_table, local_ring))), + ntohs(readw(opt+offsetof(struct olympic_parameters_table, mon_error))), + ntohs(readw(opt+offsetof(struct olympic_parameters_table, frame_correl)))); + + size += sprintf(buffer+size, "%6s: Beacon Details : Tx : Rx : NAUN Node Address : NAUN Node Phys : \n", + dev->name) ; + + size += sprintf(buffer+size, "%6s: : %02x : %02x : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x : \n", + dev->name, + ntohs(readw(opt+offsetof(struct olympic_parameters_table, beacon_transmit))), + ntohs(readw(opt+offsetof(struct olympic_parameters_table, beacon_receive))), + readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)), + readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+1), + readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+2), + readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+3), + readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+4), + readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+5), + readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)), + readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+1), + readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+2), + readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+3)); + + + return size; +} +#endif +#endif + +#ifdef MODULE + +static struct device* dev_olympic[OLYMPIC_MAX_ADAPTERS]; + +int init_module(void) +{ + int i; + +#if OLYMPIC_NETWORK_MONITOR +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *ent ; + + ent = create_proc_entry("net/olympic_tr",0,0); + ent->read_proc = &olympic_proc_info ; +#endif +#endif + for (i = 0; (iinit = &olympic_probe; + + if (register_trdev(dev_olympic[i]) != 0) { + kfree_s(dev_olympic[i], sizeof(struct device)); + dev_olympic[i] = NULL; + if (i == 0) { + printk("Olympic: No IBM PCI Token Ring cards found in system.\n"); + return -EIO; + } else { + printk("Olympic: %d IBM PCI Token Ring card(s) found in system.\n",i) ; + return 0; + } + } + } + + return 0; +} + +void cleanup_module(void) +{ + int i; + + for (i = 0; i < OLYMPIC_MAX_ADAPTERS; i++) + if (dev_olympic[i]) { + unregister_trdev(dev_olympic[i]); + release_region(dev_olympic[i]->base_addr, OLYMPIC_IO_SPACE); + kfree_s(dev_olympic[i]->priv, sizeof(struct olympic_private)); + kfree_s(dev_olympic[i], sizeof(struct device)); + dev_olympic[i] = NULL; + } + +#if OLYMPIC_NETWORK_MONITOR +#ifdef CONFIG_PROC_FS + remove_proc_entry("net/olympic_tr", NULL) ; +#endif +#endif +} +#endif /* MODULE */ + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/olympic.h linux.pre11.3/drivers/net/olympic.h --- linux.vanilla/drivers/net/olympic.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/net/olympic.h Mon Jul 19 23:27:35 1999 @@ -0,0 +1,303 @@ +/* + * olympic.h (c) 1999 Peter De Schrijver All Rights Reserved + * 1999 Mike Phillips (phillim@amtrak.com) + * + * Linux driver for IBM PCI tokenring cards based on the olympic and the PIT/PHY chipset. + * + * Base Driver Skeleton: + * Written 1993-94 by Donald Becker. + * + * Copyright 1993 United States Government as represented by the + * Director, National Security Agency. + * + * This software may be used and distributed according to the terms + * of the GNU Public License, incorporated herein by reference. + */ + +#define CID 0x4e + +#define BCTL 0x70 +#define BCTL_SOFTRESET (1<<15) +#define BCTL_MIMREB (1<<6) + +#define GPR 0x4a +#define GPR_OPTI_BF (1<<6) +#define GPR_NEPTUNE_BF (1<<4) +#define GPR_AUTOSENSE (1<<2) +#define GPR_16MBPS (1<<3) + +#define PAG 0x85 +#define LBC 0x8e + +#define LISR 0x10 +#define LISR_SUM 0x14 +#define LISR_RWM 0x18 + +#define LISR_LIE (1<<15) +#define LISR_SLIM (1<<13) +#define LISR_SLI (1<<12) +#define LISR_PCMSRMASK (1<<11) +#define LISR_PCMSRINT (1<<10) +#define LISR_WOLMASK (1<<9) +#define LISR_WOL (1<<8) +#define LISR_SRB_CMD (1<<5) +#define LISR_ASB_REPLY (1<<4) +#define LISR_ASB_FREE_REQ (1<<2) +#define LISR_ARB_FREE (1<<1) +#define LISR_TRB_FRAME (1<<0) + +#define SISR 0x20 +#define SISR_SUM 0x24 +#define SISR_RWM 0x28 +#define SISR_RR 0x2C +#define SISR_RESMASK 0x30 +#define SISR_MASK 0x54 +#define SISR_MASK_SUM 0x58 +#define SISR_MASK_RWM 0x5C + +#define SISR_TX2_IDLE (1<<31) +#define SISR_TX2_HALT (1<<29) +#define SISR_TX2_EOF (1<<28) +#define SISR_TX1_IDLE (1<<27) +#define SISR_TX1_HALT (1<<25) +#define SISR_TX1_EOF (1<<24) +#define SISR_TIMEOUT (1<<23) +#define SISR_RX_NOBUF (1<<22) +#define SISR_RX_STATUS (1<<21) +#define SISR_RX_HALT (1<<18) +#define SISR_RX_EOF_EARLY (1<<16) +#define SISR_MI (1<<15) +#define SISR_PI (1<<13) +#define SISR_ERR (1<<9) +#define SISR_ADAPTER_CHECK (1<<6) +#define SISR_SRB_REPLY (1<<5) +#define SISR_ASB_FREE (1<<4) +#define SISR_ARB_CMD (1<<3) +#define SISR_TRB_REPLY (1<<2) + +#define EISR 0x34 +#define EISR_RWM 0x38 +#define EISR_MASK 0x3c + +#define LAPA 0x60 +#define LAPWWO 0x64 +#define LAPWWC 0x68 +#define LAPCTL 0x6C +#define LAIPD 0x78 +#define LAIPDDINC 0x7C + +#define TIMER 0x50 + +#define CLKCTL 0x74 + +#define PM_CON 0x4 + +#define BMCTL_SUM 0x40 +#define BMCTL_RWM 0x44 +#define BMCTL_TX2_DIS (1<<30) +#define BMCTL_TX1_DIS (1<<26) +#define BMCTL_RX_DIS (1<<22) + +#define BMASR 0xcc + +#define RXDESCQ 0x90 +#define RXDESCQCNT 0x94 +#define RXCDA 0x98 +#define RXENQ 0x9C +#define RXSTATQ 0xA0 +#define RXSTATQCNT 0xA4 +#define RXCSA 0xA8 +#define RXCLEN 0xAC +#define RXHLEN 0xAE + +#define TXDESCQ_1 0xb0 +#define TXDESCQ_2 0xd0 +#define TXDESCQCNT_1 0xb4 +#define TXDESCQCNT_2 0xd4 +#define TXCDA_1 0xb8 +#define TXCDA_2 0xd8 +#define TXENQ_1 0xbc +#define TXENQ_2 0xdc +#define TXSTATQ_1 0xc0 +#define TXSTATQ_2 0xe0 +#define TXSTATQCNT_1 0xc4 +#define TXSTATQCNT_2 0xe4 +#define TXCSA_1 0xc8 +#define TXCSA_2 0xe8 + +#define OLYMPIC_IO_SPACE 256 + +#define SRB_COMMAND_SIZE 50 + +#define OLYMPIC_MAX_ADAPTERS 8 /* 0x08 __MODULE_STRING can't hand 0xnn */ + +/* Defines for LAN STATUS CHANGE reports */ +#define LSC_SIG_LOSS 0x8000 +#define LSC_HARD_ERR 0x4000 +#define LSC_SOFT_ERR 0x2000 +#define LSC_TRAN_BCN 0x1000 +#define LSC_LWF 0x0800 +#define LSC_ARW 0x0400 +#define LSC_FPE 0x0200 +#define LSC_RR 0x0100 +#define LSC_CO 0x0080 +#define LSC_SS 0x0040 +#define LSC_RING_REC 0x0020 +#define LSC_SR_CO 0x0010 +#define LSC_FDX_MODE 0x0004 + +/* Defines for OPEN ADAPTER command */ + +#define OPEN_ADAPTER_EXT_WRAP (1<<15) +#define OPEN_ADAPTER_DIS_HARDEE (1<<14) +#define OPEN_ADAPTER_DIS_SOFTERR (1<<13) +#define OPEN_ADAPTER_PASS_ADC_MAC (1<<12) +#define OPEN_ADAPTER_PASS_ATT_MAC (1<<11) +#define OPEN_ADAPTER_ENABLE_EC (1<<10) +#define OPEN_ADAPTER_CONTENDER (1<<8) +#define OPEN_ADAPTER_PASS_BEACON (1<<7) +#define OPEN_ADAPTER_ENABLE_FDX (1<<6) +#define OPEN_ADAPTER_ENABLE_RPL (1<<5) +#define OPEN_ADAPTER_INHIBIT_ETR (1<<4) +#define OPEN_ADAPTER_INTERNAL_WRAP (1<<3) +#define OPEN_ADAPTER_USE_OPTS2 (1<<0) + +#define OPEN_ADAPTER_2_ENABLE_ONNOW (1<<15) + +/* Defines for SRB Commands */ + +#define SRB_ACCESS_REGISTER 0x1f +#define SRB_CLOSE_ADAPTER 0x04 +#define SRB_CONFIGURE_BRIDGE 0x0c +#define SRB_CONFIGURE_WAKEUP_EVENT 0x1a +#define SRB_MODIFY_BRIDGE_PARMS 0x15 +#define SRB_MODIFY_OPEN_OPTIONS 0x01 +#define SRB_MODIFY_RECEIVE_OPTIONS 0x17 +#define SRB_NO_OPERATION 0x00 +#define SRB_OPEN_ADAPTER 0x03 +#define SRB_READ_LOG 0x08 +#define SRB_READ_SR_COUNTERS 0x16 +#define SRB_RESET_GROUP_ADDRESS 0x02 +#define SRB_SAVE_CONFIGURATION 0x1b +#define SRB_SET_BRIDGE_PARMS 0x09 +#define SRB_SET_BRIDGE_TARGETS 0x10 +#define SRB_SET_FUNC_ADDRESS 0x07 +#define SRB_SET_GROUP_ADDRESS 0x06 +#define SRB_SET_GROUP_ADDR_OPTIONS 0x11 +#define SRB_UPDATE_WAKEUP_PATTERN 0x19 + +/* Clear return code */ + +#define OLYMPIC_CLEAR_RET_CODE 0xfe + +/* ARB Commands */ +#define ARB_RECEIVE_DATA 0x81 +#define ARB_LAN_CHANGE_STATUS 0x84 +/* ASB Response commands */ + +#define ASB_RECEIVE_DATA 0x81 + + +/* Olympic defaults for buffers */ + +#define OLYMPIC_RX_RING_SIZE 16 /* should be a power of 2 */ +#define OLYMPIC_TX_RING_SIZE 8 /* should be a power of 2 */ + +#define PKT_BUF_SZ 4096 /* Default packet size */ + +/* Olympic data structures */ + +struct olympic_tx_desc { + __u32 buffer; + __u32 status_length; +}; + +struct olympic_tx_status { + __u32 status; +}; + +struct olympic_rx_desc { + __u32 buffer; + __u32 res_length ; +}; + +struct olympic_rx_status { + __u32 fragmentcnt_framelen; + __u32 status_buffercnt; +}; + +struct mac_receive_buffer { + __u16 next ; + __u8 padding ; + __u8 frame_status ; + __u16 buffer_length ; + __u8 frame_data ; +}; + +struct olympic_private { + + __u16 srb; + __u16 trb; + __u16 arb; + __u16 asb; + + __u8 *olympic_mmio; + __u8 *olympic_lap; + + volatile int srb_queued; /* True if an SRB is still posted */ + struct wait_queue *srb_wait; + + volatile int asb_queued; /* True if an ASB is posted */ + + volatile int trb_queued; /* True if a TRB is posted */ + struct wait_queue *trb_wait ; + + struct olympic_rx_desc olympic_rx_ring[OLYMPIC_RX_RING_SIZE]; + struct olympic_tx_desc olympic_tx_ring[OLYMPIC_TX_RING_SIZE]; + struct olympic_rx_status olympic_rx_status_ring[OLYMPIC_RX_RING_SIZE]; + struct olympic_tx_status olympic_tx_status_ring[OLYMPIC_TX_RING_SIZE]; + struct sk_buff *tx_ring_skb[OLYMPIC_TX_RING_SIZE], *rx_ring_skb[OLYMPIC_RX_RING_SIZE]; + int tx_ring_free, tx_ring_last_status, rx_ring_last_received,rx_status_last_received, free_tx_ring_entries; + + struct net_device_stats olympic_stats ; + __u16 olympic_lan_status ; + __u8 olympic_ring_speed ; + __u16 pkt_buf_sz ; + __u8 olympic_receive_options, olympic_copy_all_options, olympic_message_level; + __u8 olympic_multicast_set ; + __u16 olympic_addr_table_addr, olympic_parms_addr ; + __u8 olympic_laa[6] ; +}; + +struct olympic_adapter_addr_table { + + __u8 node_addr[6] ; + __u8 reserved[4] ; + __u8 func_addr[4] ; +} ; + +struct olympic_parameters_table { + + __u8 phys_addr[4] ; + __u8 up_node_addr[6] ; + __u8 up_phys_addr[6] ; + __u8 poll_addr[6] ; + __u16 reserved ; + __u16 acc_priority ; + __u16 auth_source_class ; + __u16 att_code ; + __u8 source_addr[6] ; + __u16 beacon_type ; + __u16 major_vector ; + __u16 lan_status ; + __u16 soft_error_time ; + __u16 reserved1 ; + __u16 local_ring ; + __u16 mon_error ; + __u16 beacon_transmit ; + __u16 beacon_receive ; + __u16 frame_correl ; + __u8 beacon_naun[6] ; + __u32 reserved2 ; + __u8 beacon_phys[4] ; +}; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/rtl8139.c linux.pre11.3/drivers/net/rtl8139.c --- linux.vanilla/drivers/net/rtl8139.c Thu Dec 3 13:48:36 1998 +++ linux.pre11.3/drivers/net/rtl8139.c Tue Jul 20 00:00:38 1999 @@ -1,6 +1,6 @@ /* rtl8139.c: A RealTek RTL8129/8139 Fast Ethernet driver for Linux. */ /* - Written 1997-1998 by Donald Becker. + Written 1997-1999 by Donald Becker. This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference. @@ -16,11 +16,11 @@ Support and updates available at http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html - Twister-tuning code contributed by Kinston . + Twister-tuning table provided by Kinston . */ static const char *version = -"rtl8139.c:v1.04 9/22/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html\n"; +"rtl8139.c:v1.07 5/6/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html\n"; /* A few user-configurable values. */ /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ @@ -178,7 +178,9 @@ 0x10ec, 0x8129, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1}, { "RealTek RTL8139 Fast Ethernet", 0x10ec, 0x8139, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1}, - { "RealTek RTL8139 Fast Ethernet (mislabeled)", + { "SMC1211TX EZCard 10/100 (RealTek RTL8139)", + 0x1113, 0x1211, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1}, + { "Accton MPX5030 (RealTek RTL8139)", 0x1113, 0x1211, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1}, {0,}, /* 0 terminated list. */ }; @@ -235,13 +237,13 @@ RxBadAlign=0x0002, RxStatusOK=0x0001, }; +/* Twister tuning parameters from RealTek. + Completely undocumented, but required to tune bad links. */ enum CSCRBits { CSCR_LinkOKBit=0x0400, CSCR_LinkChangeBit=0x0800, CSCR_LinkStatusBits=0x0f000, CSCR_LinkDownOffCmd=0x003c0, CSCR_LinkDownCmd=0x0f3c0, -}; - -/* Twister tuning parameters from RealTek. Completely undocumented. */ +}; unsigned long param[4][4]={ {0x0cb39de43,0x0cb39ce43,0x0fb38de03,0x0cb38de43}, {0x0cb39de43,0x0cb39ce43,0x0cb39ce83,0x0cb39ce83}, @@ -270,9 +272,10 @@ unsigned char *rx_ring; unsigned char *tx_bufs; /* Tx bounce buffer region. */ char phys[4]; /* MII device addresses. */ + char twistie, twist_cnt; /* Twister tune state. */ unsigned int tx_full:1; /* The Tx queue is full. */ unsigned int full_duplex:1; /* Full-duplex operation requested. */ - unsigned int duplex_lock:1; /* Full-duplex operation requested. */ + unsigned int duplex_lock:1; unsigned int default_port:4; /* Last dev->if_port value. */ unsigned int media2:4; /* Secondary monitored media port. */ unsigned int medialock:1; /* Don't sense media type. */ @@ -325,7 +328,7 @@ if ( ! pcibios_present()) return -ENODEV; - for (;pci_index < 0xff; pci_index++) { + for (; pci_index < 0xff; pci_index++) { u16 vendor, device, pci_command, new_command; int chip_idx, irq; long ioaddr; @@ -402,9 +405,9 @@ return cards_found ? 0 : -ENODEV; } -static struct device * rtl8129_probe1(int pci_bus, int pci_devfn, - struct device *dev, long ioaddr, - int irq, int chip_idx, int found_cnt) +static struct device *rtl8129_probe1(int pci_bus, int pci_devfn, + struct device *dev, long ioaddr, + int irq, int chip_idx, int found_cnt) { static int did_version = 0; /* Already printed version info. */ struct rtl8129_private *tp; @@ -470,9 +473,8 @@ dev->name); tp->phys[0] = -1; } - } else { - tp->phys[0] = 32; - } + } else + tp->phys[0] = 32; /* Put the chip into low-power mode. */ outb(0xC0, ioaddr + Cfg9346); @@ -601,7 +603,7 @@ int retval = 0; int i; - if ((phy_id & 0x1f) == 0) { /* Really a 8139. Use internal registers. */ + if (phy_id > 31) { /* Really a 8139. Use internal registers. */ return location < 8 && mii_2_8139_map[location] ? inw(dev->base_addr + mii_2_8139_map[location]) : 0; } @@ -633,7 +635,7 @@ int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value; int i; - if (phy_id == 32) { /* Really a 8139. Use internal registers. */ + if (phy_id > 31) { /* Really a 8139. Use internal registers. */ if (location < 8 && mii_2_8139_map[location]) outw(value, dev->base_addr + mii_2_8139_map[location]); return; @@ -678,6 +680,7 @@ tp->tx_bufs = kmalloc(TX_BUF_SIZE * NUM_TX_DESC, GFP_KERNEL); tp->rx_ring = kmalloc(RX_BUF_LEN + 16, GFP_KERNEL); if (tp->tx_bufs == NULL || tp->rx_ring == NULL) { + free_irq(dev->irq, dev); if (tp->tx_bufs) kfree(tp->tx_bufs); if (rtl8129_debug > 0) @@ -736,7 +739,7 @@ /* Enable all known interrupts by setting the interrupt mask. */ outw(PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver - | TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask); + | TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask); if (rtl8129_debug > 1) printk(KERN_DEBUG"%s: rtl8129_open() ioaddr %#lx IRQ %d" @@ -749,7 +752,7 @@ init_timer(&tp->timer); tp->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */ tp->timer.data = (unsigned long)dev; - tp->timer.function = &rtl8129_timer; /* timer handler */ + tp->timer.function = &rtl8129_timer; add_timer(&tp->timer); return 0; @@ -760,7 +763,7 @@ struct device *dev = (struct device *)data; struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; long ioaddr = dev->base_addr; - int next_tick = 0; + int next_tick = 60*HZ; int mii_reg5 = mdio_read(dev, tp->phys[0], 5); if (! tp->duplex_lock && mii_reg5 != 0xffff) { @@ -774,8 +777,65 @@ outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1); outb(0x00, ioaddr + Cfg9346); } - next_tick = 60*HZ; } + /* Check for bogusness. */ + if (inw(ioaddr + IntrStatus) & (TxOK | RxOK)) { + int status = inw(ioaddr + IntrStatus); + if (status & (TxOK | RxOK)) { /* Double check */ + printk(KERN_ERR "%s: RTL8139 Interrupt line blocked, status %x.\n", + dev->name, status); + rtl8129_interrupt(dev->irq, dev, 0); + } + } + if (dev->tbusy && jiffies - dev->trans_start >= 2*TX_TIMEOUT) + rtl8129_tx_timeout(dev); + +#if 0 + if (tp->twistie) { + unsigned int CSCRval = inw(ioaddr + CSCR); /* Read link status. */ + if (tp->twistie == 1) { + if (CSCRval & CSCR_LinkOKBit) { + outw(CSCR_LinkDownOffCmd, ioaddr + CSCR); + tp->twistie = 2; + next_tick = HZ/10; + } else { + outw(CSCR_LinkDownCmd, ioaddr + CSCR); + outl(FIFOTMS_default,ioaddr + FIFOTMS); + outl(PARA78_default ,ioaddr + PARA78); + outl(PARA7c_default ,ioaddr + PARA7c); + tp->twistie = 0; + } + } else if (tp->twistie == 2) { + int linkcase = (CSCRval & CSCR_LinkStatusBits) >> 12; + int row; + if (linkcase >= 0x7000) row = 3; + else if (linkcase >= 0x3000) row = 2; + else if (linkcase >= 0x1000) row = 1; + else row = 0; + tp->twistie == row + 3; + outw(0,ioaddr+FIFOTMS); + outl(param[row][0], ioaddr+PARA7c); + tp->twist_cnt = 1; + } else { + outl(param[tp->twistie-3][tp->twist_cnt], ioaddr+PARA7c); + if (++tp->twist_cnt < 4) { + next_tick = HZ/10; + } else if (tp->twistie-3 == 3) { + if ((CSCRval & CSCR_LinkStatusBits) != 0x7000) { + outl(PARA7c_xxx, ioaddr+PARA7c); + next_tick = HZ/10; /* 100ms. */ + outl(FIFOTMS_default, ioaddr+FIFOTMS); + outl(PARA78_default, ioaddr+PARA78); + outl(PARA7c_default, ioaddr+PARA7c); + tp->twistie == 3 + 3; + outw(0,ioaddr+FIFOTMS); + outl(param[3][0], ioaddr+PARA7c); + tp->twist_cnt = 1; + } + } + } + } +#endif if (rtl8129_debug > 2) { if (rtl_cap_tbl[tp->chip_id] & HAS_MII_XCVR) @@ -792,10 +852,8 @@ dev->name, inb(ioaddr + Config0), inb(ioaddr + Config1)); } - if (next_tick) { - tp->timer.expires = RUN_AT(next_tick); - add_timer(&tp->timer); - } + tp->timer.expires = RUN_AT(next_tick); + add_timer(&tp->timer); } static void rtl8129_tx_timeout(struct device *dev) @@ -861,7 +919,7 @@ } tp->cur_tx = i; while (i < NUM_TX_DESC) - tp->tx_skbuff[i] = 0; + tp->tx_skbuff[i++] = 0; if (tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {/* Typical path */ dev->tbusy = 0; tp->tx_full = 0; @@ -906,9 +964,8 @@ /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - if (jiffies - dev->trans_start < TX_TIMEOUT) - return 1; - rtl8129_tx_timeout(dev); + if (jiffies - dev->trans_start >= TX_TIMEOUT) + rtl8129_tx_timeout(dev); return 1; } @@ -925,7 +982,7 @@ outl(tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN), ioaddr + TxStatus0 + entry*4); - if (++tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {/* Typical path */ + if (++tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) { /* Typical path */ clear_bit(0, (void*)&dev->tbusy); } else { tp->tx_full = 1; @@ -946,7 +1003,7 @@ struct device *dev = (struct device *)dev_instance; struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; int boguscnt = max_interrupt_work; - int status; + int status, link_changed = 0; long ioaddr = dev->base_addr; #if defined(__i386__) @@ -967,7 +1024,10 @@ do { status = inw(ioaddr + IntrStatus); - /* Acknowledge all of the current interrupt sources ASAP. */ + /* Acknowledge all of the current interrupt sources ASAP, but + an first get an additional status bit from CSCR. */ + if ((status & RxUnderrun) && inw(ioaddr+CSCR) & CSCR_LinkChangeBit) + link_changed = 1; outw(status, ioaddr + IntrStatus); if (rtl8129_debug > 4) @@ -982,9 +1042,9 @@ rtl8129_rx(dev); if (status & (TxOK | TxErr)) { - unsigned int dirty_tx; + unsigned int dirty_tx = tp->dirty_tx; - for (dirty_tx = tp->dirty_tx; dirty_tx < tp->cur_tx; dirty_tx++) { + while (tp->cur_tx - dirty_tx > 0) { int entry = dirty_tx % NUM_TX_DESC; int txstatus = inl(ioaddr + TxStatus0 + entry*4); @@ -994,11 +1054,9 @@ /* Note: TxCarrierLost is always asserted at 100mbps. */ if (txstatus & (TxOutOfWindow | TxAborted)) { /* There was an major error, log it. */ -#ifndef final_version if (rtl8129_debug > 1) printk(KERN_NOTICE"%s: Transmit error, Tx status %8.8x.\n", dev->name, txstatus); -#endif tp->stats.tx_errors++; if (txstatus&TxAborted) { tp->stats.tx_aborted_errors++; @@ -1011,9 +1069,6 @@ tp->stats.collisions16++; #endif } else { -#ifdef ETHER_STATS - /* No count for tp->stats.tx_deferred */ -#endif if (txstatus & TxUnderrun) { /* Add 64 to the Tx FIFO threshold. */ if (tp->tx_flag < 0x00300000) @@ -1030,6 +1085,13 @@ /* Free the original skb. */ dev_free_skb(tp->tx_skbuff[entry]); tp->tx_skbuff[entry] = 0; + if (tp->tx_full) { + /* The ring is no longer full, clear tbusy. */ + tp->tx_full = 0; + clear_bit(0, (void*)&dev->tbusy); + mark_bh(NET_BH); + } + dirty_tx++; } #ifndef final_version @@ -1039,14 +1101,6 @@ dirty_tx += NUM_TX_DESC; } #endif - - if (tp->tx_full && dirty_tx > tp->cur_tx - NUM_TX_DESC) { - /* The ring is no longer full, clear tbusy. */ - tp->tx_full = 0; - dev->tbusy = 0; - mark_bh(NET_BH); - } - tp->dirty_tx = dirty_tx; } @@ -1063,7 +1117,7 @@ tp->stats.rx_missed_errors += inl(ioaddr + RxMissed); outl(0, ioaddr + RxMissed); - if ((status & RxUnderrun) && + if ((status & RxUnderrun) && link_changed && (rtl_cap_tbl[tp->chip_id] & HAS_LNK_CHNG)) { /* Really link-change on new chips. */ int lpar = inw(ioaddr + NWayLPAR); @@ -1284,12 +1338,12 @@ data[0] = tp->phys[0] & 0x3f; /* Fall Through */ case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ - data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f); + data[3] = mdio_read(dev, data[0], data[1] & 0x1f); return 0; case SIOCDEVPRIVATE+2: /* Write the specified MII register */ - if (!suser()) + if (!capable(CAP_NET_ADMIN)) return -EPERM; - mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]); + mdio_write(dev, data[0], data[1] & 0x1f, data[2]); return 0; default: return -EOPNOTSUPP; @@ -1318,7 +1372,7 @@ { int crc = -1; - while(--length >= 0) { + while (--length >= 0) { unsigned char current_octet = *data++; int bit; for (bit = 0; bit < 8; bit++, current_octet >>= 1) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/sealevel.c linux.pre11.3/drivers/net/sealevel.c --- linux.vanilla/drivers/net/sealevel.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/net/sealevel.c Mon Jul 19 23:27:35 1999 @@ -0,0 +1,471 @@ +#define LINUX_21 + +/* + * Sealevel Systems 4021 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. + * + * (c) Copyright 1999 Building Number Three Ltd + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "syncppp.h" +#include "z85230.h" + + +struct slvl_device +{ + struct z8530_channel *chan; + struct ppp_device netdev; + char name[16]; + int channel; +}; + + +struct slvl_board +{ + struct slvl_device dev[2]; + struct z8530_dev board; + int iobase; +}; + +/* + * Network driver support routines + */ + +/* + * Frame receive. Simple for our card as we do sync ppp and there + * is no funny garbage involved + */ + +static void sealevel_input(struct z8530_channel *c, struct sk_buff *skb) +{ + /* Drop the CRC - its not a good idea to try and negotiate it ;) */ + skb_trim(skb, skb->len-2); + skb->protocol=htons(ETH_P_WAN_PPP); + skb->mac.raw=skb->data; + skb->dev=c->netdevice; + /* + * Send it to the PPP layer. We dont have time to process + * it right now. + */ + netif_rx(skb); +} + +/* + * We've been placed in the UP state + */ + +static int sealevel_open(struct device *d) +{ + struct slvl_device *slvl=d->priv; + int err = -1; + int unit = slvl->channel; + + /* + * Link layer up. + */ + + switch(unit) + { + case 0: + err=z8530_sync_dma_open(d, slvl->chan); + break; + case 1: + err=z8530_sync_open(d, slvl->chan); + break; + } + + if(err) + return err; + /* + * Begin PPP + */ + err=sppp_open(d); + if(err) + { + switch(unit) + { + case 0: + z8530_sync_dma_close(d, slvl->chan); + break; + case 1: + z8530_sync_close(d, slvl->chan); + break; + } + return err; + } + + slvl->chan->rx_function=sealevel_input; + + /* + * Go go go + */ + d->tbusy=0; + MOD_INC_USE_COUNT; + return 0; +} + +static int sealevel_close(struct device *d) +{ + struct slvl_device *slvl=d->priv; + int unit = slvl->channel; + + /* + * Discard new frames + */ + + slvl->chan->rx_function=z8530_null_rx; + + /* + * PPP off + */ + sppp_close(d); + /* + * Link layer down + */ + d->tbusy=1; + + switch(unit) + { + case 0: + z8530_sync_dma_close(d, slvl->chan); + break; + case 1: + z8530_sync_close(d, slvl->chan); + break; + } + MOD_DEC_USE_COUNT; + return 0; +} + +static int sealevel_ioctl(struct device *d, struct ifreq *ifr, int cmd) +{ + /* struct slvl_device *slvl=d->priv; + z8530_ioctl(d,&slvl->sync.chanA,ifr,cmd) */ + return sppp_do_ioctl(d, ifr,cmd); +} + +static struct enet_statistics *sealevel_get_stats(struct device *d) +{ + struct slvl_device *slvl=d->priv; + if(slvl) + return z8530_get_stats(slvl->chan); + else + return NULL; +} + +/* + * Passed PPP frames, fire them downwind. + */ + +static int sealevel_queue_xmit(struct sk_buff *skb, struct device *d) +{ + struct slvl_device *slvl=d->priv; + return z8530_queue_xmit(slvl->chan, skb); +} + +#ifdef LINUX_21 +static int sealevel_neigh_setup(struct neighbour *n) +{ + if (n->nud_state == NUD_NONE) { + n->ops = &arp_broken_ops; + n->output = n->ops->output; + } + return 0; +} + +static int sealevel_neigh_setup_dev(struct device *dev, struct neigh_parms *p) +{ + if (p->tbl->family == AF_INET) { + p->neigh_setup = sealevel_neigh_setup; + p->ucast_probes = 0; + p->mcast_probes = 0; + } + return 0; +} + +#else + +static int return_0(struct device *d) +{ + return 0; +} + +#endif + +/* + * Description block for a Comtrol Hostess SV11 card + */ + +static struct slvl_board *slvl_init(int iobase, int irq, int txdma, int rxdma, int slow) +{ + struct z8530_dev *dev; + struct slvl_device *sv; + struct slvl_board *b; + + int i; + unsigned long flags; + int u; + + /* + * Get the needed I/O space + */ + + if(check_region(iobase, 8)) + { + printk(KERN_WARNING "sealevel: I/O 0x%X already in use.\n", iobase); + return NULL; + } + request_region(iobase, 8, "Sealevel 4021"); + + b=(struct slvl_board *)kmalloc(sizeof(struct slvl_board), GFP_KERNEL); + if(!b) + goto fail3; + + memset(b, 0, sizeof(*sv)); + + b->dev[0].chan = &b->board.chanA; + b->dev[1].chan = &b->board.chanB; + + dev=&b->board; + + /* + * Stuff in the I/O addressing + */ + + dev->active = 0; + + b->iobase = iobase; + + /* + * Select 8530 delays for the old board + */ + + if(slow) + iobase |= Z8530_PORT_SLEEP; + + dev->chanA.ctrlio=iobase+1; + dev->chanA.dataio=iobase; + dev->chanB.ctrlio=iobase+3; + dev->chanB.dataio=iobase+2; + + dev->chanA.irqs=&z8530_nop; + dev->chanB.irqs=&z8530_nop; + + /* + * Assert DTR enable DMA + */ + + outb(3|(1<<7), b->iobase+4); + + + /* We want a fast IRQ for this device. Actually we'd like an even faster + IRQ ;) - This is one driver RtLinux is made for */ + + if(request_irq(irq, &z8530_interrupt, SA_INTERRUPT, "SeaLevel", dev)<0) + { + printk(KERN_WARNING "sealevel: IRQ %d already in use.\n", irq); + goto fail2; + } + + dev->irq=irq; + dev->chanA.private=&b->dev[0]; + dev->chanB.private=&b->dev[1]; + dev->chanA.netdevice=&b->dev[0].netdev.dev; + dev->chanB.netdevice=&b->dev[1].netdev.dev; + dev->chanA.dev=dev; + dev->chanB.dev=dev; + dev->name=b->dev[0].name; + + dev->chanA.txdma=3; + dev->chanA.rxdma=1; + if(request_dma(dev->chanA.txdma, "SeaLevel (TX)")!=0) + goto fail; + + if(request_dma(dev->chanA.rxdma, "SeaLevel (RX)")!=0) + goto dmafail; + + save_flags(flags); + cli(); + + /* + * Begin normal initialise + */ + + if(z8530_init(dev)!=0) + { + printk(KERN_ERR "Z8530 series device not found.\n"); + goto dmafail2; + } + if(dev->type==Z85C30) + { + z8530_channel_load(&dev->chanA, z8530_hdlc_kilostream); + z8530_channel_load(&dev->chanB, z8530_hdlc_kilostream); + } + else + { + z8530_channel_load(&dev->chanA, z8530_hdlc_kilostream_85230); + z8530_channel_load(&dev->chanB, z8530_hdlc_kilostream_85230); + } + + /* + * Now we can take the IRQ + */ + + restore_flags(flags); + + for(u=0; u<2; u++) + { + sv=&b->dev[u]; + sv->channel = u; + + for(i=0;i<999;i++) + { + sprintf(sv->name,"hdlc%d", i); + if(dev_get(sv->name)==NULL) + { + struct device *d=sv->chan->netdevice; + + /* + * Initialise the PPP components + */ + sppp_attach(&sv->netdev); + + /* + * Local fields + */ + sprintf(sv->name,"hdlc%d", i); + + d->name = sv->name; + d->base_addr = iobase; + d->irq = irq; + d->priv = sv; + d->init = NULL; + + d->open = sealevel_open; + d->stop = sealevel_close; + d->hard_start_xmit = sealevel_queue_xmit; + d->get_stats = sealevel_get_stats; + d->set_multicast_list = NULL; + d->do_ioctl = sealevel_ioctl; +#ifdef LINUX_21 + d->neigh_setup = sealevel_neigh_setup_dev; + dev_init_buffers(d); +#else + d->init = return_0; +#endif + d->set_mac_address = NULL; + + if(register_netdev(d)==-1) + { + printk(KERN_ERR "%s: unable to register device.\n", + sv->name); + goto fail_unit; + } + + break; + } + } + } + z8530_describe(dev, "I/O", iobase); + dev->active=1; + return b; + +fail_unit: + if(u==1) + unregister_netdev(b->dev[0].chan->netdevice); + +dmafail2: + free_dma(dev->chanA.rxdma); +dmafail: + free_dma(dev->chanA.txdma); +fail: + free_irq(irq, dev); +fail2: + kfree(b); +fail3: + release_region(iobase,8); + return NULL; +} + +static void slvl_shutdown(struct slvl_board *b) +{ + int u; + + z8530_shutdown(&b->board); + + for(u=0; u<2; u++) + { + sppp_detach(&b->dev[u].netdev.dev); + unregister_netdev(&b->dev[u].netdev.dev); + } + + free_irq(b->board.irq, &b->board); + free_dma(b->board.chanA.rxdma); + free_dma(b->board.chanA.txdma); + /* DMA off on the card, drop DTR */ + outb(0, b->iobase); + release_region(b->iobase, 8); +} + +#ifdef MODULE + +static int io=0x238; +static int txdma=1; +static int rxdma=3; +static int irq=5; +static int slow=0; + +#ifdef LINUX_21 +MODULE_PARM(io,"i"); +MODULE_PARM_DESC(io, "The I/O base of the Sealevel card"); +MODULE_PARM(txdma,"i"); +MODULE_PARM_DESC(txdma, "Transmit DMA channel"); +MODULE_PARM(rxdma,"i"); +MODULE_PARM_DESC(rxdma, "Receive DMA channel"); +MODULE_PARM(irq,"i"); +MODULE_PARM_DESC(irq, "The interrupt line setting for the SeaLevel card"); +MODULE_PARM(slow,"i"); +MODULE_PARM_DESC(slow, "Set this for an older Sealevel card such as the 4012"); + +MODULE_AUTHOR("Bulding Number Three Ltd"); +MODULE_DESCRIPTION("Modular driver for the SeaLevel 4021"); +#endif + +static struct slvl_board *slvl_unit; + +int init_module(void) +{ + printk(KERN_INFO "SeaLevel Z85230 Synchronous Driver v 0.01.\n"); + printk(KERN_INFO "(c) Copyright 1998, Building Number Three Ltd.\n"); + if((slvl_unit=slvl_init(io,irq, txdma, rxdma, slow))==NULL) + return -ENODEV; + return 0; +} + +void cleanup_module(void) +{ + if(slvl_unit) + slvl_shutdown(slvl_unit); +} + +#endif + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/seeq8005.c linux.pre11.3/drivers/net/seeq8005.c --- linux.vanilla/drivers/net/seeq8005.c Thu Dec 31 18:10:43 1998 +++ linux.pre11.3/drivers/net/seeq8005.c Mon Jul 19 23:27:26 1999 @@ -736,6 +736,54 @@ outw( SEEQCMD_WINDOW_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD); } +#ifdef MODULE + +static char devicename[9] = { 0, }; + +static struct device dev_seeq = +{ + devicename, /* device name is inserted by linux/drivers/net/net_init.c */ + 0, 0, 0, 0, + 0x300, 5, + 0, 0, 0, NULL, seeq8005_probe +}; + +static int io=0x320; +static int irq=10; +MODULE_PARM(io, "i"); +MODULE_PARM(irq, "i"); + +int init_module(void) +{ + dev_seeq.irq=irq; + dev_seeq.base_addr=io; + if (register_netdev(&dev_seeq) != 0) + return -EIO; + return 0; +} + +void cleanup_module(void) +{ + /* + * No need to check MOD_IN_USE, as sys_delete_module() checks. + */ + + unregister_netdev(&dev_seeq); + + /* + * Free up the private structure, or leak memory :-) + */ + + kfree(dev_seeq.priv); + dev_seeq.priv = NULL; /* gets re-allocated by el1_probe1 */ + + /* + * If we don't do this, we can't re-insmod it later. + */ + release_region(dev_seeq.base_addr, EL1_IO_EXTENT); +} + +#endif /* MODULE */ /* * Local variables: diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/sgiseeq.c linux.pre11.3/drivers/net/sgiseeq.c --- linux.vanilla/drivers/net/sgiseeq.c Thu Nov 19 18:38:38 1998 +++ linux.pre11.3/drivers/net/sgiseeq.c Mon Jul 19 23:27:30 1999 @@ -1,11 +1,9 @@ -/* +/* $Id: sgiseeq.c,v 1.9 1998/10/14 23:40:46 ralf Exp $ + * * sgiseeq.c: Seeq8003 ethernet driver for SGI machines. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: sgiseeq.c,v 1.6 1998/10/14 17:29:44 ralf Exp $ */ - #include #include #include @@ -695,6 +693,7 @@ dev->irq = irq; dev->dma = 0; ether_setup(dev); + return 0; } @@ -724,15 +723,20 @@ int sgiseeq_probe(struct device *dev) { + static int initialized; char *ep; + if (initialized) /* Already initialized? */ + return 0; + initialized++; + /* First get the ethernet address of the onboard * interface from ARCS. + * (This is fragile; PROM doesn't like running from cache.) */ ep = romvec->get_evar("eaddr"); str2eaddr(onboard_eth_addr, ep); return sgiseeq_init(dev, (struct sgiseeq_regs *) (KSEG1ADDR(0x1fbd4000)), &hpc3c0->ethregs, 3); - } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/sgiseeq.h linux.pre11.3/drivers/net/sgiseeq.h --- linux.vanilla/drivers/net/sgiseeq.h Sun Nov 8 15:07:30 1998 +++ linux.pre11.3/drivers/net/sgiseeq.h Mon Jul 19 23:27:30 1999 @@ -1,4 +1,4 @@ -/* $Id: sgiseeq.h,v 1.1 1997/06/09 08:34:32 ralf Exp $ +/* $Id: sgiseeq.h,v 1.3 1998/08/25 09:17:45 ralf Exp $ * sgiseeq.h: Defines for the Seeq8003 ethernet controller. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/shaper.c linux.pre11.3/drivers/net/shaper.c --- linux.vanilla/drivers/net/shaper.c Tue Jun 15 16:49:50 1999 +++ linux.pre11.3/drivers/net/shaper.c Mon Jul 19 23:27:29 1999 @@ -51,14 +51,19 @@ * will render your machine defunct. Don't for now shape over * PPP or SLIP therefore! * This will be fixed in BETA4 - */ - -/* - * bh_atomic() SMP races fixes and rewritten the locking code to be SMP safe - * and irq-mask friendly. NOTE: we can't use start_bh_atomic() in kick_shaper() - * because it's going to be recalled from an irq handler, and synchronize_bh() - * is a nono if called from irq context. + * + * Update History : + * + * bh_atomic() SMP races fixes and rewritten the locking code to + * be SMP safe and irq-mask friendly. + * NOTE: we can't use start_bh_atomic() in kick_shaper() + * because it's going to be recalled from an irq handler, + * and synchronize_bh() is a nono if called from irq context. * 1999 Andrea Arcangeli + * + * Device statistics (tx_pakets, tx_bytes, + * tx_drops: queue_over_time and collisions: max_queue_exceded) + * 1999/06/18 Jordi Murgo */ #include @@ -228,18 +233,20 @@ /* * Queue over time. Spill packet. */ - if(skb->shapeclock-jiffies > SHAPER_LATENCY) + if(skb->shapeclock-jiffies > SHAPER_LATENCY) { dev_kfree_skb(skb); - else + shaper->stats.tx_dropped++; + } else skb_queue_tail(&shaper->sendq, skb); } #endif - if(sh_debug) + if(sh_debug) printk("Frame queued.\n"); if(skb_queue_len(&shaper->sendq)>SHAPER_QLEN) { ptr=skb_dequeue(&shaper->sendq); - dev_kfree_skb(ptr); + dev_kfree_skb(ptr); + shaper->stats.collisions++; } shaper_unlock(shaper); return 0; @@ -262,7 +269,11 @@ printk("Kick new frame to %s, %d\n", shaper->dev->name,newskb->priority); dev_queue_xmit(newskb); - if(sh_debug) + + shaper->stats.tx_bytes+=newskb->len; + shaper->stats.tx_packets++; + + if(sh_debug) printk("Kicked new frame out.\n"); dev_kfree_skb(skb); } @@ -415,7 +426,8 @@ static struct net_device_stats *shaper_get_stats(struct device *dev) { - return NULL; + struct shaper *sh=dev->priv; + return &sh->stats; } static int shaper_header(struct sk_buff *skb, struct device *dev, @@ -581,7 +593,7 @@ skb_queue_head_init(&sh->sendq); init_timer(&sh->timer); sh->timer.function=shaper_timer; - sh->timer.data=(unsigned long)sh; + sh->timer.data=(unsigned long)sh; return sh; } @@ -664,7 +676,9 @@ void cleanup_module(void) { - /* + struct shaper *sh=dev_shape.priv; + + /* * No need to check MOD_IN_USE, as sys_delete_module() checks. * To be unloadable we must be closed and detached so we don't * need to flush things. @@ -673,10 +687,9 @@ unregister_netdev(&dev_shape); /* - * Free up the private structure, or leak memory :-) + * Free up the private structure, or leak memory :-) */ - - kfree(dev_shape.priv); + kfree(sh); dev_shape.priv = NULL; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/sonic.c linux.pre11.3/drivers/net/sonic.c --- linux.vanilla/drivers/net/sonic.c Sat Jan 9 21:50:42 1999 +++ linux.pre11.3/drivers/net/sonic.c Mon Jul 19 23:27:30 1999 @@ -1,290 +1,23 @@ /* * sonic.c * - * (C) 1996 by Thomas Bogendoerfer (tsbogend@bigbug.franken.de) + * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de) * * This driver is based on work from Andreas Busse, but most of * the code is rewritten. * * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de) * - * A driver for the onboard Sonic ethernet controller on Mips Jazz - * systems (Acer Pica-61, Mips Magnum 4000, Olivetti M700 and - * perhaps others, too) + * Core code included by system sonic drivers */ -static const char *version = - "sonic.c:v0.10 6.7.96 tsbogend@bigbug.franken.de\n"; - /* * Sources: Olivetti M700-10 Risc Personal Computer hardware handbook, * National Semiconductors data sheet for the DP83932B Sonic Ethernet * controller, and the files "8390.c" and "skeleton.c" in this directory. */ -#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 "sonic.h" - -/* use 0 for production, 1 for verification, >2 for debug */ -#ifdef SONIC_DEBUG -static unsigned int sonic_debug = SONIC_DEBUG; -#else -static unsigned int sonic_debug = 2; -#endif - -/* - * Some tunables for the buffer areas. Power of 2 is required - * the current driver uses one receive buffer for each descriptor. - */ -#define SONIC_NUM_RRS 16 /* number of receive resources */ -#define SONIC_NUM_RDS SONIC_NUM_RRS /* number of receive descriptors */ -#define SONIC_NUM_TDS 16 /* number of transmit descriptors */ -#define SONIC_RBSIZE 1520 /* size of one resource buffer */ - -#define SONIC_RDS_MASK (SONIC_NUM_RDS-1) -#define SONIC_TDS_MASK (SONIC_NUM_TDS-1) -/* - * Base address and interupt of the SONIC controller on JAZZ boards - */ -static struct { - unsigned int port; - unsigned int irq; - } sonic_portlist[] = { {JAZZ_ETHERNET_BASE, JAZZ_ETHERNET_IRQ}, {0, 0}}; - - -/* Information that need to be kept for each board. */ -struct sonic_local { - sonic_cda_t cda; /* virtual CPU address of CDA */ - sonic_td_t tda[SONIC_NUM_TDS]; /* transmit descriptor area */ - sonic_rr_t rra[SONIC_NUM_RRS]; /* receive resource arrea */ - sonic_rd_t rda[SONIC_NUM_RDS]; /* receive descriptor area */ - struct sk_buff* tx_skb[SONIC_NUM_TDS]; /* skbuffs for packets to transmit */ - unsigned int tx_laddr[SONIC_NUM_TDS]; /* logical DMA address fro skbuffs */ - unsigned char *rba; /* start of receive buffer areas */ - unsigned int cda_laddr; /* logical DMA address of CDA */ - unsigned int tda_laddr; /* logical DMA address of TDA */ - unsigned int rra_laddr; /* logical DMA address of RRA */ - unsigned int rda_laddr; /* logical DMA address of RDA */ - unsigned int rba_laddr; /* logical DMA address of RBA */ - unsigned int cur_tx, cur_rx; /* current indexes to resource areas */ - unsigned int dirty_tx,cur_rra; /* last unacked transmit packet */ - char tx_full; - struct enet_statistics stats; -}; - -/* - * We cannot use station (ethernet) address prefixes to detect the - * sonic controller since these are board manufacturer depended. - * So we check for known Silicon Revision IDs instead. - */ -static unsigned short known_revisions[] = -{ - 0x04, /* Mips Magnum 4000 */ - 0xffff /* end of list */ -}; - -/* Index to functions, as function prototypes. */ - -extern int sonic_probe(struct device *dev); -static int sonic_probe1(struct device *dev, unsigned int base_addr, unsigned int irq); -static int sonic_open(struct device *dev); -static int sonic_send_packet(struct sk_buff *skb, struct device *dev); -static void sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static void sonic_rx(struct device *dev); -static int sonic_close(struct device *dev); -static struct enet_statistics *sonic_get_stats(struct device *dev); -static void sonic_multicast_list(struct device *dev); -static int sonic_init(struct device *dev); - - -/* - * Probe for a SONIC ethernet controller on a Mips Jazz board. - * Actually probing is superfluous but we're paranoid. - */ -__initfunc(int sonic_probe(struct device *dev)) -{ - unsigned int base_addr = dev ? dev->base_addr : 0; - int i; - - /* - * Don't probe if we're not running on a Jazz board. - */ - if (mips_machgroup != MACH_GROUP_JAZZ) - return -ENODEV; - if (base_addr > 0x1ff) /* Check a single specified location. */ - return sonic_probe1(dev, base_addr, dev->irq); - else if (base_addr != 0) /* Don't probe at all. */ - return -ENXIO; - - for (i = 0; sonic_portlist[i].port; i++) { - int base_addr = sonic_portlist[i].port; - if (check_region(base_addr, 0x100)) - continue; - if (sonic_probe1(dev, base_addr, sonic_portlist[i].irq) == 0) - return 0; - } - return -ENODEV; -} - -__initfunc(static int sonic_probe1(struct device *dev, - unsigned int base_addr, unsigned int irq)) -{ - static unsigned version_printed = 0; - unsigned int silicon_revision; - unsigned int val; - struct sonic_local *lp; - int i; - - /* - * get the Silicon Revision ID. If this is one of the known - * one assume that we found a SONIC ethernet controller at - * the expected location. - */ - silicon_revision = SONIC_READ(SONIC_SR); - if (sonic_debug > 1) - printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision); - - i = 0; - while ((known_revisions[i] != 0xffff) && - (known_revisions[i] != silicon_revision)) - i++; - - if (known_revisions[i] == 0xffff) { - printk("SONIC ethernet controller not found (0x%4x)\n", - silicon_revision); - return -ENODEV; - } - - request_region(base_addr, 0x100, "SONIC"); - - /* Allocate a new 'dev' if needed. */ - if (dev == NULL) - dev = init_etherdev(0, sizeof(struct sonic_local)); - - if (sonic_debug && version_printed++ == 0) - printk(version); - - printk("%s: %s found at 0x%08x, ", - dev->name, "SONIC ethernet", base_addr); - - /* Fill in the 'dev' fields. */ - dev->base_addr = base_addr; - dev->irq = irq; - - /* - * Put the sonic into software reset, then - * retrieve and print the ethernet address. - */ - SONIC_WRITE(SONIC_CMD,SONIC_CR_RST); - SONIC_WRITE(SONIC_CEP,0); - for (i=0; i<3; i++) { - val = SONIC_READ(SONIC_CAP0-i); - dev->dev_addr[i*2] = val; - dev->dev_addr[i*2+1] = val >> 8; - } - - printk("HW Address "); - for (i = 0; i < 6; i++) { - printk("%2.2x", dev->dev_addr[i]); - if (i<5) - printk(":"); - } - - printk(" IRQ %d\n", irq); - - /* Initialize the device structure. */ - if (dev->priv == NULL) { - /* - * the memory be located in the same 64kb segment - */ - lp = NULL; - i = 0; - do { - lp = (struct sonic_local *)kmalloc(sizeof(*lp), GFP_KERNEL); - if ((unsigned long)lp >> 16 != ((unsigned long)lp + sizeof(*lp) ) >> 16) { - /* FIXME, free the memory later */ - kfree (lp); - lp = NULL; - } - } while (lp == NULL && i++ < 20); - - if (lp == NULL) { - printk ("%s: couldn't allocate memory for descriptors\n", - dev->name); - return -ENOMEM; - } - - memset(lp, 0, sizeof(struct sonic_local)); - - /* get the virtual dma address */ - lp->cda_laddr = vdma_alloc(PHYSADDR(lp),sizeof(*lp)); - if (lp->cda_laddr == ~0UL) { - printk ("%s: couldn't get DMA page entry for descriptors\n", - dev->name); - return -ENOMEM; - } - - lp->tda_laddr = lp->cda_laddr + sizeof (lp->cda); - lp->rra_laddr = lp->tda_laddr + sizeof (lp->tda); - lp->rda_laddr = lp->rra_laddr + sizeof (lp->rra); - - /* allocate receive buffer area */ - /* FIXME, maybe we should use skbs */ - if ((lp->rba = (char *)kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL)) == NULL) { - printk ("%s: couldn't allocate receive buffers\n",dev->name); - return -ENOMEM; - } - - /* get virtual dma address */ - if ((lp->rba_laddr = vdma_alloc(PHYSADDR(lp->rba),SONIC_NUM_RRS * SONIC_RBSIZE)) == ~0UL) { - printk ("%s: couldn't get DMA page entry for receive buffers\n",dev->name); - return -ENOMEM; - } - - /* now convert pointer to KSEG1 pointer */ - lp->rba = (char *)KSEG1ADDR(lp->rba); - flush_cache_all(); - dev->priv = (struct sonic_local *)KSEG1ADDR(lp); - } - - lp = (struct sonic_local *)dev->priv; - dev->open = sonic_open; - dev->stop = sonic_close; - dev->hard_start_xmit = sonic_send_packet; - dev->get_stats = sonic_get_stats; - dev->set_multicast_list = &sonic_multicast_list; - - /* Fill in the fields of the device structure with ethernet values. */ - ether_setup(dev); - return 0; -} /* * Open/initialize the SONIC controller. @@ -308,8 +41,8 @@ * covering another bug otherwise corrupting data. This doesn't mean * this glue works ok under all situations. */ -// if (request_irq(dev->irq, &sonic_interrupt, 0, "sonic", dev)) { - if (request_irq(dev->irq, &sonic_interrupt, SA_INTERRUPT, "sonic", dev)) { +// if (sonic_request_irq(dev->irq, &sonic_interrupt, 0, "sonic", dev)) { + if (sonic_request_irq(dev->irq, &sonic_interrupt, SA_INTERRUPT, "sonic", dev)) { printk ("\n%s: unable to get IRQ %d .\n", dev->name, dev->irq); return EAGAIN; } @@ -351,7 +84,7 @@ SONIC_WRITE(SONIC_IMR,0); SONIC_WRITE(SONIC_CMD,SONIC_CR_RST); - free_irq(dev->irq, dev); /* release the IRQ */ + sonic_free_irq(dev->irq, dev); /* release the IRQ */ return 0; } @@ -424,11 +157,6 @@ lp->tda[entry].tx_frag_ptr_l = laddr & 0xffff; lp->tda[entry].tx_frag_ptr_h = laddr >> 16; lp->tda[entry].tx_frag_size = length; - - /* if there are already packets queued, allow sending several packets at once */ - if (lp->dirty_tx != lp->cur_tx) - lp->tda[(lp->cur_tx-1) % SONIC_TDS_MASK].link &= ~SONIC_END_OF_LINKS; - lp->cur_tx++; lp->stats.tx_bytes += length; @@ -479,20 +207,23 @@ if (status & SONIC_INT_TXDN) { int dirty_tx = lp->dirty_tx; - + while (dirty_tx < lp->cur_tx) { int entry = dirty_tx & SONIC_TDS_MASK; int status = lp->tda[entry].tx_status; - + if (sonic_debug > 3) printk ("sonic_interrupt: status %d, cur_tx %d, dirty_tx %d\n", status,lp->cur_tx,lp->dirty_tx); - - if (status == 0) - break; /* It still hasn't been Txed */ + + if (status == 0) { + /* It still hasn't been Txed, kick the sonic again */ + SONIC_WRITE(SONIC_CMD,SONIC_CR_TXP); + break; + } /* put back EOL and free descriptor */ - lp->tda[entry].link |= SONIC_END_OF_LINKS; + lp->tda[entry].tx_frag_count = 0; lp->tda[entry].tx_status = 0; if (status & 0x0001) @@ -574,27 +305,25 @@ { unsigned int base_addr = dev->base_addr; struct sonic_local *lp = (struct sonic_local *)dev->priv; - int entry = lp->cur_rx & SONIC_RDS_MASK; + sonic_rd_t *rd = &lp->rda[lp->cur_rx & SONIC_RDS_MASK]; int status; - while(lp->rda[entry].in_use == 0) - { + while (rd->in_use == 0) { struct sk_buff *skb; int pkt_len; unsigned char *pkt_ptr; - status = lp->rda[entry].rx_status; + status = rd->rx_status; if (sonic_debug > 3) - printk ("status %x, cur_rx %d, cur_rra %d\n",status,lp->cur_rx,lp->cur_rra); + printk ("status %x, cur_rx %d, cur_rra %x\n",status,lp->cur_rx,lp->cur_rra); if (status & SONIC_RCR_PRX) { - pkt_len = lp->rda[entry].rx_pktlen; - pkt_ptr = (char *)KSEG1ADDR(vdma_log2phys((lp->rda[entry].rx_pktptr_h << 16) + - lp->rda[entry].rx_pktptr_l)); + pkt_len = rd->rx_pktlen; + pkt_ptr = (char *)sonic_chiptomem((rd->rx_pktptr_h << 16) + + rd->rx_pktptr_l); if (sonic_debug > 3) - printk ("pktptr %p (rba %p) h:%x l:%x, rra h:%x l:%x bsize h:%x l:%x\n", pkt_ptr,lp->rba, - lp->rda[entry].rx_pktptr_h,lp->rda[entry].rx_pktptr_l, - lp->rra[lp->cur_rra & 15].rx_bufadr_h,lp->rra[lp->cur_rra & 15].rx_bufadr_l, + printk ("pktptr %p (rba %p) h:%x l:%x, bsize h:%x l:%x\n", pkt_ptr,lp->rba, + rd->rx_pktptr_h,rd->rx_pktptr_l, SONIC_READ(SONIC_RBWC1),SONIC_READ(SONIC_RBWC0)); /* Malloc up new buffer. */ @@ -620,21 +349,26 @@ if (status & SONIC_RCR_CRCR) lp->stats.rx_crc_errors++; } - lp->rda[entry].in_use = 1; - entry = (++lp->cur_rx) & SONIC_RDS_MASK; + rd->in_use = 1; + rd = &lp->rda[(++lp->cur_rx) & SONIC_RDS_MASK]; /* now give back the buffer to the receive buffer area */ if (status & SONIC_RCR_LPKT) { /* * this was the last packet out of the current receice buffer * give the buffer back to the SONIC */ - SONIC_WRITE(SONIC_RWP,(lp->rra_laddr + (++lp->cur_rra & 15) * sizeof(sonic_rr_t)) & 0xffff); - } + lp->cur_rra += sizeof(sonic_rr_t); + if (lp->cur_rra > (lp->rra_laddr + (SONIC_NUM_RRS-1) * sizeof(sonic_rr_t))) + lp->cur_rra = lp->rra_laddr; + SONIC_WRITE(SONIC_RWP, lp->cur_rra & 0xffff); + } else + printk ("%s: rx desc without RCR_LPKT. Shouldn't happen !?\n",dev->name); } - - /* If any worth-while packets have been received, dev_rint() - has done a mark_bh(NET_BH) for us and will work on them - when we get to the bottom-half routine. */ + /* + * If any worth-while packets have been received, dev_rint() + * has done a mark_bh(NET_BH) for us and will work on them + * when we get to the bottom-half routine. + */ return; } @@ -689,16 +423,15 @@ for (i = 1; i <= dev->mc_count; i++) { addr = dmi->dmi_addr; dmi = dmi->next; - lp->cda.cam_desc[i].cam_frag2 = addr[1] << 8 | addr[0]; - lp->cda.cam_desc[i].cam_frag1 = addr[3] << 8 | addr[2]; - lp->cda.cam_desc[i].cam_frag0 = addr[5] << 8 | addr[4]; + lp->cda.cam_desc[i].cam_cap0 = addr[1] << 8 | addr[0]; + lp->cda.cam_desc[i].cam_cap1 = addr[3] << 8 | addr[2]; + lp->cda.cam_desc[i].cam_cap2 = addr[5] << 8 | addr[4]; lp->cda.cam_enable |= (1 << i); } - /* number of CAM entries to load */ - SONIC_WRITE(SONIC_CDC,dev->mc_count+1); + SONIC_WRITE(SONIC_CDC,16); /* issue Load CAM command */ SONIC_WRITE(SONIC_CDP, lp->cda_laddr & 0xffff); - SONIC_WRITE(SONIC_CMD,SONIC_CR_LCAM); + SONIC_WRITE(SONIC_CMD,SONIC_CR_LCAM); } } @@ -736,7 +469,6 @@ SONIC_WRITE(SONIC_CMD,0); SONIC_WRITE(SONIC_CMD,SONIC_CR_RXDIS); - /* * initialize the receive resource area */ @@ -761,7 +493,7 @@ SONIC_WRITE(SONIC_URRA,lp->rra_laddr >> 16); SONIC_WRITE(SONIC_EOBC,(SONIC_RBSIZE-2) >> 1); - lp->cur_rra = SONIC_NUM_RRS - 2; + lp->cur_rra = lp->rra_laddr + (SONIC_NUM_RRS-1) * sizeof(sonic_rr_t); /* load the resource pointers */ if (sonic_debug > 3) @@ -796,7 +528,6 @@ /* fix last descriptor */ lp->rda[SONIC_NUM_RDS-1].link = lp->rda_laddr; lp->cur_rx = 0; - SONIC_WRITE(SONIC_URDA,lp->rda_laddr >> 16); SONIC_WRITE(SONIC_CRDA,lp->rda_laddr & 0xffff); @@ -816,13 +547,14 @@ SONIC_WRITE(SONIC_UTDA,lp->tda_laddr >> 16); SONIC_WRITE(SONIC_CTDA,lp->tda_laddr & 0xffff); + lp->cur_tx = lp->dirty_tx = 0; /* * put our own address to CAM desc[0] */ - lp->cda.cam_desc[0].cam_frag2 = dev->dev_addr[1] << 8 | dev->dev_addr[0]; - lp->cda.cam_desc[0].cam_frag1 = dev->dev_addr[3] << 8 | dev->dev_addr[2]; - lp->cda.cam_desc[0].cam_frag0 = dev->dev_addr[5] << 8 | dev->dev_addr[4]; + lp->cda.cam_desc[0].cam_cap0 = dev->dev_addr[1] << 8 | dev->dev_addr[0]; + lp->cda.cam_desc[0].cam_cap1 = dev->dev_addr[3] << 8 | dev->dev_addr[2]; + lp->cda.cam_desc[0].cam_cap2 = dev->dev_addr[5] << 8 | dev->dev_addr[4]; lp->cda.cam_enable = 1; for (i=0; i < 16; i++) @@ -832,7 +564,7 @@ * initialize CAM registers */ SONIC_WRITE(SONIC_CDP, lp->cda_laddr & 0xffff); - SONIC_WRITE(SONIC_CDC,1); + SONIC_WRITE(SONIC_CDC,16); /* * load the CAM diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/sonic.h linux.pre11.3/drivers/net/sonic.h --- linux.vanilla/drivers/net/sonic.h Sun Nov 8 15:07:30 1998 +++ linux.pre11.3/drivers/net/sonic.h Mon Jul 19 23:27:30 1999 @@ -15,16 +15,6 @@ #define SONIC_H /* - * Macros to access SONIC registers - */ -#define SONIC_READ(reg) \ - *((volatile unsigned int *)base_addr+reg) - -#define SONIC_WRITE(reg,val) \ - *((volatile unsigned int *)base_addr+reg) = val - - -/* * SONIC register offsets */ @@ -242,9 +232,9 @@ typedef struct { u16 rx_status; /* status after reception of a packet */ - u16 pad0; + SREGS_PAD(pad0); u16 rx_pktlen; /* length of the packet incl. CRC */ - u16 pad1; + SREGS_PAD(pad1); /* * Pointers to the location in the receive buffer area (RBA) @@ -252,22 +242,22 @@ * a contiguous piece of memory. */ u16 rx_pktptr_l; - u16 pad2; + SREGS_PAD(pad2); u16 rx_pktptr_h; - u16 pad3; + SREGS_PAD(pad3); u16 rx_seqno; /* sequence no. */ - u16 pad4; + SREGS_PAD(pad4); u16 link; /* link to next RDD (end if EOL bit set) */ - u16 pad5; + SREGS_PAD(pad5); /* * Owner of this descriptor, 0= driver, 1=sonic */ u16 in_use; - u16 pad6; + SREGS_PAD(pad6); caddr_t rda_next; /* pointer to next RD */ } sonic_rd_t; @@ -278,23 +268,23 @@ */ typedef struct { u16 tx_status; /* status after transmission of a packet */ - u16 pad0; + SREGS_PAD(pad0); u16 tx_config; /* transmit configuration for this packet */ - u16 pad1; + SREGS_PAD(pad1); u16 tx_pktsize; /* size of the packet to be transmitted */ - u16 pad2; + SREGS_PAD(pad2); u16 tx_frag_count; /* no. of fragments */ - u16 pad3; + SREGS_PAD(pad3); u16 tx_frag_ptr_l; - u16 pad4; + SREGS_PAD(pad4); u16 tx_frag_ptr_h; - u16 pad5; + SREGS_PAD(pad5); u16 tx_frag_size; - u16 pad6; + SREGS_PAD(pad6); u16 link; /* ptr to next descriptor */ - u16 pad7; + SREGS_PAD(pad7); } sonic_td_t; @@ -304,13 +294,13 @@ typedef struct { u16 cam_entry_pointer; - u16 pad; - u16 cam_frag2; - u16 pad2; - u16 cam_frag1; - u16 pad1; - u16 cam_frag0; - u16 pad0; + SREGS_PAD(pad0); + u16 cam_cap0; + SREGS_PAD(pad1); + u16 cam_cap1; + SREGS_PAD(pad2); + u16 cam_cap2; + SREGS_PAD(pad3); } sonic_cd_t; #define CAM_DESCRIPTORS 16 @@ -319,8 +309,56 @@ typedef struct { sonic_cd_t cam_desc[CAM_DESCRIPTORS]; u16 cam_enable; - u16 pad; + SREGS_PAD(pad); } sonic_cda_t; +/* + * Some tunables for the buffer areas. Power of 2 is required + * the current driver uses one receive buffer for each descriptor. + */ +#define SONIC_NUM_RRS 16 /* number of receive resources */ +#define SONIC_NUM_RDS SONIC_NUM_RRS /* number of receive descriptors */ +#define SONIC_NUM_TDS 16 /* number of transmit descriptors */ +#define SONIC_RBSIZE 1520 /* size of one resource buffer */ + +#define SONIC_RDS_MASK (SONIC_NUM_RDS-1) +#define SONIC_TDS_MASK (SONIC_NUM_TDS-1) + + +/* Information that need to be kept for each board. */ +struct sonic_local { + sonic_cda_t cda; /* virtual CPU address of CDA */ + sonic_td_t tda[SONIC_NUM_TDS]; /* transmit descriptor area */ + sonic_rr_t rra[SONIC_NUM_RRS]; /* receive resource arrea */ + sonic_rd_t rda[SONIC_NUM_RDS]; /* receive descriptor area */ + struct sk_buff* tx_skb[SONIC_NUM_TDS]; /* skbuffs for packets to transmit */ + unsigned int tx_laddr[SONIC_NUM_TDS]; /* logical DMA address fro skbuffs */ + unsigned char *rba; /* start of receive buffer areas */ + unsigned int cda_laddr; /* logical DMA address of CDA */ + unsigned int tda_laddr; /* logical DMA address of TDA */ + unsigned int rra_laddr; /* logical DMA address of RRA */ + unsigned int rda_laddr; /* logical DMA address of RDA */ + unsigned int rba_laddr; /* logical DMA address of RBA */ + unsigned int cur_rra; /* current indexes to resource areas */ + unsigned int cur_rx; + unsigned int cur_tx; + unsigned int dirty_tx; /* last unacked transmit packet */ + char tx_full; + struct enet_statistics stats; +}; + +/* Index to functions, as function prototypes. */ + +static int sonic_open(struct device *dev); +static int sonic_send_packet(struct sk_buff *skb, struct device *dev); +static void sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static void sonic_rx(struct device *dev); +static int sonic_close(struct device *dev); +static struct enet_statistics *sonic_get_stats(struct device *dev); +static void sonic_multicast_list(struct device *dev); +static int sonic_init(struct device *dev); + +static const char *version = + "sonic.c:v0.92 20.9.98 tsbogend@alpha.franken.de\n"; #endif /* SONIC_H */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/sunhme.c linux.pre11.3/drivers/net/sunhme.c --- linux.vanilla/drivers/net/sunhme.c Tue Jun 15 16:49:50 1999 +++ linux.pre11.3/drivers/net/sunhme.c Mon Jul 19 23:27:26 1999 @@ -3406,7 +3406,7 @@ /* Set the latency timer and cache line size as well, * PROM leaves it at zero. */ - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 128); + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); #ifdef __sparc_v9__ /* NOTE: Cache line size is in 32-bit word units. */ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x10); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/syncppp.c linux.pre11.3/drivers/net/syncppp.c --- linux.vanilla/drivers/net/syncppp.c Fri Apr 16 22:10:53 1999 +++ linux.pre11.3/drivers/net/syncppp.c Tue Jul 20 00:00:50 1999 @@ -48,6 +48,7 @@ #include #include #include +#include #include #include "syncppp.h" @@ -771,7 +772,7 @@ } sp->obytes += skb->len; /* Control is high priority so it doesnt get queued behind data */ - skb->priority=1; + skb->priority=TC_PRIO_CONTROL; skb->dev = dev; dev_queue_xmit(skb); } @@ -813,7 +814,7 @@ dev->name, ntohl (ch->type), ch->par1, ch->par2, ch->rel, ch->time0, ch->time1); sp->obytes += skb->len; - skb->priority=1; + skb->priority=TC_PRIO_CONTROL; skb->dev = dev; dev_queue_xmit(skb); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/tulip.c linux.pre11.3/drivers/net/tulip.c --- linux.vanilla/drivers/net/tulip.c Sun Jan 24 19:55:35 1999 +++ linux.pre11.3/drivers/net/tulip.c Tue Jul 20 00:00:55 1999 @@ -327,6 +327,10 @@ TxFIFOUnderflow=0x20, TxJabber=0x08, TxNoBuf=0x04, TxDied=0x02, TxIntr=0x01, }; +enum desc_status_bits { + DescOwned=0x80000000, RxDescFatalErr=0x8000, RxWholePkt=0x0300, +}; + /* The Tulip Rx and Tx buffer descriptors. */ struct tulip_rx_desc { s32 status; @@ -2698,8 +2702,8 @@ /* Same setup recently queued, we need not add it. */ } else { unsigned long flags; - unsigned int entry; - + unsigned int entry, dummy = 0; + save_flags(flags); cli(); entry = tp->cur_tx++ % TX_RING_SIZE; @@ -2709,7 +2713,8 @@ tp->tx_ring[entry].length = (entry == TX_RING_SIZE-1) ? 0x02000000 : 0; tp->tx_ring[entry].buffer1 = 0; - tp->tx_ring[entry].status = 0x80000000; + /* race with chip, set DescOwned later */ + dummy = entry; entry = tp->cur_tx++ % TX_RING_SIZE; } @@ -2724,6 +2729,8 @@ dev->tbusy = 1; tp->tx_full = 1; } + if (dummy >= 0) + tp->tx_ring[dummy].status = DescOwned; restore_flags(flags); /* Trigger an immediate transmit demand. */ outl(0, ioaddr + CSR1); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/via-rhine.c linux.pre11.3/drivers/net/via-rhine.c --- linux.vanilla/drivers/net/via-rhine.c Thu May 27 22:11:54 1999 +++ linux.pre11.3/drivers/net/via-rhine.c Mon Jul 19 23:27:33 1999 @@ -1,6 +1,6 @@ /* via-rhine.c: A Linux Ethernet device driver for VIA Rhine family chips. */ /* - Written 1998 by Donald Becker. + Written 1998-1999 by Donald Becker. This software may be used and distributed according to the terms of the GNU Public License (GPL), incorporated herein by reference. @@ -20,7 +20,7 @@ */ static const char *versionA = -"via-rhine.c:v1.00 9/5/98 Written by Donald Becker\n"; +"via-rhine.c:v1.01 2/27/99 Written by Donald Becker\n"; static const char *versionB = " http://cesdis.gsfc.nasa.gov/linux/drivers/via-rhine.html\n"; @@ -81,9 +81,11 @@ #include #include -/* This driver was written to use PCI memory space, however some boards - only work with I/O space accesses. */ +/* This driver was written to use PCI memory space, however some x86 + motherboards only configure I/O space accesses correctly. */ +#if defined(__i386__) && !defined(VIA_USE_MEMORY) #define VIA_USE_IO +#endif #ifdef VIA_USE_IO #undef readb #undef readw @@ -105,6 +107,7 @@ #define RUN_AT(x) (jiffies + (x)) #if (LINUX_VERSION_CODE >= 0x20100) +char kernel_version[] = UTS_RELEASE; #else #ifndef __alpha__ #define ioremap vremap @@ -502,6 +505,7 @@ #ifndef MODULE int via_rhine_probe(struct device *dev) { + printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB); return pci_etherdev_probe(dev, pci_tbl); } #endif @@ -510,13 +514,9 @@ struct device *dev, long ioaddr, int irq, int chip_id, int card_idx) { - static int did_version = 0; /* Already printed version info */ struct netdev_private *np; int i, option = card_idx < MAX_UNITS ? options[card_idx] : 0; - if (debug > 0 && did_version++ == 0) - printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB); - dev = init_etherdev(dev, 0); printk(KERN_INFO "%s: %s at 0x%lx, ", @@ -685,6 +685,8 @@ ioaddr + IntrEnable); np->chip_cmd = CmdStart|CmdTxOn|CmdRxOn|CmdNoTxPoll; + if (np->duplex_lock) + np->chip_cmd |= CmdFDuplex; writew(np->chip_cmd, ioaddr + ChipCmd); check_duplex(dev); @@ -1053,7 +1055,6 @@ skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; - np->stats.rx_bytes += pkt_len; np->stats.rx_packets++; } entry = (++np->cur_rx) % RX_RING_SIZE; @@ -1182,7 +1183,7 @@ } writel(mc_filter[0], ioaddr + MulticastFilter0); writel(mc_filter[1], ioaddr + MulticastFilter1); - rx_mode = 0x0C; + rx_mode = 0x08; } writeb(np->rx_thresh | rx_mode, ioaddr + RxConfig); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/wavelan.c linux.pre11.3/drivers/net/wavelan.c --- linux.vanilla/drivers/net/wavelan.c Thu May 27 22:11:55 1999 +++ linux.pre11.3/drivers/net/wavelan.c Tue Jul 20 00:01:04 1999 @@ -2087,12 +2087,6 @@ { struct iw_range range; - /* Verify the user buffer. */ - ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer, - sizeof(struct iw_range)); - if(ret) - break; - /* Set the length (useless: it's constant). */ wrq->u.data.length = sizeof(struct iw_range); @@ -2118,8 +2112,8 @@ range.max_qual.noise = MMR_SILENCE_LVL; /* Copy structure to the user buffer. */ - copy_to_user(wrq->u.data.pointer, &range, - sizeof(struct iw_range)); + if (copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range))) + ret = -EFAULT; } break; @@ -2136,18 +2130,12 @@ { SIOCGIPHISTO, 0, IW_PRIV_TYPE_INT | 16, "gethisto" }, }; - /* Verify the user buffer. */ - ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer, - sizeof(priv)); - if(ret) - break; - /* Set the number of available ioctls. */ wrq->u.data.length = 4; /* Copy structure to the user buffer. */ - copy_to_user(wrq->u.data.pointer, (u_char *) priv, - sizeof(priv)); + if (copy_to_user(wrq->u.data.pointer, (u_char *) priv, sizeof(priv))) + ret = -EFAULT; } break; @@ -2169,14 +2157,11 @@ struct sockaddr address[IW_MAX_SPY]; int i; - /* Verify where the user has set his addresses. */ - ret = verify_area(VERIFY_READ, wrq->u.data.pointer, - sizeof(struct sockaddr) * lp->spy_number); - if(ret) - break; /* Copy addresses to the driver. */ - copy_from_user(address, wrq->u.data.pointer, - sizeof(struct sockaddr) * lp->spy_number); + if (copy_from_user(address, wrq->u.data.pointer, sizeof(struct sockaddr) * lp->spy_number)) { + ret = -EFAULT; + break; + } /* Copy addresses to the lp structure. */ for(i = 0; i < lp->spy_number; i++) @@ -2215,13 +2200,6 @@ struct sockaddr address[IW_MAX_SPY]; int i; - /* Verify the user buffer. */ - ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer, - (sizeof(iw_qual) + sizeof(struct sockaddr)) - * IW_MAX_SPY); - if(ret) - break; - /* Copy addresses from the lp structure. */ for(i = 0; i < lp->spy_number; i++) { @@ -2231,13 +2209,18 @@ } /* Copy addresses to the user buffer. */ - copy_to_user(wrq->u.data.pointer, address, - sizeof(struct sockaddr) * lp->spy_number); - + if (copy_to_user(wrq->u.data.pointer, address, sizeof(struct sockaddr) * lp->spy_number)) { + ret = -EFAULT; + break; + } + /* Copy stats to the user buffer (just after). */ - copy_to_user(wrq->u.data.pointer + + if (copy_to_user(wrq->u.data.pointer + (sizeof(struct sockaddr) * lp->spy_number), - lp->spy_stat, sizeof(iw_qual) * lp->spy_number); + lp->spy_stat, sizeof(iw_qual) * lp->spy_number)) { + ret = -EFAULT; + break; + } /* Reset updated flags. */ for(i = 0; i < lp->spy_number; i++) @@ -2283,14 +2266,11 @@ /* Are there addresses to copy? */ if(lp->his_number > 0) { - /* Verify where the user has set his addresses. */ - ret = verify_area(VERIFY_READ, wrq->u.data.pointer, - sizeof(char) * lp->his_number); - if(ret) - break; /* Copy interval ranges to the driver */ - copy_from_user(lp->his_range, wrq->u.data.pointer, - sizeof(char) * lp->his_number); + if (copy_from_user(lp->his_range, wrq->u.data.pointer, sizeof(char) * lp->his_number)) { + ret = -EFAULT; + break; + } /* Reset structure. */ memset(lp->his_sum, 0x00, sizeof(long) * 16); @@ -2304,15 +2284,10 @@ /* Give back the distribution statistics */ if((lp->his_number > 0) && (wrq->u.data.pointer != (caddr_t) 0)) { - /* Verify the user buffer. */ - ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer, - sizeof(long) * 16); - if(ret) - break; - /* Copy data to the user buffer. */ - copy_to_user(wrq->u.data.pointer, lp->his_sum, - sizeof(long) * lp->his_number); + if (copy_to_user(wrq->u.data.pointer, lp->his_sum, sizeof(long) * lp->his_number)) + ret = -EFAULT; + } /* if(pointer != NULL) */ break; #endif /* HISTOGRAM */ @@ -4265,6 +4240,11 @@ /* Create device and set basic arguments. */ dev = kmalloc(sizeof(struct device), GFP_KERNEL); + if(dev==NULL) + { + ret = -ENOMEM; + break; + } memset(dev, 0x00, sizeof(struct device)); dev->name = name[i]; dev->base_addr = io[i]; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/yellowfin.c linux.pre11.3/drivers/net/yellowfin.c --- linux.vanilla/drivers/net/yellowfin.c Tue Dec 22 23:19:47 1998 +++ linux.pre11.3/drivers/net/yellowfin.c Mon Jul 19 23:27:31 1999 @@ -76,6 +76,7 @@ #include #include /* Processor type for cache alignment. */ #include +#include #include #include @@ -1054,7 +1055,7 @@ u16 desc_status = desc->status; int data_size = desc->request_cnt - desc->result_cnt; u8 *buf_addr = bus_to_virt(desc->addr); - s16 frame_status = *(s16*)&(buf_addr[data_size - 2]); /* ?Alpha safe on 885? */ + s16 frame_status = get_unaligned((s16*)(buf_addr+data_size-2)); if (yellowfin_debug > 4) printk(KERN_DEBUG " yellowfin_rx() status was %4.4x.\n", diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/z85230.c linux.pre11.3/drivers/net/z85230.c --- linux.vanilla/drivers/net/z85230.c Wed Apr 28 19:14:27 1999 +++ linux.pre11.3/drivers/net/z85230.c Tue Jul 20 00:01:09 1999 @@ -187,7 +187,6 @@ 1, EXT_INT_ENAB|TxINT_ENAB|INT_ALL_Rx, 9, NV|MIE|NORESET, 23, 3, /* Extended mode AUTO TX and EOM*/ - 31, 3, /* Extended mode AUTO TX and EOM*/ 255 }; @@ -673,6 +672,7 @@ { kfree(c->rx_buf[0]); c->rx_buf[0]=NULL; + c->rx_buf[1]=NULL; return -ENOBUFS; } @@ -834,6 +834,8 @@ int z8530_sync_txdma_open(struct device *dev, struct z8530_channel *c) { + unsigned long flags; + printk("Opening sync interface for TX-DMA\n"); c->sync = 1; c->mtu = dev->mtu+64; @@ -889,14 +891,21 @@ c->regs[R14]|= DTRREQ; write_zsreg(c, R14, c->regs[R14]); + c->regs[R1]&= ~TxINT_ENAB; + write_zsreg(c, R1, c->regs[R1]); + /* * Set up the DMA configuration */ + flags = claim_dma_lock(); + disable_dma(c->txdma); clear_dma_ff(c->txdma); set_dma_mode(c->txdma, DMA_MODE_WRITE); disable_dma(c->txdma); + + release_dma_lock(flags); /* * Select the DMA interrupt handlers @@ -918,6 +927,7 @@ int z8530_sync_txdma_close(struct device *dev, struct z8530_channel *c) { + unsigned long flags; u8 chk; c->irqs = &z8530_nop; c->max = 0; @@ -927,10 +937,14 @@ * Disable the PC DMA channels */ + flags = claim_dma_lock(); + disable_dma(c->txdma); clear_dma_ff(c->txdma); c->txdma_on = 0; c->tx_dma_used = 0; + + release_dma_lock(flags); /* * Disable DMA control mode diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/pci/oldproc.c linux.pre11.3/drivers/pci/oldproc.c --- linux.vanilla/drivers/pci/oldproc.c Tue Jun 15 16:49:50 1999 +++ linux.pre11.3/drivers/pci/oldproc.c Tue Jul 20 00:01:27 1999 @@ -103,6 +103,7 @@ DEVICE( DEC, DEC_21152, "DC21152"), DEVICE( DEC, DEC_21153, "DC21153"), DEVICE( DEC, DEC_21154, "DC21154"), + DEVICE( DEC, DEC_21285, "DC21285 Footbridge"), DEVICE( CIRRUS, CIRRUS_7548, "GD 7548"), DEVICE( CIRRUS, CIRRUS_5430, "GD 5430"), DEVICE( CIRRUS, CIRRUS_5434_4, "GD 5434"), @@ -222,6 +223,9 @@ DEVICE( X, X_AGX016, "ITT AGX016"), DEVICE( PICOP, PICOP_PT86C52X, "PT86C52x Vesuvius"), DEVICE( PICOP, PICOP_PT80C524, "PT80C524 Nile"), + DEVICE( MYLEX, MYLEX_DAC960P_V2,"DAC960P V2"), + DEVICE( MYLEX, MYLEX_DAC960P_V3,"DAC960P V3"), + DEVICE( MYLEX, MYLEX_DAC960P_V4,"DAC960P V4"), DEVICE( APPLE, APPLE_BANDIT, "Bandit"), DEVICE( APPLE, APPLE_GC, "Grand Central"), DEVICE( APPLE, APPLE_HYDRA, "Hydra"), @@ -303,6 +307,7 @@ DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_128V, "MagicGraph 128V"), DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_128ZV, "MagicGraph 128ZV"), DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_NM2160, "MagicGraph NM2160"), + DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_128ZVPLUS, "MagicGraph 128ZV+"), DEVICE( ASP, ASP_ABP940, "ABP940"), DEVICE( ASP, ASP_ABP940U, "ABP940U"), DEVICE( ASP, ASP_ABP940UW, "ABP940UW"), @@ -460,6 +465,7 @@ DEVICE( SATSAGEM, SATSAGEM_PCR2101,"PCR2101 DVB receiver"), DEVICE( SATSAGEM, SATSAGEM_TELSATTURBO,"Telsat Turbo DVB"), DEVICE( HUGHES, HUGHES_DIRECPC, "DirecPC"), + DEVICE( ENSONIQ, ENSONIQ_ES1371, "ES1371"), DEVICE( ENSONIQ, ENSONIQ_AUDIOPCI,"AudioPCI"), DEVICE( ALTEON, ALTEON_ACENIC, "AceNIC"), DEVICE( PICTUREL, PICTUREL_PCIVST,"PCIVST"), @@ -498,11 +504,13 @@ DEVICE( S3, S3_ViRGE_MXPMV, "ViRGE/MX+MV"), DEVICE( S3, S3_SONICVIBES, "SonicVibes"), DEVICE( DCI, DCI_PCCOM4, "PC COM PCI Bus 4 port serial Adapter"), + DEVICE( GENROCO, GENROCO_HFP832, "TURBOstor HFP832"), DEVICE( INTEL, INTEL_82375, "82375EB"), DEVICE( INTEL, INTEL_82424, "82424ZX Saturn"), DEVICE( INTEL, INTEL_82378, "82378IB"), DEVICE( INTEL, INTEL_82430, "82430ZX Aries"), DEVICE( INTEL, INTEL_82434, "82434LX Mercury/Neptune"), + DEVICE( INTEL, INTEL_I960, "i960"), DEVICE( INTEL, INTEL_82092AA_0,"82092AA PCMCIA bridge"), DEVICE( INTEL, INTEL_82092AA_1,"82092AA EIDE"), DEVICE( INTEL, INTEL_7116, "SAA7116"), @@ -536,6 +544,7 @@ DEVICE( KTI, KTI_ET32P2, "ET32P2"), DEVICE( ADAPTEC, ADAPTEC_7810, "AIC-7810 RAID"), DEVICE( ADAPTEC, ADAPTEC_7821, "AIC-7860"), + DEVICE( ADAPTEC, ADAPTEC_38602, "AIC-7860"), DEVICE( ADAPTEC, ADAPTEC_7850, "AIC-7850"), DEVICE( ADAPTEC, ADAPTEC_7855, "AIC-7855"), DEVICE( ADAPTEC, ADAPTEC_5800, "AIC-5800"), @@ -627,8 +636,8 @@ case PCI_CLASS_STORAGE_SCSI: return "SCSI storage controller"; case PCI_CLASS_STORAGE_IDE: return "IDE interface"; case PCI_CLASS_STORAGE_FLOPPY: return "Floppy disk controller"; - case PCI_CLASS_STORAGE_IPI: return "IPI bus controller"; - case PCI_CLASS_STORAGE_RAID: return "RAID bus controller"; + case PCI_CLASS_STORAGE_IPI: return "IPI storage controller"; + case PCI_CLASS_STORAGE_RAID: return "RAID storage controller"; case PCI_CLASS_STORAGE_OTHER: return "Unknown mass storage controller"; case PCI_CLASS_NETWORK_ETHERNET: return "Ethernet controller"; @@ -736,6 +745,7 @@ case PCI_VENDOR_ID_N9: return "Number Nine"; case PCI_VENDOR_ID_UMC: return "UMC"; case PCI_VENDOR_ID_X: return "X TECHNOLOGY"; + case PCI_VENDOR_ID_MYLEX: return "Mylex"; case PCI_VENDOR_ID_PICOP: return "PicoPower"; case PCI_VENDOR_ID_APPLE: return "Apple"; case PCI_VENDOR_ID_NEXGEN: return "Nexgen"; @@ -826,6 +836,7 @@ case PCI_VENDOR_ID_NETVIN: return "NetVin"; case PCI_VENDOR_ID_S3: return "S3 Inc."; case PCI_VENDOR_ID_DCI: return "Decision Computer Int."; + case PCI_VENDOR_ID_GENROCO: return "Genroco"; case PCI_VENDOR_ID_INTEL: return "Intel"; case PCI_VENDOR_ID_KTI: return "KTI"; case PCI_VENDOR_ID_ADAPTEC: return "Adaptec"; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/pci/pci.c linux.pre11.3/drivers/pci/pci.c --- linux.vanilla/drivers/pci/pci.c Wed Mar 10 21:13:04 1999 +++ linux.pre11.3/drivers/pci/pci.c Tue Jul 20 00:01:32 1999 @@ -184,6 +184,11 @@ } dev = kmalloc(sizeof(*dev), GFP_ATOMIC); + if(dev==NULL) + { + printk(KERN_ERR "pci: out of memory.\n"); + continue; + } memset(dev, 0, sizeof(*dev)); dev->bus = bus; dev->devfn = devfn; @@ -292,6 +297,11 @@ * Insert it into the tree of buses. */ child = kmalloc(sizeof(*child), GFP_ATOMIC); + if(child==NULL) + { + printk(KERN_ERR "pci: out of memory for bridge.\n"); + continue; + } memset(child, 0, sizeof(*child)); child->next = bus->children; bus->children = child; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/NCR53C9x.c linux.pre11.3/drivers/scsi/NCR53C9x.c --- linux.vanilla/drivers/scsi/NCR53C9x.c Tue Dec 22 23:19:48 1998 +++ linux.pre11.3/drivers/scsi/NCR53C9x.c Mon Jul 19 23:28:02 1999 @@ -3390,6 +3390,7 @@ struct ESP_regs *eregs; Scsi_Cmnd *SCptr; int what_next = do_intr_end; + unsigned long flags; #ifdef CONFIG_SCSI_SUNESP struct sparc_dma_registers *dregs = (struct sparc_dma_registers*) esp->dregs; @@ -3610,7 +3611,9 @@ } SCptr->result = (DID_RESET << 16); + spin_lock_irqsave(&io_request_lock,flags); SCptr->scsi_done(SCptr); + spin_unlock_irqrestore(&io_request_lock, flags); } esp->current_SC = NULL; if(esp->disconnected_SC) { @@ -3625,7 +3628,9 @@ } SCptr->result = (DID_RESET << 16); + spin_lock_irqsave(&io_request_lock,flags); SCptr->scsi_done(SCptr); + spin_unlock_irqrestore(&io_request_lock, flags); } } esp->resetting_bus = 0; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/aha152x.c linux.pre11.3/drivers/scsi/aha152x.c --- linux.vanilla/drivers/scsi/aha152x.c Fri May 28 00:32:59 1999 +++ linux.pre11.3/drivers/scsi/aha152x.c Mon Jul 19 23:27:57 1999 @@ -183,7 +183,7 @@ ************************************************************************** - + DESCRIPTION: This is the Linux low-level SCSI driver for Adaptec AHA-1520/1522 SCSI @@ -192,30 +192,30 @@ CONFIGURATION ARGUMENTS: - IOPORT base io address (0x340/0x140) - IRQ interrupt level (9-12; default 11) - SCSI_ID scsi id of controller (0-7; default 7) - RECONNECT allow targets to disconnect from the bus (0/1; default 1 [on]) - PARITY enable parity checking (0/1; default 1 [on]) - SYNCHRONOUS enable synchronous transfers (0/1; default 0 [off]) - (NOT WORKING YET) - DELAY: bus reset delay (default 100) - EXT_TRANS: enable extended translation (0/1: default 0 [off]) - (see NOTES below) + IOPORT base io address (0x340/0x140) + IRQ interrupt level (9-12; default 11) + SCSI_ID scsi id of controller (0-7; default 7) + RECONNECT allow targets to disconnect from the bus (0/1; default 1 [on]) + PARITY enable parity checking (0/1; default 1 [on]) + SYNCHRONOUS enable synchronous transfers (0/1; default 0 [off]) + (NOT WORKING YET) + DELAY: bus reset delay (default 100) + EXT_TRANS: enable extended translation (0/1: default 0 [off]) + (see NOTES below) COMPILE TIME CONFIGURATION (put into AHA152X in drivers/scsi/Makefile): -DAUTOCONF - use configuration the controller reports (AHA-152x only) + use configuration the controller reports (AHA-152x only) -DSKIP_BIOSTEST - Don't test for BIOS signature (AHA-1510 or disabled BIOS) + Don't test for BIOS signature (AHA-1510 or disabled BIOS) -DSETUP0="{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS, DELAY, EXT_TRANS }" - override for the first controller - + override for the first controller + -DSETUP1="{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS, DELAY, EXT_TRANS }" - override for the second controller + override for the second controller LILO COMMAND LINE OPTIONS: @@ -230,13 +230,13 @@ SYMBOLS FOR MODULE CONFIGURATION: - - aha152x=IOPORT,IRQ,SCSI_ID,RECONNECT,PARITY,SYNCHRONOUS,DELAY,EXT_TRANS - configuration override of first controller - - - aha152x1=IOPORT,IRQ,SCSI_ID,RECONNECT,PARITY,SYNCHRONOUS,DELAY,EXT_TRANS - configuration override of second controller + + aha152x=IOPORT,IRQ,SCSI_ID,RECONNECT,PARITY,SYNCHRONOUS,DELAY,EXT_TRANS + configuration override of first controller + + + aha152x1=IOPORT,IRQ,SCSI_ID,RECONNECT,PARITY,SYNCHRONOUS,DELAY,EXT_TRANS + configuration override of second controller NOTES ON EXT_TRANS: @@ -287,14 +287,14 @@ - for disks<1GB: use default translation (C/32/64) - for disks>1GB: - - take current geometry from the partition table - (using scsicam_bios_param and accept only `valid' geometries, - ie. either (C/32/64) or (C/63/255)). This can be extended - translation even if it's not enabled in the driver. - - if that fails, take extended translation if enabled by override, - kernel or module parameter, otherwise take default translation and - ask the user for verification. This might on not yet partitioned - disks or + - take current geometry from the partition table + (using scsicam_bios_param and accept only `valid' geometries, + ie. either (C/32/64) or (C/63/255)). This can be extended + translation even if it's not enabled in the driver. + - if that fails, take extended translation if enabled by override, + kernel or module parameter, otherwise take default translation and + ask the user for verification. This might on not yet partitioned + disks or REFERENCES USED: @@ -308,7 +308,7 @@ "Kernel Hacker's Guide", Michael K. Johnson (johnsonm@sunsite.unc.edu) "Adaptec 1520/1522 User's Guide", Adaptec Corporation. - + Michael K. Johnson (johnsonm@sunsite.unc.edu) Drew Eckhardt (drew@cs.colorado.edu) @@ -350,9 +350,10 @@ #include -struct proc_dir_entry proc_scsi_aha152x = { - PROC_SCSI_AHA152X, 7, "aha152x", - S_IFDIR | S_IRUGO | S_IXUGO, 2 +struct proc_dir_entry proc_scsi_aha152x = +{ + PROC_SCSI_AHA152X, 7, "aha152x", + S_IFDIR | S_IRUGO | S_IXUGO, 2 }; /* DEFINES */ @@ -370,25 +371,25 @@ #if defined(DEBUG_AHA152X) -#undef SKIP_PORTS /* don't display ports */ +#undef SKIP_PORTS /* don't display ports */ -#undef DEBUG_QUEUE /* debug queue() */ -#undef DEBUG_RESET /* debug reset() */ -#undef DEBUG_INTR /* debug intr() */ -#undef DEBUG_SELECTION /* debug selection part in intr() */ -#undef DEBUG_MSGO /* debug message out phase in intr() */ -#undef DEBUG_MSGI /* debug message in phase in intr() */ -#undef DEBUG_STATUS /* debug status phase in intr() */ -#undef DEBUG_CMD /* debug command phase in intr() */ -#undef DEBUG_DATAI /* debug data in phase in intr() */ -#undef DEBUG_DATAO /* debug data out phase in intr() */ -#undef DEBUG_ABORT /* debug abort() */ -#undef DEBUG_DONE /* debug done() */ -#undef DEBUG_BIOSPARAM /* debug biosparam() */ - -#undef DEBUG_RACE /* debug race conditions */ -#undef DEBUG_PHASES /* debug phases (useful to trace) */ -#undef DEBUG_QUEUES /* debug reselection */ +#undef DEBUG_QUEUE /* debug queue() */ +#undef DEBUG_RESET /* debug reset() */ +#undef DEBUG_INTR /* debug intr() */ +#undef DEBUG_SELECTION /* debug selection part in intr() */ +#undef DEBUG_MSGO /* debug message out phase in intr() */ +#undef DEBUG_MSGI /* debug message in phase in intr() */ +#undef DEBUG_STATUS /* debug status phase in intr() */ +#undef DEBUG_CMD /* debug command phase in intr() */ +#undef DEBUG_DATAI /* debug data in phase in intr() */ +#undef DEBUG_DATAO /* debug data out phase in intr() */ +#undef DEBUG_ABORT /* debug abort() */ +#undef DEBUG_DONE /* debug done() */ +#undef DEBUG_BIOSPARAM /* debug biosparam() */ + +#undef DEBUG_RACE /* debug race conditions */ +#undef DEBUG_PHASES /* debug phases (useful to trace) */ +#undef DEBUG_QUEUES /* debug reselection */ /* recently used for debugging */ #if 0 @@ -424,46 +425,50 @@ #define IRQS IRQ_MAX-IRQ_MIN+1 enum { - not_issued = 0x0001, - in_selection = 0x0002, - disconnected = 0x0004, - aborted = 0x0008, - sent_ident = 0x0010, - in_other = 0x0020, - in_sync = 0x0040, - sync_ok = 0x0080, + not_issued = 0x0001, + in_selection = 0x0002, + disconnected = 0x0004, + aborted = 0x0008, + sent_ident = 0x0010, + in_other = 0x0020, + in_sync = 0x0040, + sync_ok = 0x0080, }; #if defined(MODULE) #if defined(DEBUG_AHA152X) -int aha152x[] = { 0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0, DEBUG_DEFAULT }; -int aha152x1[] = { 0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0, DEBUG_DEFAULT }; +int aha152x[] = +{0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0, DEBUG_DEFAULT}; +int aha152x1[] = +{0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0, DEBUG_DEFAULT}; MODULE_PARM(aha152x, "1-9i"); MODULE_PARM(aha152x1, "1-9i"); #else -int aha152x[] = { 0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0 }; -int aha152x1[] = { 0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0 }; +int aha152x[] = +{0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0}; +int aha152x1[] = +{0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0}; MODULE_PARM(aha152x, "1-8i"); MODULE_PARM(aha152x1, "1-8i"); #endif #endif /* set by aha152x_setup according to the command line */ -static int setup_count=0; -static int registered_count=0; +static int setup_count = 0; +static int registered_count = 0; static struct aha152x_setup { - int io_port; - int irq; - int scsiid; - int reconnect; - int parity; - int synchronous; - int delay; - int ext_trans; + int io_port; + int irq; + int scsiid; + int reconnect; + int parity; + int synchronous; + int delay; + int ext_trans; #ifdef DEBUG_AHA152X - int debug; + int debug; #endif - char *conf; + char *conf; } setup[2]; static struct Scsi_Host *aha152x_host[IRQS]; @@ -480,30 +485,30 @@ #define ADDMSG(x) (MSG(MSGLEN++)=x) struct aha152x_hostdata { - Scsi_Cmnd *issue_SC; - Scsi_Cmnd *current_SC; - Scsi_Cmnd *disconnected_SC; - int aborting; - int abortion_complete; - int abort_result; - int commands; - - int reconnect; - int parity; - int synchronous; - int delay; - int ext_trans; - - int swint; - int service; - - unsigned char syncrate[8]; - - unsigned char message[256]; - int message_len; + Scsi_Cmnd *issue_SC; + Scsi_Cmnd *current_SC; + Scsi_Cmnd *disconnected_SC; + int aborting; + int abortion_complete; + int abort_result; + int commands; + + int reconnect; + int parity; + int synchronous; + int delay; + int ext_trans; + + int swint; + int service; + + unsigned char syncrate[8]; + + unsigned char message[256]; + int message_len; #ifdef DEBUG_AHA152X - int debug; + int debug; #endif }; @@ -516,7 +521,7 @@ static void aha152x_panic(struct Scsi_Host *shpnt, char *msg); static void disp_ports(struct Scsi_Host *shpnt); -static void show_command(Scsi_Cmnd *ptr); +static void show_command(Scsi_Cmnd * ptr); static void show_queues(struct Scsi_Host *shpnt); static void disp_enintr(struct Scsi_Host *shpnt); @@ -528,8 +533,8 @@ /* possible i/o addresses for the AIC-6260 */ static unsigned short ports[] = { - 0x340, /* default first */ - 0x140 + 0x340, /* default first */ + 0x140 }; #define PORT_COUNT (sizeof(ports) / sizeof(unsigned short)) @@ -537,15 +542,15 @@ /* possible locations for the Adaptec BIOS */ static unsigned int addresses[] = { - 0xdc000, /* default first */ - 0xc8000, - 0xcc000, - 0xd0000, - 0xd4000, - 0xd8000, - 0xe0000, - 0xeb800, /* VTech Platinum SMP */ - 0xf0000, + 0xdc000, /* default first */ + 0xc8000, + 0xcc000, + 0xd0000, + 0xd4000, + 0xd8000, + 0xe0000, + 0xeb800, /* VTech Platinum SMP */ + 0xf0000, }; #define ADDRESS_COUNT (sizeof(addresses) / sizeof(unsigned int)) @@ -557,80 +562,103 @@ needed anyway. May be an information whether or not the BIOS supports extended translation could be also useful here. */ static struct signature { - unsigned char *signature; - int sig_offset; - int sig_length; + unsigned char *signature; + int sig_offset; + int sig_length; } signatures[] = + { - { "Adaptec AHA-1520 BIOS", 0x102e, 21 }, /* Adaptec 152x */ - { "Adaptec AHA-1520B", 0x0b, 19 }, /* Adaptec 152x rev B */ - { "Adaptec ASW-B626 BIOS", 0x1029, 21 }, /* on-board controller */ - { "Adaptec BIOS: ASW-B626", 0x0f, 22 }, /* on-board controller */ - { "Adaptec ASW-B626 S2", 0x2e6c, 19 }, /* on-board controller */ - { "Adaptec BIOS:AIC-6360", 0xc, 21 }, /* on-board controller */ - { "ScsiPro SP-360 BIOS", 0x2873, 19 }, /* ScsiPro-Controller */ - { "GA-400 LOCAL BUS SCSI BIOS", 0x102e, 26 }, /* Gigabyte Local-Bus-SCSI */ - { "Adaptec BIOS:AVA-282X", 0xc, 21 }, /* Adaptec 282x */ - { "Adaptec IBM Dock II SCSI", 0x2edd, 24 }, /* IBM Thinkpad Dock II */ - { "Adaptec BIOS:AHA-1532P", 0x1c, 22 }, /* IBM Thinkpad Dock II SCSI */ - { "DTC3520A Host Adapter BIOS", 0x318a, 26 }, /* DTC 3520A ISA SCSI */ + { + "Adaptec AHA-1520 BIOS", 0x102e, 21 + }, /* Adaptec 152x */ + { + "Adaptec AHA-1520B", 0x0b, 19 + }, /* Adaptec 152x rev B */ + { + "Adaptec ASW-B626 BIOS", 0x1029, 21 + }, /* on-board controller */ + { + "Adaptec BIOS: ASW-B626", 0x0f, 22 + }, /* on-board controller */ + { + "Adaptec ASW-B626 S2", 0x2e6c, 19 + }, /* on-board controller */ + { + "Adaptec BIOS:AIC-6360", 0xc, 21 + }, /* on-board controller */ + { + "ScsiPro SP-360 BIOS", 0x2873, 19 + }, /* ScsiPro-Controller */ + { + "GA-400 LOCAL BUS SCSI BIOS", 0x102e, 26 + }, /* Gigabyte Local-Bus-SCSI */ + { + "Adaptec BIOS:AVA-282X", 0xc, 21 + }, /* Adaptec 282x */ + { + "Adaptec IBM Dock II SCSI", 0x2edd, 24 + }, /* IBM Thinkpad Dock II */ + { + "Adaptec BIOS:AHA-1532P", 0x1c, 22 + }, /* IBM Thinkpad Dock II SCSI */ + { + "DTC3520A Host Adapter BIOS", 0x318a, 26 + }, /* DTC 3520A ISA SCSI */ }; + #define SIGNATURE_COUNT (sizeof(signatures) / sizeof(struct signature)) #endif -static void do_pause(unsigned amount) /* Pause for amount*10 milliseconds */ -{ - unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */ +static void do_pause(unsigned amount) +{ /* Pause for amount*10 milliseconds */ + unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */ - while (time_before(jiffies, the_time)) - barrier(); + while (time_before(jiffies, the_time)) + barrier(); } /* * queue services: */ -static inline void append_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC) +static inline void append_SC(Scsi_Cmnd ** SC, Scsi_Cmnd * new_SC) { - Scsi_Cmnd *end; + Scsi_Cmnd *end; - new_SC->host_scribble = (unsigned char *) NULL; - if(!*SC) - *SC=new_SC; - else { - for(end=*SC; end->host_scribble; end = (Scsi_Cmnd *) end->host_scribble) - ; - end->host_scribble = (unsigned char *) new_SC; - } + new_SC->host_scribble = (unsigned char *) NULL; + if (!*SC) + *SC = new_SC; + else { + for (end = *SC; end->host_scribble; end = (Scsi_Cmnd *) end->host_scribble); + end->host_scribble = (unsigned char *) new_SC; + } } -static inline Scsi_Cmnd *remove_first_SC(Scsi_Cmnd **SC) +static inline Scsi_Cmnd *remove_first_SC(Scsi_Cmnd ** SC) { - Scsi_Cmnd *ptr; + Scsi_Cmnd *ptr; - ptr=*SC; - if(ptr) - *SC= (Scsi_Cmnd *) (*SC)->host_scribble; - return ptr; + ptr = *SC; + if (ptr) + *SC = (Scsi_Cmnd *) (*SC)->host_scribble; + return ptr; } -static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, int target, int lun) +static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd ** SC, int target, int lun) { - Scsi_Cmnd *ptr, *prev; - - for(ptr=*SC, prev=NULL; - ptr && ((ptr->target!=target) || (ptr->lun!=lun)); - prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble) - ; + Scsi_Cmnd *ptr, *prev; - if(ptr){ - if(prev) - prev->host_scribble = ptr->host_scribble; - else - *SC= (Scsi_Cmnd *) ptr->host_scribble; - } + for (ptr = *SC, prev = NULL; + ptr && ((ptr->target != target) || (ptr->lun != lun)); + prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble); - return ptr; + if (ptr) { + if (prev) + prev->host_scribble = ptr->host_scribble; + else + *SC = (Scsi_Cmnd *) ptr->host_scribble; + } + return ptr; } /* @@ -638,12 +666,12 @@ */ static void make_acklow(struct Scsi_Host *shpnt) { - SETPORT(SXFRCTL0, CH1|SPIOEN); - GETPORT(SCSIDAT); - SETPORT(SXFRCTL0, CH1); + SETPORT(SXFRCTL0, CH1 | SPIOEN); + GETPORT(SCSIDAT); + SETPORT(SXFRCTL0, CH1); - while(TESTHI(SCSISIG, ACKI)) - barrier(); + while (TESTHI(SCSISIG, ACKI)) + barrier(); } /* @@ -658,61 +686,61 @@ */ static int getphase(struct Scsi_Host *shpnt) { - int phase, sstat1; - - while(1) { - do { - while(!((sstat1 = GETPORT(SSTAT1)) & (BUSFREE|SCSIRSTI|REQINIT))) - barrier(); - if(sstat1 & BUSFREE) - return P_BUSFREE; - if(sstat1 & SCSIRSTI) { - printk("aha152x: RESET IN\n"); - SETPORT(SSTAT1, SCSIRSTI); - } - } while(TESTHI(SCSISIG, ACKI) || TESTLO(SSTAT1, REQINIT)); - - SETPORT(SSTAT1, CLRSCSIPERR); - - phase = GETPORT(SCSISIG) & P_MASK ; - - if(TESTHI(SSTAT1, SCSIPERR)) { - if((phase & (CDO|MSGO))==0) /* DATA phase */ - return P_PARITY; - - make_acklow(shpnt); - } else - return phase; - } + int phase, sstat1; + + while (1) { + do { + while (!((sstat1 = GETPORT(SSTAT1)) & (BUSFREE | SCSIRSTI | REQINIT))) + barrier(); + if (sstat1 & BUSFREE) + return P_BUSFREE; + if (sstat1 & SCSIRSTI) { + printk("aha152x: RESET IN\n"); + SETPORT(SSTAT1, SCSIRSTI); + } + } while (TESTHI(SCSISIG, ACKI) || TESTLO(SSTAT1, REQINIT)); + + SETPORT(SSTAT1, CLRSCSIPERR); + + phase = GETPORT(SCSISIG) & P_MASK; + + if (TESTHI(SSTAT1, SCSIPERR)) { + if ((phase & (CDO | MSGO)) == 0) /* DATA phase */ + return P_PARITY; + + make_acklow(shpnt); + } else + return phase; + } } /* called from init/main.c */ void aha152x_setup(char *str, int *ints) { - if(setup_count>2) - panic("aha152x: you can only configure up to two controllers\n"); + if (setup_count > 2) + panic("aha152x: you can only configure up to two controllers\n"); - setup[setup_count].conf = str; - setup[setup_count].io_port = ints[0] >= 1 ? ints[1] : 0x340; - setup[setup_count].irq = ints[0] >= 2 ? ints[2] : 11; - setup[setup_count].scsiid = ints[0] >= 3 ? ints[3] : 7; - setup[setup_count].reconnect = ints[0] >= 4 ? ints[4] : 1; - setup[setup_count].parity = ints[0] >= 5 ? ints[5] : 1; - setup[setup_count].synchronous = ints[0] >= 6 ? ints[6] : 0 /* FIXME: 1 */; - setup[setup_count].delay = ints[0] >= 7 ? ints[7] : DELAY_DEFAULT; - setup[setup_count].ext_trans = ints[0] >= 8 ? ints[8] : 0; + setup[setup_count].conf = str; + setup[setup_count].io_port = ints[0] >= 1 ? ints[1] : 0x340; + setup[setup_count].irq = ints[0] >= 2 ? ints[2] : 11; + setup[setup_count].scsiid = ints[0] >= 3 ? ints[3] : 7; + setup[setup_count].reconnect = ints[0] >= 4 ? ints[4] : 1; + setup[setup_count].parity = ints[0] >= 5 ? ints[5] : 1; + setup[setup_count].synchronous = ints[0] >= 6 ? ints[6] : 0 /* FIXME: 1 */ ; + setup[setup_count].delay = ints[0] >= 7 ? ints[7] : DELAY_DEFAULT; + setup[setup_count].ext_trans = ints[0] >= 8 ? ints[8] : 0; #ifdef DEBUG_AHA152X - setup[setup_count].debug = ints[0] >= 9 ? ints[9] : DEBUG_DEFAULT; - if(ints[0]>9) { - printk("aha152x: usage: aha152x=[,[," - "[,[,[,[,[,[,]]]]]]]]\n"); + setup[setup_count].debug = ints[0] >= 9 ? ints[9] : DEBUG_DEFAULT; + if (ints[0] > 9) { + printk("aha152x: usage: aha152x=[,[," + "[,[,[,[,[,[,]]]]]]]]\n"); #else - if(ints[0]>8) { - printk("aha152x: usage: aha152x=[,[," - "[,[,[,[,[,]]]]]]]\n"); + if (ints[0] > 8) { + printk("aha152x: usage: aha152x=[,[," + "[,[,[,[,[,]]]]]]]\n"); #endif - } else - setup_count++; + } else + setup_count++; } /* @@ -720,598 +748,589 @@ */ static int aha152x_porttest(int io_port) { - int i; + int i; - if(check_region(io_port, IO_RANGE)) - return 0; + if (check_region(io_port, IO_RANGE)) + return 0; - SETPORT(io_port+O_DMACNTRL1, 0); /* reset stack pointer */ - for(i=0; i<16; i++) - SETPORT(io_port+O_STACK, i); + SETPORT(io_port + O_DMACNTRL1, 0); /* reset stack pointer */ + for (i = 0; i < 16; i++) + SETPORT(io_port + O_STACK, i); - SETPORT(io_port+O_DMACNTRL1, 0); /* reset stack pointer */ - for(i=0; i<16 && GETPORT(io_port+O_STACK)==i; i++) - ; + SETPORT(io_port + O_DMACNTRL1, 0); /* reset stack pointer */ + for (i = 0; i < 16 && GETPORT(io_port + O_STACK) == i; i++); - return(i==16); + return (i == 16); } int aha152x_checksetup(struct aha152x_setup *setup) { - int i; - + int i; + #ifndef PCMCIA - for(i=0; iio_port != ports[i]); i++) - ; - - if(i==PORT_COUNT) - return 0; -#endif - - if(!aha152x_porttest(setup->io_port)) - return 0; - - if((setup->irqirq>IRQ_MAX)) - return 0; - - if((setup->scsiid < 0) || (setup->scsiid > 7)) - return 0; - - if((setup->reconnect < 0) || (setup->reconnect > 1)) - return 0; - - if((setup->parity < 0) || (setup->parity > 1)) - return 0; - - if((setup->synchronous < 0) || (setup->synchronous > 1)) - return 0; - - if((setup->ext_trans < 0) || (setup->ext_trans > 1)) - return 0; - - - return 1; + for (i = 0; i < PORT_COUNT && (setup->io_port != ports[i]); i++); + + if (i == PORT_COUNT) + return 0; +#endif + + if (!aha152x_porttest(setup->io_port)) + return 0; + + if ((setup->irq < IRQ_MIN) || (setup->irq > IRQ_MAX)) + return 0; + + if ((setup->scsiid < 0) || (setup->scsiid > 7)) + return 0; + + if ((setup->reconnect < 0) || (setup->reconnect > 1)) + return 0; + + if ((setup->parity < 0) || (setup->parity > 1)) + return 0; + + if ((setup->synchronous < 0) || (setup->synchronous > 1)) + return 0; + + if ((setup->ext_trans < 0) || (setup->ext_trans > 1)) + return 0; + + + return 1; } -void aha152x_swintr(int irqno, void *dev_id, struct pt_regs * regs) +void aha152x_swintr(int irqno, void *dev_id, struct pt_regs *regs) { - struct Scsi_Host *shpnt = aha152x_host[irqno-IRQ_MIN]; + struct Scsi_Host *shpnt = aha152x_host[irqno - IRQ_MIN]; - if(!shpnt) - panic("aha152x: catched software interrupt for unknown controller.\n"); + if (!shpnt) + panic("aha152x: catched software interrupt for unknown controller.\n"); - HOSTDATA(shpnt)->swint++; + HOSTDATA(shpnt)->swint++; } int aha152x_detect(Scsi_Host_Template * tpnt) { - int i, j, ok; + int i, j, ok; #if defined(AUTOCONF) - aha152x_config conf; + aha152x_config conf; #endif - - tpnt->proc_dir = &proc_scsi_aha152x; - for(i=0; iproc_dir = &proc_scsi_aha152x; + + for (i = 0; i < IRQS; i++) + aha152x_host[i] = (struct Scsi_Host *) NULL; + + if (setup_count) { + printk("aha152x: processing commandline: "); + + for (i = 0; i < setup_count; i++) + if (!aha152x_checksetup(&setup[i])) { + printk("\naha152x: %s\n", setup[i].conf); + printk("aha152x: invalid line (controller=%d)\n", i + 1); + } + printk("ok\n"); + } #ifdef SETUP0 - if(setup_count<2) { - struct aha152x_setup override = SETUP0; + if (setup_count < 2) { + struct aha152x_setup override = SETUP0; - if(setup_count==0 || (override.io_port != setup[0].io_port)) - if(!aha152x_checksetup(&override)) { - printk("\naha152x: invalid override SETUP0={0x%x,%d,%d,%d,%d,%d,%d,%d}\n", - override.io_port, - override.irq, - override.scsiid, - override.reconnect, - override.parity, - override.synchronous, - override.delay, - override.ext_trans); - } else - setup[setup_count++] = override; - } + if (setup_count == 0 || (override.io_port != setup[0].io_port)) + if (!aha152x_checksetup(&override)) { + printk("\naha152x: invalid override SETUP0={0x%x,%d,%d,%d,%d,%d,%d,%d}\n", + override.io_port, + override.irq, + override.scsiid, + override.reconnect, + override.parity, + override.synchronous, + override.delay, + override.ext_trans); + } else + setup[setup_count++] = override; + } #endif #ifdef SETUP1 - if(setup_count<2) { - struct aha152x_setup override = SETUP1; + if (setup_count < 2) { + struct aha152x_setup override = SETUP1; - if(setup_count==0 || (override.io_port != setup[0].io_port)) - if(!aha152x_checksetup(&override)) { - printk("\naha152x: invalid override SETUP1={0x%x,%d,%d,%d,%d,%d,%d,%d}\n", - override.io_port, - override.irq, - override.scsiid, - override.reconnect, - override.parity, - override.synchronous, - override.delay, - override.ext_trans); - } else - setup[setup_count++] = override; - } + if (setup_count == 0 || (override.io_port != setup[0].io_port)) + if (!aha152x_checksetup(&override)) { + printk("\naha152x: invalid override SETUP1={0x%x,%d,%d,%d,%d,%d,%d,%d}\n", + override.io_port, + override.irq, + override.scsiid, + override.reconnect, + override.parity, + override.synchronous, + override.delay, + override.ext_trans); + } else + setup[setup_count++] = override; + } #endif #if defined(MODULE) - if(setup_count<2 && aha152x[0]!=0) { - setup[setup_count].conf = ""; - setup[setup_count].io_port = aha152x[0]; - setup[setup_count].irq = aha152x[1]; - setup[setup_count].scsiid = aha152x[2]; - setup[setup_count].reconnect = aha152x[3]; - setup[setup_count].parity = aha152x[4]; - setup[setup_count].synchronous = aha152x[5]; - setup[setup_count].delay = aha152x[6]; - setup[setup_count].ext_trans = aha152x[7]; + if (setup_count < 2 && aha152x[0] != 0) { + setup[setup_count].conf = ""; + setup[setup_count].io_port = aha152x[0]; + setup[setup_count].irq = aha152x[1]; + setup[setup_count].scsiid = aha152x[2]; + setup[setup_count].reconnect = aha152x[3]; + setup[setup_count].parity = aha152x[4]; + setup[setup_count].synchronous = aha152x[5]; + setup[setup_count].delay = aha152x[6]; + setup[setup_count].ext_trans = aha152x[7]; #ifdef DEBUG_AHA152X - setup[setup_count].debug = aha152x[8]; + setup[setup_count].debug = aha152x[8]; #endif - if(aha152x_checksetup(&setup[setup_count])) - setup_count++; - else - printk("\naha152x: invalid module argument aha152x=0x%x,%d,%d,%d,%d,%d,%d,%d\n", - setup[setup_count].io_port, - setup[setup_count].irq, - setup[setup_count].scsiid, - setup[setup_count].reconnect, - setup[setup_count].parity, - setup[setup_count].synchronous, - setup[setup_count].delay, - setup[setup_count].ext_trans); - } - - if(setup_count<2 && aha152x1[0]!=0) { - setup[setup_count].conf = ""; - setup[setup_count].io_port = aha152x1[0]; - setup[setup_count].irq = aha152x1[1]; - setup[setup_count].scsiid = aha152x1[2]; - setup[setup_count].reconnect = aha152x1[3]; - setup[setup_count].parity = aha152x1[4]; - setup[setup_count].synchronous = aha152x1[5]; - setup[setup_count].delay = aha152x1[6]; - setup[setup_count].ext_trans = aha152x1[7]; + if (aha152x_checksetup(&setup[setup_count])) + setup_count++; + else + printk("\naha152x: invalid module argument aha152x=0x%x,%d,%d,%d,%d,%d,%d,%d\n", + setup[setup_count].io_port, + setup[setup_count].irq, + setup[setup_count].scsiid, + setup[setup_count].reconnect, + setup[setup_count].parity, + setup[setup_count].synchronous, + setup[setup_count].delay, + setup[setup_count].ext_trans); + } + if (setup_count < 2 && aha152x1[0] != 0) { + setup[setup_count].conf = ""; + setup[setup_count].io_port = aha152x1[0]; + setup[setup_count].irq = aha152x1[1]; + setup[setup_count].scsiid = aha152x1[2]; + setup[setup_count].reconnect = aha152x1[3]; + setup[setup_count].parity = aha152x1[4]; + setup[setup_count].synchronous = aha152x1[5]; + setup[setup_count].delay = aha152x1[6]; + setup[setup_count].ext_trans = aha152x1[7]; #ifdef DEBUG_AHA152X - setup[setup_count].debug = aha152x1[8]; + setup[setup_count].debug = aha152x1[8]; #endif - if(aha152x_checksetup(&setup[setup_count])) - setup_count++; - else - printk("\naha152x: invalid module argument aha152x1=0x%x,%d,%d,%d,%d,%d,%d,%d\n", - setup[setup_count].io_port, - setup[setup_count].irq, - setup[setup_count].scsiid, - setup[setup_count].reconnect, - setup[setup_count].parity, - setup[setup_count].synchronous, - setup[setup_count].delay, - setup[setup_count].ext_trans); - } + if (aha152x_checksetup(&setup[setup_count])) + setup_count++; + else + printk("\naha152x: invalid module argument aha152x1=0x%x,%d,%d,%d,%d,%d,%d,%d\n", + setup[setup_count].io_port, + setup[setup_count].irq, + setup[setup_count].scsiid, + setup[setup_count].reconnect, + setup[setup_count].parity, + setup[setup_count].synchronous, + setup[setup_count].delay, + setup[setup_count].ext_trans); + } #endif - + #if defined(AUTOCONF) - if(setup_count<2) { + if (setup_count < 2) { #if !defined(SKIP_BIOSTEST) - ok=0; - for(i=0; i < ADDRESS_COUNT && !ok; i++) - for(j=0; (j < SIGNATURE_COUNT) && !ok; j++) - ok = check_signature(addresses[i]+signatures[j].sig_offset, - signatures[j].signature, signatures[j].sig_length); + ok = 0; + for (i = 0; i < ADDRESS_COUNT && !ok; i++) + for (j = 0; (j < SIGNATURE_COUNT) && !ok; j++) + ok = check_signature(addresses[i] + signatures[j].sig_offset, + signatures[j].signature, signatures[j].sig_length); - if(!ok && setup_count==0) - return 0; + if (!ok && setup_count == 0) + return 0; - printk("aha152x: BIOS test: passed, "); + printk("aha152x: BIOS test: passed, "); #else - printk("aha152x: "); -#endif /* !SKIP_BIOSTEST */ - - ok=0; - for(i=0; iio_port = setup[i].io_port; + shpnt->n_io_port = IO_RANGE; + shpnt->irq = setup[i].irq; + + ISSUE_SC = (Scsi_Cmnd *) NULL; + CURRENT_SC = (Scsi_Cmnd *) NULL; + DISCONNECTED_SC = (Scsi_Cmnd *) NULL; + + HOSTDATA(shpnt)->reconnect = setup[i].reconnect; + HOSTDATA(shpnt)->parity = setup[i].parity; + HOSTDATA(shpnt)->synchronous = setup[i].synchronous; + HOSTDATA(shpnt)->delay = setup[i].delay; + HOSTDATA(shpnt)->ext_trans = setup[i].ext_trans; +#ifdef DEBUG_AHA152X + HOSTDATA(shpnt)->debug = setup[i].debug; +#endif - shpnt = aha152x_host[setup[i].irq-IRQ_MIN] = - scsi_register(tpnt, sizeof(struct aha152x_hostdata)); - registered_count++; + HOSTDATA(shpnt)->aborting = 0; + HOSTDATA(shpnt)->abortion_complete = 0; + HOSTDATA(shpnt)->abort_result = 0; + HOSTDATA(shpnt)->commands = 0; + + HOSTDATA(shpnt)->message_len = 0; + + for (j = 0; j < 8; j++) + HOSTDATA(shpnt)->syncrate[j] = 0; + + SETPORT(SCSIID, setup[i].scsiid << 4); + shpnt->this_id = setup[i].scsiid; + + if (setup[i].reconnect) + shpnt->can_queue = AHA152X_MAXQUEUE; + + /* RESET OUT */ + SETBITS(SCSISEQ, SCSIRSTO); + do_pause(30); + CLRBITS(SCSISEQ, SCSIRSTO); + do_pause(setup[i].delay); + + aha152x_reset_ports(shpnt); + + printk("aha152x%d: vital data: PORTBASE=0x%03lx, IRQ=%d, SCSI ID=%d," + " reconnect=%s, parity=%s, synchronous=%s, delay=%d, extended translation=%s\n", + i, + shpnt->io_port, + shpnt->irq, + shpnt->this_id, + HOSTDATA(shpnt)->reconnect ? "enabled" : "disabled", + HOSTDATA(shpnt)->parity ? "enabled" : "disabled", + HOSTDATA(shpnt)->synchronous ? "enabled" : "disabled", + HOSTDATA(shpnt)->delay, + HOSTDATA(shpnt)->ext_trans ? "enabled" : "disabled"); + + request_region(shpnt->io_port, IO_RANGE, "aha152x"); /* Register */ + + /* not expecting any interrupts */ + SETPORT(SIMODE0, 0); + SETPORT(SIMODE1, 0); + + SETBITS(DMACNTRL0, INTEN); + + ok = request_irq(shpnt->irq, aha152x_swintr, SA_INTERRUPT, "aha152x", shpnt); + if (ok < 0) { + if (ok == -EINVAL) + printk("aha152x%d: bad IRQ %d.\n", i, shpnt->irq); + else if (ok == -EBUSY) + printk("aha152x%d: IRQ %d already in use.\n", i, shpnt->irq); + else + printk("\naha152x%d: Unexpected error code %d on requesting IRQ %d.\n", i, ok, shpnt->irq); + printk("aha152x: driver needs an IRQ.\n"); + + scsi_unregister(shpnt); + registered_count--; + release_region(shpnt->io_port, IO_RANGE); + shpnt = aha152x_host[shpnt->irq - IRQ_MIN] = 0; + continue; + } + HOSTDATA(shpnt)->swint = 0; - shpnt->io_port = setup[i].io_port; - shpnt->n_io_port = IO_RANGE; - shpnt->irq = setup[i].irq; + printk("aha152x: trying software interrupt, "); + SETBITS(DMACNTRL0, SWINT); - ISSUE_SC = (Scsi_Cmnd *) NULL; - CURRENT_SC = (Scsi_Cmnd *) NULL; - DISCONNECTED_SC = (Scsi_Cmnd *) NULL; + the_time = jiffies + 100; + while (!HOSTDATA(shpnt)->swint && time_before(jiffies, the_time)) + barrier(); + + free_irq(shpnt->irq, shpnt); + + if (!HOSTDATA(shpnt)->swint) { + if (TESTHI(DMASTAT, INTSTAT)) { + printk("lost.\n"); + } else { + printk("failed.\n"); + } + + printk("aha152x: IRQ %d possibly wrong. Please verify.\n", shpnt->irq); + + scsi_unregister(shpnt); + registered_count--; + release_region(shpnt->io_port, IO_RANGE); + shpnt = aha152x_host[shpnt->irq - IRQ_MIN] = 0; + continue; + } + printk("ok.\n"); - HOSTDATA(shpnt)->reconnect = setup[i].reconnect; - HOSTDATA(shpnt)->parity = setup[i].parity; - HOSTDATA(shpnt)->synchronous = setup[i].synchronous; - HOSTDATA(shpnt)->delay = setup[i].delay; - HOSTDATA(shpnt)->ext_trans = setup[i].ext_trans; -#ifdef DEBUG_AHA152X - HOSTDATA(shpnt)->debug = setup[i].debug; -#endif + CLRBITS(DMACNTRL0, SWINT); - HOSTDATA(shpnt)->aborting = 0; - HOSTDATA(shpnt)->abortion_complete = 0; - HOSTDATA(shpnt)->abort_result = 0; - HOSTDATA(shpnt)->commands = 0; - - HOSTDATA(shpnt)->message_len = 0; - - for(j=0; j<8; j++) - HOSTDATA(shpnt)->syncrate[j] = 0; - - SETPORT(SCSIID, setup[i].scsiid << 4); - shpnt->this_id=setup[i].scsiid; - - if(setup[i].reconnect) - shpnt->can_queue=AHA152X_MAXQUEUE; - - /* RESET OUT */ - SETBITS(SCSISEQ, SCSIRSTO); - do_pause(30); - CLRBITS(SCSISEQ, SCSIRSTO); - do_pause(setup[i].delay); - - aha152x_reset_ports(shpnt); - - printk("aha152x%d: vital data: PORTBASE=0x%03lx, IRQ=%d, SCSI ID=%d," - " reconnect=%s, parity=%s, synchronous=%s, delay=%d, extended translation=%s\n", - i, - shpnt->io_port, - shpnt->irq, - shpnt->this_id, - HOSTDATA(shpnt)->reconnect ? "enabled" : "disabled", - HOSTDATA(shpnt)->parity ? "enabled" : "disabled", - HOSTDATA(shpnt)->synchronous ? "enabled" : "disabled", - HOSTDATA(shpnt)->delay, - HOSTDATA(shpnt)->ext_trans ? "enabled" : "disabled"); - - request_region(shpnt->io_port, IO_RANGE, "aha152x"); /* Register */ - - /* not expecting any interrupts */ - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, 0); - - SETBITS(DMACNTRL0, INTEN); - - ok = request_irq(shpnt->irq, aha152x_swintr, SA_INTERRUPT, "aha152x", shpnt); - if(ok<0) { - if(ok == -EINVAL) - printk("aha152x%d: bad IRQ %d.\n", i, shpnt->irq); - else if(ok == -EBUSY) - printk("aha152x%d: IRQ %d already in use.\n", i, shpnt->irq); - else - printk("\naha152x%d: Unexpected error code %d on requesting IRQ %d.\n", i, ok, shpnt->irq); - printk("aha152x: driver needs an IRQ.\n"); - - scsi_unregister(shpnt); - registered_count--; - release_region(shpnt->io_port, IO_RANGE); - shpnt=aha152x_host[shpnt->irq-IRQ_MIN]=0; - continue; - } - - HOSTDATA(shpnt)->swint=0; - - printk("aha152x: trying software interrupt, "); - SETBITS(DMACNTRL0, SWINT); - - the_time=jiffies+100; - while(!HOSTDATA(shpnt)->swint && time_before(jiffies, the_time)) - barrier(); - - free_irq(shpnt->irq,shpnt); - - if(!HOSTDATA(shpnt)->swint) { - if(TESTHI(DMASTAT, INTSTAT)) { - printk("lost.\n"); - } else { - printk("failed.\n"); - } - - printk("aha152x: IRQ %d possibly wrong. Please verify.\n", shpnt->irq); - - scsi_unregister(shpnt); - registered_count--; - release_region(shpnt->io_port, IO_RANGE); - shpnt=aha152x_host[shpnt->irq-IRQ_MIN]=0; - continue; - } - - printk("ok.\n"); - - CLRBITS(DMACNTRL0, SWINT); - - /* clear interrupts */ - SETPORT(SSTAT0, 0x7f); - SETPORT(SSTAT1, 0xef); - - if(request_irq(shpnt->irq,aha152x_intr,SA_INTERRUPT,"aha152x",shpnt)<0) { - printk("aha152x: failed to reassign interrupt.\n"); - } - } - - return (registered_count>0); + /* clear interrupts */ + SETPORT(SSTAT0, 0x7f); + SETPORT(SSTAT1, 0xef); + + if (request_irq(shpnt->irq, aha152x_intr, SA_INTERRUPT, "aha152x", shpnt) < 0) { + printk("aha152x: failed to reassign interrupt.\n"); + } + } + + return (registered_count > 0); } int aha152x_release(struct Scsi_Host *shpnt) { - if (shpnt->irq) - free_irq(shpnt->irq, shpnt); - if (shpnt->io_port) - release_region(shpnt->io_port, IO_RANGE); + if (shpnt->irq) + free_irq(shpnt->irq, shpnt); + if (shpnt->io_port) + release_region(shpnt->io_port, IO_RANGE); - return 0; + return 0; } /* * Queue a command and setup interrupts for a free bus. */ -int aha152x_queue(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) +int aha152x_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) { - struct Scsi_Host *shpnt = SCpnt->host; - unsigned long flags; + struct Scsi_Host *shpnt = SCpnt->host; + unsigned long flags; #if defined(DEBUG_RACE) - enter_driver("queue"); + enter_driver("queue"); #else #if defined(DEBUG_QUEUE) - if(HOSTDATA(shpnt)->debug & debug_queue) - printk("aha152x: queue(), "); + if (HOSTDATA(shpnt)->debug & debug_queue) + printk("aha152x: queue(), "); #endif #endif #if defined(DEBUG_QUEUE) - if(HOSTDATA(shpnt)->debug & debug_queue) { - printk("SCpnt (target = %d lun = %d cmnd = ", - SCpnt->target, SCpnt->lun); - print_command(SCpnt->cmnd); - printk(", cmd_len=%d, pieces = %d size = %u), ", - SCpnt->cmd_len, SCpnt->use_sg, SCpnt->request_bufflen); - disp_ports(shpnt); - } -#endif - - SCpnt->scsi_done = done; - - /* setup scratch area - SCp.ptr : buffer pointer - SCp.this_residual : buffer length - SCp.buffer : next buffer - SCp.buffers_residual : left buffers in list - SCp.phase : current state of the command */ - SCpnt->SCp.phase = not_issued; - if (SCpnt->use_sg) { - SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer; - SCpnt->SCp.ptr = SCpnt->SCp.buffer->address; - SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; - SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; - } else { - SCpnt->SCp.ptr = (char *)SCpnt->request_buffer; - SCpnt->SCp.this_residual = SCpnt->request_bufflen; - SCpnt->SCp.buffer = NULL; - SCpnt->SCp.buffers_residual = 0; - } - - SCpnt->SCp.Status = CHECK_CONDITION; - SCpnt->SCp.Message = 0; - SCpnt->SCp.have_data_in = 0; - SCpnt->SCp.sent_command = 0; - - /* Turn led on, when this is the first command. */ - save_flags(flags); - cli(); - HOSTDATA(shpnt)->commands++; - if(HOSTDATA(shpnt)->commands==1) - SETPORT(PORTA, 1); + if (HOSTDATA(shpnt)->debug & debug_queue) { + printk("SCpnt (target = %d lun = %d cmnd = ", + SCpnt->target, SCpnt->lun); + print_command(SCpnt->cmnd); + printk(", cmd_len=%d, pieces = %d size = %u), ", + SCpnt->cmd_len, SCpnt->use_sg, SCpnt->request_bufflen); + disp_ports(shpnt); + } +#endif + + SCpnt->scsi_done = done; + + /* setup scratch area + SCp.ptr : buffer pointer + SCp.this_residual : buffer length + SCp.buffer : next buffer + SCp.buffers_residual : left buffers in list + SCp.phase : current state of the command */ + SCpnt->SCp.phase = not_issued; + if (SCpnt->use_sg) { + SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer; + SCpnt->SCp.ptr = SCpnt->SCp.buffer->address; + SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; + SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; + } else { + SCpnt->SCp.ptr = (char *) SCpnt->request_buffer; + SCpnt->SCp.this_residual = SCpnt->request_bufflen; + SCpnt->SCp.buffer = NULL; + SCpnt->SCp.buffers_residual = 0; + } + + SCpnt->SCp.Status = CHECK_CONDITION; + SCpnt->SCp.Message = 0; + SCpnt->SCp.have_data_in = 0; + SCpnt->SCp.sent_command = 0; + + /* Turn led on, when this is the first command. */ + save_flags(flags); + cli(); + HOSTDATA(shpnt)->commands++; + if (HOSTDATA(shpnt)->commands == 1) + SETPORT(PORTA, 1); #if defined(DEBUG_QUEUES) - if(HOSTDATA(shpnt)->debug & debug_queues) - printk("i+ (%d), ", HOSTDATA(shpnt)->commands); + if (HOSTDATA(shpnt)->debug & debug_queues) + printk("i+ (%d), ", HOSTDATA(shpnt)->commands); #endif - append_SC(&ISSUE_SC, SCpnt); - - /* Enable bus free interrupt, when we aren't currently on the bus */ - if(!CURRENT_SC) { - SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); - SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); - } - restore_flags(flags); + append_SC(&ISSUE_SC, SCpnt); + + /* Enable bus free interrupt, when we aren't currently on the bus */ + if (!CURRENT_SC) { + SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); + SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); + } + restore_flags(flags); #if defined(DEBUG_RACE) - leave_driver("queue"); + leave_driver("queue"); #endif - return 0; + return 0; } /* * We only support commands in interrupt-driven fashion */ -int aha152x_command(Scsi_Cmnd *SCpnt) +int aha152x_command(Scsi_Cmnd * SCpnt) { - printk("aha152x: interrupt driven driver; use aha152x_queue()\n"); - return -1; + printk("aha152x: interrupt driven driver; use aha152x_queue()\n"); + return -1; } /* * Abort a queued command * (commands that are on the bus can't be aborted easily) */ -int aha152x_abort(Scsi_Cmnd *SCpnt) +int aha152x_abort(Scsi_Cmnd * SCpnt) { - struct Scsi_Host *shpnt = SCpnt->host; - unsigned long flags; - Scsi_Cmnd *ptr, *prev; + struct Scsi_Host *shpnt = SCpnt->host; + unsigned long flags; + Scsi_Cmnd *ptr, *prev; - save_flags(flags); - cli(); + save_flags(flags); + cli(); #if defined(DEBUG_ABORT) - if(HOSTDATA(shpnt)->debug & debug_abort) { - printk("aha152x: abort(), SCpnt=0x%08x, ", (unsigned int) SCpnt); - show_queues(shpnt); - } -#endif - - /* look for command in issue queue */ - for(ptr=ISSUE_SC, prev=NULL; - ptr && ptr!=SCpnt; - prev=ptr, ptr=(Scsi_Cmnd *) ptr->host_scribble) - ; - - if(ptr) { - /* dequeue */ - if(prev) - prev->host_scribble = ptr->host_scribble; - else - ISSUE_SC = (Scsi_Cmnd *) ptr->host_scribble; - - HOSTDATA(shpnt)->commands--; - - restore_flags(flags); - - ptr->host_scribble = NULL; - ptr->result = DID_ABORT << 16; - ptr->scsi_done(ptr); - - return SCSI_ABORT_SUCCESS; - } - - /* if the bus is busy or a command is currently processed, - we can't do anything more */ - if (TESTLO(SSTAT1, BUSFREE) || (CURRENT_SC && CURRENT_SC!=SCpnt)) { - /* fail abortion, if bus is busy */ - - if(!CURRENT_SC) - printk("bus busy w/o current command, "); - - restore_flags(flags); - - return SCSI_ABORT_BUSY; - } - - /* bus is free */ - - if(CURRENT_SC) { - HOSTDATA(shpnt)->commands--; - - /* target entered bus free before COMMAND COMPLETE, nothing to abort */ - restore_flags(flags); - CURRENT_SC->result = DID_ERROR << 16; - CURRENT_SC->scsi_done(CURRENT_SC); - CURRENT_SC = (Scsi_Cmnd *) NULL; - - return SCSI_ABORT_SUCCESS; - } - - /* look for command in disconnected queue */ - for(ptr=DISCONNECTED_SC, prev=NULL; - ptr && ptr!=SCpnt; - prev=ptr, ptr=(Scsi_Cmnd *) ptr->host_scribble) - ; - - if(!ptr) { - /* command wasn't found */ - printk("command not found\n"); - restore_flags(flags); - - return SCSI_ABORT_NOT_RUNNING; - } - - if(!HOSTDATA(shpnt)->aborting) { - /* dequeue */ - if(prev) - prev->host_scribble = ptr->host_scribble; - else - DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble; - - HOSTDATA(shpnt)->commands--; - - /* set command current and initiate selection, - let the interrupt routine take care of the abortion */ - CURRENT_SC = ptr; - ptr->SCp.phase = in_selection|aborted; - SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target); - - ADDMSG(ABORT); - - /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */ - SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0)); - SETPORT(SIMODE1, ENSELTIMO); - - /* Enable SELECTION OUT sequence */ - SETBITS(SCSISEQ, ENSELO | ENAUTOATNO); - - SETBITS(DMACNTRL0, INTEN); - HOSTDATA(shpnt)->abort_result=SCSI_ABORT_SUCCESS; - HOSTDATA(shpnt)->aborting++; - HOSTDATA(shpnt)->abortion_complete=0; - - restore_flags(flags); - - /* sleep until the abortion is complete */ - while(!HOSTDATA(shpnt)->abortion_complete) - barrier(); - HOSTDATA(shpnt)->aborting=0; - - return HOSTDATA(shpnt)->abort_result; - } else { - /* we're already aborting a command */ - restore_flags(flags); + if (HOSTDATA(shpnt)->debug & debug_abort) { + printk("aha152x: abort(), SCpnt=0x%08x, ", (unsigned int) SCpnt); + show_queues(shpnt); + } +#endif + + /* look for command in issue queue */ + for (ptr = ISSUE_SC, prev = NULL; + ptr && ptr != SCpnt; + prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble); + + if (ptr) { + /* dequeue */ + if (prev) + prev->host_scribble = ptr->host_scribble; + else + ISSUE_SC = (Scsi_Cmnd *) ptr->host_scribble; + + HOSTDATA(shpnt)->commands--; + + restore_flags(flags); + + ptr->host_scribble = NULL; + ptr->result = DID_ABORT << 16; + spin_lock_irqsave(&io_request_lock, flags); + ptr->scsi_done(ptr); + spin_unlock_irqrestore(&io_request_lock, flags); + + return SCSI_ABORT_SUCCESS; + } + /* if the bus is busy or a command is currently processed, + we can't do anything more */ + if (TESTLO(SSTAT1, BUSFREE) || (CURRENT_SC && CURRENT_SC != SCpnt)) { + /* fail abortion, if bus is busy */ + + if (!CURRENT_SC) + printk("bus busy w/o current command, "); + + restore_flags(flags); + + return SCSI_ABORT_BUSY; + } + /* bus is free */ + + if (CURRENT_SC) { + HOSTDATA(shpnt)->commands--; + + /* target entered bus free before COMMAND COMPLETE, nothing to abort */ + restore_flags(flags); + spin_lock_irqsave(&io_request_lock, flags); + CURRENT_SC->result = DID_ERROR << 16; + CURRENT_SC->scsi_done(CURRENT_SC); + CURRENT_SC = (Scsi_Cmnd *) NULL; + spin_unlock_irqrestore(&io_request_lock, flags); + + return SCSI_ABORT_SUCCESS; + } + /* look for command in disconnected queue */ + for (ptr = DISCONNECTED_SC, prev = NULL; + ptr && ptr != SCpnt; + prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble); + + if (!ptr) { + /* command wasn't found */ + printk("command not found\n"); + restore_flags(flags); + + return SCSI_ABORT_NOT_RUNNING; + } + if (!HOSTDATA(shpnt)->aborting) { + /* dequeue */ + if (prev) + prev->host_scribble = ptr->host_scribble; + else + DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble; + + HOSTDATA(shpnt)->commands--; + + /* set command current and initiate selection, + let the interrupt routine take care of the abortion */ + CURRENT_SC = ptr; + ptr->SCp.phase = in_selection | aborted; + SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target); + + ADDMSG(ABORT); + + /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */ + SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0)); + SETPORT(SIMODE1, ENSELTIMO); + + /* Enable SELECTION OUT sequence */ + SETBITS(SCSISEQ, ENSELO | ENAUTOATNO); + + SETBITS(DMACNTRL0, INTEN); + HOSTDATA(shpnt)->abort_result = SCSI_ABORT_SUCCESS; + HOSTDATA(shpnt)->aborting++; + HOSTDATA(shpnt)->abortion_complete = 0; + + restore_flags(flags); + + /* sleep until the abortion is complete */ + while (!HOSTDATA(shpnt)->abortion_complete) + barrier(); + HOSTDATA(shpnt)->aborting = 0; + + return HOSTDATA(shpnt)->abort_result; + } else { + /* we're already aborting a command */ + restore_flags(flags); - return SCSI_ABORT_BUSY; - } + return SCSI_ABORT_BUSY; + } } /* @@ -1319,110 +1338,113 @@ */ static void aha152x_reset_ports(struct Scsi_Host *shpnt) { - /* disable interrupts */ - SETPORT(DMACNTRL0, RSTFIFO); + /* disable interrupts */ + SETPORT(DMACNTRL0, RSTFIFO); - SETPORT(SCSISEQ, 0); + SETPORT(SCSISEQ, 0); - SETPORT(SXFRCTL1, 0); - SETPORT(SCSISIG, 0); - SETPORT(SCSIRATE, 0); + SETPORT(SXFRCTL1, 0); + SETPORT(SCSISIG, 0); + SETPORT(SCSIRATE, 0); - /* clear all interrupt conditions */ - SETPORT(SSTAT0, 0x7f); - SETPORT(SSTAT1, 0xef); + /* clear all interrupt conditions */ + SETPORT(SSTAT0, 0x7f); + SETPORT(SSTAT1, 0xef); - SETPORT(SSTAT4, SYNCERR|FWERR|FRERR); + SETPORT(SSTAT4, SYNCERR | FWERR | FRERR); - SETPORT(DMACNTRL0, 0); - SETPORT(DMACNTRL1, 0); + SETPORT(DMACNTRL0, 0); + SETPORT(DMACNTRL1, 0); - SETPORT(BRSTCNTRL, 0xf1); + SETPORT(BRSTCNTRL, 0xf1); - /* clear SCSI fifo and transfer count */ - SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT); - SETPORT(SXFRCTL0, CH1); + /* clear SCSI fifo and transfer count */ + SETPORT(SXFRCTL0, CH1 | CLRCH1 | CLRSTCNT); + SETPORT(SXFRCTL0, CH1); - /* enable interrupts */ - SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); - SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); + /* enable interrupts */ + SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); + SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); } /* * Reset registers, reset a hanging bus and * kill active and disconnected commands for target w/o soft reset */ -int aha152x_reset(Scsi_Cmnd *SCpnt, unsigned int unused) +int aha152x_reset(Scsi_Cmnd * SCpnt, unsigned int unused) { - struct Scsi_Host *shpnt = SCpnt->host; - unsigned long flags; - Scsi_Cmnd *ptr, *prev, *next; + struct Scsi_Host *shpnt = SCpnt->host; + unsigned long flags; + Scsi_Cmnd *ptr, *prev, *next; - aha152x_reset_ports(shpnt); + aha152x_reset_ports(shpnt); - /* Reset, if bus hangs */ - if(TESTLO(SSTAT1, BUSFREE)) { - CLRBITS(DMACNTRL0, INTEN); + /* Reset, if bus hangs */ + if (TESTLO(SSTAT1, BUSFREE)) { + CLRBITS(DMACNTRL0, INTEN); #if defined(DEBUG_RESET) - if(HOSTDATA(shpnt)->debug & debug_reset) { - printk("aha152x: reset(), bus not free: SCSI RESET OUT\n"); - show_queues(shpnt); - } -#endif - - ptr=CURRENT_SC; - if(ptr && !ptr->device->soft_reset) { - ptr->host_scribble = NULL; - ptr->result = DID_RESET << 16; - ptr->scsi_done(CURRENT_SC); - CURRENT_SC=NULL; - } - - save_flags(flags); - cli(); - prev=NULL; ptr=DISCONNECTED_SC; - while(ptr) { - if(!ptr->device->soft_reset) { - if(prev) - prev->host_scribble = ptr->host_scribble; - else - DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble; - - next = (Scsi_Cmnd *) ptr->host_scribble; - - ptr->host_scribble = NULL; - ptr->result = DID_RESET << 16; - ptr->scsi_done(ptr); - - ptr = next; - } else { - prev=ptr; - ptr = (Scsi_Cmnd *) ptr->host_scribble; - } - } - restore_flags(flags); + if (HOSTDATA(shpnt)->debug & debug_reset) { + printk("aha152x: reset(), bus not free: SCSI RESET OUT\n"); + show_queues(shpnt); + } +#endif + + ptr = CURRENT_SC; + if (ptr && !ptr->device->soft_reset) { + ptr->host_scribble = NULL; + ptr->result = DID_RESET << 16; + spin_lock_irqsave(&io_request_lock, flags); + ptr->scsi_done(CURRENT_SC); + spin_unlock_irqrestore(&io_request_lock, flags); + CURRENT_SC = NULL; + } + save_flags(flags); + cli(); + prev = NULL; + ptr = DISCONNECTED_SC; + while (ptr) { + if (!ptr->device->soft_reset) { + if (prev) + prev->host_scribble = ptr->host_scribble; + else + DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble; + + next = (Scsi_Cmnd *) ptr->host_scribble; + + ptr->host_scribble = NULL; + ptr->result = DID_RESET << 16; + spin_lock_irqsave(&io_request_lock, flags); + ptr->scsi_done(ptr); + spin_unlock_irqrestore(&io_request_lock, flags); + + ptr = next; + } else { + prev = ptr; + ptr = (Scsi_Cmnd *) ptr->host_scribble; + } + } + restore_flags(flags); #if defined(DEBUG_RESET) - if(HOSTDATA(shpnt)->debug & debug_reset) { - printk("commands on targets w/ soft-resets:\n"); - show_queues(shpnt); - } + if (HOSTDATA(shpnt)->debug & debug_reset) { + printk("commands on targets w/ soft-resets:\n"); + show_queues(shpnt); + } #endif - /* RESET OUT */ - SETPORT(SCSISEQ, SCSIRSTO); - do_pause(30); - SETPORT(SCSISEQ, 0); - do_pause(DELAY); - - SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); - SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); + /* RESET OUT */ + SETPORT(SCSISEQ, SCSIRSTO); + do_pause(30); + SETPORT(SCSISEQ, 0); + do_pause(DELAY); - SETPORT(DMACNTRL0, INTEN); - } + SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); + SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); - return SCSI_RESET_SUCCESS; + SETPORT(DMACNTRL0, INTEN); + } + return SCSI_RESET_SUCCESS; } /* @@ -1430,59 +1452,58 @@ */ int aha152x_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array) { - struct Scsi_Host *shpnt=disk->device->host; + struct Scsi_Host *shpnt = disk->device->host; #if defined(DEBUG_BIOSPARAM) - if(HOSTDATA(shpnt)->debug & debug_biosparam) - printk("aha152x_biosparam: dev=%s, size=%d, ", - kdevname(dev), disk->capacity); -#endif - - /* try default translation */ - info_array[0]=64; - info_array[1]=32; - info_array[2]=disk->capacity / (64 * 32); - - /* for disks >1GB do some guessing */ - if(info_array[2]>=1024) { - int info[3]; - - /* try to figure out the geometry from the partition table */ - if(scsicam_bios_param(disk, dev, info)<0 || - !((info[0]==64 && info[1]==32) || (info[0]==255 && info[1]==63))) { - if(EXT_TRANS) { - printk("aha152x: unable to verify geometry for disk with >1GB.\n" - " using extended translation.\n"); - info_array[0] = 255; - info_array[1] = 63; - info_array[2] = disk->capacity / (255 * 63); - } else { - printk("aha152x: unable to verify geometry for disk with >1GB.\n" - " Using default translation. Please verify yourself.\n" - " Perhaps you need to enable extended translation in the driver.\n" - " See /usr/src/linux/drivers/scsi/aha152x.c for details.\n"); - } - } else { - info_array[0]=info[0]; - info_array[1]=info[1]; - info_array[2]=info[2]; - - if(info[0]==255 && !EXT_TRANS) { - printk("aha152x: current partition table is using extended translation.\n" - " using it also, although it's not explicty enabled.\n"); - } - } - } - + if (HOSTDATA(shpnt)->debug & debug_biosparam) + printk("aha152x_biosparam: dev=%s, size=%d, ", + kdevname(dev), disk->capacity); +#endif + + /* try default translation */ + info_array[0] = 64; + info_array[1] = 32; + info_array[2] = disk->capacity / (64 * 32); + + /* for disks >1GB do some guessing */ + if (info_array[2] >= 1024) { + int info[3]; + + /* try to figure out the geometry from the partition table */ + if (scsicam_bios_param(disk, dev, info) < 0 || + !((info[0] == 64 && info[1] == 32) || (info[0] == 255 && info[1] == 63))) { + if (EXT_TRANS) { + printk("aha152x: unable to verify geometry for disk with >1GB.\n" + " using extended translation.\n"); + info_array[0] = 255; + info_array[1] = 63; + info_array[2] = disk->capacity / (255 * 63); + } else { + printk("aha152x: unable to verify geometry for disk with >1GB.\n" + " Using default translation. Please verify yourself.\n" + " Perhaps you need to enable extended translation in the driver.\n" + " See /usr/src/linux/drivers/scsi/aha152x.c for details.\n"); + } + } else { + info_array[0] = info[0]; + info_array[1] = info[1]; + info_array[2] = info[2]; + + if (info[0] == 255 && !EXT_TRANS) { + printk("aha152x: current partition table is using extended translation.\n" + " using it also, although it's not explicty enabled.\n"); + } + } + } #if defined(DEBUG_BIOSPARAM) - if(HOSTDATA(shpnt)->debug & debug_biosparam) { - printk("bios geometry: head=%d, sec=%d, cyl=%d\n", - info_array[0], info_array[1], info_array[2]); - printk("WARNING: check, if the bios geometry is correct.\n"); - } + if (HOSTDATA(shpnt)->debug & debug_biosparam) { + printk("bios geometry: head=%d, sec=%d, cyl=%d\n", + info_array[0], info_array[1], info_array[2]); + printk("WARNING: check, if the bios geometry is correct.\n"); + } #endif - return 0; + return 0; } /* @@ -1490,71 +1511,73 @@ */ void aha152x_done(struct Scsi_Host *shpnt, int error) { - unsigned long flags; - Scsi_Cmnd *done_SC; + unsigned long flags; + Scsi_Cmnd *done_SC; #if defined(DEBUG_DONE) - if(HOSTDATA(shpnt)->debug & debug_done) { - printk("\naha152x: done(), "); - disp_ports(shpnt); - } + if (HOSTDATA(shpnt)->debug & debug_done) { + printk("\naha152x: done(), "); + disp_ports(shpnt); + } #endif - if(CURRENT_SC) { + if (CURRENT_SC) { #if defined(DEBUG_DONE) - if(HOSTDATA(shpnt)->debug & debug_done) - printk("done(%x), ", error); + if (HOSTDATA(shpnt)->debug & debug_done) + printk("done(%x), ", error); #endif - save_flags(flags); - cli(); + save_flags(flags); + cli(); - done_SC = CURRENT_SC; - CURRENT_SC = NULL; + done_SC = CURRENT_SC; + CURRENT_SC = NULL; - /* turn led off, when no commands are in the driver */ - HOSTDATA(shpnt)->commands--; - if(!HOSTDATA(shpnt)->commands) - SETPORT(PORTA, 0); /* turn led off */ + /* turn led off, when no commands are in the driver */ + HOSTDATA(shpnt)->commands--; + if (!HOSTDATA(shpnt)->commands) + SETPORT(PORTA, 0); /* turn led off */ #if defined(DEBUG_QUEUES) - if(HOSTDATA(shpnt)->debug & debug_queues) - printk("ok (%d), ", HOSTDATA(shpnt)->commands); + if (HOSTDATA(shpnt)->debug & debug_queues) + printk("ok (%d), ", HOSTDATA(shpnt)->commands); #endif - restore_flags(flags); + restore_flags(flags); - SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); - SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); + SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); + SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); #if 0 /* Why poll for the BUS FREE phase, when we have setup the interrupt!? */ #if defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & debug_phases) - printk("BUS FREE loop, "); + if (HOSTDATA(shpnt)->debug & debug_phases) + printk("BUS FREE loop, "); #endif - while(TESTLO(SSTAT1, BUSFREE)) - barrier(); + while (TESTLO(SSTAT1, BUSFREE)) + barrier(); #if defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & debug_phases) - printk("BUS FREE\n"); + if (HOSTDATA(shpnt)->debug & debug_phases) + printk("BUS FREE\n"); #endif #endif - done_SC->result = error; - if(done_SC->scsi_done) { + done_SC->result = error; + if (done_SC->scsi_done) { #if defined(DEBUG_DONE) - if(HOSTDATA(shpnt)->debug & debug_done) - printk("calling scsi_done, "); + if (HOSTDATA(shpnt)->debug & debug_done) + printk("calling scsi_done, "); #endif - done_SC->scsi_done(done_SC); + spin_lock_irqsave(&io_request_lock, flags); + done_SC->scsi_done(done_SC); + spin_unlock_irqrestore(&io_request_lock, flags); #if defined(DEBUG_DONE) - if(HOSTDATA(shpnt)->debug & debug_done) - printk("done returned, "); + if (HOSTDATA(shpnt)->debug & debug_done) + printk("done returned, "); #endif - } else - panic("aha152x: current_SC->scsi_done() == NULL"); - } else - aha152x_panic(shpnt, "done() called outside of command"); + } else + panic("aha152x: current_SC->scsi_done() == NULL"); + } else + aha152x_panic(shpnt, "done() called outside of command"); } @@ -1563,41 +1586,39 @@ static struct tq_struct aha152x_tq; /* - * Run service completions on the card with interrupts enabled. + * Run service completions on the card with interrupts enabled. */ - + static void aha152x_run(void) { int i; - for(i=0;iservice) - { - HOSTDATA(shpnt)->service=0; + for (i = 0; i < IRQS; i++) { + struct Scsi_Host *shpnt = aha152x_host[i]; + if (shpnt && HOSTDATA(shpnt)->service) { + HOSTDATA(shpnt)->service = 0; aha152x_complete(shpnt); } } } /* - * Interrupts handler (main routine of the driver) + * Interrupts handler (main routine of the driver) */ -static void aha152x_intr(int irqno, void *dev_id, struct pt_regs * regs) +static void aha152x_intr(int irqno, void *dev_id, struct pt_regs *regs) { - struct Scsi_Host *shpnt = aha152x_host[irqno-IRQ_MIN]; + struct Scsi_Host *shpnt = aha152x_host[irqno - IRQ_MIN]; #if defined(DEBUG_RACE) enter_driver("intr"); #else #if defined(DEBUG_INTR) - if(HOSTDATA(shpnt)->debug & debug_intr) + if (HOSTDATA(shpnt)->debug & debug_intr) printk("\naha152x: intr(), "); #endif #endif - if(!shpnt) + if (!shpnt) panic("aha152x: catched interrupt for unknown controller.\n"); /* no more interrupts from the controller, while we're busy. @@ -1606,9 +1627,9 @@ CLRBITS(DMACNTRL0, INTEN); /* Poke the BH handler */ - - HOSTDATA(shpnt)->service=1; - aha152x_tq.routine = (void *)aha152x_run; + + HOSTDATA(shpnt)->service = 1; + aha152x_tq.routine = (void *) aha152x_run; queue_task(&aha152x_tq, &tq_immediate); mark_bh(IMMEDIATE_BH); } @@ -1616,1020 +1637,1001 @@ static void aha152x_complete(struct Scsi_Host *shpnt) { unsigned int flags; - int done=0, phase; + int done = 0, phase; /* disconnected target is trying to reconnect. Only possible, if we have disconnected nexuses and nothing is occupying the bus. */ - - if(TESTHI(SSTAT0, SELDI) && - DISCONNECTED_SC && - (!CURRENT_SC || (CURRENT_SC->SCp.phase & in_selection)) ) { - int identify_msg, target, i; - - /* Avoid conflicts when a target reconnects - while we are trying to connect to another. */ - if(CURRENT_SC) { + + if (TESTHI(SSTAT0, SELDI) && + DISCONNECTED_SC && + (!CURRENT_SC || (CURRENT_SC->SCp.phase & in_selection))) { + int identify_msg, target, i; + + /* Avoid conflicts when a target reconnects + while we are trying to connect to another. */ + if (CURRENT_SC) { #if defined(DEBUG_QUEUES) - if(HOSTDATA(shpnt)->debug & debug_queues) - printk("i+, "); + if (HOSTDATA(shpnt)->debug & debug_queues) + printk("i+, "); #endif - save_flags(flags); - cli(); - append_SC(&ISSUE_SC, CURRENT_SC); - CURRENT_SC=NULL; - restore_flags(flags); - } - - /* disable sequences */ - SETPORT(SCSISEQ, 0); - SETPORT(SSTAT0, CLRSELDI); - SETPORT(SSTAT1, CLRBUSFREE); + save_flags(flags); + cli(); + append_SC(&ISSUE_SC, CURRENT_SC); + CURRENT_SC = NULL; + restore_flags(flags); + } + /* disable sequences */ + SETPORT(SCSISEQ, 0); + SETPORT(SSTAT0, CLRSELDI); + SETPORT(SSTAT1, CLRBUSFREE); #if defined(DEBUG_QUEUES) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_queues|debug_phases)) - printk("reselected, "); + if (HOSTDATA(shpnt)->debug & (debug_queues | debug_phases)) + printk("reselected, "); #endif - i = GETPORT(SELID) & ~(1 << shpnt->this_id); - target=0; + i = GETPORT(SELID) & ~(1 << shpnt->this_id); + target = 0; - if(i==0) - aha152x_panic(shpnt, "reconnecting target unknown"); + if (i == 0) + aha152x_panic(shpnt, "reconnecting target unknown"); - for(; (i & 1)==0; target++, i>>=1) - ; + for (; (i & 1) == 0; target++, i >>= 1); #if defined(DEBUG_QUEUES) - if(HOSTDATA(shpnt)->debug & debug_queues) - printk("SELID=%02x, target=%d, ", GETPORT(SELID), target); + if (HOSTDATA(shpnt)->debug & debug_queues) + printk("SELID=%02x, target=%d, ", GETPORT(SELID), target); #endif - SETPORT(SCSIID, (shpnt->this_id << OID_) | target); - SETPORT(SCSISEQ, ENRESELI); - - if(TESTLO(SSTAT0, SELDI)) - aha152x_panic(shpnt, "RESELI failed"); - - SETPORT(SCSIRATE, HOSTDATA(shpnt)->syncrate[target]&0x7f); + SETPORT(SCSIID, (shpnt->this_id << OID_) | target); + SETPORT(SCSISEQ, ENRESELI); - SETPORT(SCSISIG, P_MSGI); + if (TESTLO(SSTAT0, SELDI)) + aha152x_panic(shpnt, "RESELI failed"); - /* Get identify message */ - if((i=getphase(shpnt))!=P_MSGI) { - printk("target doesn't enter MSGI to identify (phase=%02x)\n", i); - aha152x_panic(shpnt, "unknown lun"); - } - SETPORT(SCSISEQ, 0); + SETPORT(SCSIRATE, HOSTDATA(shpnt)->syncrate[target] & 0x7f); - SETPORT(SXFRCTL0, CH1); + SETPORT(SCSISIG, P_MSGI); - identify_msg = GETPORT(SCSIBUS); + /* Get identify message */ + if ((i = getphase(shpnt)) != P_MSGI) { + printk("target doesn't enter MSGI to identify (phase=%02x)\n", i); + aha152x_panic(shpnt, "unknown lun"); + } + SETPORT(SCSISEQ, 0); - if(!(identify_msg & IDENTIFY_BASE)) { - printk("target=%d, inbound message (%02x) != IDENTIFY\n", - target, identify_msg); - aha152x_panic(shpnt, "unknown lun"); - } + SETPORT(SXFRCTL0, CH1); + identify_msg = GETPORT(SCSIBUS); + if (!(identify_msg & IDENTIFY_BASE)) { + printk("target=%d, inbound message (%02x) != IDENTIFY\n", + target, identify_msg); + aha152x_panic(shpnt, "unknown lun"); + } #if defined(DEBUG_QUEUES) - if(HOSTDATA(shpnt)->debug & debug_queues) - printk("identify=%02x, lun=%d, ", identify_msg, identify_msg & 0x3f); + if (HOSTDATA(shpnt)->debug & debug_queues) + printk("identify=%02x, lun=%d, ", identify_msg, identify_msg & 0x3f); #endif - save_flags(flags); - cli(); + save_flags(flags); + cli(); #if defined(DEBUG_QUEUES) - if(HOSTDATA(shpnt)->debug & debug_queues) - printk("d-, "); + if (HOSTDATA(shpnt)->debug & debug_queues) + printk("d-, "); #endif - CURRENT_SC = remove_SC(&DISCONNECTED_SC, target, identify_msg & 0x3f); + CURRENT_SC = remove_SC(&DISCONNECTED_SC, target, identify_msg & 0x3f); + + if (!CURRENT_SC) { + printk("lun=%d, ", identify_msg & 0x3f); + aha152x_panic(shpnt, "no disconnected command for that lun"); + } + CURRENT_SC->SCp.phase &= ~disconnected; + restore_flags(flags); - if(!CURRENT_SC) { - printk("lun=%d, ", identify_msg & 0x3f); - aha152x_panic(shpnt, "no disconnected command for that lun"); - } - - CURRENT_SC->SCp.phase &= ~disconnected; - restore_flags(flags); - - make_acklow(shpnt); - if(getphase(shpnt)!=P_MSGI) { - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE); + make_acklow(shpnt); + if (getphase(shpnt) != P_MSGI) { + SETPORT(SIMODE0, 0); + SETPORT(SIMODE1, ENPHASEMIS | ENBUSFREE); #if defined(DEBUG_RACE) - leave_driver("(reselected) intr"); + leave_driver("(reselected) intr"); #endif - SETBITS(DMACNTRL0, INTEN); - return; - } - } - - /* Check, if we aren't busy with a command */ - if(!CURRENT_SC) { - /* bus is free to issue a queued command */ - if(TESTHI(SSTAT1, BUSFREE) && ISSUE_SC) { - save_flags(flags); - cli(); + SETBITS(DMACNTRL0, INTEN); + return; + } + } + /* Check, if we aren't busy with a command */ + if (!CURRENT_SC) { + /* bus is free to issue a queued command */ + if (TESTHI(SSTAT1, BUSFREE) && ISSUE_SC) { + save_flags(flags); + cli(); #if defined(DEBUG_QUEUES) - if(HOSTDATA(shpnt)->debug & debug_queues) - printk("i-, "); + if (HOSTDATA(shpnt)->debug & debug_queues) + printk("i-, "); #endif - CURRENT_SC = remove_first_SC(&ISSUE_SC); - restore_flags(flags); + CURRENT_SC = remove_first_SC(&ISSUE_SC); + restore_flags(flags); #if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_intr|debug_selection|debug_phases)) - printk("issuing command, "); + if (HOSTDATA(shpnt)->debug & (debug_intr | debug_selection | debug_phases)) + printk("issuing command, "); #endif - CURRENT_SC->SCp.phase = in_selection; + CURRENT_SC->SCp.phase = in_selection; #if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_intr|debug_selection|debug_phases)) - printk("selecting %d, ", CURRENT_SC->target); + if (HOSTDATA(shpnt)->debug & (debug_intr | debug_selection | debug_phases)) + printk("selecting %d, ", CURRENT_SC->target); #endif - SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target); + SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target); - /* Enable interrupts for SELECTION OUT DONE and SELECTION OUT INITIATED */ - SETPORT(SXFRCTL1, HOSTDATA(shpnt)->parity ? (ENSPCHK|ENSTIMER) : ENSTIMER); + /* Enable interrupts for SELECTION OUT DONE and SELECTION OUT INITIATED */ + SETPORT(SXFRCTL1, HOSTDATA(shpnt)->parity ? (ENSPCHK | ENSTIMER) : ENSTIMER); - /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */ - SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0)); - SETPORT(SIMODE1, ENSELTIMO); - - /* Enable SELECTION OUT sequence */ - SETBITS(SCSISEQ, ENSELO | ENAUTOATNO); - - } else { - /* No command we are busy with and no new to issue */ - printk("aha152x: ignoring spurious interrupt, nothing to do\n"); - if(TESTHI(DMACNTRL0, SWINT)) { - printk("aha152x: SWINT is set! Why?\n"); - CLRBITS(DMACNTRL0, SWINT); - } - show_queues(shpnt); - } + /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */ + SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0)); + SETPORT(SIMODE1, ENSELTIMO); + + /* Enable SELECTION OUT sequence */ + SETBITS(SCSISEQ, ENSELO | ENAUTOATNO); + + } else { + /* No command we are busy with and no new to issue */ + printk("aha152x: ignoring spurious interrupt, nothing to do\n"); + if (TESTHI(DMACNTRL0, SWINT)) { + printk("aha152x: SWINT is set! Why?\n"); + CLRBITS(DMACNTRL0, SWINT); + } + show_queues(shpnt); + } #if defined(DEBUG_RACE) - leave_driver("(selecting) intr"); + leave_driver("(selecting) intr"); #endif - SETBITS(DMACNTRL0, INTEN); - return; - } - - /* the bus is busy with something */ + SETBITS(DMACNTRL0, INTEN); + return; + } + /* the bus is busy with something */ #if defined(DEBUG_INTR) - if(HOSTDATA(shpnt)->debug & debug_intr) - disp_ports(shpnt); + if (HOSTDATA(shpnt)->debug & debug_intr) + disp_ports(shpnt); #endif - /* we are waiting for the result of a selection attempt */ - if(CURRENT_SC->SCp.phase & in_selection) { - if(TESTLO(SSTAT1, SELTO)) { - /* no timeout */ - if(TESTHI(SSTAT0, SELDO)) { - /* clear BUS FREE interrupt */ - SETPORT(SSTAT1, CLRBUSFREE); - - /* Disable SELECTION OUT sequence */ - CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO); - - /* Disable SELECTION OUT DONE interrupt */ - CLRBITS(SIMODE0, ENSELDO); - CLRBITS(SIMODE1, ENSELTIMO); + /* we are waiting for the result of a selection attempt */ + if (CURRENT_SC->SCp.phase & in_selection) { + if (TESTLO(SSTAT1, SELTO)) { + /* no timeout */ + if (TESTHI(SSTAT0, SELDO)) { + /* clear BUS FREE interrupt */ + SETPORT(SSTAT1, CLRBUSFREE); + + /* Disable SELECTION OUT sequence */ + CLRBITS(SCSISEQ, ENSELO | ENAUTOATNO); + + /* Disable SELECTION OUT DONE interrupt */ + CLRBITS(SIMODE0, ENSELDO); + CLRBITS(SIMODE1, ENSELTIMO); - if(TESTLO(SSTAT0, SELDO)) { - printk("aha152x: passing bus free condition\n"); + if (TESTLO(SSTAT0, SELDO)) { + printk("aha152x: passing bus free condition\n"); #if defined(DEBUG_RACE) - leave_driver("(passing bus free) intr"); + leave_driver("(passing bus free) intr"); #endif - SETBITS(DMACNTRL0, INTEN); + SETBITS(DMACNTRL0, INTEN); - if(CURRENT_SC->SCp.phase & aborted) { - HOSTDATA(shpnt)->abort_result=SCSI_ABORT_ERROR; - HOSTDATA(shpnt)->abortion_complete++; - } + if (CURRENT_SC->SCp.phase & aborted) { + HOSTDATA(shpnt)->abort_result = SCSI_ABORT_ERROR; + HOSTDATA(shpnt)->abortion_complete++; + } + aha152x_done(shpnt, DID_NO_CONNECT << 16); - aha152x_done(shpnt, DID_NO_CONNECT << 16); - - return; - } + return; + } #if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_selection|debug_phases)) - printk("SELDO (SELID=%x), ", GETPORT(SELID)); + if (HOSTDATA(shpnt)->debug & (debug_selection | debug_phases)) + printk("SELDO (SELID=%x), ", GETPORT(SELID)); #endif - /* selection was done */ - SETPORT(SSTAT0, CLRSELDO); + /* selection was done */ + SETPORT(SSTAT0, CLRSELDO); #if defined(DEBUG_ABORT) - if((HOSTDATA(shpnt)->debug & debug_abort) && (CURRENT_SC->SCp.phase & aborted)) - printk("(ABORT) target selected, "); + if ((HOSTDATA(shpnt)->debug & debug_abort) && (CURRENT_SC->SCp.phase & aborted)) + printk("(ABORT) target selected, "); #endif - CURRENT_SC->SCp.phase &= ~in_selection; - CURRENT_SC->SCp.phase |= in_other; - - ADDMSG(IDENTIFY(HOSTDATA(shpnt)->reconnect,CURRENT_SC->lun)); + CURRENT_SC->SCp.phase &= ~in_selection; + CURRENT_SC->SCp.phase |= in_other; - if(!(SYNCRATE&0x80) && HOSTDATA(shpnt)->synchronous) { - ADDMSG(EXTENDED_MESSAGE); - ADDMSG(3); - ADDMSG(EXTENDED_SDTR); - ADDMSG(50); - ADDMSG(8); + ADDMSG(IDENTIFY(HOSTDATA(shpnt)->reconnect, CURRENT_SC->lun)); - printk("outbound SDTR: "); - print_msg(&MSG(MSGLEN-5)); + if (!(SYNCRATE & 0x80) && HOSTDATA(shpnt)->synchronous) { + ADDMSG(EXTENDED_MESSAGE); + ADDMSG(3); + ADDMSG(EXTENDED_SDTR); + ADDMSG(50); + ADDMSG(8); - SYNCRATE=0x80; - CURRENT_SC->SCp.phase |= in_sync; - } + printk("outbound SDTR: "); + print_msg(&MSG(MSGLEN - 5)); + SYNCRATE = 0x80; + CURRENT_SC->SCp.phase |= in_sync; + } #if defined(DEBUG_RACE) - leave_driver("(SELDO) intr"); + leave_driver("(SELDO) intr"); #endif - SETPORT(SCSIRATE, SYNCRATE&0x7f); + SETPORT(SCSIRATE, SYNCRATE & 0x7f); - SETPORT(SCSISIG, P_MSGO); + SETPORT(SCSISIG, P_MSGO); - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, ENREQINIT|ENBUSFREE); - SETBITS(DMACNTRL0, INTEN); + SETPORT(SIMODE0, 0); + SETPORT(SIMODE1, ENREQINIT | ENBUSFREE); + SETBITS(DMACNTRL0, INTEN); - return; - } else - aha152x_panic(shpnt, "neither timeout nor selection\007"); - } else { + return; + } else + aha152x_panic(shpnt, "neither timeout nor selection\007"); + } else { #if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_selection|debug_phases)) - printk("SELTO, "); + if (HOSTDATA(shpnt)->debug & (debug_selection | debug_phases)) + printk("SELTO, "); #endif - /* end selection attempt */ - CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO); + /* end selection attempt */ + CLRBITS(SCSISEQ, ENSELO | ENAUTOATNO); - /* timeout */ - SETPORT(SSTAT1, CLRSELTIMO); + /* timeout */ + SETPORT(SSTAT1, CLRSELTIMO); - SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); - SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); - SETBITS(DMACNTRL0, INTEN); + SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); + SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); + SETBITS(DMACNTRL0, INTEN); #if defined(DEBUG_RACE) - leave_driver("(SELTO) intr"); + leave_driver("(SELTO) intr"); #endif - if(CURRENT_SC->SCp.phase & aborted) { + if (CURRENT_SC->SCp.phase & aborted) { #if defined(DEBUG_ABORT) - if(HOSTDATA(shpnt)->debug & debug_abort) - printk("(ABORT) selection timeout, "); + if (HOSTDATA(shpnt)->debug & debug_abort) + printk("(ABORT) selection timeout, "); #endif - HOSTDATA(shpnt)->abort_result=SCSI_ABORT_ERROR; - HOSTDATA(shpnt)->abortion_complete++; - } - - if(TESTLO(SSTAT0, SELINGO)) - /* ARBITRATION not won */ - aha152x_done(shpnt, DID_BUS_BUSY << 16); - else - /* ARBITRATION won, but SELECTION failed */ - aha152x_done(shpnt, DID_NO_CONNECT << 16); - - return; - } - } - - /* enable interrupt, when target leaves current phase */ - phase = getphase(shpnt); - if(!(phase & ~P_MASK)) /* "real" phase */ - SETPORT(SCSISIG, phase); - SETPORT(SSTAT1, CLRPHASECHG); - CURRENT_SC->SCp.phase = - (CURRENT_SC->SCp.phase & ~((P_MASK|1)<<16)) | (phase << 16); - - /* information transfer phase */ - switch(phase) { - case P_MSGO: /* MESSAGE OUT */ - { - int i, identify=0, abort=0; + HOSTDATA(shpnt)->abort_result = SCSI_ABORT_ERROR; + HOSTDATA(shpnt)->abortion_complete++; + } + if (TESTLO(SSTAT0, SELINGO)) + /* ARBITRATION not won */ + aha152x_done(shpnt, DID_BUS_BUSY << 16); + else + /* ARBITRATION won, but SELECTION failed */ + aha152x_done(shpnt, DID_NO_CONNECT << 16); + + return; + } + } + /* enable interrupt, when target leaves current phase */ + phase = getphase(shpnt); + if (!(phase & ~P_MASK)) /* "real" phase */ + SETPORT(SCSISIG, phase); + SETPORT(SSTAT1, CLRPHASECHG); + CURRENT_SC->SCp.phase = + (CURRENT_SC->SCp.phase & ~((P_MASK | 1) << 16)) | (phase << 16); + + /* information transfer phase */ + switch (phase) { + case P_MSGO: /* MESSAGE OUT */ + { + int i, identify = 0, abort = 0; #if defined(DEBUG_INTR) || defined(DEBUG_MSGO) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_intr|debug_msgo|debug_phases)) - printk("MESSAGE OUT, "); + if (HOSTDATA(shpnt)->debug & (debug_intr | debug_msgo | debug_phases)) + printk("MESSAGE OUT, "); #endif - if(MSGLEN==0) { - ADDMSG(MESSAGE_REJECT); + if (MSGLEN == 0) { + ADDMSG(MESSAGE_REJECT); #if defined(DEBUG_MSGO) - if(HOSTDATA(shpnt)->debug & debug_msgo) - printk("unexpected MESSAGE OUT phase; rejecting, "); + if (HOSTDATA(shpnt)->debug & debug_msgo) + printk("unexpected MESSAGE OUT phase; rejecting, "); #endif - } - - CLRBITS(SXFRCTL0, ENDMA); - - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, ENPHASEMIS|ENREQINIT|ENBUSFREE); - - /* wait for data latch to become ready or a phase change */ - while(TESTLO(DMASTAT, INTSTAT)) - barrier(); - + } + CLRBITS(SXFRCTL0, ENDMA); + + SETPORT(SIMODE0, 0); + SETPORT(SIMODE1, ENPHASEMIS | ENREQINIT | ENBUSFREE); + + /* wait for data latch to become ready or a phase change */ + while (TESTLO(DMASTAT, INTSTAT)) + barrier(); + #if defined(DEBUG_MSGO) - if(HOSTDATA(shpnt)->debug & debug_msgo) { - int i; - - printk("messages ("); - for(i=0; idebug & debug_msgo) { + int i; + + printk("messages ("); + for (i = 0; i < MSGLEN; i += print_msg(&MSG(i)), printk(" ")); + printk("), "); + } #endif - - for(i=0; idebug & debug_msgo) - printk("%x ", MSG(i)); + if (HOSTDATA(shpnt)->debug & debug_msgo) + printk("%x ", MSG(i)); #endif - if(i==MSGLEN-1) { - /* Leave MESSAGE OUT after transfer */ - SETPORT(SSTAT1, CLRATNO); - } - - SETPORT(SCSIDAT, MSG(i)); + if (i == MSGLEN - 1) { + /* Leave MESSAGE OUT after transfer */ + SETPORT(SSTAT1, CLRATNO); + } + SETPORT(SCSIDAT, MSG(i)); - make_acklow(shpnt); - getphase(shpnt); + make_acklow(shpnt); + getphase(shpnt); - if(MSG(i)==IDENTIFY(HOSTDATA(shpnt)->reconnect,CURRENT_SC->lun)) - identify++; + if (MSG(i) == IDENTIFY(HOSTDATA(shpnt)->reconnect, CURRENT_SC->lun)) + identify++; - if(MSG(i)==ABORT) - abort++; + if (MSG(i) == ABORT) + abort++; - } + } - MSGLEN=0; + MSGLEN = 0; - if(identify) - CURRENT_SC->SCp.phase |= sent_ident; + if (identify) + CURRENT_SC->SCp.phase |= sent_ident; - if(abort) { - /* revive abort(); abort() enables interrupts */ - HOSTDATA(shpnt)->abort_result=SCSI_ABORT_SUCCESS; - HOSTDATA(shpnt)->abortion_complete++; + if (abort) { + /* revive abort(); abort() enables interrupts */ + HOSTDATA(shpnt)->abort_result = SCSI_ABORT_SUCCESS; + HOSTDATA(shpnt)->abortion_complete++; - CURRENT_SC->SCp.phase &= ~(P_MASK<<16); + CURRENT_SC->SCp.phase &= ~(P_MASK << 16); - /* exit */ - SETBITS(DMACNTRL0, INTEN); + /* exit */ + SETBITS(DMACNTRL0, INTEN); #if defined(DEBUG_RACE) - leave_driver("(ABORT) intr"); + leave_driver("(ABORT) intr"); #endif - aha152x_done(shpnt, DID_ABORT<<16); + aha152x_done(shpnt, DID_ABORT << 16); - return; - } - } - break; + return; + } + } + break; - case P_CMD: /* COMMAND phase */ + case P_CMD: /* COMMAND phase */ #if defined(DEBUG_INTR) || defined(DEBUG_CMD) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_intr|debug_cmd|debug_phases)) - printk("COMMAND, "); + if (HOSTDATA(shpnt)->debug & (debug_intr | debug_cmd | debug_phases)) + printk("COMMAND, "); #endif - if(!(CURRENT_SC->SCp.sent_command)) { - int i; + if (!(CURRENT_SC->SCp.sent_command)) { + int i; + + CLRBITS(SXFRCTL0, ENDMA); + + SETPORT(SIMODE0, 0); + SETPORT(SIMODE1, ENPHASEMIS | ENREQINIT | ENBUSFREE); + + /* wait for data latch to become ready or a phase change */ + while (TESTLO(DMASTAT, INTSTAT)) + barrier(); - CLRBITS(SXFRCTL0, ENDMA); + for (i = 0; i < CURRENT_SC->cmd_len && TESTLO(SSTAT1, PHASEMIS); i++) { + SETPORT(SCSIDAT, CURRENT_SC->cmnd[i]); + + make_acklow(shpnt); + getphase(shpnt); + } + + if (i < CURRENT_SC->cmd_len && TESTHI(SSTAT1, PHASEMIS)) + aha152x_panic(shpnt, "target left COMMAND"); + + CURRENT_SC->SCp.sent_command++; + } else + aha152x_panic(shpnt, "Nothing to send while in COMMAND"); + break; + + case P_MSGI: /* MESSAGE IN phase */ + { + int start_sync = 0; - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, ENPHASEMIS|ENREQINIT|ENBUSFREE); - - /* wait for data latch to become ready or a phase change */ - while(TESTLO(DMASTAT, INTSTAT)) - barrier(); - - for(i=0; icmd_len && TESTLO(SSTAT1, PHASEMIS); i++) { - SETPORT(SCSIDAT, CURRENT_SC->cmnd[i]); - - make_acklow(shpnt); - getphase(shpnt); - } - - if(icmd_len && TESTHI(SSTAT1, PHASEMIS)) - aha152x_panic(shpnt, "target left COMMAND"); - - CURRENT_SC->SCp.sent_command++; - } else - aha152x_panic(shpnt, "Nothing to send while in COMMAND"); - break; - - case P_MSGI: /* MESSAGE IN phase */ - { - int start_sync=0; - #if defined(DEBUG_INTR) || defined(DEBUG_MSGI) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_intr|debug_msgi|debug_phases)) - printk("MESSAGE IN, "); + if (HOSTDATA(shpnt)->debug & (debug_intr | debug_msgi | debug_phases)) + printk("MESSAGE IN, "); #endif - SETPORT(SXFRCTL0, CH1); + SETPORT(SXFRCTL0, CH1); + + SETPORT(SIMODE0, 0); + SETPORT(SIMODE1, ENBUSFREE); - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, ENBUSFREE); - - while(phase == P_MSGI) { - CURRENT_SC->SCp.Message = GETPORT(SCSIDAT); - switch(CURRENT_SC->SCp.Message) { - case DISCONNECT: + while (phase == P_MSGI) { + CURRENT_SC->SCp.Message = GETPORT(SCSIDAT); + switch (CURRENT_SC->SCp.Message) { + case DISCONNECT: #if defined(DEBUG_MSGI) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_msgi|debug_phases)) - printk("target disconnected, "); + if (HOSTDATA(shpnt)->debug & (debug_msgi | debug_phases)) + printk("target disconnected, "); #endif - CURRENT_SC->SCp.Message = 0; - CURRENT_SC->SCp.phase |= disconnected; - if(!HOSTDATA(shpnt)->reconnect) - aha152x_panic(shpnt, "target was not allowed to disconnect"); - - break; - - case COMMAND_COMPLETE: + CURRENT_SC->SCp.Message = 0; + CURRENT_SC->SCp.phase |= disconnected; + if (!HOSTDATA(shpnt)->reconnect) + aha152x_panic(shpnt, "target was not allowed to disconnect"); + + break; + + case COMMAND_COMPLETE: #if defined(DEBUG_MSGI) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_msgi|debug_phases)) - printk("inbound message (COMMAND COMPLETE), "); + if (HOSTDATA(shpnt)->debug & (debug_msgi | debug_phases)) + printk("inbound message (COMMAND COMPLETE), "); #endif - done++; - break; + done++; + break; - case MESSAGE_REJECT: - if(CURRENT_SC->SCp.phase & in_sync) { - CURRENT_SC->SCp.phase &= ~in_sync; - SYNCRATE=0x80; - printk("synchronous rejected, "); - } else - printk("inbound message (MESSAGE REJECT), "); + case MESSAGE_REJECT: + if (CURRENT_SC->SCp.phase & in_sync) { + CURRENT_SC->SCp.phase &= ~in_sync; + SYNCRATE = 0x80; + printk("synchronous rejected, "); + } else + printk("inbound message (MESSAGE REJECT), "); #if defined(DEBUG_MSGI) - if(HOSTDATA(shpnt)->debug & debug_msgi) - printk("inbound message (MESSAGE REJECT), "); + if (HOSTDATA(shpnt)->debug & debug_msgi) + printk("inbound message (MESSAGE REJECT), "); #endif - break; + break; - case SAVE_POINTERS: + case SAVE_POINTERS: #if defined(DEBUG_MSGI) - if(HOSTDATA(shpnt)->debug & debug_msgi) - printk("inbound message (SAVE DATA POINTERS), "); + if (HOSTDATA(shpnt)->debug & debug_msgi) + printk("inbound message (SAVE DATA POINTERS), "); #endif - break; + break; - case RESTORE_POINTERS: + case RESTORE_POINTERS: #if defined(DEBUG_MSGI) - if(HOSTDATA(shpnt)->debug & debug_msgi) - printk("inbound message (RESTORE DATA POINTERS), "); + if (HOSTDATA(shpnt)->debug & debug_msgi) + printk("inbound message (RESTORE DATA POINTERS), "); #endif - break; + break; - case EXTENDED_MESSAGE: - { - char buffer[16]; - int i; + case EXTENDED_MESSAGE: + { + char buffer[16]; + int i; #if defined(DEBUG_MSGI) - if(HOSTDATA(shpnt)->debug & debug_msgi) - printk("inbound message (EXTENDED MESSAGE), "); + if (HOSTDATA(shpnt)->debug & debug_msgi) + printk("inbound message (EXTENDED MESSAGE), "); #endif - make_acklow(shpnt); - if(getphase(shpnt)!=P_MSGI) - break; - - buffer[0]=EXTENDED_MESSAGE; - buffer[1]=GETPORT(SCSIDAT); - - for(i=0; idebug & debug_msgi) - print_msg(buffer); + if (HOSTDATA(shpnt)->debug & debug_msgi) + print_msg(buffer); #endif - switch(buffer [2]) { - case EXTENDED_SDTR: - { - long ticks; - - if(buffer[1]!=3) - aha152x_panic(shpnt, "SDTR message length != 3"); - - if(!HOSTDATA(shpnt)->synchronous) - break; - - printk("inbound SDTR: "); print_msg(buffer); - - ticks=(buffer[3]*4+49)/50; - - if(CURRENT_SC->SCp.phase & in_sync) { - /* we initiated SDTR */ - if(ticks>9 || buffer[4]<1 || buffer[4]>8) - aha152x_panic(shpnt, "received SDTR invalid"); - - SYNCRATE |= ((ticks-2)<<4) + buffer[4]; - } else if(ticks<=9 && buffer[4]>=1) { - if(buffer[4]>8) - buffer[4]=8; - - ADDMSG(EXTENDED_MESSAGE); - ADDMSG(3); - ADDMSG(EXTENDED_SDTR); - if(ticks<4) { - ticks=4; - ADDMSG(50); - } else - ADDMSG(buffer[3]); - - ADDMSG(buffer[4]); - - printk("outbound SDTR: "); - print_msg(&MSG(MSGLEN-5)); - - CURRENT_SC->SCp.phase |= in_sync; - - SYNCRATE |= ((ticks-2)<<4) + buffer[4]; - - start_sync++; - } else { - /* requested SDTR is too slow, do it asynchronously */ - ADDMSG(MESSAGE_REJECT); - SYNCRATE = 0; - } - - SETPORT(SCSIRATE, SYNCRATE&0x7f); - } - break; - - case EXTENDED_MODIFY_DATA_POINTER: - case EXTENDED_EXTENDED_IDENTIFY: - case EXTENDED_WDTR: - default: - ADDMSG(MESSAGE_REJECT); - break; - } - } - break; - - default: - printk("unsupported inbound message %x, ", CURRENT_SC->SCp.Message); - break; - - } - - make_acklow(shpnt); - phase=getphase(shpnt); - } - - if(start_sync) - CURRENT_SC->SCp.phase |= in_sync; - else - CURRENT_SC->SCp.phase &= ~in_sync; - - if(MSGLEN>0) - SETPORT(SCSISIG, P_MSGI|ATNO); - - /* clear SCSI fifo on BUSFREE */ - if(phase==P_BUSFREE) - SETPORT(SXFRCTL0, CH1|CLRCH1); - - if(CURRENT_SC->SCp.phase & disconnected) { - save_flags(flags); - cli(); + switch (buffer[2]) { + case EXTENDED_SDTR: + { + long ticks; + + if (buffer[1] != 3) + aha152x_panic(shpnt, "SDTR message length != 3"); + + if (!HOSTDATA(shpnt)->synchronous) + break; + + printk("inbound SDTR: "); + print_msg(buffer); + + ticks = (buffer[3] * 4 + 49) / 50; + + if (CURRENT_SC->SCp.phase & in_sync) { + /* we initiated SDTR */ + if (ticks > 9 || buffer[4] < 1 || buffer[4] > 8) + aha152x_panic(shpnt, "received SDTR invalid"); + + SYNCRATE |= ((ticks - 2) << 4) + buffer[4]; + } else if (ticks <= 9 && buffer[4] >= 1) { + if (buffer[4] > 8) + buffer[4] = 8; + + ADDMSG(EXTENDED_MESSAGE); + ADDMSG(3); + ADDMSG(EXTENDED_SDTR); + if (ticks < 4) { + ticks = 4; + ADDMSG(50); + } else + ADDMSG(buffer[3]); + + ADDMSG(buffer[4]); + + printk("outbound SDTR: "); + print_msg(&MSG(MSGLEN - 5)); + + CURRENT_SC->SCp.phase |= in_sync; + + SYNCRATE |= ((ticks - 2) << 4) + buffer[4]; + + start_sync++; + } else { + /* requested SDTR is too slow, do it asynchronously */ + ADDMSG(MESSAGE_REJECT); + SYNCRATE = 0; + } + + SETPORT(SCSIRATE, SYNCRATE & 0x7f); + } + break; + + case EXTENDED_MODIFY_DATA_POINTER: + case EXTENDED_EXTENDED_IDENTIFY: + case EXTENDED_WDTR: + default: + ADDMSG(MESSAGE_REJECT); + break; + } + } + break; + + default: + printk("unsupported inbound message %x, ", CURRENT_SC->SCp.Message); + break; + + } + + make_acklow(shpnt); + phase = getphase(shpnt); + } + + if (start_sync) + CURRENT_SC->SCp.phase |= in_sync; + else + CURRENT_SC->SCp.phase &= ~in_sync; + + if (MSGLEN > 0) + SETPORT(SCSISIG, P_MSGI | ATNO); + + /* clear SCSI fifo on BUSFREE */ + if (phase == P_BUSFREE) + SETPORT(SXFRCTL0, CH1 | CLRCH1); + + if (CURRENT_SC->SCp.phase & disconnected) { + save_flags(flags); + cli(); #if defined(DEBUG_QUEUES) - if(HOSTDATA(shpnt)->debug & debug_queues) - printk("d+, "); + if (HOSTDATA(shpnt)->debug & debug_queues) + printk("d+, "); #endif - append_SC(&DISCONNECTED_SC, CURRENT_SC); - CURRENT_SC->SCp.phase |= 1<<16; - CURRENT_SC = NULL; - restore_flags(flags); + append_SC(&DISCONNECTED_SC, CURRENT_SC); + CURRENT_SC->SCp.phase |= 1 << 16; + CURRENT_SC = NULL; + restore_flags(flags); - SETBITS(SCSISEQ, ENRESELI); + SETBITS(SCSISEQ, ENRESELI); - SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); - SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); + SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); + SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); - SETBITS(DMACNTRL0, INTEN); + SETBITS(DMACNTRL0, INTEN); - return; - } - } - break; + return; + } + } + break; - case P_STATUS: /* STATUS IN phase */ + case P_STATUS: /* STATUS IN phase */ #if defined(DEBUG_STATUS) || defined(DEBUG_INTR) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_status|debug_intr|debug_phases)) - printk("STATUS, "); + if (HOSTDATA(shpnt)->debug & (debug_status | debug_intr | debug_phases)) + printk("STATUS, "); #endif - SETPORT(SXFRCTL0, CH1); + SETPORT(SXFRCTL0, CH1); - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, ENREQINIT|ENBUSFREE); + SETPORT(SIMODE0, 0); + SETPORT(SIMODE1, ENREQINIT | ENBUSFREE); - if(TESTHI(SSTAT1, PHASEMIS)) - printk("aha152x: passing STATUS phase"); - - CURRENT_SC->SCp.Status = GETPORT(SCSIBUS); - make_acklow(shpnt); - getphase(shpnt); + if (TESTHI(SSTAT1, PHASEMIS)) + printk("aha152x: passing STATUS phase"); + + CURRENT_SC->SCp.Status = GETPORT(SCSIBUS); + make_acklow(shpnt); + getphase(shpnt); #if defined(DEBUG_STATUS) - if(HOSTDATA(shpnt)->debug & debug_status) { - printk("inbound status "); - print_status(CURRENT_SC->SCp.Status); - printk(", "); - } -#endif - break; - - case P_DATAI: /* DATA IN phase */ - { - int fifodata, data_count, done; + if (HOSTDATA(shpnt)->debug & debug_status) { + printk("inbound status "); + print_status(CURRENT_SC->SCp.Status); + printk(", "); + } +#endif + break; + + case P_DATAI: /* DATA IN phase */ + { + int fifodata, data_count, done; #if defined(DEBUG_DATAI) || defined(DEBUG_INTR) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_datai|debug_intr|debug_phases)) - printk("DATA IN, "); + if (HOSTDATA(shpnt)->debug & (debug_datai | debug_intr | debug_phases)) + printk("DATA IN, "); #endif #if 0 - if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT)) - printk("aha152x: P_DATAI: %d(%d) bytes left in FIFO, resetting\n", - GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT)); + if (GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL | SFCNT)) + printk("aha152x: P_DATAI: %d(%d) bytes left in FIFO, resetting\n", + GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL | SFCNT)); #endif - /* reset host fifo */ - SETPORT(DMACNTRL0, RSTFIFO); - SETPORT(DMACNTRL0, RSTFIFO|ENDMA); + /* reset host fifo */ + SETPORT(DMACNTRL0, RSTFIFO); + SETPORT(DMACNTRL0, RSTFIFO | ENDMA); - SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN); + SETPORT(SXFRCTL0, CH1 | SCSIEN | DMAEN); - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE); + SETPORT(SIMODE0, 0); + SETPORT(SIMODE1, ENPHASEMIS | ENBUSFREE); - /* done is set when the FIFO is empty after the target left DATA IN */ - done=0; - - /* while the target stays in DATA to transfer data */ - while (!done) { + /* done is set when the FIFO is empty after the target left DATA IN */ + done = 0; + + /* while the target stays in DATA to transfer data */ + while (!done) { #if defined(DEBUG_DATAI) - if(HOSTDATA(shpnt)->debug & debug_datai) - printk("expecting data, "); + if (HOSTDATA(shpnt)->debug & debug_datai) + printk("expecting data, "); #endif - /* wait for PHASEMIS or full FIFO */ - while(TESTLO(DMASTAT, DFIFOFULL|INTSTAT)) - barrier(); + /* wait for PHASEMIS or full FIFO */ + while (TESTLO(DMASTAT, DFIFOFULL | INTSTAT)) + barrier(); #if defined(DEBUG_DATAI) - if(HOSTDATA(shpnt)->debug & debug_datai) - printk("ok, "); + if (HOSTDATA(shpnt)->debug & debug_datai) + printk("ok, "); #endif - - if(TESTHI(DMASTAT, DFIFOFULL)) - fifodata=GETPORT(FIFOSTAT); - else { - /* wait for SCSI fifo to get empty */ - while(TESTLO(SSTAT2, SEMPTY)) - barrier(); - /* rest of data in FIFO */ - fifodata=GETPORT(FIFOSTAT); + if (TESTHI(DMASTAT, DFIFOFULL)) + fifodata = GETPORT(FIFOSTAT); + else { + /* wait for SCSI fifo to get empty */ + while (TESTLO(SSTAT2, SEMPTY)) + barrier(); + + /* rest of data in FIFO */ + fifodata = GETPORT(FIFOSTAT); #if defined(DEBUG_DATAI) - if(HOSTDATA(shpnt)->debug & debug_datai) - printk("last transfer, "); + if (HOSTDATA(shpnt)->debug & debug_datai) + printk("last transfer, "); #endif - done=1; - } - + done = 1; + } + #if defined(DEBUG_DATAI) - if(HOSTDATA(shpnt)->debug & debug_datai) - printk("fifodata=%d, ", fifodata); + if (HOSTDATA(shpnt)->debug & debug_datai) + printk("fifodata=%d, ", fifodata); #endif - while(fifodata && CURRENT_SC->SCp.this_residual) { - data_count=fifodata; - - /* limit data transfer to size of first sg buffer */ - if(data_count > CURRENT_SC->SCp.this_residual) - data_count = CURRENT_SC->SCp.this_residual; - - fifodata -= data_count; + while (fifodata && CURRENT_SC->SCp.this_residual) { + data_count = fifodata; + + /* limit data transfer to size of first sg buffer */ + if (data_count > CURRENT_SC->SCp.this_residual) + data_count = CURRENT_SC->SCp.this_residual; + + fifodata -= data_count; #if defined(DEBUG_DATAI) - if(HOSTDATA(shpnt)->debug & debug_datai) - printk("data_count=%d, ", data_count); + if (HOSTDATA(shpnt)->debug & debug_datai) + printk("data_count=%d, ", data_count); #endif - - if(data_count&1) { - /* get a single byte in byte mode */ - SETBITS(DMACNTRL0, _8BIT); - *CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT); - CURRENT_SC->SCp.this_residual--; - } - - if(data_count>1) { - CLRBITS(DMACNTRL0, _8BIT); - data_count >>= 1; /* Number of words */ - insw(DATAPORT, CURRENT_SC->SCp.ptr, data_count); + + if (data_count & 1) { + /* get a single byte in byte mode */ + SETBITS(DMACNTRL0, _8BIT); + *CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT); + CURRENT_SC->SCp.this_residual--; + } + if (data_count > 1) { + CLRBITS(DMACNTRL0, _8BIT); + data_count >>= 1; /* Number of words */ + insw(DATAPORT, CURRENT_SC->SCp.ptr, data_count); #if defined(DEBUG_DATAI) - if(HOSTDATA(shpnt)->debug & debug_datai) - /* show what comes with the last transfer */ - if(done) { + if (HOSTDATA(shpnt)->debug & debug_datai) + /* show what comes with the last transfer */ + if (done) { #if 0 - int i; - unsigned char *data; + int i; + unsigned char *data; #endif - - printk("data on last transfer (%d bytes) ", - 2*data_count); -#if 0 - printk("data on last transfer (%d bytes: ", - 2*data_count); - data = (unsigned char *) CURRENT_SC->SCp.ptr; - for(i=0; i<2*data_count; i++) - printk("%2x ", *data++); - printk("), "); -#endif - } -#endif - CURRENT_SC->SCp.ptr += 2 * data_count; - CURRENT_SC->SCp.this_residual -= 2 * data_count; - } - - /* if this buffer is full and there are more buffers left */ - if(!CURRENT_SC->SCp.this_residual && - CURRENT_SC->SCp.buffers_residual) { - /* advance to next buffer */ - CURRENT_SC->SCp.buffers_residual--; - CURRENT_SC->SCp.buffer++; - CURRENT_SC->SCp.ptr = CURRENT_SC->SCp.buffer->address; - CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length; - } - } - - /* - * FIFO should be empty - */ - if(fifodata>0) { - printk("aha152x: more data than expected (%d bytes)\n", - GETPORT(FIFOSTAT)); - SETBITS(DMACNTRL0, _8BIT); - printk("aha152x: data ("); - while(fifodata--) - printk("%2x ", GETPORT(DATAPORT)); - printk(")\n"); - } + printk("data on last transfer (%d bytes) ", + 2 * data_count); +#if 0 + printk("data on last transfer (%d bytes: ", + 2 * data_count); + data = (unsigned char *) CURRENT_SC->SCp.ptr; + for (i = 0; i < 2 * data_count; i++) + printk("%2x ", *data++); + printk("), "); +#endif + } +#endif + CURRENT_SC->SCp.ptr += 2 * data_count; + CURRENT_SC->SCp.this_residual -= 2 * data_count; + } + /* if this buffer is full and there are more buffers left */ + if (!CURRENT_SC->SCp.this_residual && + CURRENT_SC->SCp.buffers_residual) { + /* advance to next buffer */ + CURRENT_SC->SCp.buffers_residual--; + CURRENT_SC->SCp.buffer++; + CURRENT_SC->SCp.ptr = CURRENT_SC->SCp.buffer->address; + CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length; + } + } + + /* + * FIFO should be empty + */ + if (fifodata > 0) { + printk("aha152x: more data than expected (%d bytes)\n", + GETPORT(FIFOSTAT)); + SETBITS(DMACNTRL0, _8BIT); + printk("aha152x: data ("); + while (fifodata--) + printk("%2x ", GETPORT(DATAPORT)); + printk(")\n"); + } #if defined(DEBUG_DATAI) - if(HOSTDATA(shpnt)->debug & debug_datai) - if(!fifodata) - printk("fifo empty, "); - else - printk("something left in fifo, "); + if (HOSTDATA(shpnt)->debug & debug_datai) + if (!fifodata) + printk("fifo empty, "); + else + printk("something left in fifo, "); #endif - } + } #if defined(DEBUG_DATAI) - if((HOSTDATA(shpnt)->debug & debug_datai) && - (CURRENT_SC->SCp.buffers_residual || - CURRENT_SC->SCp.this_residual)) - printk("left buffers (buffers=%d, bytes=%d), ", - CURRENT_SC->SCp.buffers_residual, CURRENT_SC->SCp.this_residual); -#endif - /* transfer can be considered ended, when SCSIEN reads back zero */ - CLRBITS(SXFRCTL0, SCSIEN|DMAEN); - while(TESTHI(SXFRCTL0, SCSIEN)) - barrier(); - CLRBITS(DMACNTRL0, ENDMA); + if ((HOSTDATA(shpnt)->debug & debug_datai) && + (CURRENT_SC->SCp.buffers_residual || + CURRENT_SC->SCp.this_residual)) + printk("left buffers (buffers=%d, bytes=%d), ", + CURRENT_SC->SCp.buffers_residual, CURRENT_SC->SCp.this_residual); +#endif + /* transfer can be considered ended, when SCSIEN reads back zero */ + CLRBITS(SXFRCTL0, SCSIEN | DMAEN); + while (TESTHI(SXFRCTL0, SCSIEN)) + barrier(); + CLRBITS(DMACNTRL0, ENDMA); #if defined(DEBUG_DATAI) || defined(DEBUG_INTR) - if(HOSTDATA(shpnt)->debug & (debug_datai|debug_intr)) - printk("got %d bytes, ", GETSTCNT()); + if (HOSTDATA(shpnt)->debug & (debug_datai | debug_intr)) + printk("got %d bytes, ", GETSTCNT()); #endif - CURRENT_SC->SCp.have_data_in++; - } - break; + CURRENT_SC->SCp.have_data_in++; + } + break; - case P_DATAO: /* DATA OUT phase */ - { - int data_count; + case P_DATAO: /* DATA OUT phase */ + { + int data_count; #if defined(DEBUG_DATAO) || defined(DEBUG_INTR) || defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & (debug_datao|debug_intr|debug_phases)) - printk("DATA OUT, "); + if (HOSTDATA(shpnt)->debug & (debug_datao | debug_intr | debug_phases)) + printk("DATA OUT, "); #endif #if defined(DEBUG_DATAO) - if(HOSTDATA(shpnt)->debug & debug_datao) - printk("got data to send (bytes=%d, buffers=%d), ", - CURRENT_SC->SCp.this_residual, - CURRENT_SC->SCp.buffers_residual); -#endif - - if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT)) { - printk("%d(%d) left in FIFO, ", - GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT)); - aha152x_panic(shpnt, "FIFO should be empty"); - } - - SETPORT(SXFRCTL0, CH1|CLRSTCNT|CLRCH1); - SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1); - - SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO); - SETPORT(DMACNTRL0, ENDMA|WRITE_READ); - - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE); - - /* while current buffer is not empty or - there are more buffers to transfer */ - while(TESTLO(SSTAT1, PHASEMIS) && - (CURRENT_SC->SCp.this_residual || - CURRENT_SC->SCp.buffers_residual)) { + if (HOSTDATA(shpnt)->debug & debug_datao) + printk("got data to send (bytes=%d, buffers=%d), ", + CURRENT_SC->SCp.this_residual, + CURRENT_SC->SCp.buffers_residual); +#endif + + if (GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL | SFCNT)) { + printk("%d(%d) left in FIFO, ", + GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL | SFCNT)); + aha152x_panic(shpnt, "FIFO should be empty"); + } + SETPORT(SXFRCTL0, CH1 | CLRSTCNT | CLRCH1); + SETPORT(SXFRCTL0, SCSIEN | DMAEN | CH1); + + SETPORT(DMACNTRL0, WRITE_READ | RSTFIFO); + SETPORT(DMACNTRL0, ENDMA | WRITE_READ); + + SETPORT(SIMODE0, 0); + SETPORT(SIMODE1, ENPHASEMIS | ENBUSFREE); + + /* while current buffer is not empty or + there are more buffers to transfer */ + while (TESTLO(SSTAT1, PHASEMIS) && + (CURRENT_SC->SCp.this_residual || + CURRENT_SC->SCp.buffers_residual)) { #if defined(DEBUG_DATAO) - if(HOSTDATA(shpnt)->debug & debug_datao) - printk("sending data (left: bytes=%d, buffers=%d), waiting, ", - CURRENT_SC->SCp.this_residual, - CURRENT_SC->SCp.buffers_residual); -#endif - /* transfer rest of buffer, but max. 128 byte */ - data_count = - CURRENT_SC->SCp.this_residual > 128 ? - 128 : CURRENT_SC->SCp.this_residual ; + if (HOSTDATA(shpnt)->debug & debug_datao) + printk("sending data (left: bytes=%d, buffers=%d), waiting, ", + CURRENT_SC->SCp.this_residual, + CURRENT_SC->SCp.buffers_residual); +#endif + /* transfer rest of buffer, but max. 128 byte */ + data_count = + CURRENT_SC->SCp.this_residual > 128 ? + 128 : CURRENT_SC->SCp.this_residual; #if defined(DEBUG_DATAO) - if(HOSTDATA(shpnt)->debug & debug_datao) - printk("data_count=%d, ", data_count); + if (HOSTDATA(shpnt)->debug & debug_datao) + printk("data_count=%d, ", data_count); #endif - - if(data_count&1) { - /* put a single byte in byte mode */ - SETBITS(DMACNTRL0, _8BIT); - SETPORT(DATAPORT, *CURRENT_SC->SCp.ptr++); - CURRENT_SC->SCp.this_residual--; - } - if(data_count>1) { - CLRBITS(DMACNTRL0, _8BIT); - data_count >>= 1; /* number of words */ - outsw(DATAPORT, CURRENT_SC->SCp.ptr, data_count); - CURRENT_SC->SCp.ptr += 2 * data_count; - CURRENT_SC->SCp.this_residual -= 2 * data_count; - } - - /* wait for FIFO to get empty */ - while(TESTLO(DMASTAT, DFIFOEMP|INTSTAT)) - barrier(); + + if (data_count & 1) { + /* put a single byte in byte mode */ + SETBITS(DMACNTRL0, _8BIT); + SETPORT(DATAPORT, *CURRENT_SC->SCp.ptr++); + CURRENT_SC->SCp.this_residual--; + } + if (data_count > 1) { + CLRBITS(DMACNTRL0, _8BIT); + data_count >>= 1; /* number of words */ + outsw(DATAPORT, CURRENT_SC->SCp.ptr, data_count); + CURRENT_SC->SCp.ptr += 2 * data_count; + CURRENT_SC->SCp.this_residual -= 2 * data_count; + } + /* wait for FIFO to get empty */ + while (TESTLO(DMASTAT, DFIFOEMP | INTSTAT)) + barrier(); #if defined(DEBUG_DATAO) - if(HOSTDATA(shpnt)->debug & debug_datao) - printk("fifo (%d bytes), transfered (%d bytes), ", - GETPORT(FIFOSTAT), GETSTCNT()); -#endif - - /* if this buffer is empty and there are more buffers left */ - if(TESTLO(SSTAT1, PHASEMIS) && - !CURRENT_SC->SCp.this_residual && - CURRENT_SC->SCp.buffers_residual) { - /* advance to next buffer */ - CURRENT_SC->SCp.buffers_residual--; - CURRENT_SC->SCp.buffer++; - CURRENT_SC->SCp.ptr = CURRENT_SC->SCp.buffer->address; - CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length; - } - } - - if(CURRENT_SC->SCp.this_residual || CURRENT_SC->SCp.buffers_residual) { - /* target leaves DATA OUT for an other phase (perhaps disconnect) */ - - /* data in fifos has to be resend */ - data_count = GETPORT(SSTAT2) & (SFULL|SFCNT); - - data_count += GETPORT(FIFOSTAT) ; - CURRENT_SC->SCp.ptr -= data_count; - CURRENT_SC->SCp.this_residual += data_count; + if (HOSTDATA(shpnt)->debug & debug_datao) + printk("fifo (%d bytes), transfered (%d bytes), ", + GETPORT(FIFOSTAT), GETSTCNT()); +#endif + + /* if this buffer is empty and there are more buffers left */ + if (TESTLO(SSTAT1, PHASEMIS) && + !CURRENT_SC->SCp.this_residual && + CURRENT_SC->SCp.buffers_residual) { + /* advance to next buffer */ + CURRENT_SC->SCp.buffers_residual--; + CURRENT_SC->SCp.buffer++; + CURRENT_SC->SCp.ptr = CURRENT_SC->SCp.buffer->address; + CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length; + } + } + + if (CURRENT_SC->SCp.this_residual || CURRENT_SC->SCp.buffers_residual) { + /* target leaves DATA OUT for an other phase (perhaps disconnect) */ + + /* data in fifos has to be resend */ + data_count = GETPORT(SSTAT2) & (SFULL | SFCNT); + + data_count += GETPORT(FIFOSTAT); + CURRENT_SC->SCp.ptr -= data_count; + CURRENT_SC->SCp.this_residual += data_count; #if defined(DEBUG_DATAO) - if(HOSTDATA(shpnt)->debug & debug_datao) - printk("left data (bytes=%d, buffers=%d), fifos (bytes=%d), " - "transfer incomplete, resetting fifo, ", - CURRENT_SC->SCp.this_residual, - CURRENT_SC->SCp.buffers_residual, - data_count); -#endif - SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO); - CLRBITS(SXFRCTL0, SCSIEN|DMAEN); - CLRBITS(DMACNTRL0, ENDMA); - } else { + if (HOSTDATA(shpnt)->debug & debug_datao) + printk("left data (bytes=%d, buffers=%d), fifos (bytes=%d), " + "transfer incomplete, resetting fifo, ", + CURRENT_SC->SCp.this_residual, + CURRENT_SC->SCp.buffers_residual, + data_count); +#endif + SETPORT(DMACNTRL0, WRITE_READ | RSTFIFO); + CLRBITS(SXFRCTL0, SCSIEN | DMAEN); + CLRBITS(DMACNTRL0, ENDMA); + } else { #if defined(DEBUG_DATAO) - if(HOSTDATA(shpnt)->debug & debug_datao) - printk("waiting for SCSI fifo to get empty, "); + if (HOSTDATA(shpnt)->debug & debug_datao) + printk("waiting for SCSI fifo to get empty, "); #endif - /* wait for SCSI fifo to get empty */ - while(TESTLO(SSTAT2, SEMPTY)) - barrier(); + /* wait for SCSI fifo to get empty */ + while (TESTLO(SSTAT2, SEMPTY)) + barrier(); #if defined(DEBUG_DATAO) - if(HOSTDATA(shpnt)->debug & debug_datao) - printk("ok, left data (bytes=%d, buffers=%d) ", - CURRENT_SC->SCp.this_residual, - CURRENT_SC->SCp.buffers_residual); -#endif - CLRBITS(SXFRCTL0, SCSIEN|DMAEN); - - /* transfer can be considered ended, when SCSIEN reads back zero */ - while(TESTHI(SXFRCTL0, SCSIEN)) - barrier(); + if (HOSTDATA(shpnt)->debug & debug_datao) + printk("ok, left data (bytes=%d, buffers=%d) ", + CURRENT_SC->SCp.this_residual, + CURRENT_SC->SCp.buffers_residual); +#endif + CLRBITS(SXFRCTL0, SCSIEN | DMAEN); + + /* transfer can be considered ended, when SCSIEN reads back zero */ + while (TESTHI(SXFRCTL0, SCSIEN)) + barrier(); - CLRBITS(DMACNTRL0, ENDMA); - } + CLRBITS(DMACNTRL0, ENDMA); + } #if defined(DEBUG_DATAO) || defined(DEBUG_INTR) - if(HOSTDATA(shpnt)->debug & (debug_datao|debug_intr)) - printk("sent %d data bytes, ", GETSTCNT()); + if (HOSTDATA(shpnt)->debug & (debug_datao | debug_intr)) + printk("sent %d data bytes, ", GETSTCNT()); #endif - } - break; + } + break; - case P_BUSFREE: /* BUSFREE */ + case P_BUSFREE: /* BUSFREE */ #if defined(DEBUG_RACE) - leave_driver("(BUSFREE) intr"); + leave_driver("(BUSFREE) intr"); #endif #if defined(DEBUG_PHASES) - if(HOSTDATA(shpnt)->debug & debug_phases) - printk("unexpected BUS FREE, "); + if (HOSTDATA(shpnt)->debug & debug_phases) + printk("unexpected BUS FREE, "); #endif - CURRENT_SC->SCp.phase &= ~(P_MASK<<16); + CURRENT_SC->SCp.phase &= ~(P_MASK << 16); - aha152x_done(shpnt, DID_ERROR << 16); /* Don't know any better */ - return; - break; + aha152x_done(shpnt, DID_ERROR << 16); /* Don't know any better */ + return; + break; - case P_PARITY: /* parity error in DATA phase */ + case P_PARITY: /* parity error in DATA phase */ #if defined(DEBUG_RACE) - leave_driver("(DID_PARITY) intr"); + leave_driver("(DID_PARITY) intr"); #endif - printk("PARITY error in DATA phase, "); + printk("PARITY error in DATA phase, "); - CURRENT_SC->SCp.phase &= ~(P_MASK<<16); + CURRENT_SC->SCp.phase &= ~(P_MASK << 16); - SETBITS(DMACNTRL0, INTEN); - aha152x_done(shpnt, DID_PARITY << 16); - return; - break; + SETBITS(DMACNTRL0, INTEN); + aha152x_done(shpnt, DID_PARITY << 16); + return; + break; - default: - printk("aha152x: unexpected phase\n"); - break; - } + default: + printk("aha152x: unexpected phase\n"); + break; + } - if(done) { + if (done) { #if defined(DEBUG_INTR) - if(HOSTDATA(shpnt)->debug & debug_intr) - printk("command done.\n"); + if (HOSTDATA(shpnt)->debug & debug_intr) + printk("command done.\n"); #endif #if defined(DEBUG_RACE) - leave_driver("(done) intr"); + leave_driver("(done) intr"); #endif - SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); - SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); - SETPORT(SCSISEQ, DISCONNECTED_SC ? ENRESELI : 0); - - SETBITS(DMACNTRL0, INTEN); - - aha152x_done(shpnt, - (CURRENT_SC->SCp.Status & 0xff) - | ((CURRENT_SC->SCp.Message & 0xff) << 8) - | (DID_OK << 16)); + SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); + SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); + SETPORT(SCSISEQ, DISCONNECTED_SC ? ENRESELI : 0); + + SETBITS(DMACNTRL0, INTEN); + + aha152x_done(shpnt, + (CURRENT_SC->SCp.Status & 0xff) + | ((CURRENT_SC->SCp.Message & 0xff) << 8) + | (DID_OK << 16)); #if defined(DEBUG_RACE) - printk("done returned (DID_OK: Status=%x; Message=%x).\n", - CURRENT_SC->SCp.Status, CURRENT_SC->SCp.Message); + printk("done returned (DID_OK: Status=%x; Message=%x).\n", + CURRENT_SC->SCp.Status, CURRENT_SC->SCp.Message); #endif - return; - } - - if(CURRENT_SC) - CURRENT_SC->SCp.phase |= 1<<16; + return; + } + if (CURRENT_SC) + CURRENT_SC->SCp.phase |= 1 << 16; - SETPORT(SIMODE0, 0); - SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE); + SETPORT(SIMODE0, 0); + SETPORT(SIMODE1, ENPHASEMIS | ENBUSFREE); #if defined(DEBUG_INTR) - if(HOSTDATA(shpnt)->debug & debug_intr) - disp_enintr(shpnt); + if (HOSTDATA(shpnt)->debug & debug_intr) + disp_enintr(shpnt); #endif #if defined(DEBUG_RACE) - leave_driver("(PHASEEND) intr"); + leave_driver("(PHASEEND) intr"); #endif - SETBITS(DMACNTRL0, INTEN); - return; + SETBITS(DMACNTRL0, INTEN); + return; } /* @@ -2637,9 +2639,9 @@ */ static void aha152x_panic(struct Scsi_Host *shpnt, char *msg) { - printk("\naha152x: %s\n", msg); - show_queues(shpnt); - panic("aha152x panic"); + printk("\naha152x: %s\n", msg); + show_queues(shpnt); + panic("aha152x panic"); } /* @@ -2648,166 +2650,231 @@ static void disp_ports(struct Scsi_Host *shpnt) { #ifdef DEBUG_AHA152X - int s; + int s; #ifdef SKIP_PORTS - if(HOSTDATA(shpnt)->debug & debug_skipports) - return; + if (HOSTDATA(shpnt)->debug & debug_skipports) + return; #endif - printk("\n%s: ", CURRENT_SC ? "on bus" : "waiting"); + printk("\n%s: ", CURRENT_SC ? "on bus" : "waiting"); - s=GETPORT(SCSISEQ); - printk("SCSISEQ ("); - if(s & TEMODEO) printk("TARGET MODE "); - if(s & ENSELO) printk("SELO "); - if(s & ENSELI) printk("SELI "); - if(s & ENRESELI) printk("RESELI "); - if(s & ENAUTOATNO) printk("AUTOATNO "); - if(s & ENAUTOATNI) printk("AUTOATNI "); - if(s & ENAUTOATNP) printk("AUTOATNP "); - if(s & SCSIRSTO) printk("SCSIRSTO "); - printk(");"); - - printk(" SCSISIG ("); - s=GETPORT(SCSISIG); - switch(s & P_MASK) { - case P_DATAO: - printk("DATA OUT"); - break; - case P_DATAI: - printk("DATA IN"); - break; - case P_CMD: - printk("COMMAND"); - break; - case P_STATUS: - printk("STATUS"); - break; - case P_MSGO: - printk("MESSAGE OUT"); - break; - case P_MSGI: - printk("MESSAGE IN"); - break; - default: - printk("*illegal*"); - break; - } - - printk("); "); - - printk("INTSTAT (%s); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo"); - - printk("SSTAT ("); - s=GETPORT(SSTAT0); - if(s & TARGET) printk("TARGET "); - if(s & SELDO) printk("SELDO "); - if(s & SELDI) printk("SELDI "); - if(s & SELINGO) printk("SELINGO "); - if(s & SWRAP) printk("SWRAP "); - if(s & SDONE) printk("SDONE "); - if(s & SPIORDY) printk("SPIORDY "); - if(s & DMADONE) printk("DMADONE "); - - s=GETPORT(SSTAT1); - if(s & SELTO) printk("SELTO "); - if(s & ATNTARG) printk("ATNTARG "); - if(s & SCSIRSTI) printk("SCSIRSTI "); - if(s & PHASEMIS) printk("PHASEMIS "); - if(s & BUSFREE) printk("BUSFREE "); - if(s & SCSIPERR) printk("SCSIPERR "); - if(s & PHASECHG) printk("PHASECHG "); - if(s & REQINIT) printk("REQINIT "); - printk("); "); - - - printk("SSTAT ("); - - s=GETPORT(SSTAT0) & GETPORT(SIMODE0); - - if(s & TARGET) printk("TARGET "); - if(s & SELDO) printk("SELDO "); - if(s & SELDI) printk("SELDI "); - if(s & SELINGO) printk("SELINGO "); - if(s & SWRAP) printk("SWRAP "); - if(s & SDONE) printk("SDONE "); - if(s & SPIORDY) printk("SPIORDY "); - if(s & DMADONE) printk("DMADONE "); - - s=GETPORT(SSTAT1) & GETPORT(SIMODE1); - - if(s & SELTO) printk("SELTO "); - if(s & ATNTARG) printk("ATNTARG "); - if(s & SCSIRSTI) printk("SCSIRSTI "); - if(s & PHASEMIS) printk("PHASEMIS "); - if(s & BUSFREE) printk("BUSFREE "); - if(s & SCSIPERR) printk("SCSIPERR "); - if(s & PHASECHG) printk("PHASECHG "); - if(s & REQINIT) printk("REQINIT "); - printk("); "); - - printk("SXFRCTL0 ("); - - s=GETPORT(SXFRCTL0); - if(s & SCSIEN) printk("SCSIEN "); - if(s & DMAEN) printk("DMAEN "); - if(s & CH1) printk("CH1 "); - if(s & CLRSTCNT) printk("CLRSTCNT "); - if(s & SPIOEN) printk("SPIOEN "); - if(s & CLRCH1) printk("CLRCH1 "); - printk("); "); - - printk("SIGNAL ("); - - s=GETPORT(SCSISIG); - if(s & ATNI) printk("ATNI "); - if(s & SELI) printk("SELI "); - if(s & BSYI) printk("BSYI "); - if(s & REQI) printk("REQI "); - if(s & ACKI) printk("ACKI "); - printk("); "); - - printk("SELID (%02x), ", GETPORT(SELID)); - - printk("SSTAT2 ("); - - s=GETPORT(SSTAT2); - if(s & SOFFSET) printk("SOFFSET "); - if(s & SEMPTY) printk("SEMPTY "); - if(s & SFULL) printk("SFULL "); - printk("); SFCNT (%d); ", s & (SFULL|SFCNT)); - - s=GETPORT(SSTAT3); - printk("SCSICNT (%d), OFFCNT(%d), ", (s&0xf0)>>4, s&0x0f); - - printk("SSTAT4 ("); - s=GETPORT(SSTAT4); - if(s & SYNCERR) printk("SYNCERR "); - if(s & FWERR) printk("FWERR "); - if(s & FRERR) printk("FRERR "); - printk("); "); - - printk("DMACNTRL0 ("); - s=GETPORT(DMACNTRL0); - printk("%s ", s & _8BIT ? "8BIT" : "16BIT"); - printk("%s ", s & DMA ? "DMA" : "PIO" ); - printk("%s ", s & WRITE_READ ? "WRITE" : "READ" ); - if(s & ENDMA) printk("ENDMA "); - if(s & INTEN) printk("INTEN "); - if(s & RSTFIFO) printk("RSTFIFO "); - if(s & SWINT) printk("SWINT "); - printk("); "); - - printk("DMASTAT ("); - s=GETPORT(DMASTAT); - if(s & ATDONE) printk("ATDONE "); - if(s & WORDRDY) printk("WORDRDY "); - if(s & DFIFOFULL) printk("DFIFOFULL "); - if(s & DFIFOEMP) printk("DFIFOEMP "); - printk(")"); + s = GETPORT(SCSISEQ); + printk("SCSISEQ ("); + if (s & TEMODEO) + printk("TARGET MODE "); + if (s & ENSELO) + printk("SELO "); + if (s & ENSELI) + printk("SELI "); + if (s & ENRESELI) + printk("RESELI "); + if (s & ENAUTOATNO) + printk("AUTOATNO "); + if (s & ENAUTOATNI) + printk("AUTOATNI "); + if (s & ENAUTOATNP) + printk("AUTOATNP "); + if (s & SCSIRSTO) + printk("SCSIRSTO "); + printk(");"); + + printk(" SCSISIG ("); + s = GETPORT(SCSISIG); + switch (s & P_MASK) { + case P_DATAO: + printk("DATA OUT"); + break; + case P_DATAI: + printk("DATA IN"); + break; + case P_CMD: + printk("COMMAND"); + break; + case P_STATUS: + printk("STATUS"); + break; + case P_MSGO: + printk("MESSAGE OUT"); + break; + case P_MSGI: + printk("MESSAGE IN"); + break; + default: + printk("*illegal*"); + break; + } + + printk("); "); + + printk("INTSTAT (%s); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo"); - printk("\n"); + printk("SSTAT ("); + s = GETPORT(SSTAT0); + if (s & TARGET) + printk("TARGET "); + if (s & SELDO) + printk("SELDO "); + if (s & SELDI) + printk("SELDI "); + if (s & SELINGO) + printk("SELINGO "); + if (s & SWRAP) + printk("SWRAP "); + if (s & SDONE) + printk("SDONE "); + if (s & SPIORDY) + printk("SPIORDY "); + if (s & DMADONE) + printk("DMADONE "); + + s = GETPORT(SSTAT1); + if (s & SELTO) + printk("SELTO "); + if (s & ATNTARG) + printk("ATNTARG "); + if (s & SCSIRSTI) + printk("SCSIRSTI "); + if (s & PHASEMIS) + printk("PHASEMIS "); + if (s & BUSFREE) + printk("BUSFREE "); + if (s & SCSIPERR) + printk("SCSIPERR "); + if (s & PHASECHG) + printk("PHASECHG "); + if (s & REQINIT) + printk("REQINIT "); + printk("); "); + + + printk("SSTAT ("); + + s = GETPORT(SSTAT0) & GETPORT(SIMODE0); + + if (s & TARGET) + printk("TARGET "); + if (s & SELDO) + printk("SELDO "); + if (s & SELDI) + printk("SELDI "); + if (s & SELINGO) + printk("SELINGO "); + if (s & SWRAP) + printk("SWRAP "); + if (s & SDONE) + printk("SDONE "); + if (s & SPIORDY) + printk("SPIORDY "); + if (s & DMADONE) + printk("DMADONE "); + + s = GETPORT(SSTAT1) & GETPORT(SIMODE1); + + if (s & SELTO) + printk("SELTO "); + if (s & ATNTARG) + printk("ATNTARG "); + if (s & SCSIRSTI) + printk("SCSIRSTI "); + if (s & PHASEMIS) + printk("PHASEMIS "); + if (s & BUSFREE) + printk("BUSFREE "); + if (s & SCSIPERR) + printk("SCSIPERR "); + if (s & PHASECHG) + printk("PHASECHG "); + if (s & REQINIT) + printk("REQINIT "); + printk("); "); + + printk("SXFRCTL0 ("); + + s = GETPORT(SXFRCTL0); + if (s & SCSIEN) + printk("SCSIEN "); + if (s & DMAEN) + printk("DMAEN "); + if (s & CH1) + printk("CH1 "); + if (s & CLRSTCNT) + printk("CLRSTCNT "); + if (s & SPIOEN) + printk("SPIOEN "); + if (s & CLRCH1) + printk("CLRCH1 "); + printk("); "); + + printk("SIGNAL ("); + + s = GETPORT(SCSISIG); + if (s & ATNI) + printk("ATNI "); + if (s & SELI) + printk("SELI "); + if (s & BSYI) + printk("BSYI "); + if (s & REQI) + printk("REQI "); + if (s & ACKI) + printk("ACKI "); + printk("); "); + + printk("SELID (%02x), ", GETPORT(SELID)); + + printk("SSTAT2 ("); + + s = GETPORT(SSTAT2); + if (s & SOFFSET) + printk("SOFFSET "); + if (s & SEMPTY) + printk("SEMPTY "); + if (s & SFULL) + printk("SFULL "); + printk("); SFCNT (%d); ", s & (SFULL | SFCNT)); + + s = GETPORT(SSTAT3); + printk("SCSICNT (%d), OFFCNT(%d), ", (s & 0xf0) >> 4, s & 0x0f); + + printk("SSTAT4 ("); + s = GETPORT(SSTAT4); + if (s & SYNCERR) + printk("SYNCERR "); + if (s & FWERR) + printk("FWERR "); + if (s & FRERR) + printk("FRERR "); + printk("); "); + + printk("DMACNTRL0 ("); + s = GETPORT(DMACNTRL0); + printk("%s ", s & _8BIT ? "8BIT" : "16BIT"); + printk("%s ", s & DMA ? "DMA" : "PIO"); + printk("%s ", s & WRITE_READ ? "WRITE" : "READ"); + if (s & ENDMA) + printk("ENDMA "); + if (s & INTEN) + printk("INTEN "); + if (s & RSTFIFO) + printk("RSTFIFO "); + if (s & SWINT) + printk("SWINT "); + printk("); "); + + printk("DMASTAT ("); + s = GETPORT(DMASTAT); + if (s & ATDONE) + printk("ATDONE "); + if (s & WORDRDY) + printk("WORDRDY "); + if (s & DFIFOFULL) + printk("DFIFOFULL "); + if (s & DFIFOEMP) + printk("DFIFOEMP "); + printk(")"); + + printk("\n"); #endif } @@ -2816,518 +2883,618 @@ */ static void disp_enintr(struct Scsi_Host *shpnt) { - int s; + int s; + + printk("enabled interrupts ("); - printk("enabled interrupts ("); - - s=GETPORT(SIMODE0); - if(s & ENSELDO) printk("ENSELDO "); - if(s & ENSELDI) printk("ENSELDI "); - if(s & ENSELINGO) printk("ENSELINGO "); - if(s & ENSWRAP) printk("ENSWRAP "); - if(s & ENSDONE) printk("ENSDONE "); - if(s & ENSPIORDY) printk("ENSPIORDY "); - if(s & ENDMADONE) printk("ENDMADONE "); - - s=GETPORT(SIMODE1); - if(s & ENSELTIMO) printk("ENSELTIMO "); - if(s & ENATNTARG) printk("ENATNTARG "); - if(s & ENPHASEMIS) printk("ENPHASEMIS "); - if(s & ENBUSFREE) printk("ENBUSFREE "); - if(s & ENSCSIPERR) printk("ENSCSIPERR "); - if(s & ENPHASECHG) printk("ENPHASECHG "); - if(s & ENREQINIT) printk("ENREQINIT "); - printk(")\n"); + s = GETPORT(SIMODE0); + if (s & ENSELDO) + printk("ENSELDO "); + if (s & ENSELDI) + printk("ENSELDI "); + if (s & ENSELINGO) + printk("ENSELINGO "); + if (s & ENSWRAP) + printk("ENSWRAP "); + if (s & ENSDONE) + printk("ENSDONE "); + if (s & ENSPIORDY) + printk("ENSPIORDY "); + if (s & ENDMADONE) + printk("ENDMADONE "); + + s = GETPORT(SIMODE1); + if (s & ENSELTIMO) + printk("ENSELTIMO "); + if (s & ENATNTARG) + printk("ENATNTARG "); + if (s & ENPHASEMIS) + printk("ENPHASEMIS "); + if (s & ENBUSFREE) + printk("ENBUSFREE "); + if (s & ENSCSIPERR) + printk("ENSCSIPERR "); + if (s & ENPHASECHG) + printk("ENPHASECHG "); + if (s & ENREQINIT) + printk("ENREQINIT "); + printk(")\n"); } #if defined(DEBUG_RACE) static const char *should_leave; -static int in_driver=0; +static int in_driver = 0; /* * Only one routine can be in the driver at once. */ static void enter_driver(const char *func) { - unsigned long flags; + unsigned long flags; - save_flags(flags); - cli(); - printk("aha152x: entering %s() (%x)\n", func, jiffies); - if(in_driver) { - printk("%s should leave first.\n", should_leave); - panic("aha152x: already in driver\n"); - } - - in_driver++; - should_leave=func; - restore_flags(flags); + save_flags(flags); + cli(); + printk("aha152x: entering %s() (%x)\n", func, jiffies); + if (in_driver) { + printk("%s should leave first.\n", should_leave); + panic("aha152x: already in driver\n"); + } + in_driver++; + should_leave = func; + restore_flags(flags); } static void leave_driver(const char *func) { - unsigned long flags; + unsigned long flags; - save_flags(flags); - cli(); - printk("\naha152x: leaving %s() (%x)\n", func, jiffies); - if(!in_driver) { - printk("aha152x: %s already left.\n", should_leave); - panic("aha152x: %s already left driver.\n"); - } - - in_driver--; - should_leave=func; - restore_flags(flags); + save_flags(flags); + cli(); + printk("\naha152x: leaving %s() (%x)\n", func, jiffies); + if (!in_driver) { + printk("aha152x: %s already left.\n", should_leave); + panic("aha152x: %s already left driver.\n"); + } + in_driver--; + should_leave = func; + restore_flags(flags); } #endif /* * Show the command data of a command */ -static void show_command(Scsi_Cmnd *ptr) +static void show_command(Scsi_Cmnd * ptr) { - printk("0x%08x: target=%d; lun=%d; cmnd=(", - (unsigned int) ptr, ptr->target, ptr->lun); - - print_command(ptr->cmnd); - - printk("); residual=%d; buffers=%d; phase |", - ptr->SCp.this_residual, ptr->SCp.buffers_residual); - - if(ptr->SCp.phase & not_issued ) printk("not issued|"); - if(ptr->SCp.phase & in_selection) printk("in selection|"); - if(ptr->SCp.phase & disconnected) printk("disconnected|"); - if(ptr->SCp.phase & aborted ) printk("aborted|"); - if(ptr->SCp.phase & sent_ident ) printk("send_ident|"); - if(ptr->SCp.phase & in_other) { - printk("; in other("); - switch((ptr->SCp.phase >> 16) & P_MASK) { - case P_DATAO: - printk("DATA OUT"); - break; - case P_DATAI: - printk("DATA IN"); - break; - case P_CMD: - printk("COMMAND"); - break; - case P_STATUS: - printk("STATUS"); - break; - case P_MSGO: - printk("MESSAGE OUT"); - break; - case P_MSGI: - printk("MESSAGE IN"); - break; - default: - printk("*illegal*"); - break; - } - printk(")"); - if(ptr->SCp.phase & (1<<16)) - printk("; phaseend"); - } - printk("; next=0x%08x\n", (unsigned int) ptr->host_scribble); + printk("0x%08x: target=%d; lun=%d; cmnd=(", + (unsigned int) ptr, ptr->target, ptr->lun); + + print_command(ptr->cmnd); + + printk("); residual=%d; buffers=%d; phase |", + ptr->SCp.this_residual, ptr->SCp.buffers_residual); + + if (ptr->SCp.phase & not_issued) + printk("not issued|"); + if (ptr->SCp.phase & in_selection) + printk("in selection|"); + if (ptr->SCp.phase & disconnected) + printk("disconnected|"); + if (ptr->SCp.phase & aborted) + printk("aborted|"); + if (ptr->SCp.phase & sent_ident) + printk("send_ident|"); + if (ptr->SCp.phase & in_other) { + printk("; in other("); + switch ((ptr->SCp.phase >> 16) & P_MASK) { + case P_DATAO: + printk("DATA OUT"); + break; + case P_DATAI: + printk("DATA IN"); + break; + case P_CMD: + printk("COMMAND"); + break; + case P_STATUS: + printk("STATUS"); + break; + case P_MSGO: + printk("MESSAGE OUT"); + break; + case P_MSGI: + printk("MESSAGE IN"); + break; + default: + printk("*illegal*"); + break; + } + printk(")"); + if (ptr->SCp.phase & (1 << 16)) + printk("; phaseend"); + } + printk("; next=0x%08x\n", (unsigned int) ptr->host_scribble); } - + /* * Dump the queued data */ static void show_queues(struct Scsi_Host *shpnt) { - unsigned long flags; - Scsi_Cmnd *ptr; + unsigned long flags; + Scsi_Cmnd *ptr; - save_flags(flags); - cli(); - printk("QUEUE STATUS:\nissue_SC:\n"); - for(ptr=ISSUE_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble) - show_command(ptr); - - printk("current_SC:\n"); - if(CURRENT_SC) - show_command(CURRENT_SC); - else - printk("none\n"); - - printk("disconnected_SC:\n"); - for(ptr=DISCONNECTED_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble) - show_command(ptr); - - disp_ports(shpnt); - disp_enintr(shpnt); - restore_flags(flags); + save_flags(flags); + cli(); + printk("QUEUE STATUS:\nissue_SC:\n"); + for (ptr = ISSUE_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble) + show_command(ptr); + + printk("current_SC:\n"); + if (CURRENT_SC) + show_command(CURRENT_SC); + else + printk("none\n"); + + printk("disconnected_SC:\n"); + for (ptr = DISCONNECTED_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble) + show_command(ptr); + + disp_ports(shpnt); + disp_enintr(shpnt); + restore_flags(flags); } int aha152x_set_info(char *buffer, int length, struct Scsi_Host *shpnt) { - return(-ENOSYS); /* Currently this is a no-op */ + return (-ENOSYS); /* Currently this is a no-op */ } #undef SPRINTF #define SPRINTF(args...) pos += sprintf(pos, ## args) -static int get_command(char *pos, Scsi_Cmnd *ptr) +static int get_command(char *pos, Scsi_Cmnd * ptr) { - char *start = pos; - int i; - - SPRINTF("0x%08x: target=%d; lun=%d; cmnd=( ", - (unsigned int) ptr, ptr->target, ptr->lun); - - for(i=0; icmnd[0]); i++) - SPRINTF("0x%02x ", ptr->cmnd[i]); - - SPRINTF("); residual=%d; buffers=%d; phase |", - ptr->SCp.this_residual, ptr->SCp.buffers_residual); - - if(ptr->SCp.phase & not_issued ) SPRINTF("not issued|"); - if(ptr->SCp.phase & in_selection) SPRINTF("in selection|"); - if(ptr->SCp.phase & disconnected) SPRINTF("disconnected|"); - if(ptr->SCp.phase & aborted ) SPRINTF("aborted|"); - if(ptr->SCp.phase & sent_ident ) SPRINTF("send_ident|"); - if(ptr->SCp.phase & in_other) { - SPRINTF("; in other("); - switch((ptr->SCp.phase >> 16) & P_MASK) { - case P_DATAO: - SPRINTF("DATA OUT"); - break; - case P_DATAI: - SPRINTF("DATA IN"); - break; - case P_CMD: - SPRINTF("COMMAND"); - break; - case P_STATUS: - SPRINTF("STATUS"); - break; - case P_MSGO: - SPRINTF("MESSAGE OUT"); - break; - case P_MSGI: - SPRINTF("MESSAGE IN"); - break; - default: - SPRINTF("*illegal*"); - break; - } - SPRINTF(")"); - if(ptr->SCp.phase & (1<<16)) - SPRINTF("; phaseend"); - } - SPRINTF("; next=0x%08x\n", (unsigned int) ptr->host_scribble); - - return(pos-start); + char *start = pos; + int i; + + SPRINTF("0x%08x: target=%d; lun=%d; cmnd=( ", + (unsigned int) ptr, ptr->target, ptr->lun); + + for (i = 0; i < COMMAND_SIZE(ptr->cmnd[0]); i++) + SPRINTF("0x%02x ", ptr->cmnd[i]); + + SPRINTF("); residual=%d; buffers=%d; phase |", + ptr->SCp.this_residual, ptr->SCp.buffers_residual); + + if (ptr->SCp.phase & not_issued) + SPRINTF("not issued|"); + if (ptr->SCp.phase & in_selection) + SPRINTF("in selection|"); + if (ptr->SCp.phase & disconnected) + SPRINTF("disconnected|"); + if (ptr->SCp.phase & aborted) + SPRINTF("aborted|"); + if (ptr->SCp.phase & sent_ident) + SPRINTF("send_ident|"); + if (ptr->SCp.phase & in_other) { + SPRINTF("; in other("); + switch ((ptr->SCp.phase >> 16) & P_MASK) { + case P_DATAO: + SPRINTF("DATA OUT"); + break; + case P_DATAI: + SPRINTF("DATA IN"); + break; + case P_CMD: + SPRINTF("COMMAND"); + break; + case P_STATUS: + SPRINTF("STATUS"); + break; + case P_MSGO: + SPRINTF("MESSAGE OUT"); + break; + case P_MSGI: + SPRINTF("MESSAGE IN"); + break; + default: + SPRINTF("*illegal*"); + break; + } + SPRINTF(")"); + if (ptr->SCp.phase & (1 << 16)) + SPRINTF("; phaseend"); + } + SPRINTF("; next=0x%08x\n", (unsigned int) ptr->host_scribble); + + return (pos - start); } static int get_ports(struct Scsi_Host *shpnt, char *pos) { - char *start = pos; - int s; + char *start = pos; + int s; #ifdef SKIP_PORTS - if(HOSTDATA(shpnt)->debug & debug_skipports) - return; + if (HOSTDATA(shpnt)->debug & debug_skipports) + return; #endif - SPRINTF("\n%s: ", CURRENT_SC ? "on bus" : "waiting"); + SPRINTF("\n%s: ", CURRENT_SC ? "on bus" : "waiting"); + + s = GETPORT(SCSISEQ); + SPRINTF("SCSISEQ ("); + if (s & TEMODEO) + SPRINTF("TARGET MODE "); + if (s & ENSELO) + SPRINTF("SELO "); + if (s & ENSELI) + SPRINTF("SELI "); + if (s & ENRESELI) + SPRINTF("RESELI "); + if (s & ENAUTOATNO) + SPRINTF("AUTOATNO "); + if (s & ENAUTOATNI) + SPRINTF("AUTOATNI "); + if (s & ENAUTOATNP) + SPRINTF("AUTOATNP "); + if (s & SCSIRSTO) + SPRINTF("SCSIRSTO "); + SPRINTF(");"); + + SPRINTF(" SCSISIG ("); + s = GETPORT(SCSISIG); + switch (s & P_MASK) { + case P_DATAO: + SPRINTF("DATA OUT"); + break; + case P_DATAI: + SPRINTF("DATA IN"); + break; + case P_CMD: + SPRINTF("COMMAND"); + break; + case P_STATUS: + SPRINTF("STATUS"); + break; + case P_MSGO: + SPRINTF("MESSAGE OUT"); + break; + case P_MSGI: + SPRINTF("MESSAGE IN"); + break; + default: + SPRINTF("*illegal*"); + break; + } + + SPRINTF("); "); + + SPRINTF("INTSTAT (%s); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo"); - s=GETPORT(SCSISEQ); - SPRINTF("SCSISEQ ("); - if(s & TEMODEO) SPRINTF("TARGET MODE "); - if(s & ENSELO) SPRINTF("SELO "); - if(s & ENSELI) SPRINTF("SELI "); - if(s & ENRESELI) SPRINTF("RESELI "); - if(s & ENAUTOATNO) SPRINTF("AUTOATNO "); - if(s & ENAUTOATNI) SPRINTF("AUTOATNI "); - if(s & ENAUTOATNP) SPRINTF("AUTOATNP "); - if(s & SCSIRSTO) SPRINTF("SCSIRSTO "); - SPRINTF(");"); - - SPRINTF(" SCSISIG ("); - s=GETPORT(SCSISIG); - switch(s & P_MASK) { - case P_DATAO: - SPRINTF("DATA OUT"); - break; - case P_DATAI: - SPRINTF("DATA IN"); - break; - case P_CMD: - SPRINTF("COMMAND"); - break; - case P_STATUS: - SPRINTF("STATUS"); - break; - case P_MSGO: - SPRINTF("MESSAGE OUT"); - break; - case P_MSGI: - SPRINTF("MESSAGE IN"); - break; - default: - SPRINTF("*illegal*"); - break; - } - - SPRINTF("); "); - - SPRINTF("INTSTAT (%s); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo"); - - SPRINTF("SSTAT ("); - s=GETPORT(SSTAT0); - if(s & TARGET) SPRINTF("TARGET "); - if(s & SELDO) SPRINTF("SELDO "); - if(s & SELDI) SPRINTF("SELDI "); - if(s & SELINGO) SPRINTF("SELINGO "); - if(s & SWRAP) SPRINTF("SWRAP "); - if(s & SDONE) SPRINTF("SDONE "); - if(s & SPIORDY) SPRINTF("SPIORDY "); - if(s & DMADONE) SPRINTF("DMADONE "); - - s=GETPORT(SSTAT1); - if(s & SELTO) SPRINTF("SELTO "); - if(s & ATNTARG) SPRINTF("ATNTARG "); - if(s & SCSIRSTI) SPRINTF("SCSIRSTI "); - if(s & PHASEMIS) SPRINTF("PHASEMIS "); - if(s & BUSFREE) SPRINTF("BUSFREE "); - if(s & SCSIPERR) SPRINTF("SCSIPERR "); - if(s & PHASECHG) SPRINTF("PHASECHG "); - if(s & REQINIT) SPRINTF("REQINIT "); - SPRINTF("); "); - - - SPRINTF("SSTAT ("); - - s=GETPORT(SSTAT0) & GETPORT(SIMODE0); - - if(s & TARGET) SPRINTF("TARGET "); - if(s & SELDO) SPRINTF("SELDO "); - if(s & SELDI) SPRINTF("SELDI "); - if(s & SELINGO) SPRINTF("SELINGO "); - if(s & SWRAP) SPRINTF("SWRAP "); - if(s & SDONE) SPRINTF("SDONE "); - if(s & SPIORDY) SPRINTF("SPIORDY "); - if(s & DMADONE) SPRINTF("DMADONE "); - - s=GETPORT(SSTAT1) & GETPORT(SIMODE1); - - if(s & SELTO) SPRINTF("SELTO "); - if(s & ATNTARG) SPRINTF("ATNTARG "); - if(s & SCSIRSTI) SPRINTF("SCSIRSTI "); - if(s & PHASEMIS) SPRINTF("PHASEMIS "); - if(s & BUSFREE) SPRINTF("BUSFREE "); - if(s & SCSIPERR) SPRINTF("SCSIPERR "); - if(s & PHASECHG) SPRINTF("PHASECHG "); - if(s & REQINIT) SPRINTF("REQINIT "); - SPRINTF("); "); - - SPRINTF("SXFRCTL0 ("); - - s=GETPORT(SXFRCTL0); - if(s & SCSIEN) SPRINTF("SCSIEN "); - if(s & DMAEN) SPRINTF("DMAEN "); - if(s & CH1) SPRINTF("CH1 "); - if(s & CLRSTCNT) SPRINTF("CLRSTCNT "); - if(s & SPIOEN) SPRINTF("SPIOEN "); - if(s & CLRCH1) SPRINTF("CLRCH1 "); - SPRINTF("); "); - - SPRINTF("SIGNAL ("); - - s=GETPORT(SCSISIG); - if(s & ATNI) SPRINTF("ATNI "); - if(s & SELI) SPRINTF("SELI "); - if(s & BSYI) SPRINTF("BSYI "); - if(s & REQI) SPRINTF("REQI "); - if(s & ACKI) SPRINTF("ACKI "); - SPRINTF("); "); - - SPRINTF("SELID (%02x), ", GETPORT(SELID)); - - SPRINTF("SSTAT2 ("); - - s=GETPORT(SSTAT2); - if(s & SOFFSET) SPRINTF("SOFFSET "); - if(s & SEMPTY) SPRINTF("SEMPTY "); - if(s & SFULL) SPRINTF("SFULL "); - SPRINTF("); SFCNT (%d); ", s & (SFULL|SFCNT)); - - s=GETPORT(SSTAT3); - SPRINTF("SCSICNT (%d), OFFCNT(%d), ", (s&0xf0)>>4, s&0x0f); - - SPRINTF("SSTAT4 ("); - s=GETPORT(SSTAT4); - if(s & SYNCERR) SPRINTF("SYNCERR "); - if(s & FWERR) SPRINTF("FWERR "); - if(s & FRERR) SPRINTF("FRERR "); - SPRINTF("); "); - - SPRINTF("DMACNTRL0 ("); - s=GETPORT(DMACNTRL0); - SPRINTF("%s ", s & _8BIT ? "8BIT" : "16BIT"); - SPRINTF("%s ", s & DMA ? "DMA" : "PIO" ); - SPRINTF("%s ", s & WRITE_READ ? "WRITE" : "READ" ); - if(s & ENDMA) SPRINTF("ENDMA "); - if(s & INTEN) SPRINTF("INTEN "); - if(s & RSTFIFO) SPRINTF("RSTFIFO "); - if(s & SWINT) SPRINTF("SWINT "); - SPRINTF("); "); - - SPRINTF("DMASTAT ("); - s=GETPORT(DMASTAT); - if(s & ATDONE) SPRINTF("ATDONE "); - if(s & WORDRDY) SPRINTF("WORDRDY "); - if(s & DFIFOFULL) SPRINTF("DFIFOFULL "); - if(s & DFIFOEMP) SPRINTF("DFIFOEMP "); - SPRINTF(")\n\n"); - - SPRINTF("enabled interrupts ("); - - s=GETPORT(SIMODE0); - if(s & ENSELDO) SPRINTF("ENSELDO "); - if(s & ENSELDI) SPRINTF("ENSELDI "); - if(s & ENSELINGO) SPRINTF("ENSELINGO "); - if(s & ENSWRAP) SPRINTF("ENSWRAP "); - if(s & ENSDONE) SPRINTF("ENSDONE "); - if(s & ENSPIORDY) SPRINTF("ENSPIORDY "); - if(s & ENDMADONE) SPRINTF("ENDMADONE "); - - s=GETPORT(SIMODE1); - if(s & ENSELTIMO) SPRINTF("ENSELTIMO "); - if(s & ENATNTARG) SPRINTF("ENATNTARG "); - if(s & ENPHASEMIS) SPRINTF("ENPHASEMIS "); - if(s & ENBUSFREE) SPRINTF("ENBUSFREE "); - if(s & ENSCSIPERR) SPRINTF("ENSCSIPERR "); - if(s & ENPHASECHG) SPRINTF("ENPHASECHG "); - if(s & ENREQINIT) SPRINTF("ENREQINIT "); - SPRINTF(")\n"); - - return (pos-start); + SPRINTF("SSTAT ("); + s = GETPORT(SSTAT0); + if (s & TARGET) + SPRINTF("TARGET "); + if (s & SELDO) + SPRINTF("SELDO "); + if (s & SELDI) + SPRINTF("SELDI "); + if (s & SELINGO) + SPRINTF("SELINGO "); + if (s & SWRAP) + SPRINTF("SWRAP "); + if (s & SDONE) + SPRINTF("SDONE "); + if (s & SPIORDY) + SPRINTF("SPIORDY "); + if (s & DMADONE) + SPRINTF("DMADONE "); + + s = GETPORT(SSTAT1); + if (s & SELTO) + SPRINTF("SELTO "); + if (s & ATNTARG) + SPRINTF("ATNTARG "); + if (s & SCSIRSTI) + SPRINTF("SCSIRSTI "); + if (s & PHASEMIS) + SPRINTF("PHASEMIS "); + if (s & BUSFREE) + SPRINTF("BUSFREE "); + if (s & SCSIPERR) + SPRINTF("SCSIPERR "); + if (s & PHASECHG) + SPRINTF("PHASECHG "); + if (s & REQINIT) + SPRINTF("REQINIT "); + SPRINTF("); "); + + + SPRINTF("SSTAT ("); + + s = GETPORT(SSTAT0) & GETPORT(SIMODE0); + + if (s & TARGET) + SPRINTF("TARGET "); + if (s & SELDO) + SPRINTF("SELDO "); + if (s & SELDI) + SPRINTF("SELDI "); + if (s & SELINGO) + SPRINTF("SELINGO "); + if (s & SWRAP) + SPRINTF("SWRAP "); + if (s & SDONE) + SPRINTF("SDONE "); + if (s & SPIORDY) + SPRINTF("SPIORDY "); + if (s & DMADONE) + SPRINTF("DMADONE "); + + s = GETPORT(SSTAT1) & GETPORT(SIMODE1); + + if (s & SELTO) + SPRINTF("SELTO "); + if (s & ATNTARG) + SPRINTF("ATNTARG "); + if (s & SCSIRSTI) + SPRINTF("SCSIRSTI "); + if (s & PHASEMIS) + SPRINTF("PHASEMIS "); + if (s & BUSFREE) + SPRINTF("BUSFREE "); + if (s & SCSIPERR) + SPRINTF("SCSIPERR "); + if (s & PHASECHG) + SPRINTF("PHASECHG "); + if (s & REQINIT) + SPRINTF("REQINIT "); + SPRINTF("); "); + + SPRINTF("SXFRCTL0 ("); + + s = GETPORT(SXFRCTL0); + if (s & SCSIEN) + SPRINTF("SCSIEN "); + if (s & DMAEN) + SPRINTF("DMAEN "); + if (s & CH1) + SPRINTF("CH1 "); + if (s & CLRSTCNT) + SPRINTF("CLRSTCNT "); + if (s & SPIOEN) + SPRINTF("SPIOEN "); + if (s & CLRCH1) + SPRINTF("CLRCH1 "); + SPRINTF("); "); + + SPRINTF("SIGNAL ("); + + s = GETPORT(SCSISIG); + if (s & ATNI) + SPRINTF("ATNI "); + if (s & SELI) + SPRINTF("SELI "); + if (s & BSYI) + SPRINTF("BSYI "); + if (s & REQI) + SPRINTF("REQI "); + if (s & ACKI) + SPRINTF("ACKI "); + SPRINTF("); "); + + SPRINTF("SELID (%02x), ", GETPORT(SELID)); + + SPRINTF("SSTAT2 ("); + + s = GETPORT(SSTAT2); + if (s & SOFFSET) + SPRINTF("SOFFSET "); + if (s & SEMPTY) + SPRINTF("SEMPTY "); + if (s & SFULL) + SPRINTF("SFULL "); + SPRINTF("); SFCNT (%d); ", s & (SFULL | SFCNT)); + + s = GETPORT(SSTAT3); + SPRINTF("SCSICNT (%d), OFFCNT(%d), ", (s & 0xf0) >> 4, s & 0x0f); + + SPRINTF("SSTAT4 ("); + s = GETPORT(SSTAT4); + if (s & SYNCERR) + SPRINTF("SYNCERR "); + if (s & FWERR) + SPRINTF("FWERR "); + if (s & FRERR) + SPRINTF("FRERR "); + SPRINTF("); "); + + SPRINTF("DMACNTRL0 ("); + s = GETPORT(DMACNTRL0); + SPRINTF("%s ", s & _8BIT ? "8BIT" : "16BIT"); + SPRINTF("%s ", s & DMA ? "DMA" : "PIO"); + SPRINTF("%s ", s & WRITE_READ ? "WRITE" : "READ"); + if (s & ENDMA) + SPRINTF("ENDMA "); + if (s & INTEN) + SPRINTF("INTEN "); + if (s & RSTFIFO) + SPRINTF("RSTFIFO "); + if (s & SWINT) + SPRINTF("SWINT "); + SPRINTF("); "); + + SPRINTF("DMASTAT ("); + s = GETPORT(DMASTAT); + if (s & ATDONE) + SPRINTF("ATDONE "); + if (s & WORDRDY) + SPRINTF("WORDRDY "); + if (s & DFIFOFULL) + SPRINTF("DFIFOFULL "); + if (s & DFIFOEMP) + SPRINTF("DFIFOEMP "); + SPRINTF(")\n\n"); + + SPRINTF("enabled interrupts ("); + + s = GETPORT(SIMODE0); + if (s & ENSELDO) + SPRINTF("ENSELDO "); + if (s & ENSELDI) + SPRINTF("ENSELDI "); + if (s & ENSELINGO) + SPRINTF("ENSELINGO "); + if (s & ENSWRAP) + SPRINTF("ENSWRAP "); + if (s & ENSDONE) + SPRINTF("ENSDONE "); + if (s & ENSPIORDY) + SPRINTF("ENSPIORDY "); + if (s & ENDMADONE) + SPRINTF("ENDMADONE "); + + s = GETPORT(SIMODE1); + if (s & ENSELTIMO) + SPRINTF("ENSELTIMO "); + if (s & ENATNTARG) + SPRINTF("ENATNTARG "); + if (s & ENPHASEMIS) + SPRINTF("ENPHASEMIS "); + if (s & ENBUSFREE) + SPRINTF("ENBUSFREE "); + if (s & ENSCSIPERR) + SPRINTF("ENSCSIPERR "); + if (s & ENPHASECHG) + SPRINTF("ENPHASECHG "); + if (s & ENREQINIT) + SPRINTF("ENREQINIT "); + SPRINTF(")\n"); + + return (pos - start); } #undef SPRINTF #define SPRINTF(args...) do { if(pos < buffer + length) pos += sprintf(pos, ## args); } while(0) int aha152x_proc_info(char *buffer, char **start, - off_t offset, int length, int hostno, int inout) + off_t offset, int length, int hostno, int inout) { - int i; - char *pos = buffer; - struct Scsi_Host *shpnt; - unsigned long flags; - Scsi_Cmnd *ptr; - - for(i=0, shpnt= (struct Scsi_Host *) NULL; ihost_no == hostno) - shpnt=aha152x_host[i]; - - if(!shpnt) - return(-ESRCH); - - if(inout) /* Has data been written to the file ? */ - return(aha152x_set_info(buffer, length, shpnt)); - - SPRINTF(AHA152X_REVID "\n"); - - save_flags(flags); - cli(); - - SPRINTF("ioports 0x%04lx to 0x%04lx\n", - shpnt->io_port, shpnt->io_port+shpnt->n_io_port-1); - SPRINTF("interrupt 0x%02x\n", shpnt->irq); - SPRINTF("disconnection/reconnection %s\n", - HOSTDATA(shpnt)->reconnect ? "enabled" : "disabled"); - SPRINTF("parity checking %s\n", - HOSTDATA(shpnt)->parity ? "enabled" : "disabled"); - SPRINTF("synchronous transfers %s\n", - HOSTDATA(shpnt)->synchronous ? "enabled" : "disabled"); - SPRINTF("%d commands currently queued\n", HOSTDATA(shpnt)->commands); - - if(HOSTDATA(shpnt)->synchronous) { + int i; + char *pos = buffer; + struct Scsi_Host *shpnt; + unsigned long flags; + Scsi_Cmnd *ptr; + + for (i = 0, shpnt = (struct Scsi_Host *) NULL; i < IRQS; i++) + if (aha152x_host[i] && aha152x_host[i]->host_no == hostno) + shpnt = aha152x_host[i]; + + if (!shpnt) + return (-ESRCH); + + if (inout) /* Has data been written to the file ? */ + return (aha152x_set_info(buffer, length, shpnt)); + + SPRINTF(AHA152X_REVID "\n"); + + save_flags(flags); + cli(); + + SPRINTF("ioports 0x%04lx to 0x%04lx\n", + shpnt->io_port, shpnt->io_port + shpnt->n_io_port - 1); + SPRINTF("interrupt 0x%02x\n", shpnt->irq); + SPRINTF("disconnection/reconnection %s\n", + HOSTDATA(shpnt)->reconnect ? "enabled" : "disabled"); + SPRINTF("parity checking %s\n", + HOSTDATA(shpnt)->parity ? "enabled" : "disabled"); + SPRINTF("synchronous transfers %s\n", + HOSTDATA(shpnt)->synchronous ? "enabled" : "disabled"); + SPRINTF("%d commands currently queued\n", HOSTDATA(shpnt)->commands); + + if (HOSTDATA(shpnt)->synchronous) { #if 0 - SPRINTF("synchronously operating targets (tick=%ld ns):\n", - 250000000/loops_per_sec); - for(i=0; i<8; i++) - if(HOSTDATA(shpnt)->syncrate[i]&0x7f) - SPRINTF("target %d: period %dT/%ldns; req/ack offset %d\n", - i, - (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2), - (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2)* - 250000000/loops_per_sec, - HOSTDATA(shpnt)->syncrate[i]&0x0f); + SPRINTF("synchronously operating targets (tick=%ld ns):\n", + 250000000 / loops_per_sec); + for (i = 0; i < 8; i++) + if (HOSTDATA(shpnt)->syncrate[i] & 0x7f) + SPRINTF("target %d: period %dT/%ldns; req/ack offset %d\n", + i, + (((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2), + (((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2) * + 250000000 / loops_per_sec, + HOSTDATA(shpnt)->syncrate[i] & 0x0f); #else - SPRINTF("synchronously operating targets (tick=50 ns):\n"); - for(i=0; i<8; i++) - if(HOSTDATA(shpnt)->syncrate[i]&0x7f) - SPRINTF("target %d: period %dT/%dns; req/ack offset %d\n", - i, - (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2), - (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2)*50, - HOSTDATA(shpnt)->syncrate[i]&0x0f); + SPRINTF("synchronously operating targets (tick=50 ns):\n"); + for (i = 0; i < 8; i++) + if (HOSTDATA(shpnt)->syncrate[i] & 0x7f) + SPRINTF("target %d: period %dT/%dns; req/ack offset %d\n", + i, + (((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2), + (((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2) * 50, + HOSTDATA(shpnt)->syncrate[i] & 0x0f); #endif - } - + } #ifdef DEBUG_AHA152X #define PDEBUG(flags,txt) if(HOSTDATA(shpnt)->debug & flags) SPRINTF("(%s) ", txt); - - SPRINTF("enabled debugging options: "); - - PDEBUG(debug_skipports, "skip ports"); - PDEBUG(debug_queue, "queue"); - PDEBUG(debug_intr, "interrupt"); - PDEBUG(debug_selection, "selection"); - PDEBUG(debug_msgo, "message out"); - PDEBUG(debug_msgi, "message in"); - PDEBUG(debug_status, "status"); - PDEBUG(debug_cmd, "command"); - PDEBUG(debug_datai, "data in"); - PDEBUG(debug_datao, "data out"); - PDEBUG(debug_abort, "abort"); - PDEBUG(debug_done, "done"); - PDEBUG(debug_biosparam, "bios parameters"); - PDEBUG(debug_phases, "phases"); - PDEBUG(debug_queues, "queues"); - PDEBUG(debug_reset, "reset"); - - SPRINTF("\n"); -#endif - - SPRINTF("\nqueue status:\n"); - if(ISSUE_SC) { - SPRINTF("not yet issued commands:\n"); - for(ptr=ISSUE_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble) - pos += get_command(pos, ptr); - } else - SPRINTF("no not yet issued commands\n"); - - if(CURRENT_SC) { - SPRINTF("current command:\n"); - pos += get_command(pos, CURRENT_SC); - } else - SPRINTF("no current command\n"); - - if(DISCONNECTED_SC) { - SPRINTF("disconnected commands:\n"); - for(ptr=DISCONNECTED_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble) - pos += get_command(pos, ptr); - } else - SPRINTF("no disconnected commands\n"); - - restore_flags(flags); - - pos += get_ports(shpnt, pos); - - *start=buffer+offset; - if (pos - buffer < offset) - return 0; - else if (pos - buffer - offset < length) - return pos - buffer - offset; - else - return length; + + SPRINTF("enabled debugging options: "); + + PDEBUG(debug_skipports, "skip ports"); + PDEBUG(debug_queue, "queue"); + PDEBUG(debug_intr, "interrupt"); + PDEBUG(debug_selection, "selection"); + PDEBUG(debug_msgo, "message out"); + PDEBUG(debug_msgi, "message in"); + PDEBUG(debug_status, "status"); + PDEBUG(debug_cmd, "command"); + PDEBUG(debug_datai, "data in"); + PDEBUG(debug_datao, "data out"); + PDEBUG(debug_abort, "abort"); + PDEBUG(debug_done, "done"); + PDEBUG(debug_biosparam, "bios parameters"); + PDEBUG(debug_phases, "phases"); + PDEBUG(debug_queues, "queues"); + PDEBUG(debug_reset, "reset"); + + SPRINTF("\n"); +#endif + + SPRINTF("\nqueue status:\n"); + if (ISSUE_SC) { + SPRINTF("not yet issued commands:\n"); + for (ptr = ISSUE_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble) + pos += get_command(pos, ptr); + } else + SPRINTF("no not yet issued commands\n"); + + if (CURRENT_SC) { + SPRINTF("current command:\n"); + pos += get_command(pos, CURRENT_SC); + } else + SPRINTF("no current command\n"); + + if (DISCONNECTED_SC) { + SPRINTF("disconnected commands:\n"); + for (ptr = DISCONNECTED_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble) + pos += get_command(pos, ptr); + } else + SPRINTF("no disconnected commands\n"); + + restore_flags(flags); + + pos += get_ports(shpnt, pos); + + *start = buffer + offset; + if (pos - buffer < offset) + return 0; + else if (pos - buffer - offset < length) + return pos - buffer - offset; + else + return length; } #ifdef MODULE diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/aha1542.c linux.pre11.3/drivers/scsi/aha1542.c --- linux.vanilla/drivers/scsi/aha1542.c Sun Nov 8 15:07:48 1998 +++ linux.pre11.3/drivers/scsi/aha1542.c Tue Jul 20 00:01:44 1999 @@ -18,6 +18,9 @@ * 1-Jan-97 * Modified by Bjorn L. Thordarson and Einar Thor Einarsson * Recognize that DMA0 is valid DMA channel -- 13-Jul-98 + * Modified by Chris Faulhaber + * Added module command-line options + * 18-Jul-99 */ #include @@ -84,7 +87,7 @@ static char *setup_str[MAXBOARDS] = {(char *)NULL,(char *)NULL}; /* - * LILO params: aha1542=[,,[,]] + * LILO/Module params: aha1542=[,,[,]] * * Where: is any of the valid AHA addresses: * 0x130, 0x134, 0x230, 0x234, 0x330, 0x334 @@ -100,6 +103,11 @@ * Factory default is 5 MB/s. */ +#if defined(MODULE) +int aha1542[] = { 0x330, 11, 4, -1 }; +MODULE_PARM(aha1542, "1-4i"); +#endif + #define BIOS_TRANSLATION_1632 0 /* Used by some old 1542A boards */ #define BIOS_TRANSLATION_6432 1 /* Default case these days */ #define BIOS_TRANSLATION_25563 2 /* Big disk case */ @@ -823,7 +831,8 @@ mbenable_cmd[1]=0; mbenable_cmd[2]=mbenable_result[1]; - if(mbenable_result[1] & 0x03) retval = BIOS_TRANSLATION_25563; + if((mbenable_result[0] & 0x08) && (mbenable_result[1] & 0x03)) + retval = BIOS_TRANSLATION_25563; aha1542_out(base,mbenable_cmd,3); WAIT(INTRFLAGS(base),INTRMASK,HACC,0); @@ -953,6 +962,14 @@ DEB(printk("aha1542_detect: \n")); tpnt->proc_dir = &proc_scsi_aha1542; + +#ifdef MODULE + bases[0] = 4; + bases[1] = aha1542[0]; + bases[2] = aha1542[1]; + bases[3] = aha1542[2]; + bases[4] = aha1542[3]; +#endif for(indx = 0; indx < sizeof(bases)/sizeof(bases[0]); indx++) if(bases[indx] != 0 && !check_region(bases[indx], 4)) { diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/aic7xxx/aic7xxx.reg linux.pre11.3/drivers/scsi/aic7xxx/aic7xxx.reg --- linux.vanilla/drivers/scsi/aic7xxx/aic7xxx.reg Tue Jun 15 16:49:50 1999 +++ linux.pre11.3/drivers/scsi/aic7xxx/aic7xxx.reg Mon Jul 19 23:28:02 1999 @@ -845,7 +845,7 @@ bit CRCENDCHKEN 0x20 /* CRC End Check Enable */ bit CRCREQCHKEN 0x10 bit TARGCRCENDEN 0x08 /* Enable End CRC transfer when target */ - bit TARGCRCCNTEN 0x40 /* Enable CRC transfer when target */ + bit TARGCRCCNTEN 0x04 /* Enable CRC transfer when target */ } /* diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/aic7xxx.c linux.pre11.3/drivers/scsi/aic7xxx.c --- linux.vanilla/drivers/scsi/aic7xxx.c Tue Jun 15 16:49:51 1999 +++ linux.pre11.3/drivers/scsi/aic7xxx.c Tue Jul 20 00:02:00 1999 @@ -270,7 +270,7 @@ 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -#define AIC7XXX_C_VERSION "5.1.17" +#define AIC7XXX_C_VERSION "5.1.19" #define NUMBER(arr) (sizeof(arr) / sizeof(arr[0])) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) @@ -7412,73 +7412,83 @@ /*+F************************************************************************* * Function: - * write_brdctl + * read_brdctl * * Description: - * Writes a value to the BRDCTL register. + * Reads the BRDCTL register. *-F*************************************************************************/ -static void -write_brdctl(struct aic7xxx_host *p, unsigned char value) +static unsigned char +read_brdctl(struct aic7xxx_host *p) { - unsigned char brdctl; + unsigned char brdctl, value; - if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) + if (p->features & AHC_ULTRA2) { - brdctl = BRDSTB; - if (p->flags & AHC_CHNLB) - brdctl |= BRDCS; + brdctl = BRDRW_ULTRA2; + aic_outb(p, brdctl, BRDCTL); + udelay(4); + return(aic_inb(p, BRDCTL)); + } + brdctl = BRDRW; + if ( !((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) || + (p->flags & AHC_CHNLB) ) + { + brdctl |= BRDCS; } - else if (p->features & AHC_ULTRA2) - brdctl = 0; - else - brdctl = BRDSTB | BRDCS; - aic_outb(p, brdctl, BRDCTL); - udelay(1); - brdctl |= value; aic_outb(p, brdctl, BRDCTL); udelay(1); - if (p->features & AHC_ULTRA2) - brdctl |= BRDSTB_ULTRA2; - else - brdctl &= ~BRDSTB; - aic_outb(p, brdctl, BRDCTL); - udelay(1); - if (p->features & AHC_ULTRA2) - brdctl = 0; - else - brdctl &= ~BRDCS; - aic_outb(p, brdctl, BRDCTL); + value = aic_inb(p, BRDCTL); + aic_outb(p, 0, BRDCTL); udelay(1); + return (value); } /*+F************************************************************************* * Function: - * read_brdctl + * write_brdctl * * Description: - * Reads the BRDCTL register. + * Writes a value to the BRDCTL register. *-F*************************************************************************/ -static unsigned char -read_brdctl(struct aic7xxx_host *p) +static void +write_brdctl(struct aic7xxx_host *p, unsigned char value) { - unsigned char brdctl, value; + unsigned char brdctl; - if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) + if (p->features & AHC_ULTRA2) { - brdctl = BRDRW; - if (p->flags & AHC_CHNLB) - brdctl |= BRDCS; + brdctl = value; + aic_outb(p, brdctl, BRDCTL); + udelay(4); + brdctl |= BRDSTB_ULTRA2; + aic_outb(p, brdctl, BRDCTL); + udelay(4); + brdctl &= ~BRDSTB_ULTRA2; + aic_outb(p, brdctl, BRDCTL); + udelay(4); + read_brdctl(p); } - else if (p->features & AHC_ULTRA2) - brdctl = BRDRW_ULTRA2; else - brdctl = BRDRW | BRDCS; - aic_outb(p, brdctl, BRDCTL); - udelay(1); - value = aic_inb(p, BRDCTL); - aic_outb(p, 0, BRDCTL); - udelay(1); - return (value); + { + brdctl = BRDSTB; + if ( !((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) || + (p->flags & AHC_CHNLB) ) + { + brdctl |= BRDCS; + } + brdctl = BRDSTB | BRDCS; + aic_outb(p, brdctl, BRDCTL); + udelay(1); + brdctl |= value; + aic_outb(p, brdctl, BRDCTL); + udelay(1); + brdctl &= ~BRDSTB; + aic_outb(p, brdctl, BRDCTL); + udelay(1); + brdctl &= ~BRDCS; + aic_outb(p, brdctl, BRDCTL); + udelay(1); + } } /*+F************************************************************************* @@ -7770,9 +7780,9 @@ p->host_no); } } + aic_outb(p, sxfrctl1, SXFRCTL1); write_brdctl(p, brddat); release_seeprom(p); - aic_outb(p, sxfrctl1, SXFRCTL1); } } @@ -8086,7 +8096,11 @@ /* Select channel B */ aic_outb(p, aic_inb(p, SBLKCTL) | SELBUSB, SBLKCTL); - term = ((p->flags & AHC_TERM_ENB_B) != 0) ? STPWEN : 0; + if ((p->flags & AHC_SEEPROM_FOUND) || (aic7xxx_override_term != -1)) + term = (aic_inb(p, SXFRCTL1) & STPWEN); + else + term = ((p->flags & AHC_TERM_ENB_B) ? STPWEN : 0); + aic_outb(p, p->scsi_id_b, SCSIID); scsi_conf = aic_inb(p, SCSICONF + 1); aic_outb(p, DFON | SPIOEN, SXFRCTL0); @@ -8100,11 +8114,18 @@ aic_outb(p, aic_inb(p, SBLKCTL) & ~SELBUSB, SBLKCTL); } - term = ((p->flags & AHC_TERM_ENB_SE_LOW) != 0) ? STPWEN : 0; if (p->features & AHC_ULTRA2) + { aic_outb(p, p->scsi_id, SCSIID_ULTRA2); + } else + { aic_outb(p, p->scsi_id, SCSIID); + } + if ((p->flags & AHC_SEEPROM_FOUND) || (aic7xxx_override_term != -1)) + term = (aic_inb(p, SXFRCTL1) & STPWEN); + else + term = ((p->flags & (AHC_TERM_ENB_A|AHC_TERM_ENB_LVD)) ? STPWEN : 0); scsi_conf = aic_inb(p, SCSICONF); aic_outb(p, DFON | SPIOEN, SXFRCTL0); aic_outb(p, (scsi_conf & ENSPCHK) | STIMESEL | term | @@ -8794,27 +8815,33 @@ } if (p->flags & AHC_NEWEEPROM_FMT) { - if ( (sc->device_flags[i] & CFNEWULTRAFORMAT) && - !(p->features & AHC_ULTRA2) ) + if ( !(p->features & AHC_ULTRA2) ) { /* * I know of two different Ultra BIOSes that do this differently. * One on the Gigabyte 6BXU mb that wants flags[i] & CFXFER to - * be == to 0x03 and SYNCISULTRA to be true to mean 40MByte/s + * be == to 0x03 and SYNCHISULTRA to be true to mean 40MByte/s * while on the IBM Netfinity 5000 they want the same thing * to be something else, while flags[i] & CFXFER == 0x03 and - * SYNCISULTRA false should be 40MByte/s. So, we set both to + * SYNCHISULTRA false should be 40MByte/s. So, we set both to * 40MByte/s and the lower speeds be damned. People will have * to select around the conversely mapped lower speeds in order * to select lower speeds on these boards. */ - if ((sc->device_flags[i] & (CFXFER)) == 0x03) + if ( (sc->device_flags[i] & CFNEWULTRAFORMAT) && + ((sc->device_flags[i] & CFXFER) == 0x03) ) { sc->device_flags[i] &= ~CFXFER; sc->device_flags[i] |= CFSYNCHISULTRA; } + if (sc->device_flags[i] & CFSYNCHISULTRA) + { + p->ultraenb |= mask; + } } - if (sc->device_flags[i] & CFSYNCHISULTRA) + else if ( !(sc->device_flags[i] & CFNEWULTRAFORMAT) && + (p->features & AHC_ULTRA2) && + (sc->device_flags[i] & CFSYNCHISULTRA) ) { p->ultraenb |= mask; } @@ -9035,11 +9062,44 @@ #if defined(__i386__) || defined(__alpha__) +#ifdef CONFIG_PCI + /* + * PCI-bus chipset probe. + */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92) + if (pci_present()) + { + if (pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82450GX, + NULL)) + aic7xxx_no_probe = 1; + if (pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82451NX, + NULL)) + aic7xxx_no_probe = 1; + } +#else +#define PCI_DEVICE_ID_INTEL_82451NX 0x84ca + if (pcibios_present()) + { + unsigned char pci_bus, pci_devfn; + if (!(pcibios_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82450GX, + 0, &pci_bus, &pci_devfn)) ) + aic7xxx_no_probe = 1; + if (!(pcibios_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82451NX, + 0, &pci_bus, &pci_devfn)) ) + aic7xxx_no_probe = 1; + } +#endif /* LINUX_VERSION_CODE */ +#endif /* CONFIG_PCI */ /* * EISA/VL-bus card signature probe. */ slot = MINSLOT; - while ( (slot <= MAXSLOT) && !(aic7xxx_no_probe) ) + while ( (slot <= MAXSLOT) && + !(aic7xxx_no_probe) ) { base = SLOTBASE(slot) + MINREG; @@ -9293,6 +9353,10 @@ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED, AHC_AIC7860_FE, 7, 32, C46 }, + {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_38602, AHC_AIC7860, + AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED, + AHC_AIC7860_FE, 7, + 32, C46 }, {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7860, AHC_AIC7860, AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED, AHC_AIC7860_FE, 7, @@ -9471,6 +9535,23 @@ temp_p->pci_device_fn = pdev->devfn; temp_p->base = pdev->base_address[0]; temp_p->mbase = pdev->base_address[1]; + temp_p->base &= PCI_BASE_ADDRESS_IO_MASK; + temp_p->mbase &= PCI_BASE_ADDRESS_MEM_MASK; + current_p = list_p; + while(current_p) + { + if ( ((current_p->pci_bus == temp_p->pci_bus) && + (current_p->pci_device_fn == temp_p->pci_device_fn)) || + (current_p->base == temp_p->base) ) + { + /* duplicate PCI entry, skip it */ + kfree(temp_p); + temp_p = NULL; + } + current_p = current_p->next; + } + if ( temp_p == NULL ) + continue; if (aic7xxx_verbose & VERBOSE_PROBE2) printk("aic7xxx: <%s> at PCI %d/%d\n", board_names[aic_pdevs[i].board_name_index], @@ -9504,11 +9585,6 @@ #else /* LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92) */ temp_p->pci_bus = pci_bus; temp_p->pci_device_fn = pci_devfn; - if (aic7xxx_verbose & VERBOSE_PROBE2) - printk("aic7xxx: <%s> at PCI %d/%d\n", - board_names[aic_pdevs[i].board_name_index], - PCI_SLOT(temp_p->pci_device_fn), - PCI_FUNC(temp_p->pci_device_fn)); pcibios_read_config_byte(pci_bus, pci_devfn, PCI_INTERRUPT_LINE, &pci_irq); temp_p->irq = pci_irq; @@ -9518,6 +9594,28 @@ pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_1, &mmapbase); temp_p->mbase = mmapbase; + temp_p->base &= PCI_BASE_ADDRESS_IO_MASK; + temp_p->mbase &= PCI_BASE_ADDRESS_MEM_MASK; + current_p = list_p; + while(current_p) + { + if ( ((current_p->pci_bus == temp_p->pci_bus) && + (current_p->pci_device_fn == temp_p->pci_device_fn)) || + (current_p->base == temp_p->base) ) + { + /* duplicate PCI entry, skip it */ + kfree(temp_p); + temp_p = NULL; + } + current_p = current_p->next; + } + if ( temp_p == NULL ) + continue; + if (aic7xxx_verbose & VERBOSE_PROBE2) + printk("aic7xxx: <%s> at PCI %d/%d\n", + board_names[aic_pdevs[i].board_name_index], + PCI_SLOT(temp_p->pci_device_fn), + PCI_FUNC(temp_p->pci_device_fn)); pcibios_read_config_word(pci_bus, pci_devfn, PCI_COMMAND, &command); if (aic7xxx_verbose & VERBOSE_PROBE2) { @@ -9545,12 +9643,6 @@ #endif /* AIC7XXX_STRICT_PCI_SETUP */ #endif /* LINUIX_VERSION_CODE > KERNEL_VERSION(2,1,92) */ - /* - * The first bit (LSB) of PCI_BASE_ADDRESS_0 is always set, so - * we mask it off. - */ - temp_p->base &= PCI_BASE_ADDRESS_IO_MASK; - temp_p->mbase &= PCI_BASE_ADDRESS_MEM_MASK; temp_p->unpause = INTEN; temp_p->pause = temp_p->unpause | PAUSE; if ( ((temp_p->base == 0) && @@ -9568,6 +9660,9 @@ } #ifdef MMAPIO + if ( !(temp_p->flags & AHC_MULTI_CHANNEL) || + ((temp_p->chip != (AHC_AIC7870 | AHC_PCI)) && + (temp_p->chip != (AHC_AIC7880 | AHC_PCI))) ) { unsigned long page_offset, base; @@ -9737,17 +9832,17 @@ aic_outb(temp_p, aic_inb(temp_p, SFUNCT) | ALT_MODE, SFUNCT); /* * Set our options...the last two items set our CRC after x byte - * count in target mode... + * count in target mode... */ aic_outb(temp_p, AUTO_MSGOUT_DE | DIS_MSGIN_DUALEDGE, OPTIONMODE); - aic_outb(temp_p, 0x00, 0x0b); - aic_outb(temp_p, 0x10, 0x0a); + aic_outb(temp_p, 0x00, 0x0b); + aic_outb(temp_p, 0x10, 0x0a); /* * switch back to normal mode... */ aic_outb(temp_p, aic_inb(temp_p, SFUNCT) & ~ALT_MODE, SFUNCT); aic_outb(temp_p, CRCVALCHKEN | CRCENDCHKEN | CRCREQCHKEN | - TARGCRCENDEN | TARGCRCCNTEN, + TARGCRCENDEN | TARGCRCCNTEN, CRCCONTROL1); aic_outb(temp_p, ((aic_inb(temp_p, DSCOMMAND0) | USCBSIZE32 | MPARCKEN | CIOPARCKEN | CACHETHEN) & diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/aic7xxx_proc.c linux.pre11.3/drivers/scsi/aic7xxx_proc.c --- linux.vanilla/drivers/scsi/aic7xxx_proc.c Tue Jun 15 16:49:51 1999 +++ linux.pre11.3/drivers/scsi/aic7xxx_proc.c Tue Jul 20 00:02:00 1999 @@ -29,6 +29,8 @@ * $Id: aic7xxx_proc.c,v 4.1 1997/06/97 08:23:42 deang Exp $ *-M*************************************************************************/ +#include + #define BLS (&aic7xxx_buffer[size]) #define HDRB \ " < 2K 2K+ 4K+ 8K+ 16K+ 32K+ 64K+ 128K+" diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/aic7xxx_reg.h linux.pre11.3/drivers/scsi/aic7xxx_reg.h --- linux.vanilla/drivers/scsi/aic7xxx_reg.h Tue Jun 15 16:49:51 1999 +++ linux.pre11.3/drivers/scsi/aic7xxx_reg.h Mon Jul 19 23:28:00 1999 @@ -459,11 +459,11 @@ #define CRCCONTROL1 0x9d #define CRCONSEEN 0x80 -#define TARGCRCCNTEN 0x40 #define CRCVALCHKEN 0x40 #define CRCENDCHKEN 0x20 #define CRCREQCHKEN 0x10 #define TARGCRCENDEN 0x08 +#define TARGCRCCNTEN 0x04 #define SCSIPHASE 0x9e #define SP_STATUS 0x20 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/atp870u.c linux.pre11.3/drivers/scsi/atp870u.c --- linux.vanilla/drivers/scsi/atp870u.c Wed Mar 10 21:13:04 1999 +++ linux.pre11.3/drivers/scsi/atp870u.c Mon Jul 19 23:28:05 1999 @@ -3,7 +3,9 @@ * * Copyright (C) 1997 Wu Ching Chen * 2.1.x update (C) 1998 Krzysztof G. Baranowski - * + * + * Marcelo Tosatti : SMP fixes + * */ #include @@ -17,6 +19,7 @@ #include #include #include +#include #include #include #include "scsi.h" @@ -60,6 +63,7 @@ static void atp870u_intr_handle(int irq, void *dev_id, struct pt_regs *regs) { + unsigned long flags; unsigned short int tmpcip,id; unsigned char i,j,h,tarid,lun; unsigned char *prd; @@ -364,7 +368,10 @@ outb(0x80,tmport); } */ go_42: + spin_lock_irqsave(&io_request_lock, flags); (*workrequ->scsi_done)(workrequ); + spin_unlock_irqrestore(&io_request_lock, flags); + curr_req[h][tarid]=0; workingu[h]--; if (wide_idu[h] != 0) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/constants.c linux.pre11.3/drivers/scsi/constants.c --- linux.vanilla/drivers/scsi/constants.c Sun Nov 8 15:07:49 1998 +++ linux.pre11.3/drivers/scsi/constants.c Mon Jul 19 23:27:57 1999 @@ -1,6 +1,8 @@ /* * ASCII values for a number of symbolic constants, printing functions, * etc. + * Additions for SCSI 2 and Linux 2.2.x by D. Gilbert (990422) + * */ #define __NO_VERSION__ @@ -37,7 +39,7 @@ /* 04-07 */ "Format Unit", "Read Block Limits", unknown, "Reasssign Blocks", /* 08-0d */ "Read (6)", unknown, "Write (6)", "Seek (6)", unknown, unknown, /* 0e-12 */ unknown, "Read Reverse", "Write Filemarks", "Space", "Inquiry", -/* 13-16 */ unknown, "Recover Buffered Data", "Mode Select", "Reserve", +/* 13-16 */ "Verify", "Recover Buffered Data", "Mode Select", "Reserve", /* 17-1b */ "Release", "Copy", "Erase", "Mode Sense", "Start/Stop Unit", /* 1c-1d */ "Receive Diagnostic", "Send Diagnostic", /* 1e-1f */ "Prevent/Allow Medium Removal", unknown, @@ -46,37 +48,57 @@ static const char *group_1_commands[] = { /* 20-22 */ unknown, unknown, unknown, -/* 23-28 */ unknown, unknown, "Read Capacity", unknown, unknown, "Read (10)", -/* 29-2d */ unknown, "Write (10)", "Seek (10)", unknown, unknown, +/* 23-28 */ unknown, "Define window parameters", "Read Capacity", + unknown, unknown, "Read (10)", +/* 29-2d */ "Read Generation", "Write (10)", "Seek (10)", "Erase", + "Read updated block", /* 2e-31 */ "Write Verify","Verify", "Search High", "Search Equal", /* 32-34 */ "Search Low", "Set Limits", "Prefetch or Read Position", /* 35-37 */ "Synchronize Cache","Lock/Unlock Cache", "Read Defect Data", -/* 38-3c */ "Medium Scan", "Compare","Copy Verify", "Write Buffer", "Read Buffer", +/* 38-3c */ "Medium Scan", "Compare", "Copy Verify", "Write Buffer", + "Read Buffer", /* 3d-3f */ "Update Block", "Read Long", "Write Long", }; static const char *group_2_commands[] = { /* 40-41 */ "Change Definition", "Write Same", -/* 42-48 */ unknown, "Read TOC", unknown, unknown, unknown, unknown, unknown, -/* 49-4f */ unknown, unknown, unknown, "Log Select", "Log Sense", unknown, unknown, +/* 42-48 */ "Read sub-channel", "Read TOC", "Read header", + "Play audio (10)", unknown, "Play audio msf", + "Play audio track/index", +/* 49-4f */ "Play track relative (10)", unknown, "Pause/resume", + "Log Select", "Log Sense", unknown, unknown, /* 50-55 */ unknown, unknown, unknown, unknown, unknown, "Mode Select (10)", /* 56-5b */ unknown, unknown, unknown, unknown, "Mode Sense (10)", unknown, /* 5c-5f */ unknown, unknown, unknown, }; +/* The following are 12 byte commands in group 5 */ +static const char *group_5_commands[] = { +/* a0-a5 */ unknown, unknown, unknown, unknown, unknown, + "Move medium/play audio(12)", +/* a6-a9 */ "Exchange medium", unknown, "Read(12)", "Play track relative(12)", +/* aa-ae */ "Write(12)", unknown, "Erase(12)", unknown, + "Write and verify(12)", +/* af-b1 */ "Verify(12)", "Search data high(12)", "Search data equal(12)", +/* b2-b4 */ "Search data low(12)", "Set limits(12)", unknown, +/* b5-b6 */ "Request volume element address", "Send volume tag", +/* b7-b9 */ "Read defect data(12)", "Read element status", unknown, +/* ba-bf */ unknown, unknown, unknown, unknown, unknown, unknown, +}; + + #define group(opcode) (((opcode) >> 5) & 7) #define RESERVED_GROUP 0 #define VENDOR_GROUP 1 -#define NOTEXT_GROUP 2 static const char **commands[] = { group_0_commands, group_1_commands, group_2_commands, (const char **) RESERVED_GROUP, (const char **) RESERVED_GROUP, - (const char **) NOTEXT_GROUP, (const char **) VENDOR_GROUP, + group_5_commands, (const char **) VENDOR_GROUP, (const char **) VENDOR_GROUP }; @@ -89,9 +111,6 @@ case RESERVED_GROUP: printk("%s(0x%02x) ", reserved, opcode); break; - case NOTEXT_GROUP: - printk("%s(0x%02x) ", unknown, opcode); - break; case VENDOR_GROUP: printk("%s(0x%02x) ", vendor, opcode); break; @@ -119,15 +138,18 @@ #if (CONSTANTS & CONST_STATUS) static const char * statuses[] = { -/* 0-4 */ "Good", "Check Condition", "Condition Good", unknown, "Busy", -/* 5-9 */ unknown, unknown, unknown, "Intermediate Good", unknown, -/* a-d */ "Intermediate Good", unknown, "Reservation Conflict", unknown, -/* e-f */ unknown, unknown, +/* 0-4 */ "Good", "Check Condition", "Condition Met", unknown, "Busy", +/* 5-9 */ unknown, unknown, unknown, "Intermediate", unknown, +/* a-c */ "Intermediate-Condition Met", unknown, "Reservation Conflict", +/* d-10 */ unknown, unknown, unknown, unknown, +/* 11-14 */ "Command Terminated", unknown, unknown, "Queue Full", +/* 15-1a */ unknown, unknown, unknown, unknown, unknown, unknown, +/* 1b-1f */ unknown, unknown, unknown, unknown, unknown, }; #endif void print_status (int status) { - status = (status >> 1) & 0xf; + status = (status >> 1) & 0x1f; #if (CONSTANTS & CONST_STATUS) printk("%s ",statuses[status]); #else @@ -405,8 +427,10 @@ s = sizeof(SCpnt->sense_buffer); if (!valid) - printk("extra data not valid "); - + printk("[valid=0] "); + printk("Info fld=0x%x, ", (int)((sense_buffer[3] << 24) | + (sense_buffer[4] << 16) | (sense_buffer[5] << 8) | + sense_buffer[6])); if (sense_buffer[2] & 0x80) printk( "FMK "); /* current command has read a filemark */ if (sense_buffer[2] & 0x40) @@ -427,7 +451,7 @@ error = "Invalid"; } - printk("%s error ", error); + printk("%s ", error); #if (CONSTANTS & CONST_SENSE) printk( "%s%s: sense key %s\n", devclass, @@ -603,7 +627,8 @@ #if (CONSTANTS & CONST_HOST) static const char * hostbyte_table[]={ "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",NULL}; +"DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR", +"DID_PASSTHROUGH", "DID_SOFT_ERROR", NULL}; void print_hostbyte(int scsiresult) { static int maxcode=0; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/dec_esp.c linux.pre11.3/drivers/scsi/dec_esp.c --- linux.vanilla/drivers/scsi/dec_esp.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/scsi/dec_esp.c Mon Jul 19 23:28:06 1999 @@ -0,0 +1,351 @@ +/* + * dec_esp.c: Driver for SCSI chips on IOASIC based TURBOchannel DECstations + * + * TURBOchannel changes by Harald Koerfgen + * + * based on jazz_esp.c: + * Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de) + * + * jazz_esp is based on David S. Miller's ESP driver and cyber_esp + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "NCR53C9x.h" +#include "dec_esp.h" + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count); +static void dma_drain(struct NCR_ESP *esp); +static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd * sp); +static void dma_dump_state(struct NCR_ESP *esp); +static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length); +static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length); +static void dma_ints_off(struct NCR_ESP *esp); +static void dma_ints_on(struct NCR_ESP *esp); +static int dma_irq_p(struct NCR_ESP *esp); +static int dma_ports_p(struct NCR_ESP *esp); +static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write); +static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp); +static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp); +static void dma_advance_sg(Scsi_Cmnd * sp); + + +volatile unsigned char cmd_buffer[16]; + /* This is where all commands are put + * before they are trasfered to the ESP chip + * via PIO. + */ + +volatile unsigned long *scsi_dma_ptr; +volatile unsigned long *scsi_next_ptr; +volatile unsigned long *scsi_scr; +volatile unsigned long *ioasic_ssr; +volatile unsigned long *scsi_sdr0; +volatile unsigned long *scsi_sdr1; + +static void scsi_dma_int(int, void *, struct pt_regs *); + +/***************************************************************** Detection */ +int dec_esp_detect(Scsi_Host_Template * tpnt) +{ + struct NCR_ESP *esp; + struct ConfigDev *esp_dev; + + if (IOASIC) { + esp_dev = 0; + esp = esp_allocate(tpnt, (void *) esp_dev); + + scsi_dma_ptr = (unsigned long *) (system_base + IOCTL + SCSI_DMA_P); + scsi_next_ptr = (unsigned long *) (system_base + IOCTL + SCSI_DMA_BP); + scsi_scr = (unsigned long *) (system_base + IOCTL + SCSI_SCR); + ioasic_ssr = (unsigned long *) (system_base + IOCTL + SSR); + scsi_sdr0 = (unsigned long *) (system_base + IOCTL + SCSI_SDR0); + scsi_sdr1 = (unsigned long *) (system_base + IOCTL + SCSI_SDR1); + + /* Do command transfer with programmed I/O */ + esp->do_pio_cmds = 1; + + /* Required functions */ + esp->dma_bytes_sent = &dma_bytes_sent; + esp->dma_can_transfer = &dma_can_transfer; + esp->dma_dump_state = &dma_dump_state; + esp->dma_init_read = &dma_init_read; + esp->dma_init_write = &dma_init_write; + esp->dma_ints_off = &dma_ints_off; + esp->dma_ints_on = &dma_ints_on; + esp->dma_irq_p = &dma_irq_p; + esp->dma_ports_p = &dma_ports_p; + esp->dma_setup = &dma_setup; + + /* Optional functions */ + esp->dma_barrier = 0; + esp->dma_drain = &dma_drain; + esp->dma_invalidate = 0; + esp->dma_irq_entry = 0; + esp->dma_irq_exit = 0; + esp->dma_poll = 0; + esp->dma_reset = 0; + esp->dma_led_off = 0; + esp->dma_led_on = 0; + + /* virtual DMA functions */ + esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one; + esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl; + esp->dma_mmu_release_scsi_one = 0; + esp->dma_mmu_release_scsi_sgl = 0; + esp->dma_advance_sg = &dma_advance_sg; + + + /* SCSI chip speed */ + esp->cfreq = 25000000; + + /* + * we don't give the address of DMA channel, but the number + * of DMA channel, so we can use the jazz DMA functions + * + */ + esp->dregs = JAZZ_SCSI_DMA; + + /* ESP register base */ + esp->eregs = (struct ESP_regs *) (system_base + SCSI); + + /* Set the command buffer */ + esp->esp_command = (volatile unsigned char *) cmd_buffer; + + /* get virtual dma address for command buffer */ + esp->esp_command_dvma = KSEG1ADDR((volatile unsigned char *) cmd_buffer); + + esp->irq = SCSI_INT; + request_irq(esp->irq, esp_intr, SA_INTERRUPT, "NCR 53C94 SCSI", + NULL); + request_irq(SCSI_DMA_INT, scsi_dma_int, SA_INTERRUPT, "JUNKIO SCSI DMA", + NULL); + + /* + * FIXME, look if the scsi id is availabe from NVRAM + */ + esp->scsi_id = 7; + + /* Check for differential SCSI-bus */ + /* What is this stuff? */ + esp->diff = 0; + + esp_initialize(esp); + + printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use); + esps_running = esps_in_use; + return esps_in_use; + } + return 0; +} + +/************************************************************* DMA Functions */ +static void scsi_dma_int(int irq, void *dev_id, struct pt_regs *regs) +{ + extern volatile unsigned int *isr; + unsigned int dummy; + + if (*isr & SCSI_PTR_LOADED) { + /* next page */ + *scsi_next_ptr = ((*scsi_dma_ptr + PAGE_SIZE) & PAGE_MASK) << 3; + *isr &= ~SCSI_PTR_LOADED; + } else { + printk("Got unexpected SCSI DMA Interrupt! < "); + if (*isr & SCSI_PAGOVRRUN) + printk("SCSI_PAGOVRRUN "); + if (*isr & SCSI_DMA_MEMRDERR) + printk("SCSI_DMA_MEMRDERR "); + printk(">\n"); +// panic("stop"); + *isr &= ~(SCSI_PAGOVRRUN || SCSI_DMA_MEMRDERR); + } + + /* + * This driver will only work on IOASIC machines + * so we can avoid an indirect function call here + * and flush the writeback buffer the fast way + */ + dummy = *isr; + dummy = *isr; +} + +static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count) +{ + return fifo_count; +} + +static void dma_drain(struct NCR_ESP *esp) +{ + unsigned long nw; + unsigned short *p = KSEG1ADDR((unsigned short *) ((*scsi_dma_ptr) >> 3)); + + /* + * Is there something in the dma buffers left? + */ + if (nw = *scsi_scr) { + switch (nw) { + case 1: + *p = (unsigned short) *scsi_sdr0; + break; + case 2: + *p++ = (unsigned short) (*scsi_sdr0); + *p = (unsigned short) ((*scsi_sdr0) >> 16); + break; + case 3: + *p++ = (unsigned short) (*scsi_sdr0); + *p++ = (unsigned short) ((*scsi_sdr0) >> 16); + *p = (unsigned short) (*scsi_sdr1); + break; + default: + printk("Strange: %d words in dma buffer left\n", (int) nw); + break; + } + } +} + +static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd * sp) +{ + return sp->SCp.this_residual;; +} + +static void dma_dump_state(struct NCR_ESP *esp) +{ +/* + ESPLOG(("esp%d: dma -- enable <%08x> residue <%08x\n", + esp->esp_id, vdma_get_enable((int)esp->dregs), vdma_get_resdiue((int)esp->dregs))); + */ +} + +static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length) +{ + extern volatile unsigned int *isr; + unsigned int dummy; + + if (vaddress & 3) + panic("dec_efs.c: unable to handle partial word transfers, yet..."); + + dma_cache_wback_inv((unsigned long) phys_to_virt(vaddress), length); + + *ioasic_ssr &= ~SCSI_DMA_EN; + *scsi_scr = 0; + *scsi_dma_ptr = vaddress << 3; + + /* prepare for next page */ + *scsi_next_ptr = ((vaddress + PAGE_SIZE) & PAGE_MASK) << 3; + *ioasic_ssr |= (SCSI_DMA_DIR | SCSI_DMA_EN); + + /* + * see above + */ + dummy = *isr; + dummy = *isr; +} + +static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length) +{ + extern volatile unsigned int *isr; + unsigned int dummy; + + if (vaddress & 3) + panic("dec_efs.c: unable to handle partial word transfers, yet..."); + + dma_cache_wback_inv((unsigned long) phys_to_virt(vaddress), length); + + *ioasic_ssr &= ~(SCSI_DMA_DIR | SCSI_DMA_EN); + *scsi_scr = 0; + *scsi_dma_ptr = vaddress << 3; + + /* prepare for next page */ + *scsi_next_ptr = ((vaddress + PAGE_SIZE) & PAGE_MASK) << 3; + *ioasic_ssr |= SCSI_DMA_EN; + + /* + * see above + */ + dummy = *isr; + dummy = *isr; +} + +static void dma_ints_off(struct NCR_ESP *esp) +{ + disable_irq(SCSI_DMA_INT); +} + +static void dma_ints_on(struct NCR_ESP *esp) +{ + enable_irq(SCSI_DMA_INT); +} + +static int dma_irq_p(struct NCR_ESP *esp) +{ + return (esp->eregs->esp_status & ESP_STAT_INTR); +} + +static int dma_ports_p(struct NCR_ESP *esp) +{ +/* + * FIXME: what's this good for? + */ + return 1; +} + +static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) +{ + /* + * On the Sparc, DMA_ST_WRITE means "move data from device to memory" + * so when (write) is true, it actually means READ! + */ + if (write) { + dma_init_read(esp, addr, count); + } else { + dma_init_write(esp, addr, count); + } +} + +/* + * These aren't used yet + */ +static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp) +{ + sp->SCp.have_data_in = PHYSADDR(sp->SCp.buffer); + sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.have_data_in); +} + +static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp) +{ + int sz = sp->SCp.buffers_residual; + struct mmu_sglist *sg = (struct mmu_sglist *) sp->SCp.buffer; + + while (sz >= 0) { + sg[sz].dvma_addr = PHYSADDR(sg[sz].addr); + sz--; + } + sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_address); +} + +static void dma_advance_sg(Scsi_Cmnd * sp) +{ + sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_address); +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/dec_esp.h linux.pre11.3/drivers/scsi/dec_esp.h --- linux.vanilla/drivers/scsi/dec_esp.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/scsi/dec_esp.h Mon Jul 19 23:28:06 1999 @@ -0,0 +1,42 @@ +/* dec_esp.h: Defines and structures for the JAZZ SCSI driver. + * + * DECstation changes Copyright (C) 1998 Harald Koerfgen + * + * based on jazz_esp.h: + * Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de) + */ + +#ifndef DEC_ESP_H +#define DEC_ESP_H + +#define EREGS_PAD(n) unchar n[3]; + +#include "NCR53C9x.h" + + +extern int dec_esp_detect(struct SHT *); +extern const char *esp_info(struct Scsi_Host *); +extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +extern int esp_command(Scsi_Cmnd *); +extern int esp_abort(Scsi_Cmnd *); +extern int esp_reset(Scsi_Cmnd *, unsigned int); +extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, + int hostno, int inout); + +#define SCSI_DEC_ESP { \ + proc_dir: &proc_scsi_esp, \ + proc_info: &esp_proc_info, \ + name: "PMAZ-AA", \ + detect: dec_esp_detect, \ + info: esp_info, \ + command: esp_command, \ + queuecommand: esp_queue, \ + abort: esp_abort, \ + reset: esp_reset, \ + can_queue: 7, \ + this_id: 7, \ + sg_tablesize: SG_ALL, \ + cmd_per_lun: 1, \ + use_clustering: DISABLE_CLUSTERING, } + +#endif /* DEC_ESP_H */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/eata_dma.c linux.pre11.3/drivers/scsi/eata_dma.c --- linux.vanilla/drivers/scsi/eata_dma.c Thu Dec 31 18:10:44 1998 +++ linux.pre11.3/drivers/scsi/eata_dma.c Tue Jul 20 00:02:10 1999 @@ -31,6 +31,10 @@ * mike@i-Connect.Net * * neuffer@mail.uni-mainz.de * * * + * + * Changes: + * Marcelo Tosatti, Jul/8/99 : SMP fixes + * * This program is free software; you can redistribute it * * and/or modify it under the terms of the GNU General * * Public License as published by the Free Software * @@ -777,7 +781,10 @@ x, sp->pid); DBG(DBG_ABNORM && DBG_DELAY, DELAY(1)); + + spin_lock_irqsave(&io_request_lock, flags); sp->scsi_done(sp); + spin_unlock_irqrestore(&io_request_lock, flags); } HD(cmd)->state = FALSE; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/gdth_proc.c linux.pre11.3/drivers/scsi/gdth_proc.c --- linux.vanilla/drivers/scsi/gdth_proc.c Fri Apr 16 22:10:54 1999 +++ linux.pre11.3/drivers/scsi/gdth_proc.c Tue Jul 20 00:02:18 1999 @@ -3,6 +3,7 @@ */ #include "gdth_ioctl.h" +#include int gdth_proc_info(char *buffer,char **start,off_t offset,int length, int hostno,int inout) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/ide-scsi.c linux.pre11.3/drivers/scsi/ide-scsi.c --- linux.vanilla/drivers/scsi/ide-scsi.c Wed Apr 28 19:14:28 1999 +++ linux.pre11.3/drivers/scsi/ide-scsi.c Tue Jul 20 00:02:57 1999 @@ -1,7 +1,7 @@ /* - * linux/drivers/scsi/ide-scsi.c Version 0.6 Jan 27, 1998 + * linux/drivers/scsi/ide-scsi.c Version 0.9 Jul 4, 1999 * - * Copyright (C) 1996 - 1998 Gadi Oxman + * Copyright (C) 1996 - 1999 Gadi Oxman */ /* @@ -25,10 +25,11 @@ * Fix MODE_SENSE_6/MODE_SELECT_6/INQUIRY translation. * Ver 0.7 Dec 04 98 Ignore commands where lun != 0 to avoid multiple * detection of devices with CONFIG_SCSI_MULTI_LUN - * Ver 0.8 Feb 05 99 Optical media need translation too. + * 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. */ -#define IDESCSI_VERSION "0.6" +#define IDESCSI_VERSION "0.9" #include #include @@ -632,9 +633,13 @@ { ide_drive_t *drive = idescsi_drives[dev->id]; idescsi_scsi_t *scsi = drive->driver_data; + int enable = (int) arg; if (cmd == SG_SET_TRANSFORM) { - set_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); + if (enable) + set_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); + else + clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); return 0; } else if (cmd == SG_GET_TRANSFORM) return put_user(test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform), (int *) arg); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/in2000.h linux.pre11.3/drivers/scsi/in2000.h --- linux.vanilla/drivers/scsi/in2000.h Sun Nov 8 15:07:50 1998 +++ linux.pre11.3/drivers/scsi/in2000.h Tue Jul 20 01:43:00 1999 @@ -67,7 +67,7 @@ orl %%ecx, %%ecx \n \ jz 1f \n \ rep \n \ - insw %%dx \n \ + insw (%%dx),%%es:(%%edi) \n \ 1: " \ : "=D" (sp) /* output */ \ : "d" (f), "D" (sp), "c" (i) /* input */ \ @@ -79,7 +79,7 @@ orl %%ecx, %%ecx \n \ jz 1f \n \ rep \n \ - outsw %%dx \n \ + outsw %%ds:(%%esi),(%%dx) \n \ 1: " \ : "=S" (sp) /* output */ \ : "d" (f), "S" (sp), "c" (i) /* input */ \ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/jazz_esp.c linux.pre11.3/drivers/scsi/jazz_esp.c --- linux.vanilla/drivers/scsi/jazz_esp.c Sun Nov 8 15:08:00 1998 +++ linux.pre11.3/drivers/scsi/jazz_esp.c Mon Jul 19 23:28:05 1999 @@ -1,7 +1,7 @@ /* * jazz_esp.c: Driver for SCSI chip on Mips Magnum Boards (JAZZ architecture) * - * Copyright (C) 1997 Thomas Boegndoerfer (tsbogend@alpha.franken.de) + * Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de) * * jazz_esp is based on David S. Miller's ESP driver and cyber_esp */ @@ -161,7 +161,7 @@ { ESPLOG(("esp%d: dma -- enable <%08x> residue <%08x\n", - esp->esp_id, vdma_get_enable((int)esp->dregs), vdma_get_resdiue((int)esp->dregs))); + esp->esp_id, vdma_get_enable((int)esp->dregs), vdma_get_residue((int)esp->dregs))); } static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/megaraid.c linux.pre11.3/drivers/scsi/megaraid.c --- linux.vanilla/drivers/scsi/megaraid.c Thu May 27 22:11:56 1999 +++ linux.pre11.3/drivers/scsi/megaraid.c Tue Jul 20 00:03:10 1999 @@ -9,14 +9,14 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Version : 1.00 + * Version : 1.01 * * Description: Linux device driver for AMI MegaRAID controller * * Supported controllers: MegaRAID 418, 428, 438, 466, 762 * * Maintainer: Jeff L Jones - * + * Xi Shine Chen * History: * * Version 0.90: @@ -38,10 +38,10 @@ * Removed setting of SA_INTERRUPT flag when requesting Irq. * * Version 0.92ac: - * Small changes to the comments/formatting. Plus a couple of + * Small changes to the comments/formatting. Plus a couple of * added notes. Returned to the authors. No actual code changes * save printk levels. - * 8 Oct 98 Alan Cox + * 8 Oct 98 Alan Cox * * Merged with 2.1.131 source tree. * 12 Dec 98 K. Baranowski @@ -73,14 +73,15 @@ * * Version 0.96: * 762 fully supported. + * * Version 0.97: * Changed megaraid_command to use wait_queue. * Fixed bug of undesirably detecting HP onboard controllers which - * are disabled. + * are disabled. * * Version 1.00: * Checks to see if an irq ocurred while in isr, and runs through - * routine again. + * routine again. * Copies mailbox to temp area before processing in isr * Added barrier() in busy wait to fix volatility bug * Uses separate list for freed Scbs, keeps track of cmd state @@ -88,6 +89,11 @@ * Full multi-io commands working stablely without previous problems * Added skipXX LILO option for Madrona motherboard support * + * Version 1.01: + * Fixed bug in mega_cmd_done() for megamgr control commands, + * the host_byte in the result code from the scsi request to + * scsi midlayer is set to DID_BAD_TARGET when adapter's + * returned codes are 0xF0 and oxF4. * * BUGS: * Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that @@ -100,6 +106,7 @@ #define CRLFSTR "\n" +#include #include #ifdef MODULE @@ -132,6 +139,7 @@ #include #include #include /* for kmalloc() */ +#include /* for CONFIG_PCI */ #if LINUX_VERSION_CODE < 0x20100 #include #else @@ -482,6 +490,8 @@ { int islogical; Scsi_Cmnd *SCpnt; + mega_passthru *pthru; + mega_mailbox *mbox; if (pScb == NULL) { TRACE(("NULL pScb in mega_cmd_done!")); @@ -489,7 +499,9 @@ } SCpnt = pScb->SCpnt; - freeSCB(megaCfg, pScb); + /*freeSCB(megaCfg, pScb);*/ /*delay this to the end of this func.*/ + pthru = &pScb->pthru; + mbox = (mega_mailbox *) &pScb->mboxData; if (SCpnt == NULL) { TRACE(("NULL SCpnt in mega_cmd_done!")); @@ -507,23 +519,48 @@ !islogical) { status = 0xF0; } - - SCpnt->result = 0; /* clear result; otherwise, success returns corrupt - value */ +/* clear result; otherwise, success returns corrupt value */ + SCpnt->result = 0; + +if (SCpnt->cmnd[0] & 0x80) /* ioctl from megamgr */{ + /*printk(KERN_WARNING "***megamgr cmnd status= %x h\n ", status); */ + switch (status) { + case 0xF0: + case 0xF4: + SCpnt->result=(DID_BAD_TARGET<<16)|status; + break; + default: + SCpnt->result|=status; + }/*end of switch*/ +} +else{ /* Convert MegaRAID status to Linux error code */ switch (status) { - case 0x00: /* SUCCESS */ - case 0x02: /* ERROR_ABORTED */ + case 0x00: /* SUCCESS , i.e. SCSI_STATUS_GOOD*/ SCpnt->result |= (DID_OK << 16); break; - case 0x8: /* ERR_DEST_DRIVE_FAILED */ - SCpnt->result |= (DID_BUS_BUSY << 16); + case 0x02: /* ERROR_ABORTED, i.e. SCSI_STATUS_CHECK_CONDITION */ + /*set sense_buffer and result fields*/ + if( mbox->cmd==MEGA_MBOXCMD_PASSTHRU ){ + memcpy( SCpnt->sense_buffer , pthru->reqsensearea, 14); + SCpnt->result = (DRIVER_SENSE<<24)|(DID_ERROR << 16)|status; + } + else{ + SCpnt->sense_buffer[0]=0x70; + SCpnt->sense_buffer[2]=ABORTED_COMMAND; + SCpnt->result |= (CHECK_CONDITION << 1); + } + break; + case 0x08: /* ERR_DEST_DRIVE_FAILED, i.e. SCSI_STATUS_BUSY */ + SCpnt->result |= (DID_BUS_BUSY << 16)|status; break; - default: + default: SCpnt->result |= (DID_BAD_TARGET << 16); break; } + } + freeSCB(megaCfg, pScb); /* Add Scsi_Command to end of completed queue */ ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble); @@ -741,7 +778,6 @@ if (data[0] == 0x03) { /* passthrough command */ unsigned char cdblen = data[2]; - pthru = &pScb->pthru; memset (pthru, 0, sizeof (mega_passthru)); pthru->islogical = (data[cdblen+3] & 0x80) ? 1:0; @@ -953,7 +989,7 @@ u_char byte; u_long cmdDone; Scsi_Cmnd *SCpnt; - + mboxData[0x1] = (pScb ? pScb->idx + 1: 0x0); /* Set cmdid */ mboxData[0xF] = 1; /* Set busy */ @@ -963,6 +999,10 @@ } #endif +#if DEBUG + showMbox(pScb); +#endif + /* Wait until mailbox is free */ while (mega_busyWaitMbox (megaCfg)) { printk("Blocked mailbox!!\n"); @@ -984,9 +1024,9 @@ callDone(SCpnt); return 0; } + pLastScb = pScb; - /* Copy mailbox data into host structure */ memcpy (mbox, mboxData, 16); @@ -995,7 +1035,7 @@ /* Issue interrupt (non-blocking) command */ if (megaCfg->flag & BOARD_QUARTZ) { - mbox->mraid_poll = 0; + mbox->mraid_poll = 0; mbox->mraid_ack = 0; WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x1); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/megaraid.h linux.pre11.3/drivers/scsi/megaraid.h --- linux.vanilla/drivers/scsi/megaraid.h Thu May 27 22:11:56 1999 +++ linux.pre11.3/drivers/scsi/megaraid.h Tue Jul 20 01:43:01 1999 @@ -1,6 +1,6 @@ #ifndef __MEGARAID_H__ #define __MEGARAID_H__ - + #ifndef LINUX_VERSION_CODE #include #endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/ncr53c8xx.c linux.pre11.3/drivers/scsi/ncr53c8xx.c --- linux.vanilla/drivers/scsi/ncr53c8xx.c Fri Apr 16 22:10:54 1999 +++ linux.pre11.3/drivers/scsi/ncr53c8xx.c Mon Jul 19 23:28:00 1999 @@ -5003,7 +5003,7 @@ ** Force ordered tag if necessary to avoid timeouts ** and to preserve interactivity. */ - if (lp && lp->tags_stime + (3*HZ) <= jiffies) { + if (lp && time_before_eq(lp->tags_stime + 3*HZ, jiffies)) { if (lp->tags_smap) { order = M_ORDERED_TAG; if ((DEBUG_FLAGS & DEBUG_TAGS)||bootverbose>2){ @@ -9850,7 +9850,8 @@ /* PCI_CACHE_LINE_SIZE value is in 32-bit words. */ cache_line_size = 64 / sizeof(u_int32); if (initverbose >= 2) - printk("ncr53c8xx: setting PCI_CACHE_LINE_SIZE to %d (fixup)\n", cache_line_size); + printk("ncr53c8xx: setting PCI_CACHE_LINE_SIZE to %d (fixup)\n", + cache_line_size); pcibios_write_config_byte(bus, device_fn, PCI_CACHE_LINE_SIZE, cache_line_size); pcibios_read_config_byte(bus, device_fn, @@ -9858,7 +9859,7 @@ } if (!latency_timer) { - latency_timer = 128; + latency_timer = 64; if (initverbose >= 2) printk("ncr53c8xx: setting PCI_LATENCY_TIMER to %d bus clocks (fixup)\n", latency_timer); pcibios_write_config_byte(bus, device_fn, diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/qlogicfc.c linux.pre11.3/drivers/scsi/qlogicfc.c --- linux.vanilla/drivers/scsi/qlogicfc.c Fri Apr 16 22:10:54 1999 +++ linux.pre11.3/drivers/scsi/qlogicfc.c Tue Jul 20 00:03:25 1999 @@ -1,5 +1,5 @@ /* - * QLogic ISP2100 SCSI-FCP + * QLogic ISP2x00 SCSI-FCP * Written by Erik H. Moe, ehm@cris.com * Copyright 1995, Erik H. Moe * @@ -17,7 +17,7 @@ /* Renamed and updated to 1.3.x by Michael Griffith */ /* This is a version of the isp1020 driver which was modified by - * Chris Loveland to support the isp2100 + * Chris Loveland to support the isp2100 and isp2200 */ /* @@ -63,28 +63,30 @@ /* Configuration section **************************************************** */ -/* Set the following macro to 1 to reload the ISP2100's firmware. This is - version 1.15.19 of the firmware. */ +/* Set the following macro to 1 to reload the ISP2x00's firmware. This is + version 1.15.37 of the isp2100's firmware and version 2.00.16 of the + isp2200's firmware. +*/ #define RELOAD_FIRMWARE 1 #define USE_NVRAM_DEFAULTS 1 -#define ISP2100_PORTDB 1 +#define ISP2x00_PORTDB 1 /* Set the following to 1 to include fabric support, fabric support is * currently not as well tested as the other aspects of the driver */ -#define ISP2100_FABRIC 0 +#define ISP2x00_FABRIC 0 /* Macros used for debugging */ /* -#define DEBUG_ISP2100 1 -#define DEBUG_ISP2100_INT 1 -#define DEBUG_ISP2100_INTR 1 -#define DEBUG_ISP2100_SETUP 1 +#define DEBUG_ISP2x00 1 +#define DEBUG_ISP2x00_INT 1 +#define DEBUG_ISP2x00_INTR 1 +#define DEBUG_ISP2x00_SETUP 1 -#define DEBUG_ISP2100_FABRIC 1 +#define DEBUG_ISP2x00_FABRIC 1 */ /* #define TRACE_ISP 1 */ @@ -127,51 +129,49 @@ #define TRACE(w, i, a) #endif -#if DEBUG_ISP2100_FABRIC +#if DEBUG_ISP2x00_FABRIC #define DEBUG_FABRIC(x) x #else #define DEBUG_FABRIC(x) -#endif /* DEBUG_ISP2100_FABRIC */ +#endif /* DEBUG_ISP2x00_FABRIC */ -#if DEBUG_ISP2100 -#define ENTER(x) printk("isp2100 : entering %s()\n", x); -#define LEAVE(x) printk("isp2100 : leaving %s()\n", x); +#if DEBUG_ISP2x00 +#define ENTER(x) printk("isp2x00 : entering %s()\n", x); +#define LEAVE(x) printk("isp2x00 : leaving %s()\n", x); #define DEBUG(x) x #else #define ENTER(x) #define LEAVE(x) #define DEBUG(x) -#endif /* DEBUG_ISP2100 */ +#endif /* DEBUG_ISP2x00 */ -#if DEBUG_ISP2100_INTR -#define ENTER_INTR(x) printk("isp2100 : entering %s()\n", x); -#define LEAVE_INTR(x) printk("isp2100 : leaving %s()\n", x); +#if DEBUG_ISP2x00_INTR +#define ENTER_INTR(x) printk("isp2x00 : entering %s()\n", x); +#define LEAVE_INTR(x) printk("isp2x00 : leaving %s()\n", x); #define DEBUG_INTR(x) x #else #define ENTER_INTR(x) #define LEAVE_INTR(x) #define DEBUG_INTR(x) -#endif /* DEBUG ISP2100_INTR */ +#endif /* DEBUG ISP2x00_INTR */ -#if defined(__i386__) -#define virt_to_bus_low32(x) virt_to_bus(x) -#define virt_to_bus_high32(x) 0x0 -#define bus_to_virt_low32(x) bus_to_virt(x) -#define bus_to_virt_high32(x) 0x0 -#elif defined(__alpha__) +#if BITS_PER_LONG > 32 #define virt_to_bus_low32(x) ((u32) (0xffffffff & virt_to_bus(x))) #define virt_to_bus_high32(x) ((u32) (0xffffffff & (virt_to_bus(x)>>32))) #define bus_to_virt_low32(x) ((u32) (0xffffffff & bus_to_virt(x))) #define bus_to_virt_high32(x) ((u32) (0xffffffff & (bus_to_virt(x)>>32))) +#else +#define virt_to_bus_low32(x) virt_to_bus(x) +#define virt_to_bus_high32(x) 0x0 +#define bus_to_virt_low32(x) bus_to_virt(x) +#define bus_to_virt_high32(x) 0x0 #endif -#define ISP2100_REV_ID 1 +#define ISP2100_REV_ID1 1 #define ISP2100_REV_ID3 3 - -#define MAX_TARGETS 16 -#define MAX_LUNS 8 +#define ISP2200_REV_ID5 5 /* host configuration and control registers */ #define HOST_HCCR 0xc0 /* host command and control */ @@ -219,6 +219,8 @@ #define PORT_DB_CHANGED 0x8014 #define CHANGE_NOTIFICATION 0x8015 #define SCSI_COMMAND_COMPLETE 0x8020 +#define POINT_TO_POINT_UP 0x8030 +#define CONNECTION_MODE 0x8036 struct Entry_header { u_char entry_type; @@ -228,19 +230,48 @@ }; /* entry header type commands */ +#if BITS_PER_LONG > 32 #define ENTRY_COMMAND 0x19 #define ENTRY_CONTINUATION 0x0a +#else +#define ENTRY_COMMAND 0x11 +#define ENTRY_CONTINUATION 0x02 +#endif + #define ENTRY_STATUS 0x03 #define ENTRY_MARKER 0x04 + /* entry header flag definitions */ #define EFLAG_BUSY 2 #define EFLAG_BAD_HEADER 4 #define EFLAG_BAD_PAYLOAD 8 +#if BITS_PER_LONG > 32 +struct dataseg { + u_int d_base; + u_int d_base_hi; + u_int d_count; +}; + +struct Command_Entry { + struct Entry_header hdr; + u_int handle; + u_char target_lun; + u_char target_id; + u_short expanded_lun; + u_short control_flags; + u_short rsvd2; + u_short time_out; + u_short segment_cnt; + u_char cdb[16]; + u_int total_byte_cnt; + struct dataseg dataseg[DATASEGS_PER_COMMAND]; +}; + +#else struct dataseg { - u_int d_base_lo; - u_int d_base_high; + u_int d_base; u_int d_count; }; @@ -249,16 +280,19 @@ u_int handle; u_char target_lun; u_char target_id; - u_short rsvd1; + u_short expanded_lun; u_short control_flags; u_short rsvd2; u_short time_out; u_short segment_cnt; u_char cdb[16]; u_int total_byte_cnt; - struct dataseg dataseg[2]; + struct dataseg dataseg[DATASEGS_PER_COMMAND]; }; +#endif + + /* command entry control flag definitions */ #define CFLAG_NODISC 0x01 #define CFLAG_HEAD_TAG 0x02 @@ -268,23 +302,18 @@ #define CFLAG_READ 0x20 #define CFLAG_WRITE 0x40 -struct Ext_Command_Entry { +#if BITS_PER_LONG > 32 +struct Continuation_Entry { struct Entry_header hdr; - u_int handle; - u_char target_lun; - u_char target_id; - u_short cdb_length; - u_short control_flags; - u_short rsvd; - u_short time_out; - u_short segment_cnt; - u_char cdb[44]; + struct dataseg dataseg[DATASEGS_PER_CONT]; }; - +#else struct Continuation_Entry { struct Entry_header hdr; - struct dataseg dataseg[5]; + u32 rsvd; + struct dataseg dataseg[DATASEGS_PER_CONT]; }; +#endif struct Marker_Entry { struct Entry_header hdr; @@ -292,7 +321,7 @@ u_char target_lun; u_char target_id; u_char modifier; - u_char rsvd; + u_char expanded_lun; u_char rsvds[52]; }; @@ -549,7 +578,7 @@ u_int response_high; u_short sub_len; u_short res2; - u_short data[22]; + u_char data[44]; }; /* address of instance of this struct is passed to adapter to initialize things @@ -574,6 +603,17 @@ u_int req_queue_addr_high; u_int res_queue_addr_lo; u_int res_queue_addr_high; + /* the rest of this structure only applies to the isp2200 */ + u_short lun_enables; + u_char cmd_resource_cnt; + u_char notify_resource_cnt; + u_short timeout; + u_short reserved3; + u_short add_firm_opts; + u_char res_accum_timer; + u_char irq_delay_timer; + u_short special_options; + u_short reserved4[13]; }; /* @@ -583,16 +623,24 @@ #define RES_QUEUE_LEN ((QLOGICFC_REQ_QUEUE_LEN + 1) / 8 - 1) #define QUEUE_ENTRY_LEN 64 -#if ISP2100_FABRIC +#if ISP2x00_FABRIC #define QLOGICFC_MAX_ID 0xff #else -#define QLOGICFC_MAX_ID 0x80 +#define QLOGICFC_MAX_ID 0x7d #endif -struct isp2100_hostdata { +#define QLOGICFC_MAX_LOOP_ID 0x7d + +/* adapter_state values */ +#define AS_FIRMWARE_DEAD -1 +#define AS_LOOP_DOWN 0 +#define AS_LOOP_GOOD 1 +#define AS_REDO_PORTDB 2 + +struct isp2x00_hostdata { u_char revision; struct pci_dev *pci_dev; - /* result and request queues (shared with isp2100): */ + /* result and request queues (shared with isp2x00): */ u_int req_in_ptr; /* index of next request slot */ u_int res_out_ptr; /* index of next result slot */ @@ -602,7 +650,7 @@ char res[RES_QUEUE_LEN + 1][QUEUE_ENTRY_LEN]; char req[QLOGICFC_REQ_QUEUE_LEN + 1][QUEUE_ENTRY_LEN]; struct init_cb control_block; - int loop_up; + int adapter_state; unsigned long int tag_ages[126]; Scsi_Cmnd *handle_ptrs[QLOGICFC_REQ_QUEUE_LEN + 1]; unsigned long handle_serials[QLOGICFC_REQ_QUEUE_LEN + 1]; @@ -611,6 +659,7 @@ u64 wwn; u_int port_id; u_char queued; + u_char host_id; }; @@ -620,177 +669,187 @@ QLOGICFC_REQ_QUEUE_LEN) #define RES_QUEUE_DEPTH(in, out) QUEUE_DEPTH(in, out, RES_QUEUE_LEN) -static void isp2100_enable_irqs(struct Scsi_Host *); -static void isp2100_disable_irqs(struct Scsi_Host *); -static int isp2100_init(struct Scsi_Host *); -static int isp2100_reset_hardware(struct Scsi_Host *); -static int isp2100_mbox_command(struct Scsi_Host *, u_short[]); -static int isp2100_return_status(struct Status_Entry *); -static void isp2100_intr_handler(int, void *, struct pt_regs *); -static void do_isp2100_intr_handler(int, void *, struct pt_regs *); -static int isp2100_make_portdb(struct Scsi_Host *); +static void isp2x00_enable_irqs(struct Scsi_Host *); +static void isp2x00_disable_irqs(struct Scsi_Host *); +static int isp2x00_init(struct Scsi_Host *); +static int isp2x00_reset_hardware(struct Scsi_Host *); +static int isp2x00_mbox_command(struct Scsi_Host *, u_short[]); +static int isp2x00_return_status(struct Status_Entry *); +static void isp2x00_intr_handler(int, void *, struct pt_regs *); +static void do_isp2x00_intr_handler(int, void *, struct pt_regs *); +static int isp2x00_make_portdb(struct Scsi_Host *); -#if ISP2100_FABRIC -static int isp2100_init_fabric(struct Scsi_Host *, struct id_name_map *, int); +#if ISP2x00_FABRIC +static int isp2x00_init_fabric(struct Scsi_Host *, struct id_name_map *, int); #endif #if USE_NVRAM_DEFAULTS -static int isp2100_get_nvram_defaults(struct Scsi_Host *, struct init_cb *); -static u_short isp2100_read_nvram_word(struct Scsi_Host *, u_short); +static int isp2x00_get_nvram_defaults(struct Scsi_Host *, struct init_cb *); +static u_short isp2x00_read_nvram_word(struct Scsi_Host *, u_short); #endif -#if DEBUG_ISP2100 -static void isp2100_print_scsi_cmd(Scsi_Cmnd *); +#if DEBUG_ISP2x00 +static void isp2x00_print_scsi_cmd(Scsi_Cmnd *); #endif -static void isp2100_print_status_entry(struct Status_Entry *); +#if DEBUG_ISP2x00_INTR +static void isp2x00_print_status_entry(struct Status_Entry *); +#endif -static struct proc_dir_entry proc_scsi_isp2100 = +static struct proc_dir_entry proc_scsi_isp2x00 = { - PROC_SCSI_QLOGICFC, 7, "isp2100", + PROC_SCSI_QLOGICFC, 7, "isp2x00", S_IFDIR | S_IRUGO | S_IXUGO, 2 }; -static inline void isp2100_enable_irqs(struct Scsi_Host *host) +static inline void isp2x00_enable_irqs(struct Scsi_Host *host) { outw(ISP_EN_INT | ISP_EN_RISC, host->io_port + PCI_INTER_CTL); } -static inline void isp2100_disable_irqs(struct Scsi_Host *host) +static inline void isp2x00_disable_irqs(struct Scsi_Host *host) { outw(0x0, host->io_port + PCI_INTER_CTL); } -int isp2100_detect(Scsi_Host_Template * tmpt) +int isp2x00_detect(Scsi_Host_Template * tmpt) { int hosts = 0; int wait_time; struct Scsi_Host *host = NULL; - struct isp2100_hostdata *hostdata; + struct isp2x00_hostdata *hostdata; struct pci_dev *pdev = NULL; + unsigned short device_ids[2]; + int i; - ENTER("isp2100_detect"); - tmpt->proc_dir = &proc_scsi_isp2100; + ENTER("isp2x00_detect"); + + device_ids[0] = PCI_DEVICE_ID_QLOGIC_ISP2100; + device_ids[1] = PCI_DEVICE_ID_QLOGIC_ISP2200; + + tmpt->proc_dir = &proc_scsi_isp2x00; if (pci_present() == 0) { printk("qlogicfc : PCI not present\n"); return 0; } - while ((pdev = pci_find_device(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100, pdev))) { - host = scsi_register(tmpt, sizeof(struct isp2100_hostdata)); - host->max_id = QLOGICFC_MAX_ID + 1; - host->hostt->use_new_eh_code = 1; - hostdata = (struct isp2100_hostdata *) host->hostdata; - - memset(hostdata, 0, sizeof(struct isp2100_hostdata)); - hostdata->pci_dev = pdev; - - hostdata->queued = 0; - /* set up the control block */ - hostdata->control_block.version = 0x0f; - hostdata->control_block.firm_opts = 0x010c; - hostdata->control_block.max_frame_len = 2048; - hostdata->control_block.max_iocb = 256; - hostdata->control_block.exec_throttle = 8; - hostdata->control_block.retry_delay = 5; - hostdata->control_block.retry_cnt = 0; - hostdata->control_block.node_name[0] = 0x0020; - hostdata->control_block.node_name[1] = 0xE000; - hostdata->control_block.node_name[2] = 0x008B; - hostdata->control_block.node_name[3] = 0x0000; - hostdata->control_block.hard_addr = 0x0003; - hostdata->control_block.req_queue_len = QLOGICFC_REQ_QUEUE_LEN + 1; - hostdata->control_block.res_queue_len = RES_QUEUE_LEN + 1; - hostdata->control_block.res_queue_addr_lo = virt_to_bus_low32(&hostdata->res); - hostdata->control_block.res_queue_addr_high = virt_to_bus_high32(&hostdata->res); - hostdata->control_block.req_queue_addr_lo = virt_to_bus_low32(&hostdata->req); - hostdata->control_block.req_queue_addr_high = virt_to_bus_high32(&hostdata->req); - - hostdata->loop_up = 0; - - if (isp2100_init(host) || isp2100_reset_hardware(host)) { - scsi_unregister(host); - continue; - } - host->this_id = 0; + for (i=0; i<2; i++){ + while ((pdev = pci_find_device(PCI_VENDOR_ID_QLOGIC, device_ids[i], pdev))) { - if (request_irq(host->irq, do_isp2100_intr_handler, SA_INTERRUPT | SA_SHIRQ, "qlogicfc", host)) { - printk("qlogicfc : interrupt %d already in use\n", - host->irq); - scsi_unregister(host); - continue; - } - if (check_region(host->io_port, 0xff)) { - printk("qlogicfc : i/o region 0x%lx-0x%lx already " - "in use\n", - host->io_port, host->io_port + 0xff); - free_irq(host->irq, host); - scsi_unregister(host); - continue; - } - request_region(host->io_port, 0xff, "qlogicfc"); + host = scsi_register(tmpt, sizeof(struct isp2x00_hostdata)); + host->max_id = QLOGICFC_MAX_ID + 1; + host->hostt->use_new_eh_code = 1; + hostdata = (struct isp2x00_hostdata *) host->hostdata; + + memset(hostdata, 0, sizeof(struct isp2x00_hostdata)); + hostdata->pci_dev = pdev; + + hostdata->queued = 0; + /* set up the control block */ + hostdata->control_block.version = 0x1; + hostdata->control_block.firm_opts = 0x0108; + hostdata->control_block.max_frame_len = 2048; + hostdata->control_block.max_iocb = 256; + hostdata->control_block.exec_throttle = 8; + hostdata->control_block.retry_delay = 5; + hostdata->control_block.retry_cnt = 1; + hostdata->control_block.node_name[0] = 0x0020; + hostdata->control_block.node_name[1] = 0xE000; + hostdata->control_block.node_name[2] = 0x008B; + hostdata->control_block.node_name[3] = 0x0000; + hostdata->control_block.hard_addr = 0x0003; + hostdata->control_block.req_queue_len = QLOGICFC_REQ_QUEUE_LEN + 1; + hostdata->control_block.res_queue_len = RES_QUEUE_LEN + 1; + hostdata->control_block.res_queue_addr_lo = virt_to_bus_low32(&hostdata->res); + hostdata->control_block.res_queue_addr_high = virt_to_bus_high32(&hostdata->res); + hostdata->control_block.req_queue_addr_lo = virt_to_bus_low32(&hostdata->req); + hostdata->control_block.req_queue_addr_high = virt_to_bus_high32(&hostdata->req); + + + hostdata->adapter_state = AS_LOOP_DOWN; + hostdata->host_id = hosts; + + if (isp2x00_init(host) || isp2x00_reset_hardware(host)) { + scsi_unregister(host); + continue; + } + host->this_id = 0; - outw(0x0, host->io_port + PCI_SEMAPHORE); - outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR); - isp2100_enable_irqs(host); - /* wait for the loop to come up */ - for (wait_time = jiffies + 10 * HZ; wait_time > jiffies && hostdata->loop_up == 0;) - barrier(); + if (request_irq(host->irq, do_isp2x00_intr_handler, SA_INTERRUPT | SA_SHIRQ, "qlogicfc", host)) { + printk("qlogicfc%d : interrupt %d already in use\n", + hostdata->host_id, host->irq); + scsi_unregister(host); + continue; + } + if (check_region(host->io_port, 0xff)) { + printk("qlogicfc%d : i/o region 0x%lx-0x%lx already " + "in use\n", + hostdata->host_id, host->io_port, host->io_port + 0xff); + free_irq(host->irq, host); + scsi_unregister(host); + continue; + } + request_region(host->io_port, 0xff, "qlogicfc"); - if (hostdata->loop_up == 0) { - printk("qlogicfc: loop is not up\n"); - release_region(host->io_port, 0xff); - free_irq(host->irq, host); - scsi_unregister(host); - continue; + outw(0x0, host->io_port + PCI_SEMAPHORE); + outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR); + isp2x00_enable_irqs(host); + /* wait for the loop to come up */ + for (wait_time = jiffies + 10 * HZ; wait_time > jiffies && hostdata->adapter_state == AS_LOOP_DOWN;) + barrier(); + + if (hostdata->adapter_state == AS_LOOP_DOWN) { + printk("qlogicfc%d : link is not up\n", hostdata->host_id); + } + hosts++; } - hosts++; } - /* this busy loop should not be needed but the isp2100 seems to need + /* this busy loop should not be needed but the isp2x00 seems to need some time before recognizing it is attached to a fabric */ -#if ISP2100_FABRIC +#if ISP2x00_FABRIC for (wait_time = jiffies + 5 * HZ; wait_time > jiffies;) barrier(); #endif - LEAVE("isp2100_detect"); + LEAVE("isp2x00_detect"); return hosts; } -static int isp2100_make_portdb(struct Scsi_Host *host) +static int isp2x00_make_portdb(struct Scsi_Host *host) { short param[8]; int i, j; struct id_name_map temp[QLOGICFC_MAX_ID + 1]; - struct isp2100_hostdata *hostdata; + struct isp2x00_hostdata *hostdata; - isp2100_disable_irqs(host); + isp2x00_disable_irqs(host); memset(temp, 0, sizeof(temp)); - hostdata = (struct isp2100_hostdata *) host->hostdata; + hostdata = (struct isp2x00_hostdata *) host->hostdata; -#if ISP2100_FABRIC +#if ISP2x00_FABRIC for (i = 0x81; i < QLOGICFC_MAX_ID; i++) { param[0] = MBOX_PORT_LOGOUT; param[1] = i << 8; param[2] = 0; param[3] = 0; - isp2100_mbox_command(host, param); + isp2x00_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - printk("logout failed %x %x\n", i, param[0]); + + DEBUG_FABRIC(printk("qlogicfc%d : logout failed %x %x\n", hostdata->host_id, i, param[0])); } } #endif @@ -798,7 +857,7 @@ param[0] = MBOX_GET_INIT_SCSI_ID; - isp2100_mbox_command(host, param); + isp2x00_mbox_command(host, param); if (param[0] == MBOX_COMMAND_COMPLETE) { hostdata->port_id = ((u_int) param[3]) << 16; @@ -807,16 +866,17 @@ temp[0].wwn = hostdata->wwn; } else { - printk("qlogicfc: error getting scsi id.\n"); + printk("qlogicfc%d : error getting scsi id.\n", hostdata->host_id); } - for (i = 1, j = 1; i <= QLOGICFC_MAX_ID; i++) { - temp[i].loop_id = temp[0].loop_id; - - param[0] = MBOX_GET_PORT_NAME; + for (i = 0; i <=QLOGICFC_MAX_ID; i++) + temp[i].loop_id = temp[0].loop_id; + + for (i = 0, j = 1; i <= QLOGICFC_MAX_LOOP_ID; i++) { + param[0] = MBOX_GET_PORT_NAME; param[1] = (i << 8) & 0xff00; - isp2100_mbox_command(host, param); + isp2x00_mbox_command(host, param); if (param[0] == MBOX_COMMAND_COMPLETE) { temp[j].loop_id = i; @@ -835,8 +895,8 @@ } -#if ISP2100_FABRIC - isp2100_init_fabric(host, temp, j); +#if ISP2x00_FABRIC + isp2x00_init_fabric(host, temp, j); #endif for (i = 0; i <= QLOGICFC_MAX_ID; i++) { @@ -856,7 +916,7 @@ } } if (j == QLOGICFC_MAX_ID + 1) - printk("qlogicfc.c: Too many scsi devices, no more room in port map.\n"); + printk("qlogicfc%d : Too many scsi devices, no more room in port map.\n", hostdata->host_id); if (!hostdata->port_db[j].wwn) { hostdata->port_db[j].loop_id = temp[i].loop_id; hostdata->port_db[j].wwn = temp[i].wwn; @@ -866,42 +926,70 @@ } - isp2100_enable_irqs(host); + isp2x00_enable_irqs(host); return 0; } -#if ISP2100_FABRIC +#if ISP2x00_FABRIC + +#define FABRIC_PORT 0x7e +#define FABRIC_CONTROLLER 0x7f +#define FABRIC_SNS 0x80 -int isp2100_init_fabric(struct Scsi_Host *host, struct id_name_map *port_db, int j) +int isp2x00_init_fabric(struct Scsi_Host *host, struct id_name_map *port_db, int cur_scsi_id) { u_short param[8]; u64 wwn; int done = 0; u_short loop_id = 0x81; - u_short scsi_id = j; + u_short scsi_id = cur_scsi_id; u_int port_id; struct sns_cb req; u_char sns_response[608]; - struct isp2100_hostdata *hostdata; + struct isp2x00_hostdata *hostdata; - hostdata = (struct isp2100_hostdata *) host->hostdata; + hostdata = (struct isp2x00_hostdata *) host->hostdata; - DEBUG_FABRIC(printk("qlogicfc.c: Checking for a fabric.\n")); + DEBUG_FABRIC(printk("qlogicfc%d : Checking for a fabric.\n", hostdata->host_id)); param[0] = MBOX_GET_PORT_NAME; - param[1] = 0x7E00; + param[1] = (u16)FABRIC_PORT << 8; - isp2100_mbox_command(host, param); + isp2x00_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - DEBUG_FABRIC(printk("fabric check result %x\n", param[0])); + DEBUG_FABRIC(printk("qlogicfc%d : fabric check result %x\n", hostdata->host_id, param[0])); return 0; } - printk("qlogicfc.c: Fabric found.\n"); + printk("qlogicfc%d : Fabric found.\n", hostdata->host_id); + memset(&req, 0, sizeof(req)); + + req.len = 8; + req.response_low = virt_to_bus_low32(sns_response); + req.response_high = virt_to_bus_high32(sns_response); + req.sub_len = 22; + req.data[0] = 0x17; + req.data[1] = 0x02; + req.data[8] = (u_char) (hostdata->port_id & 0xff); + req.data[9] = (u_char) (hostdata->port_id >> 8 & 0xff); + req.data[10] = (u_char) (hostdata->port_id >> 16 & 0xff); + req.data[13] = 0x01; + param[0] = MBOX_SEND_SNS; + param[1] = 30; + param[2] = virt_to_bus_low32(&req) >> 16; + param[3] = virt_to_bus_low32(&req); + param[6] = virt_to_bus_high32(&req) >> 16; + param[7] = virt_to_bus_high32(&req); + + isp2x00_mbox_command(host, param); + + if (param[0] != MBOX_COMMAND_COMPLETE) + printk("qlogicfc%d : error sending RFC-4\n", hostdata->host_id); + port_id = hostdata->port_id; while (!done) { memset(&req, 0, sizeof(req)); @@ -910,9 +998,11 @@ req.response_low = virt_to_bus_low32(sns_response); req.response_high = virt_to_bus_high32(sns_response); req.sub_len = 6; - req.data[0] = 0x0100; - req.data[4] = (u_short) (port_id & 0xffff); - req.data[5] = (u_short) (port_id >> 16 & 0xffff); + req.data[0] = 0x00; + req.data[1] = 0x01; + req.data[8] = (u_char) (port_id & 0xff); + req.data[9] = (u_char) (port_id >> 8 & 0xff); + req.data[10] = (u_char) (port_id >> 16 & 0xff); param[0] = MBOX_SEND_SNS; param[1] = 14; @@ -921,10 +1011,10 @@ param[6] = virt_to_bus_high32(&req) >> 16; param[7] = virt_to_bus_high32(&req); - isp2100_mbox_command(host, param); + isp2x00_mbox_command(host, param); if (param[0] == MBOX_COMMAND_COMPLETE) { - DEBUG_FABRIC(printk("found node %02x%02x%02x%02x%02x%02x%02x%02x ", sns_response[20], sns_response[21], sns_response[22], sns_response[23], sns_response[24], sns_response[25], sns_response[26], sns_response[27])); + DEBUG_FABRIC(printk("qlogicfc%d : found node %02x%02x%02x%02x%02x%02x%02x%02x ", hostdata->host_id, sns_response[20], sns_response[21], sns_response[22], sns_response[23], sns_response[24], sns_response[25], sns_response[26], sns_response[27])); DEBUG_FABRIC(printk(" port id: %02x%02x%02x\n", sns_response[17], sns_response[18], sns_response[19])); port_id = ((u_int) sns_response[17]) << 16; port_id |= ((u_int) sns_response[18]) << 8; @@ -938,13 +1028,13 @@ wwn |= ((u64) sns_response[26]) << 8; wwn |= ((u64) sns_response[27]); if (hostdata->port_id >> 8 != port_id >> 8) { - DEBUG_FABRIC(printk("adding a fabric port: %x\n", port_id)); + DEBUG_FABRIC(printk("qlogicfc%d : adding a fabric port: %x\n", hostdata->host_id, port_id)); param[0] = MBOX_PORT_LOGIN; param[1] = loop_id << 8; param[2] = (u_short) (port_id >> 16); param[3] = (u_short) (port_id); - isp2100_mbox_command(host, param); + isp2x00_mbox_command(host, param); if (param[0] == MBOX_COMMAND_COMPLETE) { port_db[scsi_id].wwn = wwn; @@ -952,15 +1042,22 @@ loop_id++; scsi_id++; } else { - printk("qlogicfc.c: Error performing port login %x\n", param[0]); - DEBUG_FABRIC(printk("loop_id: %x\n", loop_id)); + printk("qlogicfc%d : Error performing port login %x\n", hostdata->host_id, param[0]); + DEBUG_FABRIC(printk("qlogicfc%d : loop_id: %x\n", hostdata->host_id, loop_id)); + param[0] = MBOX_PORT_LOGOUT; + param[1] = loop_id << 8; + param[2] = 0; + param[3] = 0; + + isp2x00_mbox_command(host, param); + } } if (hostdata->port_id == port_id) done = 1; } else { - printk("qlogicfc.c: Get All Next failed %x.\n", param[0]); + printk("qlogicfc%d : Get All Next failed %x.\n", hostdata->host_id, param[0]); return 0; } } @@ -968,42 +1065,42 @@ return 1; } -#endif /* ISP2100_FABRIC */ +#endif /* ISP2x00_FABRIC */ -int isp2100_release(struct Scsi_Host *host) +int isp2x00_release(struct Scsi_Host *host) { - struct isp2100_hostdata *hostdata; + struct isp2x00_hostdata *hostdata; - ENTER("isp2100_release"); + ENTER("isp2x00_release"); - hostdata = (struct isp2100_hostdata *) host->hostdata; + hostdata = (struct isp2x00_hostdata *) host->hostdata; outw(0x0, host->io_port + PCI_INTER_CTL); free_irq(host->irq, host); release_region(host->io_port, 0xff); - LEAVE("isp2100_release"); + LEAVE("isp2x00_release"); return 0; } -const char *isp2100_info(struct Scsi_Host *host) +const char *isp2x00_info(struct Scsi_Host *host) { static char buf[80]; - struct isp2100_hostdata *hostdata; - ENTER("isp2100_info"); + struct isp2x00_hostdata *hostdata; + ENTER("isp2x00_info"); - hostdata = (struct isp2100_hostdata *) host->hostdata; + hostdata = (struct isp2x00_hostdata *) host->hostdata; sprintf(buf, - "QLogic ISP2100 SCSI on PCI bus %02x device %02x irq %d base 0x%lx", - hostdata->pci_dev->bus->number, hostdata->pci_dev->devfn, host->irq, + "QLogic ISP%04x SCSI on PCI bus %02x device %02x irq %d base 0x%lx", + hostdata->pci_dev->device, hostdata->pci_dev->bus->number, hostdata->pci_dev->devfn, host->irq, host->io_port); - LEAVE("isp2100_info"); + LEAVE("isp2x00_info"); return buf; } @@ -1015,7 +1112,7 @@ * interrupt handler may call this routine as part of * request-completion handling). */ -int isp2100_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *)) +int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *)) { int i, sg_count, n, num_free; u_int in_ptr, out_ptr; @@ -1024,25 +1121,26 @@ struct Command_Entry *cmd; struct Continuation_Entry *cont; struct Scsi_Host *host; - struct isp2100_hostdata *hostdata; + struct isp2x00_hostdata *hostdata; - ENTER("isp2100_queuecommand"); + ENTER("isp2x00_queuecommand"); host = Cmnd->host; - hostdata = (struct isp2100_hostdata *) host->hostdata; + hostdata = (struct isp2x00_hostdata *) host->hostdata; Cmnd->scsi_done = done; - DEBUG(isp2100_print_scsi_cmd(Cmnd)); + DEBUG(isp2x00_print_scsi_cmd(Cmnd)); - if (hostdata->loop_up == 2) { - hostdata->loop_up = 1; - isp2100_make_portdb(host); + if (hostdata->adapter_state == AS_REDO_PORTDB) { + hostdata->adapter_state = AS_LOOP_GOOD; + isp2x00_make_portdb(host); + printk("qlogicfc%d : Port Database\n", hostdata->host_id); for (i = 0; hostdata->port_db[i].wwn != 0; i++) { - DEBUG(printk("wwn: %08x%08x scsi_id: %x loop_id: %x\n", (u_int) (hostdata->port_db[i].wwn >> 32), (u_int) hostdata->port_db[i].wwn, i, hostdata->port_db[i].loop_id)); + printk("wwn: %08x%08x scsi_id: %x loop_id: %x\n", (u_int) (hostdata->port_db[i].wwn >> 32), (u_int) hostdata->port_db[i].wwn, i, hostdata->port_db[i].loop_id); } } - if (hostdata->loop_up == -1) { - printk("qlogicfc.c: The firmware is dead, just return.\n"); + if (hostdata->adapter_state == AS_FIRMWARE_DEAD) { + printk("qlogicfc%d : The firmware is dead, just return.\n", hostdata->host_id); host->max_id = 0; return 0; } @@ -1050,13 +1148,13 @@ out_ptr = inw(host->io_port + MBOX4); in_ptr = hostdata->req_in_ptr; - DEBUG(printk("qlogicfc : request queue depth %d\n", + DEBUG(printk("qlogicfc%d : request queue depth %d\n", hostdata->host_id, REQ_QUEUE_DEPTH(in_ptr, out_ptr))); cmd = (struct Command_Entry *) &hostdata->req[in_ptr][0]; in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN; if (in_ptr == out_ptr) { - DEBUG(printk("qlogicfc : request queue overflow\n")); + DEBUG(printk("qlogicfc%d : request queue overflow\n", hostdata->host_id)); return 1; } if (hostdata->send_marker) { @@ -1064,7 +1162,7 @@ TRACE("queue marker", in_ptr, 0); - DEBUG(printk("qlogicfc : adding marker entry\n")); + DEBUG(printk("qlogicfc%d : adding marker entry\n", hostdata->host_id)); marker = (struct Marker_Entry *) cmd; memset(marker, 0, sizeof(struct Marker_Entry)); @@ -1077,7 +1175,7 @@ if (((in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN) == out_ptr) { outw(in_ptr, host->io_port + MBOX4); hostdata->req_in_ptr = in_ptr; - DEBUG(printk("qlogicfc : request queue overflow\n")); + DEBUG(printk("qlogicfc%d : request queue overflow\n", hostdata->host_id)); return 1; } cmd = (struct Command_Entry *) &hostdata->req[in_ptr][0]; @@ -1094,19 +1192,27 @@ cmd->handle = i; hostdata->handle_ptrs[i] = Cmnd; hostdata->handle_serials[i] = Cmnd->serial_number; - } else - printk("qlogicfc: no handle slots, this should not happen.\n"); + } else { + printk("qlogicfc%d : no handle slots, this should not happen.\n", hostdata->host_id); + printk("hostdata->queued is %x, in_ptr: %x\n", hostdata->queued, in_ptr); + for (i = 0; i <= QLOGICFC_REQ_QUEUE_LEN; i++){ + if (!hostdata->handle_ptrs[i]){ + printk("slot %d has %p\n", i, hostdata->handle_ptrs[i]); + } + } + } cmd->hdr.entry_type = ENTRY_COMMAND; cmd->hdr.entry_cnt = 1; cmd->target_lun = Cmnd->lun; -#if ISP2100_PORTDB + cmd->expanded_lun = Cmnd->lun; +#if ISP2x00_PORTDB cmd->target_id = hostdata->port_db[Cmnd->target].loop_id; #else cmd->target_id = Cmnd->target; #endif cmd->total_byte_cnt = (u_int) Cmnd->request_bufflen; - cmd->time_out = (SCSI_TIMEOUT / HZ) * 5; + cmd->time_out = 0; memcpy(cmd->cdb, Cmnd->cmnd, Cmnd->cmd_len); if (Cmnd->use_sg) { @@ -1115,15 +1221,18 @@ ds = cmd->dataseg; /* fill in first two sg entries: */ n = sg_count; - if (n > 2) - n = 2; + if (n > DATASEGS_PER_COMMAND) + n = DATASEGS_PER_COMMAND; + for (i = 0; i < n; i++) { - ds[i].d_base_lo = virt_to_bus_low32(sg->address); - ds[i].d_base_high = virt_to_bus_high32(sg->address); + ds[i].d_base = virt_to_bus_low32(sg->address); +#if BITS_PER_LONG > 32 + ds[i].d_base_hi = virt_to_bus_high32(sg->address); +#endif ds[i].d_count = sg->length; ++sg; } - sg_count -= 2; + sg_count -= DATASEGS_PER_COMMAND; while (sg_count > 0) { ++cmd->hdr.entry_cnt; @@ -1132,28 +1241,31 @@ memset(cont, 0, sizeof(struct Continuation_Entry)); in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN; if (in_ptr == out_ptr) { - DEBUG(printk("isp2100: unexpected request queue overflow\n")); + DEBUG(printk("qlogicfc%d : unexpected request queue overflow\n", hostdata->host_id)); return 1; } TRACE("queue continuation", in_ptr, 0); cont->hdr.entry_type = ENTRY_CONTINUATION; ds = cont->dataseg; n = sg_count; - if (n > 5) - n = 5; + if (n > DATASEGS_PER_CONT) + n = DATASEGS_PER_CONT; for (i = 0; i < n; ++i) { - ds[i].d_base_lo = virt_to_bus_low32(sg->address); - ds[i].d_base_high = virt_to_bus_high32(sg->address); + ds[i].d_base = virt_to_bus_low32(sg->address); +#if BITS_PER_LONG > 32 + ds[i].d_base_hi = virt_to_bus_high32(sg->address); +#endif ds[i].d_count = sg->length; ++sg; } sg_count -= n; } } else { - cmd->dataseg[0].d_base_lo = virt_to_bus_low32(Cmnd->request_buffer); - cmd->dataseg[0].d_base_high = virt_to_bus_high32(Cmnd->request_buffer); - cmd->dataseg[0].d_count = - (u_int) Cmnd->request_bufflen; + cmd->dataseg[0].d_base = virt_to_bus_low32(Cmnd->request_buffer); +#if BITS_PER_LONG > 32 + cmd->dataseg[0].d_base_hi = virt_to_bus_high32(Cmnd->request_buffer); +#endif + cmd->dataseg[0].d_count = (u_int) Cmnd->request_bufflen; cmd->segment_cnt = 1; } @@ -1161,12 +1273,15 @@ case WRITE_10: case WRITE_6: case WRITE_BUFFER: + case MODE_SELECT: cmd->control_flags = CFLAG_WRITE; break; case REQUEST_SENSE: /* scsi.c expects sense info in a different buffer */ - cmd->dataseg[0].d_base_lo = virt_to_bus_low32(Cmnd->sense_buffer); - cmd->dataseg[0].d_base_high = virt_to_bus_high32(Cmnd->sense_buffer); + cmd->dataseg[0].d_base = virt_to_bus_low32(Cmnd->sense_buffer); +#if BITS_PER_LONG > 32 + cmd->dataseg[0].d_base_hi = virt_to_bus_high32(Cmnd->request_buffer); +#endif cmd->segment_cnt = 1; cmd->control_flags = CFLAG_READ; break; @@ -1197,6 +1312,7 @@ hostdata->req_in_ptr = in_ptr; hostdata->queued++; + num_free = QLOGICFC_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr); num_free = (num_free > 2) ? num_free - 2 : 0; host->can_queue = hostdata->queued + num_free; @@ -1207,11 +1323,11 @@ /* this is really gross */ if (host->can_queue <= host->host_busy){ if (host->can_queue+2 < host->host_busy) - DEBUG(printk("qlogicfc.c crosses its fingers.\n")); + DEBUG(printk("qlogicfc%d.c crosses its fingers.\n", hostdata->host_id)); host->can_queue = host->host_busy + 1; } - LEAVE("isp2100_queuecommand"); + LEAVE("isp2x00_queuecommand"); return 0; } @@ -1220,33 +1336,33 @@ #define ASYNC_EVENT_INTERRUPT 0x01 -void do_isp2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs) +void do_isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs) { unsigned long flags; spin_lock_irqsave(&io_request_lock, flags); - isp2100_intr_handler(irq, dev_id, regs); + isp2x00_intr_handler(irq, dev_id, regs); spin_unlock_irqrestore(&io_request_lock, flags); } -void isp2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs) +void isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs) { Scsi_Cmnd *Cmnd; struct Status_Entry *sts; struct Scsi_Host *host = dev_id; - struct isp2100_hostdata *hostdata; + struct isp2x00_hostdata *hostdata; u_int in_ptr, out_ptr, handle, num_free; u_short status; - ENTER_INTR("isp2100_intr_handler"); + ENTER_INTR("isp2x00_intr_handler"); - hostdata = (struct isp2100_hostdata *) host->hostdata; + hostdata = (struct isp2x00_hostdata *) host->hostdata; - DEBUG_INTR(printk("qlogicfc : interrupt on line %d\n", irq)); + DEBUG_INTR(printk("qlogicfc%d : interrupt on line %d\n", hostdata->host_id, irq)); if (!(inw(host->io_port + PCI_INTER_STS) & 0x08)) { /* spurious interrupts can happen legally */ - DEBUG_INTR(printk("qlogicfc: got spurious interrupt\n")); + DEBUG_INTR(printk("qlogicfc%d : got spurious interrupt\n", hostdata->host_id)); return; } in_ptr = inw(host->io_port + MBOX5); @@ -1255,26 +1371,32 @@ if ((inw(host->io_port + PCI_SEMAPHORE) & ASYNC_EVENT_INTERRUPT)) { status = inw(host->io_port + MBOX0); - DEBUG_INTR(printk("qlogicfc : mbox completion status: %x\n", - status)); + DEBUG_INTR(printk("qlogicfc%d : mbox completion status: %x\n", + hostdata->host_id, status)); switch (status) { case LOOP_UP: - hostdata->loop_up = 2; + case POINT_TO_POINT_UP: + printk("qlogicfc%d : link is up\n", hostdata->host_id); + hostdata->adapter_state = AS_REDO_PORTDB; break; case LOOP_DOWN: - hostdata->loop_up = 0; + printk("qlogicfc%d : link is down\n", hostdata->host_id); + hostdata->adapter_state = AS_LOOP_DOWN; + break; + case CONNECTION_MODE: + printk("received CONNECTION_MODE irq %x\n", inw(host->io_port + MBOX1)); break; case LIP_OCCURED: case CHANGE_NOTIFICATION: case PORT_DB_CHANGED: case LIP_RECEIVED: - if (hostdata->loop_up == 1) - hostdata->loop_up = 2; + if (hostdata->adapter_state == AS_LOOP_GOOD) + hostdata->adapter_state = AS_REDO_PORTDB; break; case SYSTEM_ERROR: - printk("The firmware just choked.\n"); - hostdata->loop_up = -1; + printk("qlogicfc%d : The firmware just choked.\n", hostdata->host_id); + hostdata->adapter_state = AS_FIRMWARE_DEAD; break; case SCSI_COMMAND_COMPLETE: handle = inw(host->io_port + MBOX1) | (inw(host->io_port + MBOX2) << 16); @@ -1286,7 +1408,7 @@ Cmnd->result = 0x0; (*Cmnd->scsi_done) (Cmnd); } else - printk("qlogicfc.c: got a null value out of handle_ptrs, this sucks\n"); + printk("qlogicfc%d.c : got a null value out of handle_ptrs, this sucks\n", hostdata->host_id); break; case MBOX_COMMAND_COMPLETE: case INVALID_COMMAND: @@ -1301,37 +1423,54 @@ outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR); return; default: - printk("qlogicfc: got an unknown status? %x\n", status); + printk("qlogicfc%d : got an unknown status? %x\n", hostdata->host_id, status); } outw(0x0, host->io_port + PCI_SEMAPHORE); } else { - DEBUG_INTR(printk("qlogicfc : response queue update\n")); - DEBUG_INTR(printk("qlogicfc : response queue depth %d\n", RES_QUEUE_DEPTH(in_ptr, out_ptr))); + DEBUG_INTR(printk("qlogicfc%d : response queue update\n", hostdata->host_id)); + DEBUG_INTR(printk("qlogicfc%d : response queue depth %d\n", hostdata->host_id, RES_QUEUE_DEPTH(in_ptr, out_ptr))); while (out_ptr != in_ptr) { sts = (struct Status_Entry *) &hostdata->res[out_ptr][0]; out_ptr = (out_ptr + 1) & RES_QUEUE_LEN; TRACE("done", out_ptr, Cmnd); - DEBUG_INTR(isp2100_print_status_entry(sts)); - if (sts->hdr.entry_type == ENTRY_STATUS) { - Cmnd = hostdata->handle_ptrs[sts->handle]; - Cmnd->result = isp2100_return_status(sts); + DEBUG_INTR(isp2x00_print_status_entry(sts)); + if (sts->hdr.entry_type == ENTRY_STATUS && (Cmnd = hostdata->handle_ptrs[sts->handle])) { + Cmnd->result = isp2x00_return_status(sts); hostdata->handle_ptrs[sts->handle] = NULL; hostdata->queued--; - if (hostdata->handle_serials[sts->handle] != Cmnd->serial_number) { + + /* + * if any of the following are true we do not + * call scsi_done. if the status is CS_ABORTED + * we dont have to call done because the upper + * level should already know its aborted. + */ + if (hostdata->handle_serials[sts->handle] != Cmnd->serial_number + || sts->completion_status == CS_ABORTED){ hostdata->handle_serials[sts->handle] = 0; outw(out_ptr, host->io_port + MBOX5); continue; } - hostdata->handle_serials[sts->handle] = 0; + /* + * if we get back an error indicating the port + * is not there or if the link is down and + * this is a device that used to be there + * allow the command to timeout. + * the device may well be back in a couple of + * seconds. + */ + if ((hostdata->adapter_state == AS_LOOP_DOWN || sts->completion_status == CS_PORT_UNAVAILABLE || sts->completion_status == CS_PORT_LOGGED_OUT || sts->completion_status == CS_PORT_CONFIG_CHANGED) && hostdata->port_db[Cmnd->target].wwn){ + outw(out_ptr, host->io_port + MBOX5); + continue; + } } else { outw(out_ptr, host->io_port + MBOX5); continue; } if (sts->completion_status == CS_RESET_OCCURRED - || sts->completion_status == CS_ABORTED || (sts->status_flags & STF_BUS_RESET)) hostdata->send_marker = 1; @@ -1345,7 +1484,7 @@ if (Cmnd->scsi_done != NULL) { (*Cmnd->scsi_done) (Cmnd); } else - printk("Ouch, scsi done is NULL\n"); + printk("qlogicfc%d : Ouch, scsi done is NULL\n", hostdata->host_id); } hostdata->res_out_ptr = out_ptr; } @@ -1363,19 +1502,19 @@ if (host->can_queue <= host->host_busy){ if (host->can_queue+2 < host->host_busy) - DEBUG(printk("qlogicfc crosses its fingers.\n")); + DEBUG(printk("qlogicfc%d : crosses its fingers.\n", hostdata->host_id)); host->can_queue = host->host_busy + 1; } outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR); - LEAVE_INTR("isp2100_intr_handler"); + LEAVE_INTR("isp2x00_intr_handler"); } -static int isp2100_return_status(struct Status_Entry *sts) +static int isp2x00_return_status(struct Status_Entry *sts) { int host_status = DID_ERROR; -#if DEBUG_ISP2100_INTR +#if DEBUG_ISP2x00_INTR static char *reason[] = { "DID_OK", @@ -1389,9 +1528,9 @@ "DID_RESET", "DID_BAD_INTR" }; -#endif /* DEBUG_ISP2100_INTR */ +#endif /* DEBUG_ISP2x00_INTR */ - ENTER("isp2100_return_status"); + ENTER("isp2x00_return_status"); DEBUG(printk("qlogicfc : completion status = 0x%04x\n", sts->completion_status)); @@ -1436,93 +1575,105 @@ DEBUG_INTR(printk("qlogicfc : host status (%s) scsi status %x\n", reason[host_status], sts->scsi_status)); - LEAVE("isp2100_return_status"); + LEAVE("isp2x00_return_status"); return (sts->scsi_status & STATUS_MASK) | (host_status << 16); } -int isp2100_abort(Scsi_Cmnd * Cmnd) +int isp2x00_abort(Scsi_Cmnd * Cmnd) { u_short param[8]; int i; struct Scsi_Host *host; - struct isp2100_hostdata *hostdata; - int return_status = SCSI_ABORT_SUCCESS; + struct isp2x00_hostdata *hostdata; + int return_status = SUCCESS; - ENTER("isp2100_abort"); + ENTER("isp2x00_abort"); host = Cmnd->host; - hostdata = (struct isp2100_hostdata *) host->hostdata; + hostdata = (struct isp2x00_hostdata *) host->hostdata; for (i = 0; i < QLOGICFC_REQ_QUEUE_LEN; i++) if (hostdata->handle_ptrs[i] == Cmnd) break; - if (i == QLOGICFC_REQ_QUEUE_LEN) - return SCSI_ABORT_ERROR; + if (i == QLOGICFC_REQ_QUEUE_LEN){ + return SUCCESS; + } - isp2100_disable_irqs(host); + isp2x00_disable_irqs(host); param[0] = MBOX_ABORT_IOCB; +#if ISP2x00_PORTDB + param[1] = (((u_short) hostdata->port_db[Cmnd->target].loop_id) << 8) | Cmnd->lun; +#else param[1] = (((u_short) Cmnd->target) << 8) | Cmnd->lun; - param[2] = i >> 16; - param[3] = i & 0xffff; +#endif + param[2] = i & 0xffff; + param[3] = i >> 16; - isp2100_mbox_command(host, param); + isp2x00_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - printk("qlogicfc : scsi abort failure: %x\n", param[0]); + printk("qlogicfc%d : scsi abort failure: %x\n", hostdata->host_id, param[0]); if (param[0] == 0x4005) Cmnd->result = DID_ERROR << 16; if (param[0] == 0x4006) Cmnd->result = DID_BAD_TARGET << 16; - (*Cmnd->scsi_done) (Cmnd); - return_status = SCSI_ABORT_ERROR; + return_status = FAILED; + } + + if (return_status != SUCCESS){ + param[0] = MBOX_GET_FIRMWARE_STATE; + isp2x00_mbox_command(host, param); + printk("qlogicfc%d : abort failed\n", hostdata->host_id); + printk("qlogicfc%d : firmware status is %x %x\n", hostdata->host_id, param[0], param[1]); } - isp2100_enable_irqs(host); - LEAVE("isp2100_abort"); + isp2x00_enable_irqs(host); + + LEAVE("isp2x00_abort"); return return_status; } -int isp2100_reset(Scsi_Cmnd * Cmnd, unsigned int reset_flags) +int isp2x00_reset(Scsi_Cmnd * Cmnd, unsigned int reset_flags) { u_short param[8]; struct Scsi_Host *host; - struct isp2100_hostdata *hostdata; + struct isp2x00_hostdata *hostdata; int return_status = SCSI_RESET_SUCCESS; - ENTER("isp2100_reset"); + ENTER("isp2x00_reset"); host = Cmnd->host; - hostdata = (struct isp2100_hostdata *) host->hostdata; + hostdata = (struct isp2x00_hostdata *) host->hostdata; param[0] = MBOX_BUS_RESET; param[1] = 3; - isp2100_disable_irqs(host); + isp2x00_disable_irqs(host); - isp2100_mbox_command(host, param); + isp2x00_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - printk("qlogicfc : scsi bus reset failure: %x\n", param[0]); + printk("qlogicfc%d : scsi bus reset failure: %x\n", hostdata->host_id, param[0]); return_status = SCSI_RESET_ERROR; } - isp2100_enable_irqs(host); + isp2x00_enable_irqs(host); - LEAVE("isp2100_reset"); + LEAVE("isp2x00_reset"); return return_status;; } -int isp2100_biosparam(Disk * disk, kdev_t n, int ip[]) +int isp2x00_biosparam(Disk * disk, kdev_t n, int ip[]) { int size = disk->capacity; - ENTER("isp2100_biosparam"); + ENTER("isp2x00_biosparam"); ip[0] = 64; ip[1] = 32; @@ -1532,19 +1683,21 @@ ip[1] = 63; ip[2] = size / (ip[0] * ip[1]); } - LEAVE("isp2100_biosparam"); + LEAVE("isp2x00_biosparam"); return 0; } -static int isp2100_reset_hardware(struct Scsi_Host *host) +static int isp2x00_reset_hardware(struct Scsi_Host *host) { u_short param[8]; - struct isp2100_hostdata *hostdata; + struct isp2x00_hostdata *hostdata; int loop_count; - ENTER("isp2100_reset_hardware"); + ENTER("isp2x00_reset_hardware"); + + hostdata = (struct isp2x00_hostdata *) host->hostdata; outw(0x01, host->io_port + ISP_CTRL_STATUS); outw(HCCR_RESET, host->io_port + HOST_HCCR); @@ -1555,35 +1708,46 @@ while (--loop_count && inw(host->io_port + HOST_HCCR) == RISC_BUSY) barrier(); if (!loop_count) - printk("qlogicfc: reset_hardware loop timeout\n"); + printk("qlogicfc%d : reset_hardware loop timeout\n", hostdata->host_id); -#if DEBUG_ISP2100 - printk("qlogicfc : mbox 0 0x%04x \n", inw(host->io_port + MBOX0)); - printk("qlogicfc : mbox 1 0x%04x \n", inw(host->io_port + MBOX1)); - printk("qlogicfc : mbox 2 0x%04x \n", inw(host->io_port + MBOX2)); - printk("qlogicfc : mbox 3 0x%04x \n", inw(host->io_port + MBOX3)); - printk("qlogicfc : mbox 4 0x%04x \n", inw(host->io_port + MBOX4)); - printk("qlogicfc : mbox 5 0x%04x \n", inw(host->io_port + MBOX5)); - printk("qlogicfc : mbox 6 0x%04x \n", inw(host->io_port + MBOX6)); - printk("qlogicfc : mbox 7 0x%04x \n", inw(host->io_port + MBOX7)); -#endif /* DEBUG_ISP2100 */ +#if DEBUG_ISP2x00 + printk("qlogicfc%d : mbox 0 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX0)); + printk("qlogicfc%d : mbox 1 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX1)); + printk("qlogicfc%d : mbox 2 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX2)); + printk("qlogicfc%d : mbox 3 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX3)); + printk("qlogicfc%d : mbox 4 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX4)); + printk("qlogicfc%d : mbox 5 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX5)); + printk("qlogicfc%d : mbox 6 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX6)); + printk("qlogicfc%d : mbox 7 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX7)); +#endif /* DEBUG_ISP2x00 */ - DEBUG(printk("qlogicfc : verifying checksum\n")); + DEBUG(printk("qlogicfc%d : verifying checksum\n", hostdata->host_id)); #if RELOAD_FIRMWARE { int i; - for (i = 0; i < risc_code_length01; i++) { + unsigned short * risc_code = NULL; + unsigned short risc_code_len = 0; + if (hostdata->pci_dev->device == PCI_DEVICE_ID_QLOGIC_ISP2100){ + risc_code = risc_code2100; + risc_code_len = risc_code_length2100; + } + else if (hostdata->pci_dev->device == PCI_DEVICE_ID_QLOGIC_ISP2200){ + risc_code = risc_code2200; + risc_code_len = risc_code_length2200; + } + + for (i = 0; i < risc_code_len; i++) { param[0] = MBOX_WRITE_RAM_WORD; param[1] = risc_code_addr01 + i; - param[2] = risc_code01[i]; + param[2] = risc_code[i]; - isp2100_mbox_command(host, param); + isp2x00_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - printk("qlogicfc : firmware load failure\n"); + printk("qlogicfc%d : firmware load failure\n", hostdata->host_id); return 1; } } @@ -1593,36 +1757,34 @@ param[0] = MBOX_VERIFY_CHECKSUM; param[1] = risc_code_addr01; - isp2100_mbox_command(host, param); + isp2x00_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - printk("qlogicfc : ram checksum failure\n"); + printk("qlogicfc%d : ram checksum failure\n", hostdata->host_id); return 1; } - DEBUG(printk("qlogicfc : executing firmware\n")); + DEBUG(printk("qlogicfc%d : executing firmware\n", hostdata->host_id)); param[0] = MBOX_EXEC_FIRMWARE; param[1] = risc_code_addr01; - isp2100_mbox_command(host, param); + isp2x00_mbox_command(host, param); param[0] = MBOX_ABOUT_FIRMWARE; - isp2100_mbox_command(host, param); + isp2x00_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - printk("qlogicfc : about firmware failure\n"); + printk("qlogicfc%d : about firmware failure\n", hostdata->host_id); return 1; } - DEBUG(printk("qlogicfc : firmware major revision %d\n", param[1])); - DEBUG(printk("qlogicfc : firmware minor revision %d\n", param[2])); - - hostdata = (struct isp2100_hostdata *) host->hostdata; + DEBUG(printk("qlogicfc%d : firmware major revision %d\n", hostdata->host_id, param[1])); + DEBUG(printk("qlogicfc%d : firmware minor revision %d\n", hostdata->host_id, param[2])); #ifdef USE_NVRAM_DEFAULTS - if (isp2100_get_nvram_defaults(host, &hostdata->control_block) != 0) { - printk("qlogicfc: Could not read from NVRAM\n"); + if (isp2x00_get_nvram_defaults(host, &hostdata->control_block) != 0) { + printk("qlogicfc%d : Could not read from NVRAM\n", hostdata->host_id); } #endif @@ -1642,38 +1804,38 @@ param[5] = 0; param[6] = (u_short) (virt_to_bus_high32(&hostdata->control_block) >> 16); param[7] = (u_short) (virt_to_bus_high32(&hostdata->control_block) & 0xffff); - isp2100_mbox_command(host, param); + isp2x00_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - printk("qlogicfc.c: Ouch 0x%04x\n", param[0]); + printk("qlogicfc%d.c: Ouch 0x%04x\n", hostdata->host_id, param[0]); return 1; } param[0] = MBOX_GET_FIRMWARE_STATE; - isp2100_mbox_command(host, param); + isp2x00_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - printk("qlogicfc.c: 0x%04x\n", param[0]); + printk("qlogicfc%d.c: 0x%04x\n", hostdata->host_id, param[0]); return 1; } - LEAVE("isp2100_reset_hardware"); + LEAVE("isp2x00_reset_hardware"); return 0; } #ifdef USE_NVRAM_DEFAULTS -static int isp2100_get_nvram_defaults(struct Scsi_Host *host, struct init_cb *control_block) +static int isp2x00_get_nvram_defaults(struct Scsi_Host *host, struct init_cb *control_block) { u_short value; - if (isp2100_read_nvram_word(host, 0) != 0x5349) + if (isp2x00_read_nvram_word(host, 0) != 0x5349) return 1; - value = isp2100_read_nvram_word(host, 8); - control_block->node_name[0] = isp2100_read_nvram_word(host, 9); - control_block->node_name[1] = isp2100_read_nvram_word(host, 10); - control_block->node_name[2] = isp2100_read_nvram_word(host, 11); - control_block->node_name[3] = isp2100_read_nvram_word(host, 12); - control_block->hard_addr = isp2100_read_nvram_word(host, 13); + value = isp2x00_read_nvram_word(host, 8); + control_block->node_name[0] = isp2x00_read_nvram_word(host, 9); + control_block->node_name[1] = isp2x00_read_nvram_word(host, 10); + control_block->node_name[2] = isp2x00_read_nvram_word(host, 11); + control_block->node_name[3] = isp2x00_read_nvram_word(host, 12); + control_block->hard_addr = isp2x00_read_nvram_word(host, 13); return 0; @@ -1681,54 +1843,53 @@ #endif -static int isp2100_init(struct Scsi_Host *sh) +static int isp2x00_init(struct Scsi_Host *sh) { u_int io_base; - struct isp2100_hostdata *hostdata; + struct isp2x00_hostdata *hostdata; u_char revision; u_int irq; u_short command; struct pci_dev *pdev; - ENTER("isp2100_init"); + ENTER("isp2x00_init"); - hostdata = (struct isp2100_hostdata *) sh->hostdata; + hostdata = (struct isp2x00_hostdata *) sh->hostdata; pdev = hostdata->pci_dev; if (pci_read_config_word(pdev, PCI_COMMAND, &command) || pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision)) { - printk("qlogicfc : error reading PCI configuration\n"); + printk("qlogicfc%d : error reading PCI configuration\n", hostdata->host_id); return 1; } io_base = pdev->base_address[0]; irq = pdev->irq; - if (pdev->vendor != PCI_VENDOR_ID_QLOGIC) { - printk("qlogicfc : 0x%04x is not QLogic vendor ID\n", + printk("qlogicfc%d : 0x%04x is not QLogic vendor ID\n", hostdata->host_id, pdev->vendor); return 1; } - if (pdev->device != PCI_DEVICE_ID_QLOGIC_ISP2100) { - printk("qlogicfc : 0x%04x does not match ISP2100 device id\n", + if (pdev->device != PCI_DEVICE_ID_QLOGIC_ISP2100 && pdev->device != PCI_DEVICE_ID_QLOGIC_ISP2200) { + printk("qlogicfc%d : 0x%04x does not match ISP2100 or ISP2200 device id\n", hostdata->host_id, pdev->device); return 1; } if (command & PCI_COMMAND_IO && (io_base & 3) == 1) io_base &= PCI_BASE_ADDRESS_IO_MASK; else { - printk("qlogicfc : i/o mapping is disabled\n"); + printk("qlogicfc%d : i/o mapping is disabled\n", hostdata->host_id); return 1; } if (!(command & PCI_COMMAND_MASTER)) { - printk("qlogicfc : bus mastering is disabled\n"); + printk("qlogicfc%d : bus mastering is disabled\n", hostdata->host_id); return 1; } - if (revision != ISP2100_REV_ID && revision != ISP2100_REV_ID3) - printk("qlogicfc : new isp2100 revision ID (%d)\n", revision); + if (revision != ISP2100_REV_ID1 && revision != ISP2100_REV_ID3 && revision != ISP2200_REV_ID5) + printk("qlogicfc%d : new isp2x00 revision ID (%d)\n", hostdata->host_id, revision); hostdata->revision = revision; @@ -1736,7 +1897,7 @@ sh->irq = irq; sh->io_port = io_base; - LEAVE("isp2100_init"); + LEAVE("isp2x00_init"); return 0; } @@ -1746,7 +1907,7 @@ #define NVRAM_DELAY() udelay(10) /* 10 microsecond delay */ -u_short isp2100_read_nvram_word(struct Scsi_Host * host, u_short byte) +u_short isp2x00_read_nvram_word(struct Scsi_Host * host, u_short byte) { int i; u_short value, output, input; @@ -1795,26 +1956,27 @@ * currently, this is only called during initialization or abort/reset, * at which times interrupts are disabled, so polling is OK, I guess... */ -static int isp2100_mbox_command(struct Scsi_Host *host, u_short param[]) +static int isp2x00_mbox_command(struct Scsi_Host *host, u_short param[]) { int loop_count; - struct isp2100_hostdata *hostdata = (struct isp2100_hostdata *) host->hostdata; + struct isp2x00_hostdata *hostdata = (struct isp2x00_hostdata *) host->hostdata; - if (mbox_param[param[0]] == 0) + if (mbox_param[param[0]] == 0 || hostdata->adapter_state == AS_FIRMWARE_DEAD) return 1; loop_count = DEFAULT_LOOP_COUNT; while (--loop_count && inw(host->io_port + HOST_HCCR) & 0x0080) barrier(); if (!loop_count) { - printk("qlogicfc: mbox_command loop timeout #1\n"); + printk("qlogicfc%d : mbox_command loop timeout #1\n", hostdata->host_id); param[0] = 0x4006; + hostdata->adapter_state = AS_FIRMWARE_DEAD; return 1; } hostdata->mbox_done = 0; if (mbox_param[param[0]] == 0) - printk("qlogicfc: invalid mbox command\n"); + printk("qlogicfc%d : invalid mbox command\n", hostdata->host_id); if (mbox_param[param[0]] & 0x80) outw(param[7], host->io_port + MBOX7); @@ -1843,10 +2005,11 @@ } if (!loop_count) { - printk("qlogicfc: mbox_command loop timeout #2\n"); + hostdata->adapter_state = AS_FIRMWARE_DEAD; + printk("qlogicfc%d : mbox_command loop timeout #2\n", hostdata->host_id); break; } - isp2100_intr_handler(host->irq, host, NULL); + isp2x00_intr_handler(host->irq, host, NULL); if (hostdata->mbox_done == 1) break; @@ -1858,7 +2021,7 @@ barrier(); } if (!loop_count) - printk("qlogicfc: mbox_command loop timeout #3\n"); + printk("qlogicfc%d : mbox_command loop timeout #3\n", hostdata->host_id); param[7] = inw(host->io_port + MBOX7); param[6] = inw(host->io_port + MBOX6); @@ -1873,19 +2036,21 @@ outw(0x0, host->io_port + PCI_SEMAPHORE); if (inw(host->io_port + HOST_HCCR) & 0x0080) { - printk("mbox op is still pending\n"); + hostdata->adapter_state = AS_FIRMWARE_DEAD; + printk("qlogicfc%d : mbox op is still pending\n", hostdata->host_id); } return 0; } +#if DEBUG_ISP2x00_INTR -void isp2100_print_status_entry(struct Status_Entry *status) +void isp2x00_print_status_entry(struct Status_Entry *status) { - printk("qlogicfc : entry count = 0x%02x, type = 0x%02x, flags = 0x%02x\n", + printk("qlogicfc : entry count = 0x%02x, type = 0x%02x, flags = 0x%02x\n", status->hdr.entry_cnt, status->hdr.entry_type, status->hdr.flags); printk("qlogicfc : scsi status = 0x%04x, completion status = 0x%04x\n", status->scsi_status, status->completion_status); - printk("qlogicfc : state flags = 0x%04x, status flags = 0x%04x\n", + printk("qlogicfc : state flags = 0x%04x, status flags = 0x%04x\n", status->state_flags, status->status_flags); printk("qlogicfc : response info length = 0x%04x, request sense length = 0x%04x\n", status->res_info_len, status->req_sense_len); @@ -1893,15 +2058,16 @@ } +#endif /* DEBUG_ISP2x00_INTR */ -#if DEBUG_ISP2100 +#if DEBUG_ISP2x00 -void isp2100_print_scsi_cmd(Scsi_Cmnd * cmd) +void isp2x00_print_scsi_cmd(Scsi_Cmnd * cmd) { int i; - printk("qlogicfc : target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n", + printk("qlogicfc : target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n", cmd->target, cmd->lun, cmd->cmd_len); printk("qlogicfc : command = "); for (i = 0; i < cmd->cmd_len; i++) @@ -1909,7 +2075,7 @@ printk("\n"); } -#endif /* DEBUG_ISP2100 */ +#endif /* DEBUG_ISP2x00 */ #ifdef MODULE diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/qlogicfc.h linux.pre11.3/drivers/scsi/qlogicfc.h --- linux.vanilla/drivers/scsi/qlogicfc.h Wed Mar 10 21:13:05 1999 +++ linux.pre11.3/drivers/scsi/qlogicfc.h Tue Jul 20 00:03:25 1999 @@ -1,5 +1,5 @@ /* - * QLogic ISP2100 SCSI-FCP + * QLogic ISP2x00 SCSI-FCP * * Written by Erik H. Moe, ehm@cris.com * Copyright 1995, Erik H. Moe @@ -18,7 +18,7 @@ /* Renamed and updated to 1.3.x by Michael Griffith */ /* This is a version of the isp1020 driver which was modified by - * Chris Loveland to support the isp2100 + * Chris Loveland to support the isp2x00 */ @@ -61,39 +61,48 @@ * requests are queued serially and the scatter/gather limit is * determined for each queue request anew. */ -#define QLOGICFC_REQ_QUEUE_LEN 63 /* must be power of two - 1 */ -#define QLOGICFC_MAX_SG(ql) (2 + (((ql) > 0) ? 5*((ql) - 1) : 0)) + +#if BITS_PER_LONG > 32 +#define DATASEGS_PER_COMMAND 2 +#define DATASEGS_PER_CONT 5 +#else +#define DATASEGS_PER_COMMAND 3 +#define DATASEGS_PER_CONT 7 +#endif + +#define QLOGICFC_REQ_QUEUE_LEN 127 /* 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 -int isp2100_detect(Scsi_Host_Template *); -int isp2100_release(struct Scsi_Host *); -const char * isp2100_info(struct Scsi_Host *); -int isp2100_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); -int isp2100_abort(Scsi_Cmnd *); -int isp2100_reset(Scsi_Cmnd *, unsigned int); -int isp2100_biosparam(Disk *, kdev_t, int[]); +int isp2x00_detect(Scsi_Host_Template *); +int isp2x00_release(struct Scsi_Host *); +const char * isp2x00_info(struct Scsi_Host *); +int isp2x00_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); +int isp2x00_abort(Scsi_Cmnd *); +int isp2x00_reset(Scsi_Cmnd *, unsigned int); +int isp2x00_biosparam(Disk *, kdev_t, int[]); #ifndef NULL #define NULL (0) #endif -extern struct proc_dir_entry proc_scsi_isp2100; +extern struct proc_dir_entry proc_scsi_isp2x00; #define QLOGICFC { \ - detect: isp2100_detect, \ - release: isp2100_release, \ - info: isp2100_info, \ - queuecommand: isp2100_queuecommand, \ - abort: isp2100_abort, \ - reset: isp2100_reset, \ - bios_param: isp2100_biosparam, \ + detect: isp2x00_detect, \ + release: isp2x00_release, \ + info: isp2x00_info, \ + queuecommand: isp2x00_queuecommand, \ + eh_abort_handler: isp2x00_abort, \ + reset: isp2x00_reset, \ + bios_param: isp2x00_biosparam, \ can_queue: QLOGICFC_REQ_QUEUE_LEN, \ this_id: -1, \ sg_tablesize: QLOGICFC_MAX_SG(QLOGICFC_REQ_QUEUE_LEN), \ - cmd_per_lun: QLOGICFC_CMD_PER_LUN, \ + cmd_per_lun: QLOGICFC_CMD_PER_LUN, \ present: 0, \ unchecked_isa_dma: 0, \ - use_clustering: DISABLE_CLUSTERING \ + use_clustering: ENABLE_CLUSTERING \ } #endif /* _QLOGICFC_H */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/qlogicfc_asm.c linux.pre11.3/drivers/scsi/qlogicfc_asm.c --- linux.vanilla/drivers/scsi/qlogicfc_asm.c Fri Apr 16 22:10:55 1999 +++ linux.pre11.3/drivers/scsi/qlogicfc_asm.c Tue Jul 20 00:03:26 1999 @@ -1,160 +1,141 @@ -/************************************************************************ - * * - * --- ISP2100 Fabric Initiator/Target Firmware --- * - * * - * * - ************************************************************************ - * * - * NOTICE * - * * - * COPYRIGHT 1998 QLOGIC CORPORATION * - * ALL RIGHTS RESERVED * - * * - ************************************************************************ - */ /* - * Firmware Version 1.15.19 (14:58 Jan 19, 1999) + * Firmware Version 1.15.37 (15:37 May 03, 1999) */ -unsigned short risc_code_version = 1*1024+15; - -unsigned char firmware_version[] = {1,15,19}; - -#define FW_VERSION_STRING "1.15.19" - unsigned short risc_code_addr01 = 0x1000 ; +unsigned short risc_code_length2100 = 0x65db; +unsigned short risc_code_length2200 = 0x81bd; -unsigned short risc_code01[] = { - 0x0078, 0x1029, 0x0000, 0x65e6, 0x0000, 0x2043, 0x4f50, 0x5952, +unsigned short risc_code2100[] = { + 0x0078, 0x1029, 0x0000, 0x65db, 0x0000, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939, 0x3620, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3231, 0x3030, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, 0x312e, 0x3135, 0x2020, 0x2020, - 0x2400, 0x20c1, 0x0021, 0x20a1, 0x75e6, 0x2009, 0x0000, 0x20a9, - 0x071a, 0x41a4, 0x3400, 0x20c9, 0x7aff, 0x2091, 0x2000, 0x2059, - 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x20a0, 0x2051, 0x7600, + 0x2400, 0x20c1, 0x0021, 0x20a1, 0x75db, 0x2009, 0x0000, 0x20a9, + 0x0725, 0x41a4, 0x3400, 0x20c9, 0x7aff, 0x2091, 0x2000, 0x2059, + 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x209a, 0x2051, 0x7600, 0x2a70, 0x705b, 0x9500, 0x705f, 0xffff, 0x7057, 0x94f9, 0x7063, - 0x0300, 0x1078, 0x1282, 0x20a1, 0x7d00, 0x715c, 0x810d, 0x810d, + 0x0300, 0x1078, 0x127a, 0x20a1, 0x7d00, 0x715c, 0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0007, 0xa112, 0xa00e, 0x21a8, 0x41a4, 0x3400, 0x8211, 0x00c0, 0x1058, 0x715c, 0x3400, 0xa102, 0x0040, 0x1068, 0x0048, 0x1068, 0x20a8, 0xa00e, 0x41a4, - 0x1078, 0x1249, 0x1078, 0x136e, 0x1078, 0x14f3, 0x1078, 0x19c8, - 0x1078, 0x3615, 0x1078, 0x5b94, 0x1078, 0x12f9, 0x1078, 0x242f, - 0x1078, 0x3c56, 0x1078, 0x3a2e, 0x1078, 0x4494, 0x1078, 0x1e5b, - 0x1078, 0x46d3, 0x1078, 0x4174, 0x1078, 0x1d7a, 0x1078, 0x1e3a, + 0x1078, 0x1241, 0x1078, 0x1366, 0x1078, 0x14eb, 0x1078, 0x19c0, + 0x1078, 0x360d, 0x1078, 0x5b8c, 0x1078, 0x12f1, 0x1078, 0x2429, + 0x1078, 0x3c4e, 0x1078, 0x3a26, 0x1078, 0x448c, 0x1078, 0x1e55, + 0x1078, 0x46cb, 0x1078, 0x416c, 0x1078, 0x1d74, 0x1078, 0x1e34, 0x2091, 0x3009, 0x7823, 0x0000, 0x0090, 0x109d, 0x7820, 0xa086, 0x0002, 0x00c0, 0x109d, 0x7823, 0x4000, 0x0068, 0x1095, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, 0x7003, 0x0000, 0x2001, 0x017f, 0x2003, 0x0000, 0x2a70, 0x7000, 0xa08e, 0x0003, - 0x00c0, 0x10bd, 0x1078, 0x2d8d, 0x1078, 0x2457, 0x1078, 0x3ca6, - 0x1078, 0x3b19, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048, - 0x10c1, 0x1078, 0x44ac, 0x0078, 0x10a4, 0x1079, 0x10c5, 0x0078, - 0x10aa, 0x1078, 0x5866, 0x0078, 0x10b9, 0x10cf, 0x10d0, 0x114b, - 0x10cd, 0x11c6, 0x1246, 0x1247, 0x1248, 0x1078, 0x12d5, 0x007c, - 0x127e, 0x0f7e, 0x2091, 0x8000, 0x1078, 0x2eb2, 0x2079, 0x0100, - 0x7844, 0xa005, 0x00c0, 0x113c, 0x2011, 0x3542, 0x1078, 0x456e, + 0x00c0, 0x10bd, 0x1078, 0x2d7e, 0x1078, 0x2451, 0x1078, 0x3c9e, + 0x1078, 0x3b11, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048, + 0x10c1, 0x1078, 0x44a4, 0x0078, 0x10a4, 0x1079, 0x10c5, 0x0078, + 0x10aa, 0x1078, 0x585e, 0x0078, 0x10b9, 0x10cf, 0x10d0, 0x1143, + 0x10cd, 0x11be, 0x123e, 0x123f, 0x1240, 0x1078, 0x12cd, 0x007c, + 0x127e, 0x0f7e, 0x2091, 0x8000, 0x1078, 0x2ea3, 0x2079, 0x0100, + 0x7844, 0xa005, 0x00c0, 0x1134, 0x2011, 0x353a, 0x1078, 0x4566, 0x780f, 0x00ff, 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011, 0x8010, - 0x73b8, 0x1078, 0x2d4a, 0x1078, 0x56b1, 0x2011, 0x0004, 0x1078, - 0x6953, 0x1078, 0x39c8, 0x70c7, 0x0000, 0x70bf, 0x0000, 0x70c3, - 0x0000, 0x1078, 0x113f, 0x2011, 0x0000, 0x2079, 0x7651, 0x7804, - 0xd0ac, 0x0040, 0x1104, 0xc295, 0x70a4, 0xa005, 0x0040, 0x1109, - 0xc29d, 0x72be, 0xa296, 0x0004, 0x0040, 0x112a, 0x2011, 0x0001, - 0x1078, 0x6953, 0x708b, 0x0000, 0x708f, 0xffff, 0x7003, 0x0002, - 0x0f7f, 0x1078, 0x2150, 0x2011, 0x0005, 0x1078, 0x57c0, 0x1078, - 0x4c7a, 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f, 0x127f, - 0x0078, 0x113e, 0x708b, 0x0000, 0x708f, 0xffff, 0x7003, 0x0002, - 0x2011, 0x0005, 0x1078, 0x57c0, 0x1078, 0x4c7a, 0x0c7e, 0x2061, + 0x73b8, 0x1078, 0x2d3b, 0x1078, 0x56a9, 0x2011, 0x0004, 0x1078, + 0x694d, 0x1078, 0x39c0, 0x70c7, 0x0000, 0x70c3, 0x0000, 0x1078, + 0x1137, 0x72bc, 0x2079, 0x7651, 0x7804, 0xd0ac, 0x0040, 0x1101, + 0xc295, 0x72be, 0xa296, 0x0004, 0x0040, 0x1122, 0x2011, 0x0001, + 0x1078, 0x694d, 0x708b, 0x0000, 0x708f, 0xffff, 0x7003, 0x0002, + 0x0f7f, 0x1078, 0x214a, 0x2011, 0x0005, 0x1078, 0x57b8, 0x1078, + 0x4c72, 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f, 0x127f, + 0x0078, 0x1136, 0x708b, 0x0000, 0x708f, 0xffff, 0x7003, 0x0002, + 0x2011, 0x0005, 0x1078, 0x57b8, 0x1078, 0x4c72, 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f, 0x0f7f, 0x127f, 0x007c, 0x0c7e, - 0x20a9, 0x0082, 0x2009, 0x007e, 0x1078, 0x380d, 0x8108, 0x00f0, - 0x1144, 0x0c7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x708c, 0xa086, - 0xffff, 0x0040, 0x1159, 0x1078, 0x2150, 0x1078, 0x4c7a, 0x0078, - 0x11c4, 0x70bc, 0xd09c, 0x0040, 0x1181, 0xd084, 0x0040, 0x1181, + 0x20a9, 0x0082, 0x2009, 0x007e, 0x1078, 0x3805, 0x8108, 0x00f0, + 0x113c, 0x0c7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x708c, 0xa086, + 0xffff, 0x0040, 0x1151, 0x1078, 0x214a, 0x1078, 0x4c72, 0x0078, + 0x11bc, 0x70bc, 0xd09c, 0x0040, 0x1179, 0xd084, 0x0040, 0x1179, 0x0f7e, 0x2079, 0x0100, 0x790c, 0xc1b5, 0x790e, 0x0f7f, 0xd08c, - 0x0040, 0x1181, 0x70c0, 0xa086, 0xffff, 0x0040, 0x117d, 0x1078, - 0x2245, 0x1078, 0x4c7a, 0x2011, 0x0001, 0x2019, 0x0000, 0x1078, - 0x227d, 0x1078, 0x4c7a, 0x0078, 0x11c4, 0x70c4, 0xa005, 0x00c0, - 0x11c4, 0x7088, 0xa005, 0x00c0, 0x11c4, 0x2001, 0x7652, 0x2004, - 0xd0ac, 0x0040, 0x11a7, 0x157e, 0x0c7e, 0x20a9, 0x007f, 0x2009, - 0x0000, 0x017e, 0x1078, 0x3825, 0x00c0, 0x119a, 0x6000, 0xd0ec, - 0x00c0, 0x11a2, 0x017f, 0x8108, 0x00f0, 0x1191, 0x0c7f, 0x157f, - 0x0078, 0x11a7, 0x017f, 0x0c7f, 0x157f, 0x0078, 0x11c4, 0x7003, - 0x0003, 0x708f, 0xffff, 0x2001, 0x0000, 0x1078, 0x202b, 0x1078, - 0x2dc8, 0x2001, 0x7837, 0x2004, 0xa086, 0x0005, 0x00c0, 0x11bc, - 0x2011, 0x0000, 0x1078, 0x57c0, 0x2011, 0x0000, 0x1078, 0x57ca, - 0x1078, 0x4c7a, 0x1078, 0x4d3a, 0x127f, 0x007c, 0x017e, 0x0f7e, + 0x0040, 0x1179, 0x70c0, 0xa086, 0xffff, 0x0040, 0x1175, 0x1078, + 0x223f, 0x1078, 0x4c72, 0x2011, 0x0001, 0x2019, 0x0000, 0x1078, + 0x2277, 0x1078, 0x4c72, 0x0078, 0x11bc, 0x70c4, 0xa005, 0x00c0, + 0x11bc, 0x7088, 0xa005, 0x00c0, 0x11bc, 0x2001, 0x7652, 0x2004, + 0xd0ac, 0x0040, 0x119f, 0x157e, 0x0c7e, 0x20a9, 0x007f, 0x2009, + 0x0000, 0x017e, 0x1078, 0x381d, 0x00c0, 0x1192, 0x6000, 0xd0ec, + 0x00c0, 0x119a, 0x017f, 0x8108, 0x00f0, 0x1189, 0x0c7f, 0x157f, + 0x0078, 0x119f, 0x017f, 0x0c7f, 0x157f, 0x0078, 0x11bc, 0x7003, + 0x0003, 0x708f, 0xffff, 0x2001, 0x0000, 0x1078, 0x2025, 0x1078, + 0x2db9, 0x2001, 0x7837, 0x2004, 0xa086, 0x0005, 0x00c0, 0x11b4, + 0x2011, 0x0000, 0x1078, 0x57b8, 0x2011, 0x0000, 0x1078, 0x57c2, + 0x1078, 0x4c72, 0x1078, 0x4d32, 0x127f, 0x007c, 0x017e, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079, 0x0100, 0x7940, 0xa18c, 0x0010, - 0x7942, 0x7924, 0xd1b4, 0x0040, 0x11d7, 0x7827, 0x0040, 0xd19c, - 0x0040, 0x11dc, 0x7827, 0x0008, 0x007e, 0x037e, 0x157e, 0x7900, - 0xa18a, 0x0003, 0x0050, 0x1202, 0x7954, 0xd1ac, 0x00c0, 0x1202, - 0x2009, 0x00f8, 0x1078, 0x35e4, 0x7843, 0x0090, 0x7843, 0x0010, - 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x00c0, 0x11fa, 0x7824, 0xd0ac, - 0x00c0, 0x1236, 0x00f0, 0x11f2, 0x2001, 0x0001, 0x1078, 0x202b, - 0x0078, 0x123f, 0x7853, 0x0000, 0x782f, 0x0020, 0x20a9, 0x0008, - 0x00e0, 0x1208, 0x2091, 0x6000, 0x00f0, 0x1208, 0x7853, 0x0400, - 0x782f, 0x0000, 0x2009, 0x00f8, 0x1078, 0x35e4, 0x20a9, 0x000e, - 0x0005, 0x00f0, 0x1218, 0x7853, 0x1400, 0x7843, 0x0090, 0x7843, + 0x7942, 0x7924, 0xd1b4, 0x0040, 0x11cf, 0x7827, 0x0040, 0xd19c, + 0x0040, 0x11d4, 0x7827, 0x0008, 0x007e, 0x037e, 0x157e, 0x7900, + 0xa18a, 0x0003, 0x0050, 0x11fa, 0x7954, 0xd1ac, 0x00c0, 0x11fa, + 0x2009, 0x00f8, 0x1078, 0x35dc, 0x7843, 0x0090, 0x7843, 0x0010, + 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x00c0, 0x11f2, 0x7824, 0xd0ac, + 0x00c0, 0x122e, 0x00f0, 0x11ea, 0x2001, 0x0001, 0x1078, 0x2025, + 0x0078, 0x1237, 0x7853, 0x0000, 0x782f, 0x0020, 0x20a9, 0x0008, + 0x00e0, 0x1200, 0x2091, 0x6000, 0x00f0, 0x1200, 0x7853, 0x0400, + 0x782f, 0x0000, 0x2009, 0x00f8, 0x1078, 0x35dc, 0x20a9, 0x000e, + 0x0005, 0x00f0, 0x1210, 0x7853, 0x1400, 0x7843, 0x0090, 0x7843, 0x0010, 0x2019, 0x61a8, 0x7854, 0x0005, 0x0005, 0xd08c, 0x0040, - 0x122d, 0x7824, 0xd0ac, 0x00c0, 0x1236, 0x8319, 0x00c0, 0x1223, - 0x2001, 0x0001, 0x1078, 0x202b, 0x0078, 0x123d, 0x7828, 0xc09d, + 0x1225, 0x7824, 0xd0ac, 0x00c0, 0x122e, 0x8319, 0x00c0, 0x121b, + 0x2001, 0x0001, 0x1078, 0x2025, 0x0078, 0x1235, 0x7828, 0xc09d, 0x782a, 0x7827, 0x0008, 0x7827, 0x0040, 0x7853, 0x0400, 0x157f, 0x037f, 0x007f, 0x127f, 0x0f7f, 0x017f, 0x007c, 0x007c, 0x007c, 0x007c, 0x2a70, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048, - 0x1255, 0x704f, 0xffff, 0x0078, 0x1257, 0x704f, 0x0000, 0x7053, + 0x124d, 0x704f, 0xffff, 0x0078, 0x124f, 0x704f, 0x0000, 0x7053, 0xffff, 0x7067, 0x0000, 0x706b, 0x0000, 0x2061, 0x7820, 0x6003, 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, 0x07d0, 0x2061, 0x7828, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, 0x0000, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001, 0x601f, - 0x0000, 0x007c, 0x1078, 0x12a8, 0x2011, 0x0000, 0x81ff, 0x0040, - 0x12a7, 0xa186, 0x0001, 0x00c0, 0x1297, 0x705f, 0x8fff, 0x7057, - 0x8501, 0x7063, 0x0100, 0x705b, 0x8500, 0x0078, 0x12a5, 0xa186, - 0x0002, 0x00c0, 0x129f, 0x2011, 0x0000, 0x0078, 0x12a5, 0xa186, - 0x0005, 0x00c0, 0x12a5, 0x2011, 0x0001, 0x1078, 0x12cf, 0x007c, - 0x2009, 0x0000, 0x2011, 0x0000, 0x1078, 0x12cf, 0x2019, 0xaaaa, + 0x0000, 0x007c, 0x1078, 0x12a0, 0x2011, 0x0000, 0x81ff, 0x0040, + 0x129f, 0xa186, 0x0001, 0x00c0, 0x128f, 0x705f, 0x8fff, 0x7057, + 0x8501, 0x7063, 0x0100, 0x705b, 0x8500, 0x0078, 0x129d, 0xa186, + 0x0002, 0x00c0, 0x1297, 0x2011, 0x0000, 0x0078, 0x129d, 0xa186, + 0x0005, 0x00c0, 0x129d, 0x2011, 0x0001, 0x1078, 0x12c7, 0x007c, + 0x2009, 0x0000, 0x2011, 0x0000, 0x1078, 0x12c7, 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2362, 0x2c24, 0x2061, 0x7fff, 0x2c04, 0xa406, - 0x0040, 0x12bd, 0xc18d, 0x0078, 0x12ca, 0xc185, 0x2011, 0x0001, - 0x1078, 0x12cf, 0x2061, 0xffff, 0x2362, 0x2c04, 0xa306, 0x00c0, - 0x12ca, 0xc195, 0x2011, 0x0001, 0x1078, 0x12cf, 0x007c, 0x3800, + 0x0040, 0x12b5, 0xc18d, 0x0078, 0x12c2, 0xc185, 0x2011, 0x0001, + 0x1078, 0x12c7, 0x2061, 0xffff, 0x2362, 0x2c04, 0xa306, 0x00c0, + 0x12c2, 0xc195, 0x2011, 0x0001, 0x1078, 0x12c7, 0x007c, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x007c, 0x2091, 0x8000, 0x0068, - 0x12d7, 0x007e, 0x017e, 0x2079, 0x0000, 0x7818, 0xa084, 0x0000, - 0x00c0, 0x12dd, 0x017f, 0x792e, 0x007f, 0x782a, 0x007f, 0x7826, + 0x12cf, 0x007e, 0x017e, 0x2079, 0x0000, 0x7818, 0xa084, 0x0000, + 0x00c0, 0x12d5, 0x017f, 0x792e, 0x007f, 0x782a, 0x007f, 0x7826, 0x3900, 0x783a, 0x7823, 0x8002, 0x781b, 0x0001, 0x2091, 0x5000, - 0x2091, 0x4080, 0x2079, 0x7600, 0x7803, 0x0005, 0x0078, 0x12f6, + 0x2091, 0x4080, 0x2079, 0x7600, 0x7803, 0x0005, 0x0078, 0x12ee, 0x007c, 0x2071, 0x7600, 0x7158, 0x712e, 0x2021, 0x0001, 0xa190, - 0x002d, 0xa298, 0x002d, 0x0048, 0x130f, 0x705c, 0xa302, 0x00c8, - 0x130f, 0x220a, 0x2208, 0x2310, 0x8420, 0x0078, 0x1301, 0x200b, + 0x002d, 0xa298, 0x002d, 0x0048, 0x1307, 0x705c, 0xa302, 0x00c8, + 0x1307, 0x220a, 0x2208, 0x2310, 0x8420, 0x0078, 0x12f9, 0x200b, 0x0000, 0x749e, 0x74a2, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000, - 0x2071, 0x7600, 0x70a0, 0xa0ea, 0x0010, 0x00c8, 0x1322, 0xa06e, - 0x0078, 0x132c, 0x8001, 0x70a2, 0x702c, 0x2068, 0x2d04, 0x702e, + 0x2071, 0x7600, 0x70a0, 0xa0ea, 0x0010, 0x00c8, 0x131a, 0xa06e, + 0x0078, 0x1324, 0x8001, 0x70a2, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x127f, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0x7600, 0x127e, 0x2091, 0x8000, 0x70a0, 0x8001, 0x00c8, - 0x133c, 0xa06e, 0x0078, 0x1345, 0x70a2, 0x702c, 0x2068, 0x2d04, + 0x1334, 0xa06e, 0x0078, 0x133d, 0x70a2, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x127f, 0x0e7f, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000, 0x2071, 0x7600, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70a0, 0x8000, 0x70a2, 0x127f, 0x0e7f, 0x007c, - 0x8dff, 0x0040, 0x1364, 0x6804, 0x6807, 0x0000, 0x007e, 0x1078, - 0x1348, 0x0d7f, 0x0078, 0x1358, 0x007c, 0x0e7e, 0x2071, 0x7600, + 0x8dff, 0x0040, 0x135c, 0x6804, 0x6807, 0x0000, 0x007e, 0x1078, + 0x1340, 0x0d7f, 0x0078, 0x1350, 0x007c, 0x0e7e, 0x2071, 0x7600, 0x70a0, 0xa08a, 0x0010, 0xa00d, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0x7859, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x2071, 0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x0e7f, 0x007c, 0x0e7e, 0x2270, 0x700b, 0x0000, 0x2071, 0x7859, 0x7018, 0xa088, 0x7862, 0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, 0x00c0, - 0x1397, 0x0f7e, 0x2079, 0x0010, 0x1078, 0x13a8, 0x0f7f, 0x0e7f, - 0x007c, 0x0e7e, 0x2071, 0x7859, 0x7004, 0xa005, 0x00c0, 0x13a6, - 0x0f7e, 0x2079, 0x0010, 0x1078, 0x13a8, 0x0f7f, 0x0e7f, 0x007c, - 0x7000, 0x0079, 0x13ab, 0x13af, 0x1419, 0x1436, 0x1436, 0x7018, - 0x711c, 0xa106, 0x00c0, 0x13b7, 0x7007, 0x0000, 0x007c, 0x0d7e, + 0x138f, 0x0f7e, 0x2079, 0x0010, 0x1078, 0x13a0, 0x0f7f, 0x0e7f, + 0x007c, 0x0e7e, 0x2071, 0x7859, 0x7004, 0xa005, 0x00c0, 0x139e, + 0x0f7e, 0x2079, 0x0010, 0x1078, 0x13a0, 0x0f7f, 0x0e7f, 0x007c, + 0x7000, 0x0079, 0x13a3, 0x13a7, 0x1411, 0x142e, 0x142e, 0x7018, + 0x711c, 0xa106, 0x00c0, 0x13af, 0x7007, 0x0000, 0x007c, 0x0d7e, 0xa180, 0x7862, 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, 0x13d9, 0x7007, 0x0001, 0x1078, 0x13de, - 0x007c, 0x7007, 0x0002, 0x1078, 0x13f4, 0x007c, 0x017e, 0x027e, - 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x13e9, 0x2110, + 0x0d7f, 0xd084, 0x0040, 0x13d1, 0x7007, 0x0001, 0x1078, 0x13d6, + 0x007c, 0x7007, 0x0002, 0x1078, 0x13ec, 0x007c, 0x017e, 0x027e, + 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x13e1, 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, 0x1408, 0x2110, 0xa006, + 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x1400, 0x2110, 0xa006, 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803, 0x0020, 0x7803, 0x0001, 0x3300, 0x7016, 0x157f, 0x147f, 0x137f, 0x027f, 0x017f, 0x007c, 0x137e, 0x147e, 0x157e, 0x2099, 0x76e5, 0x20a1, 0x0018, @@ -167,1088 +148,1088 @@ 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c, 0x7002, 0x700b, 0x7711, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x017e, 0x0e7e, 0x2071, 0x7859, 0x0f7e, 0x2079, 0x0010, 0x7904, 0x7803, 0x0002, - 0xd1fc, 0x0040, 0x1479, 0xa18c, 0x0700, 0x0040, 0x1476, 0x7008, - 0xa080, 0x0002, 0x2003, 0x0200, 0x0078, 0x1479, 0x7004, 0x1079, - 0x147d, 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x13a8, 0x1485, 0x14a7, - 0x14c1, 0x14ea, 0x1483, 0x0078, 0x1483, 0x137e, 0x147e, 0x157e, + 0xd1fc, 0x0040, 0x1471, 0xa18c, 0x0700, 0x0040, 0x146e, 0x7008, + 0xa080, 0x0002, 0x2003, 0x0200, 0x0078, 0x1471, 0x7004, 0x1079, + 0x1475, 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x13a0, 0x147d, 0x149f, + 0x14b9, 0x14e2, 0x147b, 0x0078, 0x147b, 0x137e, 0x147e, 0x157e, 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400, 0x7016, 0x157f, 0x147f, 0x137f, 0x700c, 0xa005, - 0x0040, 0x14ae, 0x1078, 0x13de, 0x007c, 0x7008, 0xa080, 0x0002, - 0x2003, 0x0100, 0x7007, 0x0000, 0x1078, 0x13a8, 0x007c, 0x700c, - 0xa005, 0x0040, 0x14ae, 0x1078, 0x13f4, 0x007c, 0x0d7e, 0x7008, + 0x0040, 0x14a6, 0x1078, 0x13d6, 0x007c, 0x7008, 0xa080, 0x0002, + 0x2003, 0x0100, 0x7007, 0x0000, 0x1078, 0x13a0, 0x007c, 0x700c, + 0xa005, 0x0040, 0x14a6, 0x1078, 0x13ec, 0x007c, 0x0d7e, 0x7008, 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, 0x682e, 0x783c, - 0x6832, 0x680b, 0x0100, 0x0d7f, 0x7007, 0x0000, 0x1078, 0x13a8, + 0x6832, 0x680b, 0x0100, 0x0d7f, 0x7007, 0x0000, 0x1078, 0x13a0, 0x007c, 0x137e, 0x147e, 0x157e, 0x2001, 0x76e3, 0x2004, 0xa080, 0x000d, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, - 0x53a5, 0x2001, 0x76e5, 0x2004, 0xd0bc, 0x0040, 0x14e0, 0x2001, + 0x53a5, 0x2001, 0x76e5, 0x2004, 0xd0bc, 0x0040, 0x14d8, 0x2001, 0x76ee, 0x2004, 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020, 0x53a5, - 0x157f, 0x147f, 0x137f, 0x7007, 0x0000, 0x1078, 0x3d4f, 0x1078, - 0x13a8, 0x007c, 0x2001, 0x7713, 0x2003, 0x0100, 0x7007, 0x0000, - 0x1078, 0x13a8, 0x007c, 0x127e, 0x2091, 0x2100, 0x2079, 0x0030, + 0x157f, 0x147f, 0x137f, 0x7007, 0x0000, 0x1078, 0x3d47, 0x1078, + 0x13a0, 0x007c, 0x2001, 0x7713, 0x2003, 0x0100, 0x7007, 0x0000, + 0x1078, 0x13a0, 0x007c, 0x127e, 0x2091, 0x2100, 0x2079, 0x0030, 0x2071, 0x786a, 0x7003, 0x0000, 0x700f, 0x7870, 0x7013, 0x7870, 0x780f, 0x0070, 0x127f, 0x007c, 0x6934, 0xa184, 0x0007, 0x0079, - 0x1509, 0x1511, 0x1557, 0x1511, 0x1511, 0x1511, 0x153c, 0x1520, - 0x1515, 0xa085, 0x0001, 0x0078, 0x1571, 0x684c, 0xd0bc, 0x0040, - 0x1511, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x0078, 0x155f, - 0xa18c, 0x00ff, 0xa186, 0x001e, 0x00c0, 0x1511, 0x684c, 0xd0bc, - 0x0040, 0x1511, 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a, - 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x1c84, 0x2004, - 0x6832, 0x6858, 0x0078, 0x1567, 0xa18c, 0x00ff, 0xa186, 0x0015, - 0x00c0, 0x1511, 0x684c, 0xd0ac, 0x0040, 0x1511, 0x6804, 0x681a, - 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x1c84, 0x2004, - 0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0078, 0x1567, 0x684c, - 0xd0ac, 0x0040, 0x1511, 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c, - 0x000f, 0xa188, 0x1c84, 0x210c, 0x6932, 0x2d08, 0x691a, 0x6826, + 0x1501, 0x1509, 0x154f, 0x1509, 0x1509, 0x1509, 0x1534, 0x1518, + 0x150d, 0xa085, 0x0001, 0x0078, 0x1569, 0x684c, 0xd0bc, 0x0040, + 0x1509, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x0078, 0x1557, + 0xa18c, 0x00ff, 0xa186, 0x001e, 0x00c0, 0x1509, 0x684c, 0xd0bc, + 0x0040, 0x1509, 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a, + 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x1c7e, 0x2004, + 0x6832, 0x6858, 0x0078, 0x155f, 0xa18c, 0x00ff, 0xa186, 0x0015, + 0x00c0, 0x1509, 0x684c, 0xd0ac, 0x0040, 0x1509, 0x6804, 0x681a, + 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x1c7e, 0x2004, + 0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0078, 0x155f, 0x684c, + 0xd0ac, 0x0040, 0x1509, 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c, + 0x000f, 0xa188, 0x1c7e, 0x210c, 0x6932, 0x2d08, 0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x007c, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a, - 0x2004, 0x82ff, 0x0040, 0x158c, 0xa280, 0x0004, 0x0d7e, 0x206c, - 0x684c, 0xd0dc, 0x00c0, 0x1588, 0x1078, 0x1504, 0x10c0, 0x12d5, + 0x2004, 0x82ff, 0x0040, 0x1584, 0xa280, 0x0004, 0x0d7e, 0x206c, + 0x684c, 0xd0dc, 0x00c0, 0x1580, 0x1078, 0x14fc, 0x10c0, 0x12cd, 0x6808, 0x8000, 0x680a, 0x0d7f, 0x127e, 0x047e, 0x037e, 0x027e, 0x2091, 0x2100, 0x027f, 0x037f, 0x047f, 0x7000, 0xa005, 0x00c0, - 0x15a0, 0x7206, 0x2001, 0x15b4, 0x007e, 0x2260, 0x0078, 0x16cc, + 0x1598, 0x7206, 0x2001, 0x15ac, 0x007e, 0x2260, 0x0078, 0x16c4, 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, 0x8108, 0xa182, - 0x788b, 0x0048, 0x15ad, 0x2009, 0x7870, 0x710e, 0x7000, 0xa005, - 0x00c0, 0x15b4, 0x1078, 0x16b5, 0x127f, 0x007c, 0x127e, 0x027e, + 0x788b, 0x0048, 0x15a5, 0x2009, 0x7870, 0x710e, 0x7000, 0xa005, + 0x00c0, 0x15ac, 0x1078, 0x16ad, 0x127f, 0x007c, 0x127e, 0x027e, 0x037e, 0x0c7e, 0x007e, 0x2091, 0x2100, 0x007f, 0x047f, 0x037f, 0x027f, 0x0d7e, 0x0c7e, 0x2460, 0x6110, 0x2168, 0x6a62, 0x6b5e, - 0xa005, 0x0040, 0x1608, 0x6808, 0xa005, 0x0040, 0x166e, 0x7000, - 0xa005, 0x00c0, 0x15d5, 0x0078, 0x1602, 0x700c, 0x7110, 0xa106, - 0x00c0, 0x1672, 0x7004, 0xa406, 0x00c0, 0x1602, 0x2001, 0x0005, - 0x2004, 0xd08c, 0x0040, 0x15eb, 0x047e, 0x1078, 0x178d, 0x047f, - 0x2460, 0x0078, 0x15cb, 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, - 0x15de, 0x7804, 0xa084, 0x6000, 0x0040, 0x15fc, 0xa086, 0x6000, - 0x0040, 0x15fc, 0x0078, 0x15de, 0x7803, 0x0004, 0x7003, 0x0000, - 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x5c29, 0x0078, 0x1672, - 0x6808, 0xa005, 0x0040, 0x166e, 0x7000, 0xa005, 0x00c0, 0x1612, - 0x0078, 0x166e, 0x700c, 0x7110, 0xa106, 0x00c0, 0x161b, 0x7004, - 0xa406, 0x00c0, 0x166e, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040, - 0x1628, 0x047e, 0x1078, 0x178d, 0x047f, 0x2460, 0x0078, 0x1608, - 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, 0x161b, 0x2001, 0x0005, - 0x2004, 0xd08c, 0x00c0, 0x1621, 0x7804, 0xa084, 0x6000, 0x0040, - 0x163f, 0xa086, 0x6000, 0x0040, 0x163f, 0x0078, 0x161b, 0x7007, - 0x0000, 0xa016, 0x2218, 0x7000, 0xa08e, 0x0001, 0x0040, 0x1660, - 0xa08e, 0x0002, 0x00c0, 0x166e, 0x0c7e, 0x0e7e, 0x6818, 0x2060, - 0x1078, 0x1c59, 0x2804, 0xac70, 0x6034, 0xd09c, 0x00c0, 0x165c, - 0x7308, 0x720c, 0x0078, 0x165e, 0x7310, 0x7214, 0x0e7f, 0x0c7f, + 0xa005, 0x0040, 0x1600, 0x6808, 0xa005, 0x0040, 0x1666, 0x7000, + 0xa005, 0x00c0, 0x15cd, 0x0078, 0x15fa, 0x700c, 0x7110, 0xa106, + 0x00c0, 0x166a, 0x7004, 0xa406, 0x00c0, 0x15fa, 0x2001, 0x0005, + 0x2004, 0xd08c, 0x0040, 0x15e3, 0x047e, 0x1078, 0x1785, 0x047f, + 0x2460, 0x0078, 0x15c3, 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, + 0x15d6, 0x7804, 0xa084, 0x6000, 0x0040, 0x15f4, 0xa086, 0x6000, + 0x0040, 0x15f4, 0x0078, 0x15d6, 0x7803, 0x0004, 0x7003, 0x0000, + 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x5c21, 0x0078, 0x166a, + 0x6808, 0xa005, 0x0040, 0x1666, 0x7000, 0xa005, 0x00c0, 0x160a, + 0x0078, 0x1666, 0x700c, 0x7110, 0xa106, 0x00c0, 0x1613, 0x7004, + 0xa406, 0x00c0, 0x1666, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040, + 0x1620, 0x047e, 0x1078, 0x1785, 0x047f, 0x2460, 0x0078, 0x1600, + 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, 0x1613, 0x2001, 0x0005, + 0x2004, 0xd08c, 0x00c0, 0x1619, 0x7804, 0xa084, 0x6000, 0x0040, + 0x1637, 0xa086, 0x6000, 0x0040, 0x1637, 0x0078, 0x1613, 0x7007, + 0x0000, 0xa016, 0x2218, 0x7000, 0xa08e, 0x0001, 0x0040, 0x1658, + 0xa08e, 0x0002, 0x00c0, 0x1666, 0x0c7e, 0x0e7e, 0x6818, 0x2060, + 0x1078, 0x1c53, 0x2804, 0xac70, 0x6034, 0xd09c, 0x00c0, 0x1654, + 0x7308, 0x720c, 0x0078, 0x1656, 0x7310, 0x7214, 0x0e7f, 0x0c7f, 0x7820, 0xa318, 0x7824, 0xa211, 0x6810, 0xa300, 0x6812, 0x6814, 0xa201, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, 0x2009, 0x0048, - 0x1078, 0x5c29, 0x0c7f, 0x0d7f, 0x127f, 0x007c, 0x0f7e, 0x0e7e, - 0x2071, 0x786a, 0x7000, 0xa086, 0x0000, 0x0040, 0x16b2, 0x7004, - 0xac06, 0x00c0, 0x16a3, 0x2079, 0x0030, 0x7804, 0xd0fc, 0x00c0, - 0x169f, 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, 0x1685, 0x7803, - 0x0004, 0x7804, 0xd0ac, 0x00c0, 0x1691, 0x7803, 0x0002, 0x7803, - 0x0009, 0x7003, 0x0003, 0x7007, 0x0000, 0x0078, 0x16a3, 0x1078, - 0x178d, 0x0078, 0x167a, 0x157e, 0x20a9, 0x0009, 0x2009, 0x7870, - 0x2104, 0xac06, 0x00c0, 0x16ad, 0x200a, 0xa188, 0x0003, 0x00f0, - 0x16a8, 0x157f, 0x0e7f, 0x0f7f, 0x007c, 0x700c, 0x7110, 0xa106, - 0x00c0, 0x16bd, 0x7003, 0x0000, 0x007c, 0x2104, 0x7006, 0x2060, + 0x1078, 0x5c21, 0x0c7f, 0x0d7f, 0x127f, 0x007c, 0x0f7e, 0x0e7e, + 0x2071, 0x786a, 0x7000, 0xa086, 0x0000, 0x0040, 0x16aa, 0x7004, + 0xac06, 0x00c0, 0x169b, 0x2079, 0x0030, 0x7804, 0xd0fc, 0x00c0, + 0x1697, 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, 0x167d, 0x7803, + 0x0004, 0x7804, 0xd0ac, 0x00c0, 0x1689, 0x7803, 0x0002, 0x7803, + 0x0009, 0x7003, 0x0003, 0x7007, 0x0000, 0x0078, 0x169b, 0x1078, + 0x1785, 0x0078, 0x1672, 0x157e, 0x20a9, 0x0009, 0x2009, 0x7870, + 0x2104, 0xac06, 0x00c0, 0x16a5, 0x200a, 0xa188, 0x0003, 0x00f0, + 0x16a0, 0x157f, 0x0e7f, 0x0f7f, 0x007c, 0x700c, 0x7110, 0xa106, + 0x00c0, 0x16b5, 0x7003, 0x0000, 0x007c, 0x2104, 0x7006, 0x2060, 0x8108, 0x211c, 0x8108, 0x2124, 0x8108, 0xa182, 0x788b, 0x0048, - 0x16cb, 0x2009, 0x7870, 0x7112, 0x8cff, 0x00c0, 0x16d3, 0x1078, - 0x1958, 0x0078, 0x16fa, 0x6010, 0x2068, 0x2d58, 0x6828, 0xa406, - 0x00c0, 0x16de, 0x682c, 0xa306, 0x0040, 0x16e2, 0x1078, 0x1ca4, - 0x00c0, 0x16cf, 0x684c, 0xd0f4, 0x00c0, 0x16cf, 0x6824, 0x2050, + 0x16c3, 0x2009, 0x7870, 0x7112, 0x8cff, 0x00c0, 0x16cb, 0x1078, + 0x1950, 0x0078, 0x16f2, 0x6010, 0x2068, 0x2d58, 0x6828, 0xa406, + 0x00c0, 0x16d6, 0x682c, 0xa306, 0x0040, 0x16da, 0x1078, 0x1c9e, + 0x00c0, 0x16c7, 0x684c, 0xd0f4, 0x00c0, 0x16c7, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, 0x2009, - 0x0011, 0x1078, 0x16fb, 0x0040, 0x16f9, 0x2009, 0x0001, 0x1078, - 0x16fb, 0x2d58, 0x007c, 0x8aff, 0x0040, 0x1788, 0xa03e, 0x2730, - 0x6850, 0xd0fc, 0x00c0, 0x171a, 0x0d7e, 0x2804, 0xac68, 0x2900, - 0x0079, 0x170a, 0x176a, 0x172a, 0x172a, 0x176a, 0x176a, 0x1762, - 0x176a, 0x172a, 0x176a, 0x1730, 0x1730, 0x176a, 0x176a, 0x176a, - 0x1759, 0x1730, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, - 0x0d7e, 0xd99c, 0x0040, 0x176d, 0x2804, 0xac68, 0x6f08, 0x6e0c, - 0x0078, 0x176d, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0078, 0x176d, - 0x7b0c, 0xd3bc, 0x0040, 0x1751, 0x7004, 0x0e7e, 0x2070, 0x701c, - 0x0e7f, 0xa086, 0x0008, 0x00c0, 0x1751, 0x7b08, 0xa39c, 0x0fff, - 0x2d20, 0x0d7f, 0x0d7e, 0x6a14, 0x82ff, 0x00c0, 0x174c, 0x6810, - 0xa302, 0x0048, 0x174c, 0x6b10, 0x2011, 0x0000, 0x2468, 0x0078, - 0x1753, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0078, - 0x176d, 0x0d7f, 0x0d7e, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, - 0x00c0, 0x176a, 0x0d7f, 0x1078, 0x1c40, 0x00c0, 0x16fb, 0xa00e, - 0x0078, 0x1788, 0x0d7f, 0x1078, 0x12d5, 0x7b22, 0x7a26, 0x7d32, + 0x0011, 0x1078, 0x16f3, 0x0040, 0x16f1, 0x2009, 0x0001, 0x1078, + 0x16f3, 0x2d58, 0x007c, 0x8aff, 0x0040, 0x1780, 0xa03e, 0x2730, + 0x6850, 0xd0fc, 0x00c0, 0x1712, 0x0d7e, 0x2804, 0xac68, 0x2900, + 0x0079, 0x1702, 0x1762, 0x1722, 0x1722, 0x1762, 0x1762, 0x175a, + 0x1762, 0x1722, 0x1762, 0x1728, 0x1728, 0x1762, 0x1762, 0x1762, + 0x1751, 0x1728, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, + 0x0d7e, 0xd99c, 0x0040, 0x1765, 0x2804, 0xac68, 0x6f08, 0x6e0c, + 0x0078, 0x1765, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0078, 0x1765, + 0x7b0c, 0xd3bc, 0x0040, 0x1749, 0x7004, 0x0e7e, 0x2070, 0x701c, + 0x0e7f, 0xa086, 0x0008, 0x00c0, 0x1749, 0x7b08, 0xa39c, 0x0fff, + 0x2d20, 0x0d7f, 0x0d7e, 0x6a14, 0x82ff, 0x00c0, 0x1744, 0x6810, + 0xa302, 0x0048, 0x1744, 0x6b10, 0x2011, 0x0000, 0x2468, 0x0078, + 0x174b, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0078, + 0x1765, 0x0d7f, 0x0d7e, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, + 0x00c0, 0x1762, 0x0d7f, 0x1078, 0x1c3a, 0x00c0, 0x16f3, 0xa00e, + 0x0078, 0x1780, 0x0d7f, 0x1078, 0x12cd, 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, 0x1c40, - 0x007c, 0x1078, 0x12d5, 0x1078, 0x12d5, 0x127e, 0x2091, 0x2100, + 0xa302, 0x6812, 0x2200, 0x6a14, 0xa203, 0x6816, 0x1078, 0x1c3a, + 0x007c, 0x1078, 0x12cd, 0x1078, 0x12cd, 0x127e, 0x2091, 0x2100, 0x007e, 0x017e, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, - 0xa184, 0x0700, 0x00c0, 0x178b, 0xa184, 0x0003, 0xa086, 0x0003, - 0x0040, 0x178b, 0x7000, 0x0079, 0x17a5, 0x17ad, 0x17af, 0x1887, - 0x18ef, 0x1906, 0x17ad, 0x17ad, 0x17ad, 0x1078, 0x12d5, 0x8001, - 0x7002, 0xa184, 0x0880, 0x00c0, 0x17c4, 0x8aff, 0x0040, 0x1827, - 0x2009, 0x0001, 0x1078, 0x16fb, 0x0040, 0x1918, 0x2009, 0x0001, - 0x1078, 0x16fb, 0x0078, 0x1918, 0x7803, 0x0004, 0x7003, 0x0000, - 0xd1bc, 0x00c0, 0x180f, 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x7820, + 0xa184, 0x0700, 0x00c0, 0x1783, 0xa184, 0x0003, 0xa086, 0x0003, + 0x0040, 0x1783, 0x7000, 0x0079, 0x179d, 0x17a5, 0x17a7, 0x187f, + 0x18e7, 0x18fe, 0x17a5, 0x17a5, 0x17a5, 0x1078, 0x12cd, 0x8001, + 0x7002, 0xa184, 0x0880, 0x00c0, 0x17bc, 0x8aff, 0x0040, 0x181f, + 0x2009, 0x0001, 0x1078, 0x16f3, 0x0040, 0x1910, 0x2009, 0x0001, + 0x1078, 0x16f3, 0x0078, 0x1910, 0x7803, 0x0004, 0x7003, 0x0000, + 0xd1bc, 0x00c0, 0x1807, 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x7820, 0x686e, 0xa31a, 0x7824, 0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x7820, 0x6910, 0xa100, 0x6812, 0x7824, 0x6914, 0xa101, 0x6816, 0x037f, - 0x027f, 0x7830, 0x681e, 0x7834, 0x6822, 0x1078, 0x1c59, 0x2a00, + 0x027f, 0x7830, 0x681e, 0x7834, 0x6822, 0x1078, 0x1c53, 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, 0x6850, - 0xc0fd, 0x6852, 0x6808, 0x8001, 0x680a, 0x00c0, 0x1801, 0x684c, - 0xd0e4, 0x0040, 0x1801, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, - 0x5c29, 0x7808, 0xd0ec, 0x00c0, 0x180b, 0x7803, 0x0009, 0x7003, - 0x0004, 0x0078, 0x1918, 0x1078, 0x16b5, 0x0078, 0x1918, 0x057e, - 0x7d0c, 0xd5bc, 0x00c0, 0x1816, 0x1078, 0x7592, 0x057f, 0x1078, - 0x191c, 0x682b, 0xffff, 0x682f, 0xffff, 0x697c, 0x6912, 0x6980, - 0x6916, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, 0x1918, 0x684c, - 0xc0f5, 0x684e, 0x7814, 0xa005, 0x00c0, 0x183f, 0x7003, 0x0000, - 0x6808, 0x8001, 0x680a, 0x00c0, 0x183b, 0x7004, 0x2060, 0x2009, - 0x0048, 0x1078, 0x5c29, 0x1078, 0x16b5, 0x0078, 0x1918, 0x7814, + 0xc0fd, 0x6852, 0x6808, 0x8001, 0x680a, 0x00c0, 0x17f9, 0x684c, + 0xd0e4, 0x0040, 0x17f9, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, + 0x5c21, 0x7808, 0xd0ec, 0x00c0, 0x1803, 0x7803, 0x0009, 0x7003, + 0x0004, 0x0078, 0x1910, 0x1078, 0x16ad, 0x0078, 0x1910, 0x057e, + 0x7d0c, 0xd5bc, 0x00c0, 0x180e, 0x1078, 0x7587, 0x057f, 0x1078, + 0x1914, 0x682b, 0xffff, 0x682f, 0xffff, 0x697c, 0x6912, 0x6980, + 0x6916, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, 0x1910, 0x684c, + 0xc0f5, 0x684e, 0x7814, 0xa005, 0x00c0, 0x1837, 0x7003, 0x0000, + 0x6808, 0x8001, 0x680a, 0x00c0, 0x1833, 0x7004, 0x2060, 0x2009, + 0x0048, 0x1078, 0x5c21, 0x1078, 0x16ad, 0x0078, 0x1910, 0x7814, 0x6910, 0xa102, 0x6812, 0x6914, 0xa183, 0x0000, 0x6816, 0x7814, 0x7908, 0xa18c, 0x0fff, 0xa188, 0x0007, 0x8114, 0x8214, 0x8214, 0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b, 0x810b, - 0x1078, 0x1983, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, 0x0001, - 0x7804, 0xd0fc, 0x0040, 0x1860, 0x7803, 0x0002, 0x7803, 0x0004, + 0x1078, 0x197b, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, 0x0001, + 0x7804, 0xd0fc, 0x0040, 0x1858, 0x7803, 0x0002, 0x7803, 0x0004, 0x780f, 0x0070, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, 0x0048, - 0x1078, 0x5c29, 0x1078, 0x19a6, 0x0040, 0x183b, 0x7908, 0xd1ec, - 0x00c0, 0x187e, 0x2009, 0x0009, 0x0078, 0x1880, 0x2009, 0x0019, - 0x7902, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, 0x1918, 0x8001, - 0x7002, 0xd194, 0x0040, 0x1899, 0x7804, 0xd0fc, 0x00c0, 0x1795, - 0x8aff, 0x0040, 0x1918, 0x2009, 0x0001, 0x1078, 0x16fb, 0x0078, - 0x1918, 0xa184, 0x0880, 0x00c0, 0x18a6, 0x8aff, 0x0040, 0x1918, - 0x2009, 0x0001, 0x1078, 0x16fb, 0x0078, 0x1918, 0x7803, 0x0004, - 0x7003, 0x0000, 0xd1bc, 0x00c0, 0x18da, 0x027e, 0x037e, 0x6b28, - 0x6a2c, 0x1078, 0x1c59, 0x0d7e, 0x0f7e, 0x2d78, 0x2804, 0xac68, - 0x6034, 0xd09c, 0x00c0, 0x18ca, 0x6808, 0x2008, 0xa31a, 0x680c, + 0x1078, 0x5c21, 0x1078, 0x199e, 0x0040, 0x1833, 0x7908, 0xd1ec, + 0x00c0, 0x1876, 0x2009, 0x0009, 0x0078, 0x1878, 0x2009, 0x0019, + 0x7902, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, 0x1910, 0x8001, + 0x7002, 0xd194, 0x0040, 0x1891, 0x7804, 0xd0fc, 0x00c0, 0x178d, + 0x8aff, 0x0040, 0x1910, 0x2009, 0x0001, 0x1078, 0x16f3, 0x0078, + 0x1910, 0xa184, 0x0880, 0x00c0, 0x189e, 0x8aff, 0x0040, 0x1910, + 0x2009, 0x0001, 0x1078, 0x16f3, 0x0078, 0x1910, 0x7803, 0x0004, + 0x7003, 0x0000, 0xd1bc, 0x00c0, 0x18d2, 0x027e, 0x037e, 0x6b28, + 0x6a2c, 0x1078, 0x1c53, 0x0d7e, 0x0f7e, 0x2d78, 0x2804, 0xac68, + 0x6034, 0xd09c, 0x00c0, 0x18c2, 0x6808, 0x2008, 0xa31a, 0x680c, 0xa213, 0x7810, 0xa100, 0x7812, 0x690c, 0x7814, 0xa101, 0x7816, - 0x0078, 0x18d6, 0x6810, 0x2008, 0xa31a, 0x6814, 0xa213, 0x7810, + 0x0078, 0x18ce, 0x6810, 0x2008, 0xa31a, 0x6814, 0xa213, 0x7810, 0xa100, 0x7812, 0x6914, 0x7814, 0xa101, 0x7816, 0x0f7f, 0x0d7f, - 0x0078, 0x17cf, 0x057e, 0x7d0c, 0x1078, 0x7592, 0x057f, 0x1078, - 0x191c, 0x682b, 0xffff, 0x682f, 0xffff, 0x697c, 0x6912, 0x6980, - 0x6916, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, 0x1918, 0x7803, - 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, 0x0040, 0x1902, 0x6808, - 0x8001, 0x680a, 0x00c0, 0x1902, 0x7004, 0x2060, 0x2009, 0x0048, - 0x1078, 0x5c29, 0x1078, 0x16b5, 0x0078, 0x1918, 0x7803, 0x0004, - 0x7003, 0x0000, 0x7004, 0x2060, 0x6010, 0xa005, 0x0040, 0x1902, - 0x2068, 0x6808, 0x8000, 0x680a, 0x6c28, 0x6b2c, 0x1078, 0x16cc, - 0x017f, 0x007f, 0x127f, 0x007c, 0x1078, 0x192d, 0x20e1, 0x9028, + 0x0078, 0x17c7, 0x057e, 0x7d0c, 0x1078, 0x7587, 0x057f, 0x1078, + 0x1914, 0x682b, 0xffff, 0x682f, 0xffff, 0x697c, 0x6912, 0x6980, + 0x6916, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, 0x1910, 0x7803, + 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, 0x0040, 0x18fa, 0x6808, + 0x8001, 0x680a, 0x00c0, 0x18fa, 0x7004, 0x2060, 0x2009, 0x0048, + 0x1078, 0x5c21, 0x1078, 0x16ad, 0x0078, 0x1910, 0x7803, 0x0004, + 0x7003, 0x0000, 0x7004, 0x2060, 0x6010, 0xa005, 0x0040, 0x18fa, + 0x2068, 0x6808, 0x8000, 0x680a, 0x6c28, 0x6b2c, 0x1078, 0x16c4, + 0x017f, 0x007f, 0x127f, 0x007c, 0x1078, 0x1925, 0x20e1, 0x9028, 0x700f, 0x7870, 0x7013, 0x7870, 0x2001, 0x015d, 0x200c, 0x810a, 0x2102, 0x2001, 0x0138, 0x2202, 0x007c, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, 0x2021, 0xb015, 0x2001, 0x0141, 0x201c, 0xd3dc, - 0x00c0, 0x194a, 0x2001, 0x0109, 0x201c, 0xa39c, 0x0048, 0x00c0, - 0x194a, 0x2001, 0x0111, 0x201c, 0x83ff, 0x00c0, 0x194a, 0x8421, - 0x00c0, 0x1934, 0x007c, 0x2011, 0x0201, 0x2009, 0x003c, 0x2204, - 0xa005, 0x00c0, 0x1957, 0x8109, 0x00c0, 0x194f, 0x007c, 0x007c, - 0x1078, 0x194b, 0x0040, 0x1980, 0x7908, 0xd1ec, 0x00c0, 0x1970, - 0x1078, 0x19a6, 0x0040, 0x1970, 0x7803, 0x0009, 0x7904, 0xd1fc, - 0x0040, 0x1966, 0x7803, 0x0006, 0x1078, 0x194b, 0x0040, 0x1980, - 0x780c, 0xd0a4, 0x00c0, 0x1980, 0x7007, 0x0000, 0x1078, 0x19a6, - 0x0040, 0x1982, 0x7803, 0x0019, 0x7003, 0x0003, 0x0078, 0x1982, - 0x1078, 0x191c, 0x007c, 0x3c00, 0x007e, 0x0e7e, 0x2071, 0x0200, - 0x7808, 0xa084, 0xf000, 0xa10d, 0x1078, 0x192d, 0x20e1, 0x7000, + 0x00c0, 0x1942, 0x2001, 0x0109, 0x201c, 0xa39c, 0x0048, 0x00c0, + 0x1942, 0x2001, 0x0111, 0x201c, 0x83ff, 0x00c0, 0x1942, 0x8421, + 0x00c0, 0x192c, 0x007c, 0x2011, 0x0201, 0x2009, 0x003c, 0x2204, + 0xa005, 0x00c0, 0x194f, 0x8109, 0x00c0, 0x1947, 0x007c, 0x007c, + 0x1078, 0x1943, 0x0040, 0x1978, 0x7908, 0xd1ec, 0x00c0, 0x1968, + 0x1078, 0x199e, 0x0040, 0x1968, 0x7803, 0x0009, 0x7904, 0xd1fc, + 0x0040, 0x195e, 0x7803, 0x0006, 0x1078, 0x1943, 0x0040, 0x1978, + 0x780c, 0xd0a4, 0x00c0, 0x1978, 0x7007, 0x0000, 0x1078, 0x199e, + 0x0040, 0x197a, 0x7803, 0x0019, 0x7003, 0x0003, 0x0078, 0x197a, + 0x1078, 0x1914, 0x007c, 0x3c00, 0x007e, 0x0e7e, 0x2071, 0x0200, + 0x7808, 0xa084, 0xf000, 0xa10d, 0x1078, 0x1925, 0x20e1, 0x7000, 0x7324, 0x7420, 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f, 0x712e, 0x702f, 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001, 0x0138, 0x2202, 0x0e7f, 0x007f, 0x20e0, 0x007c, 0x3c00, 0x007e, - 0x7908, 0xa18c, 0x0fff, 0xa182, 0x0009, 0x0048, 0x19b3, 0xa085, - 0x0001, 0x0078, 0x19c5, 0x2001, 0x020a, 0x81ff, 0x0040, 0x19be, + 0x7908, 0xa18c, 0x0fff, 0xa182, 0x0009, 0x0048, 0x19ab, 0xa085, + 0x0001, 0x0078, 0x19bd, 0x2001, 0x020a, 0x81ff, 0x0040, 0x19b6, 0x20e1, 0x6000, 0x200c, 0x200c, 0x200c, 0x200c, 0x20e1, 0x7000, 0x200c, 0x200c, 0x7003, 0x0000, 0xa006, 0x007f, 0x20e0, 0x007c, 0x0e7e, 0x2071, 0x788b, 0x7003, 0x0000, 0x0e7f, 0x007c, 0x0d7e, - 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x00c0, 0x1a4a, 0x6934, - 0xa184, 0x0007, 0x0079, 0x19dc, 0x19e4, 0x1a35, 0x19e4, 0x19e4, - 0x19e4, 0x1a1a, 0x19f7, 0x19e6, 0x1078, 0x12d5, 0x684c, 0xd0b4, - 0x0040, 0x1b4c, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, - 0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0078, 0x1a3d, 0x6834, - 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x19e4, 0x684c, 0xd0b4, - 0x0040, 0x1b4c, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, + 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x00c0, 0x1a42, 0x6934, + 0xa184, 0x0007, 0x0079, 0x19d4, 0x19dc, 0x1a2d, 0x19dc, 0x19dc, + 0x19dc, 0x1a12, 0x19ef, 0x19de, 0x1078, 0x12cd, 0x684c, 0xd0b4, + 0x0040, 0x1b46, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, + 0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0078, 0x1a35, 0x6834, + 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x19dc, 0x684c, 0xd0b4, + 0x0040, 0x1b46, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880, 0x680e, 0x6804, 0x681a, 0xa080, 0x000d, - 0x2004, 0xa084, 0x000f, 0xa080, 0x1c84, 0x2004, 0x6832, 0x6958, - 0x0078, 0x1a46, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x00c0, 0x1a4a, - 0x684c, 0xd0b4, 0x0040, 0x1b4c, 0x6804, 0x681a, 0xa080, 0x000d, - 0x2004, 0xa084, 0x000f, 0xa080, 0x1c84, 0x2004, 0x6832, 0x6958, - 0xa006, 0x682e, 0x682a, 0x0078, 0x1a46, 0x684c, 0xd0b4, 0x0040, - 0x1789, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00, 0x681a, 0x6834, - 0xa084, 0x000f, 0xa080, 0x1c84, 0x2004, 0x6832, 0x6926, 0x684c, + 0x2004, 0xa084, 0x000f, 0xa080, 0x1c7e, 0x2004, 0x6832, 0x6958, + 0x0078, 0x1a3e, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x00c0, 0x1a42, + 0x684c, 0xd0b4, 0x0040, 0x1b46, 0x6804, 0x681a, 0xa080, 0x000d, + 0x2004, 0xa084, 0x000f, 0xa080, 0x1c7e, 0x2004, 0x6832, 0x6958, + 0xa006, 0x682e, 0x682a, 0x0078, 0x1a3e, 0x684c, 0xd0b4, 0x0040, + 0x1781, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00, 0x681a, 0x6834, + 0xa084, 0x000f, 0xa080, 0x1c7e, 0x2004, 0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, 0x0d7f, 0x007c, 0x0f7e, 0x2079, 0x0020, 0x7804, - 0xd0fc, 0x10c0, 0x1b50, 0x0e7e, 0x0d7e, 0x2071, 0x788b, 0x7000, - 0xa005, 0x00c0, 0x1ac6, 0x0c7e, 0x7206, 0xa280, 0x0004, 0x205c, - 0x7004, 0x2068, 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, 0xa184, - 0x0007, 0x0040, 0x1a88, 0x017e, 0x2009, 0x0008, 0xa102, 0x017f, - 0xa108, 0x791a, 0x7116, 0x701e, 0x680c, 0xa081, 0x0000, 0x781e, - 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, 0x692c, 0x6814, 0xa106, - 0x00c0, 0x1a9f, 0x6928, 0x6810, 0xa106, 0x0040, 0x1aac, 0x037e, - 0x047e, 0x6b14, 0x6c10, 0x1078, 0x1ca4, 0x047f, 0x037f, 0x0040, - 0x1aac, 0x0c7f, 0x0078, 0x1ac6, 0x8aff, 0x00c0, 0x1ab4, 0x0c7f, - 0xa085, 0x0001, 0x0078, 0x1ac6, 0x127e, 0x2091, 0x8000, 0x2079, - 0x0020, 0x2009, 0x0001, 0x1078, 0x1aca, 0x0040, 0x1ac3, 0x2009, - 0x0001, 0x1078, 0x1aca, 0x127f, 0x0c7f, 0xa006, 0x0d7f, 0x0e7f, - 0x0f7f, 0x007c, 0x077e, 0x067e, 0x057e, 0x047e, 0x037e, 0x027e, - 0x8aff, 0x0040, 0x1b45, 0x700c, 0x7214, 0xa202, 0x7010, 0x7218, - 0xa203, 0x0048, 0x1b44, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x00c0, - 0x1af7, 0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079, 0x1ae7, 0x1b26, - 0x1b07, 0x1b07, 0x1b26, 0x1b26, 0x1b1e, 0x1b26, 0x1b07, 0x1b26, - 0x1b0d, 0x1b0d, 0x1b26, 0x1b26, 0x1b26, 0x1b15, 0x1b0d, 0xc0fc, - 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c, 0x0040, 0x1b2a, - 0x0d7e, 0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078, 0x1b29, 0x6b08, - 0x6a0c, 0x6d00, 0x6c04, 0x0078, 0x1b29, 0x6b10, 0x6a14, 0x6d00, - 0x6c04, 0x6f08, 0x6e0c, 0x0078, 0x1b29, 0x0d7f, 0x0d7e, 0x6834, - 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x1b26, 0x0d7f, 0x1078, - 0x1c40, 0x00c0, 0x1ad0, 0xa00e, 0x0078, 0x1b45, 0x0d7f, 0x1078, - 0x12d5, 0x0d7f, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, - 0x7902, 0x7000, 0x8000, 0x7002, 0x6828, 0xa300, 0x682a, 0x682c, - 0xa201, 0x682e, 0x700c, 0xa300, 0x700e, 0x7010, 0xa201, 0x7012, - 0x1078, 0x1c40, 0x0078, 0x1b45, 0xa006, 0x027f, 0x037f, 0x047f, - 0x057f, 0x067f, 0x077f, 0x007c, 0x1078, 0x12d5, 0x1078, 0x12d5, - 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x0f7e, 0x0e7e, 0x0d7e, - 0x0c7e, 0x2079, 0x0020, 0x2071, 0x788b, 0x2b68, 0x6818, 0x2060, - 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x00c0, 0x1b4e, 0x7000, - 0x0079, 0x1b6a, 0x1c11, 0x1b6e, 0x1bde, 0x1c0f, 0x8001, 0x7002, - 0xd19c, 0x00c0, 0x1b82, 0x8aff, 0x0040, 0x1ba1, 0x2009, 0x0001, - 0x1078, 0x1aca, 0x0040, 0x1c11, 0x2009, 0x0001, 0x1078, 0x1aca, - 0x0078, 0x1c11, 0x7803, 0x0004, 0xd194, 0x0040, 0x1b92, 0x6850, - 0xc0fc, 0x6852, 0x8aff, 0x00c0, 0x1b97, 0x684c, 0xc0f5, 0x684e, - 0x0078, 0x1b97, 0x1078, 0x1c59, 0x6850, 0xc0fd, 0x6852, 0x2a00, - 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, 0x0078, - 0x1c11, 0x711c, 0x81ff, 0x0040, 0x1bb7, 0x7918, 0x7922, 0x7827, - 0x0000, 0x7803, 0x0001, 0x7000, 0x8000, 0x7002, 0x700c, 0xa100, - 0x700e, 0x7010, 0xa081, 0x0000, 0x7012, 0x0078, 0x1c11, 0x0f7e, - 0x027e, 0x781c, 0x007e, 0x7818, 0x007e, 0x2079, 0x0100, 0x7a14, - 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x7820, 0xd0bc, 0x00c0, - 0x1bc5, 0x79c8, 0x007f, 0xa102, 0x78ca, 0x79c4, 0x007f, 0xa102, - 0x78c6, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x027f, 0x0f7f, - 0x7803, 0x0008, 0x7003, 0x0000, 0x0078, 0x1c11, 0x8001, 0x7002, - 0xd194, 0x0040, 0x1bf3, 0x7804, 0xd0fc, 0x00c0, 0x1b60, 0xd19c, - 0x00c0, 0x1c0d, 0x8aff, 0x0040, 0x1c11, 0x2009, 0x0001, 0x1078, - 0x1aca, 0x0078, 0x1c11, 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x1078, - 0x1c59, 0x0d7e, 0x2804, 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1c06, - 0x6808, 0xa31a, 0x680c, 0xa213, 0x0078, 0x1c0a, 0x6810, 0xa31a, - 0x6814, 0xa213, 0x0d7f, 0x0078, 0x1b92, 0x0078, 0x1b92, 0x1078, - 0x12d5, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x017f, 0x007f, 0x127f, - 0x007c, 0x0f7e, 0x0e7e, 0x2071, 0x788b, 0x7000, 0xa086, 0x0000, - 0x0040, 0x1c3d, 0x2079, 0x0020, 0x20e1, 0x9040, 0x7804, 0xd0fc, - 0x0040, 0x1c24, 0x1078, 0x1b50, 0x7000, 0xa086, 0x0000, 0x00c0, - 0x1c24, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0, 0x1c33, 0x20e1, - 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x0e7f, 0x0f7f, 0x007c, - 0x8840, 0x2804, 0xa005, 0x00c0, 0x1c54, 0x6004, 0xa005, 0x0040, - 0x1c56, 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x1c84, - 0x2044, 0x88ff, 0x1040, 0x12d5, 0x8a51, 0x007c, 0x2051, 0x0000, - 0x007c, 0x8a50, 0x8841, 0x2804, 0xa005, 0x00c0, 0x1c73, 0x2c00, - 0xad06, 0x0040, 0x1c68, 0x6000, 0xa005, 0x00c0, 0x1c68, 0x2d00, - 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080, 0x1c94, 0x2044, - 0x88ff, 0x1040, 0x12d5, 0x007c, 0x0000, 0x0011, 0x0015, 0x0019, - 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f, 0x0015, 0x001b, - 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x1c79, 0x1c75, 0x0000, - 0x0000, 0x1c83, 0x0000, 0x1c79, 0x0000, 0x1c80, 0x1c7d, 0x0000, - 0x0000, 0x0000, 0x1c83, 0x1c80, 0x0000, 0x1c7b, 0x1c7b, 0x0000, - 0x0000, 0x1c83, 0x0000, 0x1c7b, 0x0000, 0x1c81, 0x1c81, 0x0000, - 0x0000, 0x0000, 0x1c83, 0x1c81, 0x0a7e, 0x097e, 0x087e, 0x6858, - 0xa055, 0x0040, 0x1d45, 0x2d60, 0x6034, 0xa0cc, 0x000f, 0xa9c0, - 0x1c84, 0xa986, 0x0007, 0x0040, 0x1cbd, 0xa986, 0x000e, 0x0040, - 0x1cbd, 0xa986, 0x000f, 0x00c0, 0x1cc1, 0x605c, 0xa422, 0x6060, - 0xa31a, 0x2804, 0xa045, 0x00c0, 0x1ccf, 0x0050, 0x1cc9, 0x0078, - 0x1d45, 0x6004, 0xa065, 0x0040, 0x1d45, 0x0078, 0x1cac, 0x2804, - 0xa005, 0x0040, 0x1ced, 0xac68, 0xd99c, 0x00c0, 0x1cdd, 0x6808, - 0xa422, 0x680c, 0xa31b, 0x0078, 0x1ce1, 0x6810, 0xa422, 0x6814, - 0xa31b, 0x0048, 0x1d0c, 0x2300, 0xa405, 0x0040, 0x1cf3, 0x8a51, - 0x0040, 0x1d45, 0x8840, 0x0078, 0x1ccf, 0x6004, 0xa065, 0x0040, - 0x1d45, 0x0078, 0x1cac, 0x8a51, 0x0040, 0x1d45, 0x8840, 0x2804, - 0xa005, 0x00c0, 0x1d06, 0x6004, 0xa065, 0x0040, 0x1d45, 0x6034, - 0xa0cc, 0x000f, 0xa9c0, 0x1c84, 0x2804, 0x2040, 0x2b68, 0x6850, - 0xc0fc, 0x6852, 0x0078, 0x1d39, 0x8422, 0x8420, 0x831a, 0xa399, - 0x0000, 0x0d7e, 0x2b68, 0x6c6e, 0x6b72, 0x0d7f, 0xd99c, 0x00c0, - 0x1d27, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x1048, - 0x12d5, 0x6800, 0xa420, 0x6804, 0xa319, 0x0078, 0x1d33, 0x6910, - 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x1048, 0x12d5, 0x6800, - 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22, 0x6850, 0xc0fd, - 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00, 0x6826, 0x007f, - 0x007f, 0x007f, 0xa006, 0x0078, 0x1d4a, 0x087f, 0x097f, 0x0a7f, - 0xa085, 0x0001, 0x007c, 0x2001, 0x0005, 0x2004, 0xa084, 0x0007, - 0x0079, 0x1d52, 0x1d5a, 0x1d5b, 0x1d5e, 0x1d61, 0x1d66, 0x1d69, - 0x1d6e, 0x1d73, 0x007c, 0x1078, 0x1b50, 0x007c, 0x1078, 0x178d, - 0x007c, 0x1078, 0x178d, 0x1078, 0x1b50, 0x007c, 0x1078, 0x145e, - 0x007c, 0x1078, 0x1b50, 0x1078, 0x145e, 0x007c, 0x1078, 0x178d, - 0x1078, 0x145e, 0x007c, 0x1078, 0x178d, 0x1078, 0x1b50, 0x1078, - 0x145e, 0x007c, 0x127e, 0x2091, 0x2300, 0x2079, 0x0200, 0x2071, - 0x7b80, 0x2069, 0x7600, 0x2009, 0x0004, 0x7912, 0x7817, 0x0004, - 0x1078, 0x2058, 0x781b, 0x0002, 0x20e1, 0x8700, 0x127f, 0x007c, - 0x127e, 0x2091, 0x2300, 0x781c, 0xa084, 0x0007, 0x0079, 0x1d98, - 0x1dbc, 0x1da0, 0x1da4, 0x1da8, 0x1dae, 0x1db2, 0x1db6, 0x1dba, - 0x1078, 0x417d, 0x0078, 0x1dbc, 0x1078, 0x41ac, 0x0078, 0x1dbc, - 0x1078, 0x417d, 0x1078, 0x41ac, 0x0078, 0x1dbc, 0x1078, 0x1dbe, - 0x0078, 0x1dbc, 0x1078, 0x1dbe, 0x0078, 0x1dbc, 0x1078, 0x1dbe, - 0x0078, 0x1dbc, 0x1078, 0x1dbe, 0x127f, 0x007c, 0x007e, 0x017e, - 0x027e, 0x7930, 0xa184, 0x0003, 0x0040, 0x1dc8, 0x1078, 0x12d5, - 0xa184, 0x0030, 0x0040, 0x1dd9, 0x6a00, 0xa286, 0x0003, 0x00c0, - 0x1dd3, 0x1078, 0x12d5, 0x1078, 0x357b, 0x20e1, 0x9010, 0x0078, - 0x1de5, 0xa184, 0x00c0, 0x0040, 0x1ddf, 0x1078, 0x12d5, 0xa184, - 0x0300, 0x0040, 0x1de5, 0x20e1, 0x9020, 0x7932, 0x027f, 0x017f, - 0x007f, 0x007c, 0x017e, 0x0e7e, 0x0f7e, 0x2071, 0x7600, 0x7128, - 0x2001, 0x7823, 0x2102, 0x2001, 0x782b, 0x2102, 0xa182, 0x0211, - 0x00c8, 0x1dfe, 0x2009, 0x0008, 0x0078, 0x1e28, 0xa182, 0x0259, - 0x00c8, 0x1e06, 0x2009, 0x0007, 0x0078, 0x1e28, 0xa182, 0x02c1, - 0x00c8, 0x1e0e, 0x2009, 0x0006, 0x0078, 0x1e28, 0xa182, 0x0349, - 0x00c8, 0x1e16, 0x2009, 0x0005, 0x0078, 0x1e28, 0xa182, 0x0421, - 0x00c8, 0x1e1e, 0x2009, 0x0004, 0x0078, 0x1e28, 0xa182, 0x0581, - 0x00c8, 0x1e26, 0x2009, 0x0003, 0x0078, 0x1e28, 0x2009, 0x0002, - 0x2079, 0x0200, 0x7912, 0xa182, 0x0005, 0x00c8, 0x1e32, 0x7916, - 0x0078, 0x1e34, 0x7817, 0x0004, 0x1078, 0x2058, 0x0f7f, 0x0e7f, - 0x017f, 0x007c, 0x127e, 0x2091, 0x2200, 0x2061, 0x0100, 0x2071, - 0x7600, 0x6024, 0x6026, 0x6033, 0x00ef, 0x60e7, 0x0000, 0x60eb, - 0x00ef, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, - 0x0080, 0x602f, 0x0000, 0x6007, 0x0caf, 0x600f, 0x00ff, 0x602b, - 0x002f, 0x127f, 0x007c, 0x2001, 0x762d, 0x2003, 0x0000, 0x2001, - 0x762c, 0x2003, 0x0001, 0x007c, 0x127e, 0x2091, 0x2200, 0x007e, - 0x017e, 0x027e, 0x6124, 0xa184, 0x002c, 0x00c0, 0x1e73, 0xa184, - 0x0007, 0x0079, 0x1e79, 0xa195, 0x0004, 0xa284, 0x0007, 0x0079, - 0x1e79, 0x1ea5, 0x1e81, 0x1e85, 0x1e89, 0x1e8f, 0x1e93, 0x1e99, - 0x1e9f, 0x1078, 0x46e6, 0x0078, 0x1ea5, 0x1078, 0x47d5, 0x0078, - 0x1ea5, 0x1078, 0x47d5, 0x1078, 0x46e6, 0x0078, 0x1ea5, 0x1078, - 0x1eaa, 0x0078, 0x1ea5, 0x1078, 0x46e6, 0x1078, 0x1eaa, 0x0078, - 0x1ea5, 0x1078, 0x47d5, 0x1078, 0x1eaa, 0x0078, 0x1ea5, 0x1078, - 0x47d5, 0x1078, 0x46e6, 0x1078, 0x1eaa, 0x027f, 0x017f, 0x007f, - 0x127f, 0x007c, 0xd1ac, 0x0040, 0x1f5e, 0x017e, 0x047e, 0x0c7e, - 0x644c, 0x74ba, 0xa48c, 0xff00, 0xa196, 0xff00, 0x0040, 0x1ed9, - 0x6030, 0xa084, 0x00ff, 0x810f, 0xa116, 0x0040, 0x1ed9, 0x7130, - 0xd18c, 0x00c0, 0x1ed9, 0x2011, 0x7652, 0x2214, 0xd2ec, 0x0040, - 0x1ecd, 0xc18d, 0x7132, 0x0078, 0x1ed9, 0x6240, 0xa294, 0x0010, - 0x0040, 0x1f1b, 0x6248, 0xa294, 0xff00, 0xa296, 0xff00, 0x00c0, - 0x1f1b, 0x037e, 0x73b8, 0x2011, 0x8013, 0x1078, 0x2d4a, 0x037f, - 0x7130, 0xc185, 0x7132, 0x2011, 0x7652, 0x220c, 0xd1a4, 0x0040, - 0x1f03, 0x017e, 0x2009, 0x0001, 0x2011, 0x0100, 0x1078, 0x46b4, - 0x2019, 0x000e, 0x1078, 0x74d9, 0xa484, 0x00ff, 0xa080, 0x232f, - 0x200c, 0xa18c, 0xff00, 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, - 0x1078, 0x7541, 0x017f, 0xd1ac, 0x00c0, 0x1f0c, 0x2019, 0x0004, - 0x1078, 0x2299, 0x0078, 0x1f1b, 0x157e, 0x20a9, 0x007f, 0x2009, - 0x0000, 0x1078, 0x3825, 0x00c0, 0x1f17, 0x1078, 0x3621, 0x8108, - 0x00f0, 0x1f11, 0x157f, 0x0c7f, 0x047f, 0x6043, 0x0000, 0x2009, - 0x00f7, 0x1078, 0x35e4, 0x0f7e, 0x2079, 0x7849, 0x783c, 0xa086, - 0x0000, 0x0040, 0x1f33, 0x6027, 0x0004, 0x783f, 0x0000, 0x2079, - 0x0140, 0x7803, 0x0000, 0x0f7f, 0x2011, 0x0003, 0x1078, 0x57c0, - 0x2011, 0x0002, 0x1078, 0x57ca, 0x1078, 0x56d6, 0x1078, 0x45eb, - 0x037e, 0x2019, 0x0000, 0x1078, 0x5768, 0x037f, 0x60e3, 0x0000, - 0x017f, 0x2001, 0x7600, 0x2014, 0xa296, 0x0004, 0x00c0, 0x1f56, - 0xd19c, 0x00c0, 0x1f56, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, - 0x2001, 0x7620, 0x2003, 0x0000, 0x6027, 0x0020, 0xd194, 0x0040, - 0x1fff, 0x0f7e, 0x2079, 0x7849, 0x783c, 0xa086, 0x0001, 0x00c0, - 0x1f82, 0x017e, 0x6027, 0x0004, 0x783f, 0x0000, 0x2079, 0x0140, - 0x7803, 0x1000, 0x7803, 0x0000, 0x2079, 0x7836, 0x7807, 0x0000, - 0x7833, 0x0000, 0x1078, 0x4c7a, 0x1078, 0x4d3a, 0x017f, 0x0f7f, - 0x0078, 0x1fff, 0x0f7f, 0x017e, 0x6220, 0xd2b4, 0x0040, 0x1fb7, - 0x1078, 0x45eb, 0x1078, 0x5582, 0x6027, 0x0004, 0x0d7e, 0x2069, - 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x1f9a, 0x6803, 0x1000, - 0x6803, 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0x7836, 0x6028, 0xa09a, - 0x0002, 0x00c8, 0x1faa, 0x8000, 0x602a, 0x0c7f, 0x1078, 0x5574, - 0x0078, 0x1ffe, 0x2019, 0x783f, 0x2304, 0xa065, 0x0040, 0x1fb4, - 0x2009, 0x0027, 0x1078, 0x5c29, 0x0c7f, 0x0078, 0x1ffe, 0xd2bc, - 0x0040, 0x1ffe, 0x1078, 0x45f9, 0x6017, 0x0010, 0x6027, 0x0004, - 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x1fcc, + 0xd0fc, 0x10c0, 0x1b4a, 0x0e7e, 0x0d7e, 0x2071, 0x788b, 0x7000, + 0xa005, 0x00c0, 0x1ac0, 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, 0xa184, 0x0007, 0x0040, 0x1a82, 0x017e, 0x2009, 0x0008, + 0xa102, 0x017f, 0xa108, 0x791a, 0x7116, 0x701e, 0x680c, 0xa081, + 0x0000, 0x781e, 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, 0x692c, + 0x6814, 0xa106, 0x00c0, 0x1a99, 0x6928, 0x6810, 0xa106, 0x0040, + 0x1aa6, 0x037e, 0x047e, 0x6b14, 0x6c10, 0x1078, 0x1c9e, 0x047f, + 0x037f, 0x0040, 0x1aa6, 0x0c7f, 0x0078, 0x1ac0, 0x8aff, 0x00c0, + 0x1aae, 0x0c7f, 0xa085, 0x0001, 0x0078, 0x1ac0, 0x127e, 0x2091, + 0x8000, 0x2079, 0x0020, 0x2009, 0x0001, 0x1078, 0x1ac4, 0x0040, + 0x1abd, 0x2009, 0x0001, 0x1078, 0x1ac4, 0x127f, 0x0c7f, 0xa006, + 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x077e, 0x067e, 0x057e, 0x047e, + 0x037e, 0x027e, 0x8aff, 0x0040, 0x1b3f, 0x700c, 0x7214, 0xa202, + 0x7010, 0x7218, 0xa203, 0x0048, 0x1b3e, 0xa03e, 0x2730, 0x6850, + 0xd0fc, 0x00c0, 0x1af1, 0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079, + 0x1ae1, 0x1b20, 0x1b01, 0x1b01, 0x1b20, 0x1b20, 0x1b18, 0x1b20, + 0x1b01, 0x1b20, 0x1b07, 0x1b07, 0x1b20, 0x1b20, 0x1b20, 0x1b0f, + 0x1b07, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c, + 0x0040, 0x1b24, 0x0d7e, 0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078, + 0x1b23, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0078, 0x1b23, 0x6b10, + 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0078, 0x1b23, 0x0d7f, + 0x0d7e, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x1b20, + 0x0d7f, 0x1078, 0x1c3a, 0x00c0, 0x1aca, 0xa00e, 0x0078, 0x1b3f, + 0x0d7f, 0x1078, 0x12cd, 0x0d7f, 0x7b22, 0x7a26, 0x7d32, 0x7c36, + 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x6828, 0xa300, + 0x682a, 0x682c, 0xa201, 0x682e, 0x700c, 0xa300, 0x700e, 0x7010, + 0xa201, 0x7012, 0x1078, 0x1c3a, 0x0078, 0x1b3f, 0xa006, 0x027f, + 0x037f, 0x047f, 0x057f, 0x067f, 0x077f, 0x007c, 0x1078, 0x12cd, + 0x1078, 0x12cd, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x0f7e, + 0x0e7e, 0x0d7e, 0x0c7e, 0x2079, 0x0020, 0x2071, 0x788b, 0x2b68, + 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x00c0, + 0x1b48, 0x7000, 0x0079, 0x1b64, 0x1c0b, 0x1b68, 0x1bd8, 0x1c09, + 0x8001, 0x7002, 0xd19c, 0x00c0, 0x1b7c, 0x8aff, 0x0040, 0x1b9b, + 0x2009, 0x0001, 0x1078, 0x1ac4, 0x0040, 0x1c0b, 0x2009, 0x0001, + 0x1078, 0x1ac4, 0x0078, 0x1c0b, 0x7803, 0x0004, 0xd194, 0x0040, + 0x1b8c, 0x6850, 0xc0fc, 0x6852, 0x8aff, 0x00c0, 0x1b91, 0x684c, + 0xc0f5, 0x684e, 0x0078, 0x1b91, 0x1078, 0x1c53, 0x6850, 0xc0fd, + 0x6852, 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, + 0x0000, 0x0078, 0x1c0b, 0x711c, 0x81ff, 0x0040, 0x1bb1, 0x7918, + 0x7922, 0x7827, 0x0000, 0x7803, 0x0001, 0x7000, 0x8000, 0x7002, + 0x700c, 0xa100, 0x700e, 0x7010, 0xa081, 0x0000, 0x7012, 0x0078, + 0x1c0b, 0x0f7e, 0x027e, 0x781c, 0x007e, 0x7818, 0x007e, 0x2079, + 0x0100, 0x7a14, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x7820, + 0xd0bc, 0x00c0, 0x1bbf, 0x79c8, 0x007f, 0xa102, 0x78ca, 0x79c4, + 0x007f, 0xa102, 0x78c6, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, + 0x027f, 0x0f7f, 0x7803, 0x0008, 0x7003, 0x0000, 0x0078, 0x1c0b, + 0x8001, 0x7002, 0xd194, 0x0040, 0x1bed, 0x7804, 0xd0fc, 0x00c0, + 0x1b5a, 0xd19c, 0x00c0, 0x1c07, 0x8aff, 0x0040, 0x1c0b, 0x2009, + 0x0001, 0x1078, 0x1ac4, 0x0078, 0x1c0b, 0x027e, 0x037e, 0x6b28, + 0x6a2c, 0x1078, 0x1c53, 0x0d7e, 0x2804, 0xac68, 0x6034, 0xd09c, + 0x00c0, 0x1c00, 0x6808, 0xa31a, 0x680c, 0xa213, 0x0078, 0x1c04, + 0x6810, 0xa31a, 0x6814, 0xa213, 0x0d7f, 0x0078, 0x1b8c, 0x0078, + 0x1b8c, 0x1078, 0x12cd, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x017f, + 0x007f, 0x127f, 0x007c, 0x0f7e, 0x0e7e, 0x2071, 0x788b, 0x7000, + 0xa086, 0x0000, 0x0040, 0x1c37, 0x2079, 0x0020, 0x20e1, 0x9040, + 0x7804, 0xd0fc, 0x0040, 0x1c1e, 0x1078, 0x1b4a, 0x7000, 0xa086, + 0x0000, 0x00c0, 0x1c1e, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0, + 0x1c2d, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x0e7f, + 0x0f7f, 0x007c, 0x8840, 0x2804, 0xa005, 0x00c0, 0x1c4e, 0x6004, + 0xa005, 0x0040, 0x1c50, 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, + 0xa080, 0x1c7e, 0x2044, 0x88ff, 0x1040, 0x12cd, 0x8a51, 0x007c, + 0x2051, 0x0000, 0x007c, 0x8a50, 0x8841, 0x2804, 0xa005, 0x00c0, + 0x1c6d, 0x2c00, 0xad06, 0x0040, 0x1c62, 0x6000, 0xa005, 0x00c0, + 0x1c62, 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080, + 0x1c8e, 0x2044, 0x88ff, 0x1040, 0x12cd, 0x007c, 0x0000, 0x0011, + 0x0015, 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f, + 0x0015, 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x1c73, + 0x1c6f, 0x0000, 0x0000, 0x1c7d, 0x0000, 0x1c73, 0x0000, 0x1c7a, + 0x1c77, 0x0000, 0x0000, 0x0000, 0x1c7d, 0x1c7a, 0x0000, 0x1c75, + 0x1c75, 0x0000, 0x0000, 0x1c7d, 0x0000, 0x1c75, 0x0000, 0x1c7b, + 0x1c7b, 0x0000, 0x0000, 0x0000, 0x1c7d, 0x1c7b, 0x0a7e, 0x097e, + 0x087e, 0x6858, 0xa055, 0x0040, 0x1d3f, 0x2d60, 0x6034, 0xa0cc, + 0x000f, 0xa9c0, 0x1c7e, 0xa986, 0x0007, 0x0040, 0x1cb7, 0xa986, + 0x000e, 0x0040, 0x1cb7, 0xa986, 0x000f, 0x00c0, 0x1cbb, 0x605c, + 0xa422, 0x6060, 0xa31a, 0x2804, 0xa045, 0x00c0, 0x1cc9, 0x0050, + 0x1cc3, 0x0078, 0x1d3f, 0x6004, 0xa065, 0x0040, 0x1d3f, 0x0078, + 0x1ca6, 0x2804, 0xa005, 0x0040, 0x1ce7, 0xac68, 0xd99c, 0x00c0, + 0x1cd7, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0078, 0x1cdb, 0x6810, + 0xa422, 0x6814, 0xa31b, 0x0048, 0x1d06, 0x2300, 0xa405, 0x0040, + 0x1ced, 0x8a51, 0x0040, 0x1d3f, 0x8840, 0x0078, 0x1cc9, 0x6004, + 0xa065, 0x0040, 0x1d3f, 0x0078, 0x1ca6, 0x8a51, 0x0040, 0x1d3f, + 0x8840, 0x2804, 0xa005, 0x00c0, 0x1d00, 0x6004, 0xa065, 0x0040, + 0x1d3f, 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x1c7e, 0x2804, 0x2040, + 0x2b68, 0x6850, 0xc0fc, 0x6852, 0x0078, 0x1d33, 0x8422, 0x8420, + 0x831a, 0xa399, 0x0000, 0x0d7e, 0x2b68, 0x6c6e, 0x6b72, 0x0d7f, + 0xd99c, 0x00c0, 0x1d21, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, + 0xa11b, 0x1048, 0x12cd, 0x6800, 0xa420, 0x6804, 0xa319, 0x0078, + 0x1d2d, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x1048, + 0x12cd, 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22, + 0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00, + 0x6826, 0x007f, 0x007f, 0x007f, 0xa006, 0x0078, 0x1d44, 0x087f, + 0x097f, 0x0a7f, 0xa085, 0x0001, 0x007c, 0x2001, 0x0005, 0x2004, + 0xa084, 0x0007, 0x0079, 0x1d4c, 0x1d54, 0x1d55, 0x1d58, 0x1d5b, + 0x1d60, 0x1d63, 0x1d68, 0x1d6d, 0x007c, 0x1078, 0x1b4a, 0x007c, + 0x1078, 0x1785, 0x007c, 0x1078, 0x1785, 0x1078, 0x1b4a, 0x007c, + 0x1078, 0x1456, 0x007c, 0x1078, 0x1b4a, 0x1078, 0x1456, 0x007c, + 0x1078, 0x1785, 0x1078, 0x1456, 0x007c, 0x1078, 0x1785, 0x1078, + 0x1b4a, 0x1078, 0x1456, 0x007c, 0x127e, 0x2091, 0x2300, 0x2079, + 0x0200, 0x2071, 0x7b80, 0x2069, 0x7600, 0x2009, 0x0004, 0x7912, + 0x7817, 0x0004, 0x1078, 0x2052, 0x781b, 0x0002, 0x20e1, 0x8700, + 0x127f, 0x007c, 0x127e, 0x2091, 0x2300, 0x781c, 0xa084, 0x0007, + 0x0079, 0x1d92, 0x1db6, 0x1d9a, 0x1d9e, 0x1da2, 0x1da8, 0x1dac, + 0x1db0, 0x1db4, 0x1078, 0x4175, 0x0078, 0x1db6, 0x1078, 0x41a4, + 0x0078, 0x1db6, 0x1078, 0x4175, 0x1078, 0x41a4, 0x0078, 0x1db6, + 0x1078, 0x1db8, 0x0078, 0x1db6, 0x1078, 0x1db8, 0x0078, 0x1db6, + 0x1078, 0x1db8, 0x0078, 0x1db6, 0x1078, 0x1db8, 0x127f, 0x007c, + 0x007e, 0x017e, 0x027e, 0x7930, 0xa184, 0x0003, 0x0040, 0x1dc2, + 0x1078, 0x12cd, 0xa184, 0x0030, 0x0040, 0x1dd3, 0x6a00, 0xa286, + 0x0003, 0x00c0, 0x1dcd, 0x1078, 0x12cd, 0x1078, 0x3573, 0x20e1, + 0x9010, 0x0078, 0x1ddf, 0xa184, 0x00c0, 0x0040, 0x1dd9, 0x1078, + 0x12cd, 0xa184, 0x0300, 0x0040, 0x1ddf, 0x20e1, 0x9020, 0x7932, + 0x027f, 0x017f, 0x007f, 0x007c, 0x017e, 0x0e7e, 0x0f7e, 0x2071, + 0x7600, 0x7128, 0x2001, 0x7823, 0x2102, 0x2001, 0x782b, 0x2102, + 0xa182, 0x0211, 0x00c8, 0x1df8, 0x2009, 0x0008, 0x0078, 0x1e22, + 0xa182, 0x0259, 0x00c8, 0x1e00, 0x2009, 0x0007, 0x0078, 0x1e22, + 0xa182, 0x02c1, 0x00c8, 0x1e08, 0x2009, 0x0006, 0x0078, 0x1e22, + 0xa182, 0x0349, 0x00c8, 0x1e10, 0x2009, 0x0005, 0x0078, 0x1e22, + 0xa182, 0x0421, 0x00c8, 0x1e18, 0x2009, 0x0004, 0x0078, 0x1e22, + 0xa182, 0x0581, 0x00c8, 0x1e20, 0x2009, 0x0003, 0x0078, 0x1e22, + 0x2009, 0x0002, 0x2079, 0x0200, 0x7912, 0xa182, 0x0005, 0x00c8, + 0x1e2c, 0x7916, 0x0078, 0x1e2e, 0x7817, 0x0004, 0x1078, 0x2052, + 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x127e, 0x2091, 0x2200, 0x2061, + 0x0100, 0x2071, 0x7600, 0x6024, 0x6026, 0x6033, 0x00ef, 0x60e7, + 0x0000, 0x60eb, 0x00ef, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, + 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, 0x0caf, 0x600f, + 0x00ff, 0x602b, 0x002f, 0x127f, 0x007c, 0x2001, 0x762d, 0x2003, + 0x0000, 0x2001, 0x762c, 0x2003, 0x0001, 0x007c, 0x127e, 0x2091, + 0x2200, 0x007e, 0x017e, 0x027e, 0x6124, 0xa184, 0x002c, 0x00c0, + 0x1e6d, 0xa184, 0x0007, 0x0079, 0x1e73, 0xa195, 0x0004, 0xa284, + 0x0007, 0x0079, 0x1e73, 0x1e9f, 0x1e7b, 0x1e7f, 0x1e83, 0x1e89, + 0x1e8d, 0x1e93, 0x1e99, 0x1078, 0x46de, 0x0078, 0x1e9f, 0x1078, + 0x47cd, 0x0078, 0x1e9f, 0x1078, 0x47cd, 0x1078, 0x46de, 0x0078, + 0x1e9f, 0x1078, 0x1ea4, 0x0078, 0x1e9f, 0x1078, 0x46de, 0x1078, + 0x1ea4, 0x0078, 0x1e9f, 0x1078, 0x47cd, 0x1078, 0x1ea4, 0x0078, + 0x1e9f, 0x1078, 0x47cd, 0x1078, 0x46de, 0x1078, 0x1ea4, 0x027f, + 0x017f, 0x007f, 0x127f, 0x007c, 0xd1ac, 0x0040, 0x1f58, 0x017e, + 0x047e, 0x0c7e, 0x644c, 0x74ba, 0xa48c, 0xff00, 0xa196, 0xff00, + 0x0040, 0x1ed3, 0x6030, 0xa084, 0x00ff, 0x810f, 0xa116, 0x0040, + 0x1ed3, 0x7130, 0xd18c, 0x00c0, 0x1ed3, 0x2011, 0x7652, 0x2214, + 0xd2ec, 0x0040, 0x1ec7, 0xc18d, 0x7132, 0x0078, 0x1ed3, 0x6240, + 0xa294, 0x0010, 0x0040, 0x1f15, 0x6248, 0xa294, 0xff00, 0xa296, + 0xff00, 0x00c0, 0x1f15, 0x037e, 0x73b8, 0x2011, 0x8013, 0x1078, + 0x2d3b, 0x037f, 0x7130, 0xc185, 0x7132, 0x2011, 0x7652, 0x220c, + 0xd1a4, 0x0040, 0x1efd, 0x017e, 0x2009, 0x0001, 0x2011, 0x0100, + 0x1078, 0x46ac, 0x2019, 0x000e, 0x1078, 0x74ce, 0xa484, 0x00ff, + 0xa080, 0x2329, 0x200c, 0xa18c, 0xff00, 0x810f, 0x8127, 0xa006, + 0x2009, 0x000e, 0x1078, 0x7536, 0x017f, 0xd1ac, 0x00c0, 0x1f06, + 0x2019, 0x0004, 0x1078, 0x2293, 0x0078, 0x1f15, 0x157e, 0x20a9, + 0x007f, 0x2009, 0x0000, 0x1078, 0x381d, 0x00c0, 0x1f11, 0x1078, + 0x3619, 0x8108, 0x00f0, 0x1f0b, 0x157f, 0x0c7f, 0x047f, 0x6043, + 0x0000, 0x2009, 0x00f7, 0x1078, 0x35dc, 0x0f7e, 0x2079, 0x7849, + 0x783c, 0xa086, 0x0000, 0x0040, 0x1f2d, 0x6027, 0x0004, 0x783f, + 0x0000, 0x2079, 0x0140, 0x7803, 0x0000, 0x0f7f, 0x2011, 0x0003, + 0x1078, 0x57b8, 0x2011, 0x0002, 0x1078, 0x57c2, 0x1078, 0x56ce, + 0x1078, 0x45e3, 0x037e, 0x2019, 0x0000, 0x1078, 0x5760, 0x037f, + 0x60e3, 0x0000, 0x017f, 0x2001, 0x7600, 0x2014, 0xa296, 0x0004, + 0x00c0, 0x1f50, 0xd19c, 0x00c0, 0x1f50, 0x6228, 0xc29d, 0x622a, + 0x2003, 0x0001, 0x2001, 0x7620, 0x2003, 0x0000, 0x6027, 0x0020, + 0xd194, 0x0040, 0x1ff9, 0x0f7e, 0x2079, 0x7849, 0x783c, 0xa086, + 0x0001, 0x00c0, 0x1f7c, 0x017e, 0x6027, 0x0004, 0x783f, 0x0000, + 0x2079, 0x0140, 0x7803, 0x1000, 0x7803, 0x0000, 0x2079, 0x7836, + 0x7807, 0x0000, 0x7833, 0x0000, 0x1078, 0x4c72, 0x1078, 0x4d32, + 0x017f, 0x0f7f, 0x0078, 0x1ff9, 0x0f7f, 0x017e, 0x6220, 0xd2b4, + 0x0040, 0x1fb1, 0x1078, 0x45e3, 0x1078, 0x557a, 0x6027, 0x0004, + 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x1f94, 0x6803, 0x1000, 0x6803, 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0x7836, - 0x6044, 0xa09a, 0x0002, 0x00c8, 0x1fed, 0x8000, 0x6046, 0x603c, - 0x0c7f, 0xa005, 0x0040, 0x1ffe, 0x1078, 0x45f0, 0xa080, 0x0007, - 0x2004, 0xa086, 0x0006, 0x00c0, 0x1fe9, 0x6017, 0x0012, 0x0078, - 0x1ffe, 0x6017, 0x0016, 0x0078, 0x1ffe, 0x037e, 0x2019, 0x0001, - 0x1078, 0x5768, 0x037f, 0x2019, 0x7845, 0x2304, 0xa065, 0x0040, - 0x1ffd, 0x2009, 0x004f, 0x1078, 0x5c29, 0x0c7f, 0x017f, 0xd19c, - 0x0040, 0x2027, 0x017e, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, - 0x1078, 0x57c0, 0x2011, 0x0002, 0x1078, 0x57ca, 0x1078, 0x56d6, - 0x1078, 0x45eb, 0x037e, 0x2019, 0x0000, 0x1078, 0x5768, 0x037f, - 0x60e3, 0x0000, 0x1078, 0x75b0, 0x1078, 0x75ce, 0x2001, 0x7600, - 0x2003, 0x0004, 0x6027, 0x0008, 0x1078, 0x11c6, 0x017f, 0xa18c, - 0xffd0, 0x6126, 0x007c, 0x007e, 0x017e, 0x027e, 0x0e7e, 0x0f7e, - 0x127e, 0x2091, 0x8000, 0x2071, 0x7600, 0x71b0, 0x70b2, 0xa116, - 0x0040, 0x2051, 0x81ff, 0x0040, 0x2043, 0x2011, 0x8011, 0x1078, - 0x2d4a, 0x0078, 0x2051, 0x2011, 0x8012, 0x1078, 0x2d4a, 0x037e, - 0x0c7e, 0x2061, 0x0100, 0x2019, 0x0028, 0x1078, 0x2299, 0x0c7f, - 0x037f, 0x127f, 0x0f7f, 0x0e7f, 0x027f, 0x017f, 0x007f, 0x007c, - 0x0c7e, 0x0f7e, 0x007e, 0x027e, 0x2061, 0x0100, 0xa190, 0x2073, - 0x2204, 0x60f2, 0xa192, 0x0005, 0x00c8, 0x206a, 0xa190, 0x207c, - 0x0078, 0x206c, 0x2011, 0x2080, 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, 0x2130, 0xa094, - 0xff00, 0x00c0, 0x208e, 0x81ff, 0x0040, 0x2092, 0x1078, 0x4330, - 0x0078, 0x2099, 0xa080, 0x232f, 0x200c, 0xa18c, 0xff00, 0x810f, - 0xa006, 0x007c, 0xa080, 0x232f, 0x200c, 0xa18c, 0x00ff, 0x007c, - 0x20c0, 0x20c4, 0x20c8, 0x20ce, 0x20d4, 0x20da, 0x20e0, 0x20e8, - 0x20f0, 0x20f6, 0x20fc, 0x2104, 0x210c, 0x2114, 0x211c, 0x2126, - 0x2130, 0x2130, 0x2130, 0x2130, 0x2130, 0x2130, 0x2130, 0x2130, - 0x2130, 0x2130, 0x2130, 0x2130, 0x2130, 0x2130, 0x2130, 0x2130, - 0x107e, 0x007e, 0x0078, 0x2149, 0x107e, 0x007e, 0x0078, 0x2149, - 0x107e, 0x007e, 0x1078, 0x1e64, 0x0078, 0x2149, 0x107e, 0x007e, - 0x1078, 0x1e64, 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1d4b, - 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1d4b, 0x0078, 0x2149, - 0x107e, 0x007e, 0x1078, 0x1e64, 0x1078, 0x1d4b, 0x0078, 0x2149, - 0x107e, 0x007e, 0x1078, 0x1e64, 0x1078, 0x1d4b, 0x0078, 0x2149, - 0x107e, 0x007e, 0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e, - 0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1e64, - 0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1e64, - 0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1d4b, - 0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1d4b, - 0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1e64, - 0x1078, 0x1d4b, 0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e, - 0x1078, 0x1e64, 0x1078, 0x1d4b, 0x1078, 0x1d90, 0x0078, 0x2149, - 0x0005, 0x0078, 0x2130, 0xb084, 0x003c, 0x8004, 0x8004, 0x0079, - 0x2139, 0x2149, 0x20c6, 0x20ca, 0x20d0, 0x20d6, 0x20dc, 0x20e2, - 0x20ea, 0x20f2, 0x20f8, 0x20fe, 0x2106, 0x210e, 0x2116, 0x211e, - 0x2128, 0x0008, 0x2133, 0x007f, 0x107f, 0x2091, 0x8001, 0x007c, - 0x0c7e, 0x027e, 0x2041, 0x007e, 0x70bc, 0xd09c, 0x0040, 0x215a, - 0x2041, 0x007f, 0x2001, 0x010c, 0x203c, 0x727c, 0x82ff, 0x0040, - 0x21a5, 0x037e, 0x738c, 0xa38e, 0xffff, 0x00c0, 0x2169, 0x2019, - 0x0001, 0x8314, 0xa2e0, 0x7cc0, 0x2c04, 0xa38c, 0x0001, 0x0040, - 0x2176, 0xa084, 0xff00, 0x8007, 0x0078, 0x2178, 0xa084, 0x00ff, - 0xa70e, 0x0040, 0x219a, 0xa08e, 0x00ff, 0x0040, 0x21a0, 0x2009, - 0x0000, 0x1078, 0x2085, 0x1078, 0x37ee, 0x00c0, 0x219d, 0x6004, - 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2194, 0x1078, 0x21f7, - 0x0040, 0x219d, 0x0078, 0x219a, 0x1078, 0x22fb, 0x1078, 0x221e, - 0x0040, 0x219d, 0x8318, 0x0078, 0x2169, 0x738e, 0x0078, 0x21a2, - 0x708f, 0xffff, 0x037f, 0x0078, 0x21f4, 0xa780, 0x232f, 0x203c, - 0xa7bc, 0xff00, 0x873f, 0x708c, 0xa096, 0xffff, 0x0040, 0x21b7, - 0xa812, 0x00c8, 0x21c7, 0x708f, 0xffff, 0x0078, 0x21f1, 0x2009, - 0x0000, 0x70bc, 0xd09c, 0x0040, 0x21c2, 0xd094, 0x0040, 0x21c2, - 0x2009, 0x007e, 0x2100, 0xa802, 0x20a8, 0x0078, 0x21cb, 0x2008, - 0x2810, 0xa202, 0x20a8, 0x2700, 0x157e, 0x017e, 0xa106, 0x0040, - 0x21e8, 0x1078, 0x37ee, 0x00c0, 0x21f1, 0x6004, 0xa084, 0x00ff, - 0xa086, 0x0006, 0x00c0, 0x21e2, 0x1078, 0x21f7, 0x0040, 0x21f1, - 0x0078, 0x21e8, 0x1078, 0x22fb, 0x1078, 0x221e, 0x0040, 0x21f1, - 0x017f, 0x8108, 0x157f, 0x00f0, 0x21cb, 0x708f, 0xffff, 0x0078, - 0x21f4, 0x017f, 0x157f, 0x718e, 0x027f, 0x0c7f, 0x007c, 0x017e, - 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x5b9c, 0x0040, 0x2219, - 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x37bd, - 0x2001, 0x0000, 0x1078, 0x37d1, 0x127e, 0x2091, 0x8000, 0x7088, - 0x8000, 0x708a, 0x127f, 0x2009, 0x0004, 0x1078, 0x5c29, 0xa085, - 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x017e, 0x077e, - 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x5b9c, 0x0040, 0x2240, 0x2d00, - 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x37bd, 0x2001, - 0x0002, 0x1078, 0x37d1, 0x127e, 0x2091, 0x8000, 0x7088, 0x8000, - 0x708a, 0x127f, 0x2009, 0x0002, 0x1078, 0x5c29, 0xa085, 0x0001, - 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e, 0x027e, 0x2009, - 0x0080, 0x1078, 0x37ee, 0x00c0, 0x2253, 0x1078, 0x2256, 0x0040, - 0x2253, 0x70c3, 0xffff, 0x027f, 0x0c7f, 0x007c, 0x017e, 0x077e, - 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x5b9c, 0x0040, 0x2278, 0x2d00, - 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x37bd, 0x2001, - 0x0002, 0x1078, 0x37d1, 0x127e, 0x2091, 0x8000, 0x70c4, 0x8000, - 0x70c6, 0x127f, 0x2009, 0x0002, 0x1078, 0x5c29, 0xa085, 0x0001, - 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e, 0x0d7e, 0x2009, - 0x007f, 0x1078, 0x37ee, 0x00c0, 0x2296, 0x2c68, 0x1078, 0x5b9c, - 0x0040, 0x2296, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, 0x620a, - 0x2009, 0x0022, 0x1078, 0x5c29, 0xa085, 0x0001, 0x0d7f, 0x0c7f, - 0x007c, 0x0e7e, 0x0c7e, 0x067e, 0x037e, 0x027e, 0x1078, 0x4969, - 0x1078, 0x4919, 0x1078, 0x6103, 0x20a9, 0x007f, 0x2009, 0x0000, - 0x017e, 0x1078, 0x3825, 0x00c0, 0x22b1, 0x1078, 0x39a6, 0x1078, - 0x3621, 0x017f, 0x8108, 0x00f0, 0x22a8, 0x027f, 0x037f, 0x067f, - 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, - 0x6218, 0x2270, 0x72a0, 0x027e, 0x2019, 0x0029, 0x1078, 0x4962, - 0x1078, 0x48a5, 0x2c08, 0x1078, 0x737b, 0x017f, 0x2e60, 0x1078, - 0x39a6, 0x6210, 0x6314, 0x1078, 0x3621, 0x6212, 0x6316, 0x017f, - 0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x007e, 0x6018, - 0xa080, 0x0028, 0x2004, 0xd0bc, 0x00c0, 0x22f1, 0x2071, 0x7600, - 0x7088, 0xa005, 0x0040, 0x22ee, 0x8001, 0x708a, 0x007f, 0x0e7f, - 0x007c, 0x2071, 0x7600, 0x70c4, 0xa005, 0x0040, 0x22ee, 0x8001, - 0x70c6, 0x0078, 0x22ee, 0x6000, 0xc08c, 0x6002, 0x007c, 0x0e7e, - 0x0c7e, 0x037e, 0x027e, 0x017e, 0x157e, 0x81ff, 0x00c0, 0x230c, - 0x20a9, 0x0001, 0x0078, 0x2310, 0x20a9, 0x007f, 0x2011, 0x0000, - 0x027e, 0xa2e0, 0x7720, 0x2c64, 0x8cff, 0x0040, 0x2322, 0x2019, - 0x0029, 0x1078, 0x4962, 0x1078, 0x48a5, 0x2c08, 0x1078, 0x737b, - 0x1078, 0x39a6, 0x027f, 0x8210, 0x00f0, 0x2310, 0x027e, 0x027f, - 0x157f, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, 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, + 0x6028, 0xa09a, 0x0002, 0x00c8, 0x1fa4, 0x8000, 0x602a, 0x0c7f, + 0x1078, 0x556c, 0x0078, 0x1ff8, 0x2019, 0x783f, 0x2304, 0xa065, + 0x0040, 0x1fae, 0x2009, 0x0027, 0x1078, 0x5c21, 0x0c7f, 0x0078, + 0x1ff8, 0xd2bc, 0x0040, 0x1ff8, 0x1078, 0x45f1, 0x6017, 0x0010, + 0x6027, 0x0004, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, + 0x0040, 0x1fc6, 0x6803, 0x1000, 0x6803, 0x0000, 0x0d7f, 0x0c7e, + 0x2061, 0x7836, 0x6044, 0xa09a, 0x0002, 0x00c8, 0x1fe7, 0x8000, + 0x6046, 0x603c, 0x0c7f, 0xa005, 0x0040, 0x1ff8, 0x1078, 0x45e8, + 0xa080, 0x0007, 0x2004, 0xa086, 0x0006, 0x00c0, 0x1fe3, 0x6017, + 0x0012, 0x0078, 0x1ff8, 0x6017, 0x0016, 0x0078, 0x1ff8, 0x037e, + 0x2019, 0x0001, 0x1078, 0x5760, 0x037f, 0x2019, 0x7845, 0x2304, + 0xa065, 0x0040, 0x1ff7, 0x2009, 0x004f, 0x1078, 0x5c21, 0x0c7f, + 0x017f, 0xd19c, 0x0040, 0x2021, 0x017e, 0x6028, 0xc09c, 0x602a, + 0x2011, 0x0003, 0x1078, 0x57b8, 0x2011, 0x0002, 0x1078, 0x57c2, + 0x1078, 0x56ce, 0x1078, 0x45e3, 0x037e, 0x2019, 0x0000, 0x1078, + 0x5760, 0x037f, 0x60e3, 0x0000, 0x1078, 0x75a5, 0x1078, 0x75c3, + 0x2001, 0x7600, 0x2003, 0x0004, 0x6027, 0x0008, 0x1078, 0x11be, + 0x017f, 0xa18c, 0xffd0, 0x6126, 0x007c, 0x007e, 0x017e, 0x027e, + 0x0e7e, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2071, 0x7600, 0x71b0, + 0x70b2, 0xa116, 0x0040, 0x204b, 0x81ff, 0x0040, 0x203d, 0x2011, + 0x8011, 0x1078, 0x2d3b, 0x0078, 0x204b, 0x2011, 0x8012, 0x1078, + 0x2d3b, 0x037e, 0x0c7e, 0x2061, 0x0100, 0x2019, 0x0028, 0x1078, + 0x2293, 0x0c7f, 0x037f, 0x127f, 0x0f7f, 0x0e7f, 0x027f, 0x017f, + 0x007f, 0x007c, 0x0c7e, 0x0f7e, 0x007e, 0x027e, 0x2061, 0x0100, + 0xa190, 0x206d, 0x2204, 0x60f2, 0xa192, 0x0005, 0x00c8, 0x2064, + 0xa190, 0x2076, 0x0078, 0x2066, 0x2011, 0x207a, 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, + 0x2130, 0xa094, 0xff00, 0x00c0, 0x2088, 0x81ff, 0x0040, 0x208c, + 0x1078, 0x4328, 0x0078, 0x2093, 0xa080, 0x2329, 0x200c, 0xa18c, + 0xff00, 0x810f, 0xa006, 0x007c, 0xa080, 0x2329, 0x200c, 0xa18c, + 0x00ff, 0x007c, 0x20ba, 0x20be, 0x20c2, 0x20c8, 0x20ce, 0x20d4, + 0x20da, 0x20e2, 0x20ea, 0x20f0, 0x20f6, 0x20fe, 0x2106, 0x210e, + 0x2116, 0x2120, 0x212a, 0x212a, 0x212a, 0x212a, 0x212a, 0x212a, + 0x212a, 0x212a, 0x212a, 0x212a, 0x212a, 0x212a, 0x212a, 0x212a, + 0x212a, 0x212a, 0x107e, 0x007e, 0x0078, 0x2143, 0x107e, 0x007e, + 0x0078, 0x2143, 0x107e, 0x007e, 0x1078, 0x1e5e, 0x0078, 0x2143, + 0x107e, 0x007e, 0x1078, 0x1e5e, 0x0078, 0x2143, 0x107e, 0x007e, + 0x1078, 0x1d45, 0x0078, 0x2143, 0x107e, 0x007e, 0x1078, 0x1d45, + 0x0078, 0x2143, 0x107e, 0x007e, 0x1078, 0x1e5e, 0x1078, 0x1d45, + 0x0078, 0x2143, 0x107e, 0x007e, 0x1078, 0x1e5e, 0x1078, 0x1d45, + 0x0078, 0x2143, 0x107e, 0x007e, 0x1078, 0x1d8a, 0x0078, 0x2143, + 0x107e, 0x007e, 0x1078, 0x1d8a, 0x0078, 0x2143, 0x107e, 0x007e, + 0x1078, 0x1e5e, 0x1078, 0x1d8a, 0x0078, 0x2143, 0x107e, 0x007e, + 0x1078, 0x1e5e, 0x1078, 0x1d8a, 0x0078, 0x2143, 0x107e, 0x007e, + 0x1078, 0x1d45, 0x1078, 0x1d8a, 0x0078, 0x2143, 0x107e, 0x007e, + 0x1078, 0x1d45, 0x1078, 0x1d8a, 0x0078, 0x2143, 0x107e, 0x007e, + 0x1078, 0x1e5e, 0x1078, 0x1d45, 0x1078, 0x1d8a, 0x0078, 0x2143, + 0x107e, 0x007e, 0x1078, 0x1e5e, 0x1078, 0x1d45, 0x1078, 0x1d8a, + 0x0078, 0x2143, 0x0005, 0x0078, 0x212a, 0xb084, 0x003c, 0x8004, + 0x8004, 0x0079, 0x2133, 0x2143, 0x20c0, 0x20c4, 0x20ca, 0x20d0, + 0x20d6, 0x20dc, 0x20e4, 0x20ec, 0x20f2, 0x20f8, 0x2100, 0x2108, + 0x2110, 0x2118, 0x2122, 0x0008, 0x212d, 0x007f, 0x107f, 0x2091, + 0x8001, 0x007c, 0x0c7e, 0x027e, 0x2041, 0x007e, 0x70bc, 0xd09c, + 0x0040, 0x2154, 0x2041, 0x007f, 0x2001, 0x010c, 0x203c, 0x727c, + 0x82ff, 0x0040, 0x219f, 0x037e, 0x738c, 0xa38e, 0xffff, 0x00c0, + 0x2163, 0x2019, 0x0001, 0x8314, 0xa2e0, 0x7cc0, 0x2c04, 0xa38c, + 0x0001, 0x0040, 0x2170, 0xa084, 0xff00, 0x8007, 0x0078, 0x2172, + 0xa084, 0x00ff, 0xa70e, 0x0040, 0x2194, 0xa08e, 0x00ff, 0x0040, + 0x219a, 0x2009, 0x0000, 0x1078, 0x207f, 0x1078, 0x37e6, 0x00c0, + 0x2197, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x218e, + 0x1078, 0x21f1, 0x0040, 0x2197, 0x0078, 0x2194, 0x1078, 0x22f5, + 0x1078, 0x2218, 0x0040, 0x2197, 0x8318, 0x0078, 0x2163, 0x738e, + 0x0078, 0x219c, 0x708f, 0xffff, 0x037f, 0x0078, 0x21ee, 0xa780, + 0x2329, 0x203c, 0xa7bc, 0xff00, 0x873f, 0x708c, 0xa096, 0xffff, + 0x0040, 0x21b1, 0xa812, 0x00c8, 0x21c1, 0x708f, 0xffff, 0x0078, + 0x21eb, 0x2009, 0x0000, 0x70bc, 0xd09c, 0x0040, 0x21bc, 0xd094, + 0x0040, 0x21bc, 0x2009, 0x007e, 0x2100, 0xa802, 0x20a8, 0x0078, + 0x21c5, 0x2008, 0x2810, 0xa202, 0x20a8, 0x2700, 0x157e, 0x017e, + 0xa106, 0x0040, 0x21e2, 0x1078, 0x37e6, 0x00c0, 0x21eb, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x21dc, 0x1078, 0x21f1, + 0x0040, 0x21eb, 0x0078, 0x21e2, 0x1078, 0x22f5, 0x1078, 0x2218, + 0x0040, 0x21eb, 0x017f, 0x8108, 0x157f, 0x00f0, 0x21c5, 0x708f, + 0xffff, 0x0078, 0x21ee, 0x017f, 0x157f, 0x718e, 0x027f, 0x0c7f, + 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x5b94, + 0x0040, 0x2213, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, + 0x1078, 0x37b5, 0x2001, 0x0000, 0x1078, 0x37c9, 0x127e, 0x2091, + 0x8000, 0x7088, 0x8000, 0x708a, 0x127f, 0x2009, 0x0004, 0x1078, + 0x5c21, 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, + 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x5b94, 0x0040, + 0x223a, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, + 0x37b5, 0x2001, 0x0002, 0x1078, 0x37c9, 0x127e, 0x2091, 0x8000, + 0x7088, 0x8000, 0x708a, 0x127f, 0x2009, 0x0002, 0x1078, 0x5c21, + 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e, + 0x027e, 0x2009, 0x0080, 0x1078, 0x37e6, 0x00c0, 0x224d, 0x1078, + 0x2250, 0x0040, 0x224d, 0x70c3, 0xffff, 0x027f, 0x0c7f, 0x007c, + 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x5b94, 0x0040, + 0x2272, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, + 0x37b5, 0x2001, 0x0002, 0x1078, 0x37c9, 0x127e, 0x2091, 0x8000, + 0x70c4, 0x8000, 0x70c6, 0x127f, 0x2009, 0x0002, 0x1078, 0x5c21, + 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e, + 0x0d7e, 0x2009, 0x007f, 0x1078, 0x37e6, 0x00c0, 0x2290, 0x2c68, + 0x1078, 0x5b94, 0x0040, 0x2290, 0x2d00, 0x601a, 0x6312, 0x601f, + 0x0001, 0x620a, 0x2009, 0x0022, 0x1078, 0x5c21, 0xa085, 0x0001, + 0x0d7f, 0x0c7f, 0x007c, 0x0e7e, 0x0c7e, 0x067e, 0x037e, 0x027e, + 0x1078, 0x4961, 0x1078, 0x4911, 0x1078, 0x60f9, 0x20a9, 0x007f, + 0x2009, 0x0000, 0x017e, 0x1078, 0x381d, 0x00c0, 0x22ab, 0x1078, + 0x399e, 0x1078, 0x3619, 0x017f, 0x8108, 0x00f0, 0x22a2, 0x027f, + 0x037f, 0x067f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x0c7e, 0x037e, + 0x027e, 0x017e, 0x6218, 0x2270, 0x72a0, 0x027e, 0x2019, 0x0029, + 0x1078, 0x495a, 0x1078, 0x489d, 0x2c08, 0x1078, 0x7370, 0x017f, + 0x2e60, 0x1078, 0x399e, 0x6210, 0x6314, 0x1078, 0x3619, 0x6212, + 0x6316, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, + 0x007e, 0x6018, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x00c0, 0x22eb, + 0x2071, 0x7600, 0x7088, 0xa005, 0x0040, 0x22e8, 0x8001, 0x708a, + 0x007f, 0x0e7f, 0x007c, 0x2071, 0x7600, 0x70c4, 0xa005, 0x0040, + 0x22e8, 0x8001, 0x70c6, 0x0078, 0x22e8, 0x6000, 0xc08c, 0x6002, + 0x007c, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x157e, 0x81ff, + 0x00c0, 0x2306, 0x20a9, 0x0001, 0x0078, 0x230a, 0x20a9, 0x007f, + 0x2011, 0x0000, 0x027e, 0xa2e0, 0x7720, 0x2c64, 0x8cff, 0x0040, + 0x231c, 0x2019, 0x0029, 0x1078, 0x495a, 0x1078, 0x489d, 0x2c08, + 0x1078, 0x7370, 0x1078, 0x399e, 0x027f, 0x8210, 0x00f0, 0x230a, + 0x027e, 0x027f, 0x157f, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, + 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, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, - 0x766d, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, 0x703e, - 0x7033, 0x767d, 0x7037, 0x767d, 0x7007, 0x0001, 0x2061, 0x76bd, - 0x6003, 0x0002, 0x007c, 0x0090, 0x2456, 0x0068, 0x2456, 0x2071, - 0x766d, 0x2b78, 0x7818, 0xd084, 0x00c0, 0x2456, 0x2a60, 0x7820, - 0xa08e, 0x0069, 0x00c0, 0x253d, 0x0079, 0x24da, 0x007c, 0x2071, - 0x766d, 0x7004, 0x0079, 0x245c, 0x2460, 0x2461, 0x246b, 0x247d, - 0x007c, 0x0090, 0x246a, 0x0068, 0x246a, 0x2b78, 0x7818, 0xd084, - 0x0040, 0x2489, 0x007c, 0x2b78, 0x2061, 0x76bd, 0x6008, 0xa08e, - 0x0100, 0x0040, 0x2478, 0xa086, 0x0200, 0x0040, 0x2535, 0x007c, - 0x7014, 0x2068, 0x2a60, 0x7018, 0x007a, 0x7010, 0x2068, 0x6834, - 0xa086, 0x0103, 0x0040, 0x2485, 0x007c, 0x2a60, 0x2b78, 0x7018, - 0x007a, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x00c8, 0x2492, 0x61b0, - 0x0079, 0x249a, 0x2100, 0xa08a, 0x0036, 0x00c8, 0x2531, 0x61b0, - 0x0079, 0x24da, 0x2513, 0x2545, 0x254d, 0x2551, 0x2559, 0x255f, - 0x2563, 0x256c, 0x2570, 0x2578, 0x257c, 0x2531, 0x2531, 0x2531, - 0x2580, 0x2531, 0x2590, 0x25a7, 0x25be, 0x263a, 0x263f, 0x266c, - 0x26b9, 0x26c8, 0x26e9, 0x271f, 0x2729, 0x2736, 0x2749, 0x2761, - 0x276a, 0x27a7, 0x27ad, 0x2531, 0x27bd, 0x2531, 0x2531, 0x2531, - 0x2531, 0x2531, 0x27c1, 0x27c7, 0x2531, 0x2531, 0x2531, 0x2531, - 0x2531, 0x2531, 0x2531, 0x2531, 0x27cf, 0x2531, 0x2531, 0x2531, - 0x2531, 0x2531, 0x27dc, 0x27e2, 0x2531, 0x2531, 0x2531, 0x2531, - 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, - 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, - 0x2531, 0x2531, 0x2578, 0x257c, 0x2531, 0x2531, 0x27f4, 0x2531, - 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, - 0x2531, 0x2531, 0x2841, 0x290e, 0x2922, 0x2929, 0x298c, 0x29e7, - 0x29f2, 0x2a34, 0x2a41, 0x2a4e, 0x2a51, 0x27f8, 0x2a7a, 0x2ac1, - 0x2ace, 0x2bc8, 0x2cb6, 0x2cdd, 0x2dd5, 0x2de3, 0x2df0, 0x2e2a, - 0x713c, 0x0078, 0x2513, 0x2021, 0x4000, 0x1078, 0x2d24, 0x127e, - 0x2091, 0x8000, 0x0068, 0x2520, 0x7818, 0xd084, 0x0040, 0x2523, - 0x127f, 0x0078, 0x2517, 0x781b, 0x0001, 0x7c22, 0x7926, 0x7a2a, - 0x7b2e, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, 0x5000, 0x127f, - 0x007c, 0x2021, 0x4001, 0x0078, 0x2515, 0x2021, 0x4002, 0x0078, - 0x2515, 0x2021, 0x4003, 0x0078, 0x2515, 0x2021, 0x4005, 0x0078, - 0x2515, 0x2021, 0x4006, 0x0078, 0x2515, 0xa02e, 0x2520, 0x7b28, - 0x7a2c, 0x7824, 0x7930, 0x0078, 0x2d33, 0x7823, 0x0004, 0x7824, - 0x007a, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0078, - 0x2d37, 0x7924, 0x7828, 0x2114, 0x200a, 0x0078, 0x2513, 0x7924, - 0x2114, 0x0078, 0x2513, 0x2099, 0x0009, 0x20a1, 0x0009, 0x20a9, - 0x0007, 0x53a3, 0x0078, 0x2513, 0x7824, 0x2060, 0x0078, 0x2582, - 0x2009, 0x0001, 0x2011, 0x000f, 0x2019, 0x0013, 0x0078, 0x2513, - 0x7d38, 0x7c3c, 0x0078, 0x2547, 0x7d38, 0x7c3c, 0x0078, 0x2553, - 0x2061, 0x1000, 0x610c, 0xa006, 0x2c14, 0xa200, 0x8c60, 0x8109, - 0x00c0, 0x2584, 0x2010, 0xa005, 0x0040, 0x2513, 0x0078, 0x2539, - 0x2061, 0x7651, 0x7824, 0x7930, 0xa11a, 0x00c8, 0x2541, 0x8019, - 0x0040, 0x2541, 0x604a, 0x6142, 0x782c, 0x6052, 0x7828, 0x6056, - 0xa006, 0x605a, 0x605e, 0x1078, 0x3c71, 0x0078, 0x2513, 0x2061, - 0x7651, 0x7824, 0x7930, 0xa11a, 0x00c8, 0x2541, 0x8019, 0x0040, - 0x2541, 0x604e, 0x6146, 0x782c, 0x6062, 0x7828, 0x6066, 0xa006, - 0x606a, 0x606e, 0x1078, 0x3a47, 0x0078, 0x2513, 0xa02e, 0x2520, - 0x81ff, 0x00c0, 0x253d, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, - 0x20a1, 0x7674, 0x41a1, 0x1078, 0x2cfb, 0x0040, 0x253d, 0x2009, - 0x0020, 0x1078, 0x2d33, 0x701b, 0x25d6, 0x007c, 0x6834, 0x2008, - 0xa084, 0x00ff, 0xa096, 0x0011, 0x0040, 0x25e2, 0xa096, 0x0019, - 0x00c0, 0x253d, 0x810f, 0xa18c, 0x00ff, 0x0040, 0x253d, 0x710e, - 0x700c, 0x8001, 0x0040, 0x2613, 0x700e, 0x1078, 0x2cfb, 0x0040, - 0x253d, 0x2009, 0x0020, 0x2061, 0x76bd, 0x6224, 0x6328, 0x642c, - 0x6530, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, - 0x0000, 0x1078, 0x2d33, 0x701b, 0x2606, 0x007c, 0x6834, 0xa084, - 0x00ff, 0xa096, 0x0002, 0x0040, 0x2611, 0xa096, 0x000a, 0x00c0, - 0x253d, 0x0078, 0x25e8, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, - 0x1078, 0x3722, 0x00c0, 0x2621, 0x7007, 0x0003, 0x701b, 0x2623, - 0x007c, 0x1078, 0x3b0a, 0x127e, 0x2091, 0x8000, 0x20a9, 0x0005, - 0x2099, 0x7674, 0x530a, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, - 0x0000, 0xa5a9, 0x0000, 0xad80, 0x000d, 0x2009, 0x0020, 0x127f, - 0x0078, 0x2d37, 0x6198, 0x7824, 0x609a, 0x0078, 0x2513, 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, 0x253d, 0x1078, - 0x2d13, 0x0040, 0x2541, 0x7c28, 0x7d2c, 0x1078, 0x3969, 0xd28c, - 0x00c0, 0x267e, 0x1078, 0x38f9, 0x0078, 0x2680, 0x1078, 0x3935, - 0x00c0, 0x26aa, 0x2061, 0x7d00, 0x127e, 0x2091, 0x8000, 0x6000, - 0xa086, 0x0000, 0x0040, 0x2698, 0x6010, 0xa06d, 0x0040, 0x2698, - 0x683c, 0xa406, 0x00c0, 0x2698, 0x6840, 0xa506, 0x0040, 0x26a3, - 0x127f, 0xace0, 0x0008, 0x2001, 0x7615, 0x2004, 0xac02, 0x00c8, - 0x253d, 0x0078, 0x2684, 0x1078, 0x6738, 0x127f, 0x0040, 0x253d, - 0x0078, 0x2513, 0xa00e, 0x2001, 0x0005, 0x1078, 0x3b0a, 0x127e, - 0x2091, 0x8000, 0x1078, 0x6b47, 0x1078, 0x3a7a, 0x127f, 0x0078, - 0x2513, 0x81ff, 0x00c0, 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541, - 0x1078, 0x38ae, 0x1078, 0x397a, 0x0040, 0x253d, 0x0078, 0x2513, - 0x81ff, 0x00c0, 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541, 0x2031, - 0x000f, 0x1078, 0x38ae, 0x8631, 0x00c8, 0x26d1, 0x2019, 0x0005, - 0x1078, 0x399b, 0x0040, 0x253d, 0x7828, 0xa08a, 0x1000, 0x00c8, - 0x2541, 0x8003, 0x800b, 0x810b, 0xa108, 0x1078, 0x457b, 0x0078, - 0x2513, 0x127e, 0x2091, 0x8000, 0x81ff, 0x00c0, 0x2719, 0x2029, - 0x00ff, 0x644c, 0x2400, 0xa506, 0x0040, 0x2713, 0x2508, 0x1078, - 0x3825, 0x00c0, 0x2713, 0x2031, 0x000f, 0x1078, 0x38ae, 0x8631, - 0x00c8, 0x26fd, 0x2019, 0x0004, 0x1078, 0x399b, 0x0040, 0x2719, - 0x7824, 0xa08a, 0x1000, 0x00c8, 0x271c, 0x8003, 0x800b, 0x810b, - 0xa108, 0x1078, 0x457b, 0x8529, 0x00c8, 0x26f2, 0x127f, 0x0078, - 0x2513, 0x127f, 0x0078, 0x253d, 0x127f, 0x0078, 0x2541, 0x1078, - 0x2d13, 0x0040, 0x2541, 0x1078, 0x38de, 0x1078, 0x3969, 0x0078, - 0x2513, 0x81ff, 0x00c0, 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541, - 0x1078, 0x38c7, 0x1078, 0x3969, 0x0078, 0x2513, 0x81ff, 0x00c0, - 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541, 0x1078, 0x3938, 0x0040, - 0x253d, 0x1078, 0x376a, 0x1078, 0x38f2, 0x1078, 0x3969, 0x0078, - 0x2513, 0x1078, 0x2d13, 0x0040, 0x2541, 0x1078, 0x38ae, 0x62a0, - 0x2019, 0x0005, 0x0c7e, 0x1078, 0x39a6, 0x0c7f, 0x1078, 0x4962, - 0x1078, 0x48a5, 0x2c08, 0x1078, 0x737b, 0x1078, 0x3969, 0x0078, - 0x2513, 0x1078, 0x2d13, 0x0040, 0x2541, 0x1078, 0x3969, 0x2208, - 0x0078, 0x2513, 0x157e, 0x0d7e, 0x0e7e, 0x2069, 0x76ff, 0x6810, - 0x6914, 0xa10a, 0x00c8, 0x2776, 0x2009, 0x0000, 0x6816, 0x2011, - 0x0000, 0x2019, 0x0000, 0x20a9, 0x007e, 0x2069, 0x7720, 0x2d04, - 0xa075, 0x0040, 0x278b, 0x704c, 0x1078, 0x2795, 0xa210, 0x7080, - 0x1078, 0x2795, 0xa318, 0x8d68, 0x00f0, 0x277f, 0x2300, 0xa218, - 0x0e7f, 0x0d7f, 0x157f, 0x0078, 0x2513, 0x0f7e, 0x017e, 0xa07d, - 0x0040, 0x27a4, 0x2001, 0x0000, 0x8000, 0x2f0c, 0x81ff, 0x0040, - 0x27a4, 0x2178, 0x0078, 0x279c, 0x017f, 0x0f7f, 0x007c, 0x2069, - 0x76ff, 0x6910, 0x629c, 0x0078, 0x2513, 0x81ff, 0x00c0, 0x253d, - 0x614c, 0xa190, 0x232f, 0x2214, 0xa294, 0x00ff, 0x6068, 0xa084, - 0xff00, 0xa215, 0x6364, 0x0078, 0x2513, 0x613c, 0x6240, 0x0078, - 0x2513, 0x1078, 0x2d13, 0x0040, 0x2541, 0x0078, 0x2513, 0x1078, - 0x2d13, 0x0040, 0x2541, 0x6244, 0x6338, 0x0078, 0x2513, 0x613c, - 0x6240, 0x7824, 0x603e, 0x7b28, 0x6342, 0x2069, 0x7651, 0x831f, - 0xa305, 0x6816, 0x0078, 0x2513, 0x1078, 0x2d13, 0x0040, 0x2541, - 0x0078, 0x2513, 0x1078, 0x2d13, 0x0040, 0x2541, 0x7828, 0xa00d, - 0x0040, 0x2541, 0x782c, 0xa005, 0x0040, 0x2541, 0x6244, 0x6146, - 0x6338, 0x603a, 0x0078, 0x2513, 0x7d38, 0x7c3c, 0x0078, 0x25c0, - 0x7824, 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x00c8, 0x253d, 0x624c, - 0xa084, 0xff00, 0x8007, 0xa206, 0x00c0, 0x2810, 0x2001, 0x7640, - 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x2d37, - 0x81ff, 0x00c0, 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541, 0x6004, - 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x253d, 0x0c7e, 0x1078, - 0x2cfb, 0x0c7f, 0x0040, 0x253d, 0x6837, 0x0000, 0x6838, 0xc0fd, - 0x683a, 0x1078, 0x6a41, 0x0040, 0x253d, 0x7007, 0x0003, 0x701b, - 0x2832, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x253d, 0xad80, - 0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, - 0x2d37, 0x1078, 0x2cfb, 0x0040, 0x253d, 0x2009, 0x001c, 0x7a2c, - 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x2d33, 0x701b, 0x2850, 0x007c, - 0xade8, 0x000d, 0x6800, 0xa005, 0x0040, 0x2541, 0x6804, 0xd0ac, - 0x0040, 0x285d, 0xd0a4, 0x0040, 0x2541, 0xd094, 0x0040, 0x2868, - 0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18c, 0xffdf, 0x6106, 0x0c7f, - 0xd08c, 0x0040, 0x2873, 0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18d, - 0x0010, 0x6106, 0x0c7f, 0x2009, 0x0100, 0x210c, 0xa18a, 0x0002, - 0x0048, 0x2888, 0xd084, 0x0040, 0x2888, 0x6a28, 0xa28a, 0x007f, - 0x00c8, 0x2541, 0xa288, 0x232f, 0x210c, 0xa18c, 0x00ff, 0x6152, - 0xd0dc, 0x0040, 0x2891, 0x6828, 0xa08a, 0x007f, 0x00c8, 0x2541, - 0x604e, 0x6808, 0xa08a, 0x0100, 0x0048, 0x2541, 0xa08a, 0x0841, - 0x00c8, 0x2541, 0xa084, 0x0007, 0x00c0, 0x2541, 0x680c, 0xa005, - 0x0040, 0x2541, 0x6810, 0xa005, 0x0040, 0x2541, 0x6848, 0x6940, - 0xa10a, 0x00c8, 0x2541, 0x8001, 0x0040, 0x2541, 0x684c, 0x6944, - 0xa10a, 0x00c8, 0x2541, 0x8001, 0x0040, 0x2541, 0x20a9, 0x001c, - 0x2d98, 0x2069, 0x7651, 0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff, - 0x613e, 0x8007, 0xa084, 0x00ff, 0x6042, 0x1078, 0x3c71, 0x1078, - 0x3a47, 0x6000, 0xa086, 0x0000, 0x00c0, 0x290c, 0x6808, 0x602a, - 0x1078, 0x1dea, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, - 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, - 0x0040, 0x28ec, 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, - 0x8217, 0x831f, 0x0078, 0x28ee, 0xa084, 0xf0ff, 0x6006, 0x610a, - 0x620e, 0x6312, 0x1078, 0x4607, 0x0c7e, 0x2061, 0x0100, 0x602f, - 0x0040, 0x602f, 0x0000, 0x0c7f, 0x60b4, 0xa005, 0x0040, 0x2908, - 0x6003, 0x0001, 0x2091, 0x301d, 0x1078, 0x357b, 0x0078, 0x290c, - 0x6003, 0x0004, 0x2091, 0x301d, 0x0078, 0x2513, 0x6000, 0xa086, - 0x0000, 0x0040, 0x253d, 0x2069, 0x7651, 0x7830, 0x6842, 0x7834, - 0x6846, 0x2d00, 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, - 0x0078, 0x2d37, 0x81ff, 0x00c0, 0x253d, 0x1078, 0x357b, 0x0078, - 0x2513, 0x81ff, 0x00c0, 0x253d, 0x617c, 0x81ff, 0x0040, 0x2943, - 0x703f, 0x0000, 0x2001, 0x7cc0, 0x2009, 0x0040, 0x7a2c, 0x7b28, - 0x7c3c, 0x7d38, 0x127e, 0x2091, 0x8000, 0x1078, 0x2d37, 0x701b, - 0x2510, 0x127f, 0x007c, 0x703f, 0x0001, 0x0d7e, 0x2069, 0x7cc0, - 0x20a9, 0x0040, 0x20a1, 0x7cc0, 0x2019, 0xffff, 0x43a4, 0x654c, - 0xa588, 0x232f, 0x210c, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, - 0x0002, 0x2100, 0xa506, 0x0040, 0x2975, 0x1078, 0x3825, 0x00c0, - 0x2975, 0x6014, 0x821c, 0x0048, 0x296d, 0xa398, 0x7cc0, 0xa085, - 0xff00, 0x8007, 0x201a, 0x0078, 0x2974, 0xa398, 0x7cc0, 0x2324, - 0xa4a4, 0xff00, 0xa405, 0x201a, 0x8210, 0x8108, 0xa182, 0x0080, - 0x00c8, 0x297c, 0x0078, 0x2959, 0x8201, 0x8007, 0x2d0c, 0xa105, - 0x206a, 0x0d7f, 0x20a9, 0x0040, 0x20a1, 0x7cc0, 0x2099, 0x7cc0, - 0x1078, 0x35c4, 0x0078, 0x2932, 0x1078, 0x2d13, 0x0040, 0x2541, - 0x0c7e, 0x1078, 0x2cfb, 0x0c7f, 0x0040, 0x253d, 0x2001, 0x7652, - 0x2004, 0xd0b4, 0x0040, 0x29b9, 0x6000, 0xd08c, 0x00c0, 0x29b9, - 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x29b9, 0x6837, - 0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x6a79, 0x0040, 0x253d, - 0x7007, 0x0003, 0x701b, 0x29b5, 0x007c, 0x1078, 0x2d13, 0x0040, - 0x2541, 0x20a9, 0x0029, 0x2c98, 0xade8, 0x0002, 0x2da0, 0x53a3, - 0x20a9, 0x0002, 0xac80, 0x0004, 0x2098, 0xad80, 0x0004, 0x20a0, - 0x1078, 0x35c4, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, 0xad80, - 0x0006, 0x20a0, 0x1078, 0x35c4, 0x20a9, 0x0004, 0xac80, 0x000a, - 0x2098, 0xad80, 0x000a, 0x20a0, 0x1078, 0x35c4, 0x2d00, 0x2009, - 0x0029, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x2d37, 0x81ff, - 0x00c0, 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541, 0x1078, 0x3985, - 0x0078, 0x2513, 0x81ff, 0x00c0, 0x253d, 0x7828, 0xa08a, 0x1000, - 0x00c8, 0x2541, 0x1078, 0x2d13, 0x0040, 0x2541, 0x2031, 0x000f, - 0x1078, 0x38ae, 0x8631, 0x00c8, 0x2a00, 0x2019, 0x0004, 0x1078, - 0x399b, 0x7924, 0x810f, 0x7a28, 0x1078, 0x2a10, 0x0078, 0x2513, - 0xa186, 0x00ff, 0x0040, 0x2a18, 0x1078, 0x2a28, 0x0078, 0x2a27, + 0x8000, 0x2071, 0x766d, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, + 0x703a, 0x703e, 0x7033, 0x767d, 0x7037, 0x767d, 0x7007, 0x0001, + 0x2061, 0x76bd, 0x6003, 0x0002, 0x007c, 0x0090, 0x2450, 0x0068, + 0x2450, 0x2071, 0x766d, 0x2b78, 0x7818, 0xd084, 0x00c0, 0x2450, + 0x2a60, 0x7820, 0xa08e, 0x0069, 0x00c0, 0x2537, 0x0079, 0x24d4, + 0x007c, 0x2071, 0x766d, 0x7004, 0x0079, 0x2456, 0x245a, 0x245b, + 0x2465, 0x2477, 0x007c, 0x0090, 0x2464, 0x0068, 0x2464, 0x2b78, + 0x7818, 0xd084, 0x0040, 0x2483, 0x007c, 0x2b78, 0x2061, 0x76bd, + 0x6008, 0xa08e, 0x0100, 0x0040, 0x2472, 0xa086, 0x0200, 0x0040, + 0x252f, 0x007c, 0x7014, 0x2068, 0x2a60, 0x7018, 0x007a, 0x7010, + 0x2068, 0x6834, 0xa086, 0x0103, 0x0040, 0x247f, 0x007c, 0x2a60, + 0x2b78, 0x7018, 0x007a, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x00c8, + 0x248c, 0x61b0, 0x0079, 0x2494, 0x2100, 0xa08a, 0x0036, 0x00c8, + 0x252b, 0x61b0, 0x0079, 0x24d4, 0x250d, 0x253f, 0x2547, 0x254b, + 0x2553, 0x2559, 0x255d, 0x2566, 0x256a, 0x2572, 0x2576, 0x252b, + 0x252b, 0x252b, 0x257a, 0x252b, 0x258a, 0x25a1, 0x25b8, 0x2634, + 0x2639, 0x2666, 0x26b3, 0x26c2, 0x26e3, 0x2719, 0x2723, 0x2730, + 0x2743, 0x275b, 0x2764, 0x27a1, 0x27a7, 0x252b, 0x27b7, 0x252b, + 0x252b, 0x252b, 0x252b, 0x252b, 0x27bb, 0x27c1, 0x252b, 0x252b, + 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x27c9, 0x252b, + 0x252b, 0x252b, 0x252b, 0x252b, 0x27d6, 0x27dc, 0x252b, 0x252b, + 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, + 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, + 0x252b, 0x252b, 0x252b, 0x252b, 0x2572, 0x2576, 0x252b, 0x252b, + 0x27ee, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, + 0x252b, 0x252b, 0x252b, 0x252b, 0x283b, 0x2908, 0x291c, 0x2923, + 0x2986, 0x29d7, 0x29e2, 0x2a24, 0x2a31, 0x2a3e, 0x2a41, 0x27f2, + 0x2a6a, 0x2ab1, 0x2abe, 0x2bb9, 0x2ca7, 0x2cce, 0x2dc6, 0x2dd4, + 0x2de1, 0x2e1b, 0x713c, 0x0078, 0x250d, 0x2021, 0x4000, 0x1078, + 0x2d15, 0x127e, 0x2091, 0x8000, 0x0068, 0x251a, 0x7818, 0xd084, + 0x0040, 0x251d, 0x127f, 0x0078, 0x2511, 0x781b, 0x0001, 0x7c22, + 0x7926, 0x7a2a, 0x7b2e, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, + 0x5000, 0x127f, 0x007c, 0x2021, 0x4001, 0x0078, 0x250f, 0x2021, + 0x4002, 0x0078, 0x250f, 0x2021, 0x4003, 0x0078, 0x250f, 0x2021, + 0x4005, 0x0078, 0x250f, 0x2021, 0x4006, 0x0078, 0x250f, 0xa02e, + 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0078, 0x2d24, 0x7823, + 0x0004, 0x7824, 0x007a, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, + 0x7930, 0x0078, 0x2d28, 0x7924, 0x7828, 0x2114, 0x200a, 0x0078, + 0x250d, 0x7924, 0x2114, 0x0078, 0x250d, 0x2099, 0x0009, 0x20a1, + 0x0009, 0x20a9, 0x0007, 0x53a3, 0x0078, 0x250d, 0x7824, 0x2060, + 0x0078, 0x257c, 0x2009, 0x0001, 0x2011, 0x000f, 0x2019, 0x0025, + 0x0078, 0x250d, 0x7d38, 0x7c3c, 0x0078, 0x2541, 0x7d38, 0x7c3c, + 0x0078, 0x254d, 0x2061, 0x1000, 0x610c, 0xa006, 0x2c14, 0xa200, + 0x8c60, 0x8109, 0x00c0, 0x257e, 0x2010, 0xa005, 0x0040, 0x250d, + 0x0078, 0x2533, 0x2061, 0x7651, 0x7824, 0x7930, 0xa11a, 0x00c8, + 0x253b, 0x8019, 0x0040, 0x253b, 0x604a, 0x6142, 0x782c, 0x6052, + 0x7828, 0x6056, 0xa006, 0x605a, 0x605e, 0x1078, 0x3c69, 0x0078, + 0x250d, 0x2061, 0x7651, 0x7824, 0x7930, 0xa11a, 0x00c8, 0x253b, + 0x8019, 0x0040, 0x253b, 0x604e, 0x6146, 0x782c, 0x6062, 0x7828, + 0x6066, 0xa006, 0x606a, 0x606e, 0x1078, 0x3a3f, 0x0078, 0x250d, + 0xa02e, 0x2520, 0x81ff, 0x00c0, 0x2537, 0x7924, 0x7b28, 0x7a2c, + 0x20a9, 0x0005, 0x20a1, 0x7674, 0x41a1, 0x1078, 0x2cec, 0x0040, + 0x2537, 0x2009, 0x0020, 0x1078, 0x2d24, 0x701b, 0x25d0, 0x007c, + 0x6834, 0x2008, 0xa084, 0x00ff, 0xa096, 0x0011, 0x0040, 0x25dc, + 0xa096, 0x0019, 0x00c0, 0x2537, 0x810f, 0xa18c, 0x00ff, 0x0040, + 0x2537, 0x710e, 0x700c, 0x8001, 0x0040, 0x260d, 0x700e, 0x1078, + 0x2cec, 0x0040, 0x2537, 0x2009, 0x0020, 0x2061, 0x76bd, 0x6224, + 0x6328, 0x642c, 0x6530, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, + 0x0000, 0xa5a9, 0x0000, 0x1078, 0x2d24, 0x701b, 0x2600, 0x007c, + 0x6834, 0xa084, 0x00ff, 0xa096, 0x0002, 0x0040, 0x260b, 0xa096, + 0x000a, 0x00c0, 0x2537, 0x0078, 0x25e2, 0x7010, 0x2068, 0x6838, + 0xc0fd, 0x683a, 0x1078, 0x371a, 0x00c0, 0x261b, 0x7007, 0x0003, + 0x701b, 0x261d, 0x007c, 0x1078, 0x3b02, 0x127e, 0x2091, 0x8000, + 0x20a9, 0x0005, 0x2099, 0x7674, 0x530a, 0x2100, 0xa210, 0xa399, + 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0xad80, 0x000d, 0x2009, + 0x0020, 0x127f, 0x0078, 0x2d28, 0x6198, 0x7824, 0x609a, 0x0078, + 0x250d, 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, + 0x2537, 0x1078, 0x2d04, 0x0040, 0x253b, 0x7c28, 0x7d2c, 0x1078, + 0x3961, 0xd28c, 0x00c0, 0x2678, 0x1078, 0x38f1, 0x0078, 0x267a, + 0x1078, 0x392d, 0x00c0, 0x26a4, 0x2061, 0x7d00, 0x127e, 0x2091, + 0x8000, 0x6000, 0xa086, 0x0000, 0x0040, 0x2692, 0x6010, 0xa06d, + 0x0040, 0x2692, 0x683c, 0xa406, 0x00c0, 0x2692, 0x6840, 0xa506, + 0x0040, 0x269d, 0x127f, 0xace0, 0x0008, 0x2001, 0x7615, 0x2004, + 0xac02, 0x00c8, 0x2537, 0x0078, 0x267e, 0x1078, 0x6732, 0x127f, + 0x0040, 0x2537, 0x0078, 0x250d, 0xa00e, 0x2001, 0x0005, 0x1078, + 0x3b02, 0x127e, 0x2091, 0x8000, 0x1078, 0x6b3c, 0x1078, 0x3a72, + 0x127f, 0x0078, 0x250d, 0x81ff, 0x00c0, 0x2537, 0x1078, 0x2d04, + 0x0040, 0x253b, 0x1078, 0x38a6, 0x1078, 0x3972, 0x0040, 0x2537, + 0x0078, 0x250d, 0x81ff, 0x00c0, 0x2537, 0x1078, 0x2d04, 0x0040, + 0x253b, 0x2031, 0x000f, 0x1078, 0x38a6, 0x8631, 0x00c8, 0x26cb, + 0x2019, 0x0005, 0x1078, 0x3993, 0x0040, 0x2537, 0x7828, 0xa08a, + 0x1000, 0x00c8, 0x253b, 0x8003, 0x800b, 0x810b, 0xa108, 0x1078, + 0x4573, 0x0078, 0x250d, 0x127e, 0x2091, 0x8000, 0x81ff, 0x00c0, + 0x2713, 0x2029, 0x00ff, 0x644c, 0x2400, 0xa506, 0x0040, 0x270d, + 0x2508, 0x1078, 0x381d, 0x00c0, 0x270d, 0x2031, 0x000f, 0x1078, + 0x38a6, 0x8631, 0x00c8, 0x26f7, 0x2019, 0x0004, 0x1078, 0x3993, + 0x0040, 0x2713, 0x7824, 0xa08a, 0x1000, 0x00c8, 0x2716, 0x8003, + 0x800b, 0x810b, 0xa108, 0x1078, 0x4573, 0x8529, 0x00c8, 0x26ec, + 0x127f, 0x0078, 0x250d, 0x127f, 0x0078, 0x2537, 0x127f, 0x0078, + 0x253b, 0x1078, 0x2d04, 0x0040, 0x253b, 0x1078, 0x38d6, 0x1078, + 0x3961, 0x0078, 0x250d, 0x81ff, 0x00c0, 0x2537, 0x1078, 0x2d04, + 0x0040, 0x253b, 0x1078, 0x38bf, 0x1078, 0x3961, 0x0078, 0x250d, + 0x81ff, 0x00c0, 0x2537, 0x1078, 0x2d04, 0x0040, 0x253b, 0x1078, + 0x3930, 0x0040, 0x2537, 0x1078, 0x3762, 0x1078, 0x38ea, 0x1078, + 0x3961, 0x0078, 0x250d, 0x1078, 0x2d04, 0x0040, 0x253b, 0x1078, + 0x38a6, 0x62a0, 0x2019, 0x0005, 0x0c7e, 0x1078, 0x399e, 0x0c7f, + 0x1078, 0x495a, 0x1078, 0x489d, 0x2c08, 0x1078, 0x7370, 0x1078, + 0x3961, 0x0078, 0x250d, 0x1078, 0x2d04, 0x0040, 0x253b, 0x1078, + 0x3961, 0x2208, 0x0078, 0x250d, 0x157e, 0x0d7e, 0x0e7e, 0x2069, + 0x76ff, 0x6810, 0x6914, 0xa10a, 0x00c8, 0x2770, 0x2009, 0x0000, + 0x6816, 0x2011, 0x0000, 0x2019, 0x0000, 0x20a9, 0x007e, 0x2069, + 0x7720, 0x2d04, 0xa075, 0x0040, 0x2785, 0x704c, 0x1078, 0x278f, + 0xa210, 0x7080, 0x1078, 0x278f, 0xa318, 0x8d68, 0x00f0, 0x2779, + 0x2300, 0xa218, 0x0e7f, 0x0d7f, 0x157f, 0x0078, 0x250d, 0x0f7e, + 0x017e, 0xa07d, 0x0040, 0x279e, 0x2001, 0x0000, 0x8000, 0x2f0c, + 0x81ff, 0x0040, 0x279e, 0x2178, 0x0078, 0x2796, 0x017f, 0x0f7f, + 0x007c, 0x2069, 0x76ff, 0x6910, 0x629c, 0x0078, 0x250d, 0x81ff, + 0x00c0, 0x2537, 0x614c, 0xa190, 0x2329, 0x2214, 0xa294, 0x00ff, + 0x6068, 0xa084, 0xff00, 0xa215, 0x6364, 0x0078, 0x250d, 0x613c, + 0x6240, 0x0078, 0x250d, 0x1078, 0x2d04, 0x0040, 0x253b, 0x0078, + 0x250d, 0x1078, 0x2d04, 0x0040, 0x253b, 0x6244, 0x6338, 0x0078, + 0x250d, 0x613c, 0x6240, 0x7824, 0x603e, 0x7b28, 0x6342, 0x2069, + 0x7651, 0x831f, 0xa305, 0x6816, 0x0078, 0x250d, 0x1078, 0x2d04, + 0x0040, 0x253b, 0x0078, 0x250d, 0x1078, 0x2d04, 0x0040, 0x253b, + 0x7828, 0xa00d, 0x0040, 0x253b, 0x782c, 0xa005, 0x0040, 0x253b, + 0x6244, 0x6146, 0x6338, 0x603a, 0x0078, 0x250d, 0x7d38, 0x7c3c, + 0x0078, 0x25ba, 0x7824, 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x00c8, + 0x2537, 0x624c, 0xa084, 0xff00, 0x8007, 0xa206, 0x00c0, 0x280a, + 0x2001, 0x7640, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, + 0x0078, 0x2d28, 0x81ff, 0x00c0, 0x2537, 0x1078, 0x2d04, 0x0040, + 0x253b, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2537, + 0x0c7e, 0x1078, 0x2cec, 0x0c7f, 0x0040, 0x2537, 0x6837, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x1078, 0x6a36, 0x0040, 0x2537, 0x7007, + 0x0003, 0x701b, 0x282c, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, + 0x2537, 0xad80, 0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x0078, 0x2d28, 0x1078, 0x2cec, 0x0040, 0x2537, 0x2009, + 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x2d24, 0x701b, + 0x284a, 0x007c, 0xade8, 0x000d, 0x6800, 0xa005, 0x0040, 0x253b, + 0x6804, 0xd0ac, 0x0040, 0x2857, 0xd0a4, 0x0040, 0x253b, 0xd094, + 0x0040, 0x2862, 0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18c, 0xffdf, + 0x6106, 0x0c7f, 0xd08c, 0x0040, 0x286d, 0x0c7e, 0x2061, 0x0100, + 0x6104, 0xa18d, 0x0010, 0x6106, 0x0c7f, 0x2009, 0x0100, 0x210c, + 0xa18a, 0x0002, 0x0048, 0x2882, 0xd084, 0x0040, 0x2882, 0x6a28, + 0xa28a, 0x007f, 0x00c8, 0x253b, 0xa288, 0x2329, 0x210c, 0xa18c, + 0x00ff, 0x6152, 0xd0dc, 0x0040, 0x288b, 0x6828, 0xa08a, 0x007f, + 0x00c8, 0x253b, 0x604e, 0x6808, 0xa08a, 0x0100, 0x0048, 0x253b, + 0xa08a, 0x0841, 0x00c8, 0x253b, 0xa084, 0x0007, 0x00c0, 0x253b, + 0x680c, 0xa005, 0x0040, 0x253b, 0x6810, 0xa005, 0x0040, 0x253b, + 0x6848, 0x6940, 0xa10a, 0x00c8, 0x253b, 0x8001, 0x0040, 0x253b, + 0x684c, 0x6944, 0xa10a, 0x00c8, 0x253b, 0x8001, 0x0040, 0x253b, + 0x20a9, 0x001c, 0x2d98, 0x2069, 0x7651, 0x2da0, 0x53a3, 0x6814, + 0xa08c, 0x00ff, 0x613e, 0x8007, 0xa084, 0x00ff, 0x6042, 0x1078, + 0x3c69, 0x1078, 0x3a3f, 0x6000, 0xa086, 0x0000, 0x00c0, 0x2906, + 0x6808, 0x602a, 0x1078, 0x1de4, 0x6818, 0x691c, 0x6a20, 0x6b24, + 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, + 0x6c04, 0xd4f4, 0x0040, 0x28e6, 0x6830, 0x6934, 0x6a38, 0x6b3c, + 0x8007, 0x810f, 0x8217, 0x831f, 0x0078, 0x28e8, 0xa084, 0xf0ff, + 0x6006, 0x610a, 0x620e, 0x6312, 0x1078, 0x45ff, 0x0c7e, 0x2061, + 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x0c7f, 0x60b4, 0xa005, + 0x0040, 0x2902, 0x6003, 0x0001, 0x2091, 0x301d, 0x1078, 0x3573, + 0x0078, 0x2906, 0x6003, 0x0004, 0x2091, 0x301d, 0x0078, 0x250d, + 0x6000, 0xa086, 0x0000, 0x0040, 0x2537, 0x2069, 0x7651, 0x7830, + 0x6842, 0x7834, 0x6846, 0x2d00, 0x2009, 0x001c, 0x7a2c, 0x7b28, + 0x7c3c, 0x7d38, 0x0078, 0x2d28, 0x81ff, 0x00c0, 0x2537, 0x1078, + 0x3573, 0x0078, 0x250d, 0x81ff, 0x00c0, 0x2537, 0x617c, 0x81ff, + 0x0040, 0x293d, 0x703f, 0x0000, 0x2001, 0x7cc0, 0x2009, 0x0040, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x127e, 0x2091, 0x8000, 0x1078, + 0x2d28, 0x701b, 0x250a, 0x127f, 0x007c, 0x703f, 0x0001, 0x0d7e, + 0x2069, 0x7cc0, 0x20a9, 0x0040, 0x20a1, 0x7cc0, 0x2019, 0xffff, + 0x43a4, 0x654c, 0xa588, 0x2329, 0x210c, 0xa18c, 0x00ff, 0x216a, + 0xa00e, 0x2011, 0x0002, 0x2100, 0xa506, 0x0040, 0x296f, 0x1078, + 0x381d, 0x00c0, 0x296f, 0x6014, 0x821c, 0x0048, 0x2967, 0xa398, + 0x7cc0, 0xa085, 0xff00, 0x8007, 0x201a, 0x0078, 0x296e, 0xa398, + 0x7cc0, 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a, 0x8210, 0x8108, + 0xa182, 0x0080, 0x00c8, 0x2976, 0x0078, 0x2953, 0x8201, 0x8007, + 0x2d0c, 0xa105, 0x206a, 0x0d7f, 0x20a9, 0x0040, 0x20a1, 0x7cc0, + 0x2099, 0x7cc0, 0x1078, 0x35bc, 0x0078, 0x292c, 0x1078, 0x2d04, + 0x0040, 0x253b, 0x0c7e, 0x1078, 0x2cec, 0x0c7f, 0x0040, 0x2537, + 0x2001, 0x7652, 0x2004, 0xd0b4, 0x0040, 0x29b3, 0x6000, 0xd08c, + 0x00c0, 0x29b3, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, + 0x29b3, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x6a6e, + 0x0040, 0x2537, 0x7007, 0x0003, 0x701b, 0x29af, 0x007c, 0x1078, + 0x2d04, 0x0040, 0x253b, 0x20a9, 0x0029, 0x2c98, 0xade8, 0x0002, + 0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, 0xad80, + 0x0006, 0x20a0, 0x1078, 0x35bc, 0x20a9, 0x0004, 0xac80, 0x000a, + 0x2098, 0xad80, 0x000a, 0x20a0, 0x1078, 0x35bc, 0x2d00, 0x2009, + 0x0029, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x2d28, 0x81ff, + 0x00c0, 0x2537, 0x1078, 0x2d04, 0x0040, 0x253b, 0x1078, 0x397d, + 0x0078, 0x250d, 0x81ff, 0x00c0, 0x2537, 0x7828, 0xa08a, 0x1000, + 0x00c8, 0x253b, 0x1078, 0x2d04, 0x0040, 0x253b, 0x2031, 0x000f, + 0x1078, 0x38a6, 0x8631, 0x00c8, 0x29f0, 0x2019, 0x0004, 0x1078, + 0x3993, 0x7924, 0x810f, 0x7a28, 0x1078, 0x2a00, 0x0078, 0x250d, + 0xa186, 0x00ff, 0x0040, 0x2a08, 0x1078, 0x2a18, 0x0078, 0x2a17, 0x2029, 0x007e, 0x2061, 0x7600, 0x644c, 0x2400, 0xa506, 0x0040, - 0x2a24, 0x2508, 0x1078, 0x2a28, 0x8529, 0x00c8, 0x2a1d, 0x007c, - 0x1078, 0x3825, 0x00c0, 0x2a33, 0x2200, 0x8003, 0x800b, 0x810b, - 0xa108, 0x1078, 0x457b, 0x007c, 0x81ff, 0x00c0, 0x253d, 0x1078, - 0x2d13, 0x0040, 0x2541, 0x1078, 0x38ae, 0x1078, 0x3990, 0x0078, - 0x2513, 0x81ff, 0x00c0, 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541, - 0x1078, 0x38ae, 0x1078, 0x397a, 0x0078, 0x2513, 0x6100, 0x0078, - 0x2513, 0x1078, 0x2d13, 0x0040, 0x2541, 0x6004, 0xa086, 0x0707, - 0x0040, 0x2541, 0x2001, 0x7600, 0x2004, 0xa086, 0x0003, 0x00c0, - 0x253d, 0x0d7e, 0xace8, 0x000a, 0x7924, 0xd184, 0x0040, 0x2a6a, + 0x2a14, 0x2508, 0x1078, 0x2a18, 0x8529, 0x00c8, 0x2a0d, 0x007c, + 0x1078, 0x381d, 0x00c0, 0x2a23, 0x2200, 0x8003, 0x800b, 0x810b, + 0xa108, 0x1078, 0x4573, 0x007c, 0x81ff, 0x00c0, 0x2537, 0x1078, + 0x2d04, 0x0040, 0x253b, 0x1078, 0x38a6, 0x1078, 0x3988, 0x0078, + 0x250d, 0x81ff, 0x00c0, 0x2537, 0x1078, 0x2d04, 0x0040, 0x253b, + 0x1078, 0x38a6, 0x1078, 0x3972, 0x0078, 0x250d, 0x6100, 0x0078, + 0x250d, 0x1078, 0x2d04, 0x0040, 0x253b, 0x6004, 0xa086, 0x0707, + 0x0040, 0x253b, 0x2001, 0x7600, 0x2004, 0xa086, 0x0003, 0x00c0, + 0x2537, 0x0d7e, 0xace8, 0x000a, 0x7924, 0xd184, 0x0040, 0x2a5a, 0xace8, 0x0006, 0x680c, 0x8007, 0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f, 0x6a00, 0x8217, 0x0d7f, 0x6100, 0xa18c, 0x0200, - 0x0078, 0x2513, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff, 0x0040, - 0x2a84, 0x81ff, 0x00c0, 0x253d, 0x7828, 0xa08a, 0x1000, 0x00c8, - 0x2541, 0x7924, 0xa18c, 0xff00, 0x810f, 0xa186, 0x00ff, 0x0040, - 0x2a98, 0xa182, 0x007f, 0x00c8, 0x2541, 0x2100, 0x1078, 0x209a, + 0x0078, 0x250d, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff, 0x0040, + 0x2a74, 0x81ff, 0x00c0, 0x2537, 0x7828, 0xa08a, 0x1000, 0x00c8, + 0x253b, 0x7924, 0xa18c, 0xff00, 0x810f, 0xa186, 0x00ff, 0x0040, + 0x2a88, 0xa182, 0x007f, 0x00c8, 0x253b, 0x2100, 0x1078, 0x2094, 0x027e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x2061, 0x7849, 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0x0100, 0x6030, 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, - 0x001e, 0x2011, 0x35a0, 0x1078, 0x45fe, 0x7924, 0xa18c, 0xff00, - 0x810f, 0x7a28, 0x1078, 0x2a10, 0x127f, 0x0c7f, 0x027f, 0x0078, - 0x2513, 0x7924, 0xa18c, 0xff00, 0x810f, 0x0c7e, 0x1078, 0x37ee, - 0x2c08, 0x0c7f, 0x00c0, 0x2541, 0x0078, 0x2513, 0x81ff, 0x00c0, - 0x253d, 0x60bc, 0xd09c, 0x0040, 0x253d, 0x1078, 0x2cfb, 0x0040, - 0x253d, 0x6823, 0x0000, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, - 0x1078, 0x2d33, 0x701b, 0x2ae5, 0x007c, 0x2009, 0x0080, 0x1078, - 0x3825, 0x00c0, 0x2af2, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, - 0x0040, 0x2af6, 0x2021, 0x400a, 0x0078, 0x2515, 0x0d7e, 0xade8, + 0x001e, 0x2011, 0x3598, 0x1078, 0x45f6, 0x7924, 0xa18c, 0xff00, + 0x810f, 0x7a28, 0x1078, 0x2a00, 0x127f, 0x0c7f, 0x027f, 0x0078, + 0x250d, 0x7924, 0xa18c, 0xff00, 0x810f, 0x0c7e, 0x1078, 0x37e6, + 0x2c08, 0x0c7f, 0x00c0, 0x253b, 0x0078, 0x250d, 0x81ff, 0x00c0, + 0x2537, 0x60bc, 0xd09c, 0x0040, 0x2537, 0x1078, 0x2cec, 0x0040, + 0x2537, 0x6823, 0x0000, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, + 0x1078, 0x2d24, 0x701b, 0x2ad5, 0x007c, 0x2009, 0x0080, 0x1078, + 0x381d, 0x00c0, 0x2ae2, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x0040, 0x2ae6, 0x2021, 0x400a, 0x0078, 0x250f, 0x0d7e, 0xade8, 0x000d, 0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, - 0xa0be, 0x0100, 0x0040, 0x2b68, 0xa0be, 0x0112, 0x0040, 0x2b68, - 0xa0be, 0x0113, 0x0040, 0x2b68, 0xa0be, 0x0114, 0x0040, 0x2b68, - 0xa0be, 0x0117, 0x0040, 0x2b68, 0xa0be, 0x011a, 0x0040, 0x2b68, - 0xa0be, 0x0121, 0x0040, 0x2b5e, 0xa0be, 0x0131, 0x0040, 0x2b5e, - 0xa0be, 0x0171, 0x0040, 0x2b68, 0xa0be, 0x0173, 0x0040, 0x2b68, - 0xa0be, 0x01a1, 0x00c0, 0x2b31, 0x6830, 0x8007, 0x6832, 0x0078, - 0x2b6e, 0xa0be, 0x0212, 0x0040, 0x2b64, 0xa0be, 0x0213, 0x0040, - 0x2b64, 0xa0be, 0x0214, 0x0040, 0x2b56, 0xa0be, 0x0217, 0x0040, - 0x2b50, 0xa0be, 0x021a, 0x00c0, 0x2b4a, 0x6838, 0x8007, 0x683a, - 0x0078, 0x2b68, 0xa0be, 0x0300, 0x0040, 0x2b68, 0x0078, 0x2541, - 0xad80, 0x0010, 0x20a9, 0x0007, 0x1078, 0x2ba4, 0xad80, 0x000e, - 0x20a9, 0x0001, 0x1078, 0x2ba4, 0x0078, 0x2b68, 0xad80, 0x000c, - 0x1078, 0x2bb2, 0x0078, 0x2b6e, 0xad80, 0x000e, 0x1078, 0x2bb2, - 0xad80, 0x000c, 0x20a9, 0x0001, 0x1078, 0x2ba4, 0x0c7e, 0x1078, - 0x2cfb, 0x0040, 0x2b99, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, - 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883, 0x0000, - 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000, 0x0c7f, - 0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, - 0x1078, 0x6a5d, 0x0040, 0x253d, 0x7007, 0x0003, 0x701b, 0x2b9d, - 0x007c, 0x0c7f, 0x0d7f, 0x0078, 0x253d, 0x6820, 0xa086, 0x8001, - 0x0040, 0x253d, 0x0078, 0x2513, 0x017e, 0x2008, 0x2044, 0x8000, - 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, 0x00f0, 0x2ba6, - 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, 0x00c0, 0x253d, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, - 0xa182, 0x0080, 0x0048, 0x2541, 0xa182, 0x00ff, 0x00c8, 0x2541, - 0x7a2c, 0x7b28, 0x6064, 0xa306, 0x00c0, 0x2be6, 0x6068, 0xa24e, - 0x0040, 0x2541, 0xa9cc, 0xff00, 0x0040, 0x2541, 0x0c7e, 0x1078, - 0x2c5a, 0x2c68, 0x0c7f, 0x0040, 0x2c0d, 0xa0c6, 0x4000, 0x00c0, - 0x2bf3, 0x0078, 0x2c0a, 0xa0c6, 0x4007, 0x00c0, 0x2bfa, 0x2408, - 0x0078, 0x2c0a, 0xa0c6, 0x4008, 0x00c0, 0x2c02, 0x2708, 0x2610, - 0x0078, 0x2c0a, 0xa0c6, 0x4009, 0x00c0, 0x2c08, 0x0078, 0x2c0a, - 0x2001, 0x4006, 0x2020, 0x0078, 0x2515, 0x017e, 0x0b7e, 0x0c7e, - 0x0e7e, 0x2c70, 0x1078, 0x5b9c, 0x0040, 0x2c48, 0x2d00, 0x601a, - 0x2e58, 0x0e7f, 0x0e7e, 0x0c7e, 0x1078, 0x2cfb, 0x0c7f, 0x2b70, - 0x0040, 0x253d, 0x6837, 0x0000, 0x2d00, 0x6012, 0x6833, 0x0000, - 0x6838, 0xc0fd, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x22bb, - 0x127f, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x37bd, 0x2001, - 0x0002, 0x1078, 0x37d1, 0x127e, 0x2091, 0x8000, 0x7088, 0x8000, - 0x708a, 0x127f, 0x2009, 0x0002, 0x1078, 0x5c29, 0xa085, 0x0001, - 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, 0x0040, 0x253d, 0x7007, 0x0003, - 0x701b, 0x2c53, 0x007c, 0x6830, 0xa086, 0x0100, 0x00c0, 0x2513, - 0x0078, 0x253d, 0x0e7e, 0x0d7e, 0x2029, 0x0000, 0x2021, 0x0080, - 0x20a9, 0x007f, 0x2071, 0x77a0, 0x2e04, 0xa005, 0x00c0, 0x2c6e, - 0x2100, 0xa406, 0x0040, 0x2cab, 0x0078, 0x2c9f, 0x2068, 0x6f10, - 0x2700, 0xa306, 0x00c0, 0x2c90, 0x6e14, 0x2600, 0xa206, 0x00c0, - 0x2c90, 0x2400, 0xa106, 0x00c0, 0x2c8c, 0x2d60, 0xd884, 0x0040, - 0x2cb1, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2cb1, - 0x2001, 0x4000, 0x0078, 0x2cb2, 0x2001, 0x4007, 0x0078, 0x2cb2, - 0x2400, 0xa106, 0x00c0, 0x2c9f, 0x6e14, 0x87ff, 0x00c0, 0x2c9b, - 0x86ff, 0x0040, 0x2cab, 0x2001, 0x4008, 0x0078, 0x2cb2, 0x8420, - 0x8e70, 0x00f0, 0x2c64, 0x2001, 0x4009, 0x0078, 0x2cb2, 0x2001, - 0x0001, 0x0078, 0x2cb2, 0x1078, 0x37ee, 0x00c0, 0x2ca7, 0x6312, - 0x6216, 0xa006, 0xa005, 0x0d7f, 0x0e7f, 0x007c, 0x81ff, 0x00c0, - 0x253d, 0x1078, 0x2cfb, 0x0040, 0x253d, 0x6837, 0x0000, 0x7824, - 0xa005, 0x0040, 0x2541, 0xa096, 0x00ff, 0x0040, 0x2ccb, 0xa092, - 0x0004, 0x00c8, 0x2541, 0x2010, 0x2d18, 0x1078, 0x227d, 0x0040, - 0x253d, 0x7007, 0x0003, 0x701b, 0x2cd6, 0x007c, 0x6830, 0xa086, - 0x0100, 0x0040, 0x253d, 0x0078, 0x2513, 0x81ff, 0x00c0, 0x253d, - 0x7924, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080, 0x0048, 0x2541, - 0xa182, 0x00ff, 0x00c8, 0x2541, 0x127e, 0x2091, 0x8000, 0x1078, - 0x697f, 0x00c0, 0x2cf8, 0x1078, 0x380d, 0x127f, 0x0078, 0x2513, - 0x127f, 0x0078, 0x253d, 0x1078, 0x132f, 0x0040, 0x2d12, 0xa006, - 0x6802, 0x7010, 0xa005, 0x00c0, 0x2d0a, 0x2d00, 0x7012, 0x7016, - 0x0078, 0x2d10, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, - 0xad80, 0x000d, 0x007c, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x1078, - 0x3825, 0x00c0, 0x2d21, 0xa6b4, 0x00ff, 0xa682, 0x0010, 0x0048, - 0x2d22, 0xa066, 0x8cff, 0x007c, 0x017e, 0x7110, 0x81ff, 0x0040, - 0x2d2f, 0x2168, 0x6904, 0x1078, 0x1348, 0x0078, 0x2d26, 0x7112, - 0x7116, 0x017f, 0x007c, 0x2031, 0x0001, 0x0078, 0x2d39, 0x2031, - 0x0000, 0x2061, 0x76bd, 0x6606, 0x6112, 0x600e, 0x6226, 0x632a, - 0x642e, 0x6532, 0x2c10, 0x1078, 0x137f, 0x7007, 0x0002, 0x701b, - 0x2513, 0x007c, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079, 0x0000, - 0x2001, 0x767b, 0x2004, 0xa005, 0x00c0, 0x2d65, 0x0068, 0x2d65, - 0x7818, 0xd084, 0x00c0, 0x2d65, 0x781b, 0x0001, 0x7a22, 0x7b26, - 0x7c2a, 0x2091, 0x4080, 0x0078, 0x2d8a, 0x017e, 0x0c7e, 0x0e7e, - 0x2071, 0x766d, 0x7138, 0xa182, 0x0008, 0x0048, 0x2d73, 0x7030, - 0x2060, 0x0078, 0x2d84, 0x7030, 0xa0e0, 0x0008, 0xac82, 0x76bd, - 0x0048, 0x2d7c, 0x2061, 0x767d, 0x2c00, 0x7032, 0x81ff, 0x00c0, - 0x2d82, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, 0x0e7f, - 0x0c7f, 0x017f, 0x127f, 0x0f7f, 0x007c, 0x0e7e, 0x2071, 0x766d, - 0x7038, 0xa005, 0x0040, 0x2dc6, 0x127e, 0x2091, 0x8000, 0x0068, - 0x2dc5, 0x0f7e, 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, 0x2dc4, - 0x0c7e, 0x781b, 0x0001, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, - 0x7826, 0x6008, 0x782a, 0x2091, 0x4080, 0x7038, 0x8001, 0x703a, - 0xa005, 0x00c0, 0x2dba, 0x7033, 0x767d, 0x7037, 0x767d, 0x0c7f, - 0x0078, 0x2dc4, 0xac80, 0x0008, 0xa0fa, 0x76bd, 0x0048, 0x2dc2, - 0x2001, 0x767d, 0x7036, 0x0c7f, 0x0f7f, 0x127f, 0x0e7f, 0x007c, - 0x027e, 0x2001, 0x7652, 0x2004, 0xd0c4, 0x0040, 0x2dd3, 0x2011, - 0x8014, 0x1078, 0x2d4a, 0x027f, 0x007c, 0x81ff, 0x00c0, 0x253d, - 0x127e, 0x2091, 0x8000, 0x6030, 0xc08d, 0x6032, 0x1078, 0x357b, - 0x127f, 0x0078, 0x2513, 0x7824, 0x2008, 0xa18c, 0xfffd, 0x00c0, - 0x2dee, 0x61c8, 0xa10d, 0x61ca, 0x0078, 0x2513, 0x0078, 0x2541, - 0x81ff, 0x00c0, 0x253d, 0x6000, 0xa086, 0x0003, 0x00c0, 0x253d, - 0x2001, 0x7652, 0x2004, 0xd0a4, 0x00c0, 0x253d, 0x1078, 0x2d13, - 0x0040, 0x2541, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, - 0x2e0d, 0x7828, 0xa005, 0x0040, 0x2513, 0x0c7e, 0x1078, 0x2cfb, - 0x0c7f, 0x0040, 0x253d, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, - 0xc0fd, 0x683a, 0x1078, 0x6ae6, 0x0040, 0x253d, 0x7007, 0x0003, - 0x701b, 0x2e23, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x253d, - 0x0078, 0x2513, 0x2001, 0x7600, 0x2004, 0xa086, 0x0003, 0x00c0, - 0x253d, 0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x2cfb, - 0x0040, 0x253d, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, - 0x702f, 0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x1078, 0x3825, - 0x00c0, 0x2e70, 0x6004, 0xa0c6, 0x0707, 0x0040, 0x2e70, 0xa084, - 0x00ff, 0xa0c6, 0x0006, 0x00c0, 0x2e70, 0x87ff, 0x0040, 0x2e63, - 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x1078, - 0x2bb2, 0x0078, 0x2e6c, 0xac80, 0x000a, 0x2098, 0x3400, 0x20a9, - 0x0004, 0x53a3, 0x1078, 0x2bb2, 0x21a2, 0x94a0, 0xa6b0, 0x0005, - 0x8108, 0xa186, 0x007e, 0x0040, 0x2e7b, 0xa686, 0x0028, 0x0040, - 0x2e84, 0x0078, 0x2e46, 0x86ff, 0x00c0, 0x2e82, 0x7120, 0x810b, - 0x0078, 0x2513, 0x702f, 0x0001, 0x711e, 0x7020, 0xa600, 0x7022, - 0x772a, 0x2061, 0x76bd, 0x6007, 0x0000, 0x6612, 0x7024, 0x600e, - 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x137f, 0x7007, - 0x0002, 0x701b, 0x2e9c, 0x007c, 0x702c, 0xa005, 0x00c0, 0x2eae, - 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031, 0x0000, 0x2061, 0x76bd, - 0x6224, 0x6328, 0x642c, 0x6530, 0x0078, 0x2e46, 0x7120, 0x810b, - 0x0078, 0x2513, 0x127e, 0x0c7e, 0x0e7e, 0x2061, 0x0100, 0x2071, - 0x7600, 0x6044, 0xd0a4, 0x00c0, 0x2edb, 0xd084, 0x0040, 0x2ec4, - 0x1078, 0x3004, 0x0078, 0x2ed7, 0xd08c, 0x0040, 0x2ecb, 0x1078, - 0x2f1b, 0x0078, 0x2ed7, 0xd094, 0x0040, 0x2ed2, 0x1078, 0x2efe, - 0x0078, 0x2ed7, 0xd09c, 0x0040, 0x2ed7, 0x1078, 0x2ee5, 0x0e7f, - 0x0c7f, 0x127f, 0x007c, 0x017e, 0x6128, 0xd19c, 0x00c0, 0x2ee2, - 0xc19d, 0x612a, 0x017f, 0x0078, 0x2ed7, 0x6043, 0x0040, 0x6043, - 0x0000, 0x706f, 0x0000, 0x7087, 0x0001, 0x70a7, 0x0000, 0x2009, - 0x7cc0, 0x200b, 0x0000, 0x707f, 0x0000, 0x7073, 0x000f, 0x2009, - 0x000f, 0x2011, 0x353b, 0x1078, 0x45fe, 0x007c, 0x7070, 0xa005, - 0x00c0, 0x2f1a, 0x2011, 0x353b, 0x1078, 0x456e, 0x6043, 0x0020, - 0x6043, 0x0000, 0x6044, 0xd08c, 0x00c0, 0x2f16, 0x7083, 0x0000, - 0x6043, 0x0090, 0x6043, 0x0010, 0x0078, 0x2f1a, 0x7077, 0x0000, - 0x0078, 0x2f1a, 0x007c, 0x7074, 0xa08a, 0x0003, 0x00c8, 0x2f24, - 0x1079, 0x2f27, 0x0078, 0x2f26, 0x1078, 0x12d5, 0x007c, 0x2f2a, - 0x2f79, 0x3003, 0x0f7e, 0x7077, 0x0001, 0x20e1, 0xa000, 0x20e1, - 0x8700, 0x1078, 0x1dea, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2079, - 0x7b00, 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, 0x7b0c, 0x207b, 0x1101, 0x7807, 0x0000, 0x2099, - 0x7605, 0x20a1, 0x7b0e, 0x20a9, 0x0004, 0x53a3, 0x2079, 0x7b12, - 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0x7b00, 0x20a1, 0x020b, - 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, 0x1078, - 0x3562, 0x0f7f, 0x707b, 0x0000, 0x6043, 0x0008, 0x6043, 0x0000, - 0x007c, 0x0d7e, 0x7078, 0x707b, 0x0000, 0xa025, 0x0040, 0x2fed, - 0x6020, 0xd0b4, 0x00c0, 0x2feb, 0x7184, 0x81ff, 0x0040, 0x2fd4, - 0xa486, 0x000c, 0x00c0, 0x2fdf, 0xa480, 0x0018, 0x8004, 0x20a8, - 0x2011, 0x7b80, 0x2019, 0x7b00, 0x220c, 0x2304, 0xa106, 0x00c0, - 0x2fab, 0x8210, 0x8318, 0x00f0, 0x2f94, 0x6043, 0x0004, 0x608b, - 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x7077, 0x0002, 0x7083, - 0x0002, 0x0078, 0x2feb, 0x2069, 0x7b80, 0x6930, 0xa18e, 0x1101, - 0x00c0, 0x2fdf, 0x6834, 0xa005, 0x00c0, 0x2fdf, 0x6900, 0xa18c, - 0x00ff, 0x00c0, 0x2fbf, 0x6804, 0xa005, 0x0040, 0x2fd4, 0x2011, - 0x7b8e, 0x2019, 0x7605, 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102, - 0x0048, 0x2fd2, 0x00c0, 0x2fdf, 0x8210, 0x8318, 0x00f0, 0x2fc5, - 0x0078, 0x2fdf, 0x7087, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000, - 0x2099, 0x7b80, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043, - 0x0008, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x2feb, 0x60c3, - 0x000c, 0x1078, 0x3562, 0x0d7f, 0x007c, 0x6020, 0xd0b4, 0x00c0, - 0x2feb, 0x60c3, 0x000c, 0x2011, 0x7840, 0x2013, 0x0000, 0x707b, - 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x1078, - 0x5579, 0x0078, 0x2feb, 0x007c, 0x7080, 0xa08a, 0x001d, 0x00c8, - 0x300d, 0x1079, 0x3010, 0x0078, 0x300f, 0x1078, 0x12d5, 0x007c, - 0x3034, 0x3043, 0x3074, 0x3089, 0x30b9, 0x30e1, 0x3111, 0x313b, - 0x316b, 0x3191, 0x31da, 0x31fc, 0x3220, 0x3236, 0x325e, 0x3271, - 0x327a, 0x3293, 0x32c1, 0x32e9, 0x3317, 0x3341, 0x3384, 0x33b5, - 0x33d7, 0x3415, 0x343b, 0x3454, 0x3461, 0x7003, 0x0007, 0x6004, - 0xa084, 0xfff9, 0x6006, 0x007c, 0x608b, 0xbc94, 0x608f, 0xf0f0, - 0x6043, 0x0002, 0x7083, 0x0001, 0x2009, 0x07d0, 0x2011, 0x3542, - 0x1078, 0x4561, 0x007c, 0x0f7e, 0x7078, 0xa086, 0x0014, 0x00c0, - 0x3072, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x3072, 0x2079, - 0x7b80, 0x7a30, 0xa296, 0x1102, 0x00c0, 0x3070, 0x7834, 0xa005, - 0x00c0, 0x3070, 0x7a38, 0xd2fc, 0x0040, 0x3066, 0x70a4, 0xa005, - 0x00c0, 0x3066, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x2011, 0x3542, - 0x1078, 0x456e, 0x7083, 0x0010, 0x1078, 0x327a, 0x0078, 0x3072, - 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0003, 0x6043, 0x0004, - 0x1078, 0x35cc, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, 0x000a, - 0x20a3, 0x0000, 0x00f0, 0x3080, 0x60c3, 0x0014, 0x1078, 0x3562, - 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x30b7, 0x2011, 0x3542, - 0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x30b3, 0x2079, 0x7b80, - 0x7a30, 0xa296, 0x1102, 0x00c0, 0x30b3, 0x7834, 0xa005, 0x00c0, - 0x30b3, 0x7a38, 0xd2fc, 0x0040, 0x30ad, 0x70a4, 0xa005, 0x00c0, - 0x30ad, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x7083, 0x0004, 0x1078, - 0x30b9, 0x0078, 0x30b7, 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f, - 0x007c, 0x7083, 0x0005, 0x1078, 0x35cc, 0x20a3, 0x1103, 0x20a3, - 0x0000, 0x3430, 0x2011, 0x7b8e, 0x706c, 0xa005, 0x00c0, 0x30d3, - 0x714c, 0xa186, 0xffff, 0x0040, 0x30d3, 0x1078, 0x3506, 0x0040, - 0x30d3, 0x1078, 0x35fb, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x3562, - 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x310f, 0x2011, 0x3542, - 0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x310b, 0x2079, 0x7b80, - 0x7a30, 0xa296, 0x1103, 0x00c0, 0x310b, 0x7834, 0xa005, 0x00c0, - 0x310b, 0x7a38, 0xd2fc, 0x0040, 0x3105, 0x70a4, 0xa005, 0x00c0, - 0x3105, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x7083, 0x0006, 0x1078, - 0x3111, 0x0078, 0x310f, 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f, - 0x007c, 0x7083, 0x0007, 0x1078, 0x35cc, 0x20a3, 0x1104, 0x20a3, - 0x0000, 0x3430, 0x2011, 0x7b8e, 0x706c, 0xa005, 0x00c0, 0x312d, - 0x7150, 0xa186, 0xffff, 0x0040, 0x312d, 0xa180, 0x232f, 0x200c, - 0xa18c, 0xff00, 0x810f, 0x1078, 0x3506, 0x20a9, 0x0008, 0x2298, - 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, - 0x1078, 0x3562, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x3169, - 0x2011, 0x3542, 0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x3165, - 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3165, 0x7834, - 0xa005, 0x00c0, 0x3165, 0x7a38, 0xd2fc, 0x0040, 0x315f, 0x70a4, - 0xa005, 0x00c0, 0x315f, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x7083, - 0x0008, 0x1078, 0x316b, 0x0078, 0x3169, 0x7083, 0x0002, 0x707b, - 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0009, 0x1078, 0x35cc, 0x20a3, - 0x1105, 0x20a3, 0x0100, 0x3430, 0x706c, 0xa005, 0x00c0, 0x317e, - 0x1078, 0x3470, 0x0040, 0x318e, 0x0078, 0x3188, 0x20a9, 0x0008, - 0x2099, 0x7b8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0014, 0x1078, 0x3562, 0x0078, 0x3190, 0x1078, 0x302d, - 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x31d8, 0x2011, 0x3542, - 0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x31d4, 0x2079, 0x7b80, - 0x7a30, 0xa296, 0x1105, 0x00c0, 0x31d4, 0x7834, 0x2011, 0x0100, - 0xa21e, 0x00c0, 0x31bd, 0x7a38, 0xd2fc, 0x0040, 0x31b7, 0x70a4, - 0xa005, 0x00c0, 0x31b7, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x7083, - 0x000a, 0x1078, 0x31da, 0x0078, 0x31d8, 0xa005, 0x00c0, 0x31d4, - 0x7a38, 0xd2fc, 0x0040, 0x31cc, 0x70a4, 0xa005, 0x00c0, 0x31cc, - 0x1078, 0x35fb, 0x70a7, 0x0001, 0x707f, 0x0000, 0x7083, 0x000e, - 0x1078, 0x325e, 0x0078, 0x31d8, 0x7083, 0x0002, 0x707b, 0x0000, - 0x0f7f, 0x007c, 0x7083, 0x000b, 0x2011, 0x7b0e, 0x22a0, 0x20a9, - 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000, - 0x41a4, 0x1078, 0x35cc, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x6030, - 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, 0x60c3, - 0x0084, 0x1078, 0x3562, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, - 0x321e, 0x2011, 0x3542, 0x1078, 0x456e, 0xa086, 0x0084, 0x00c0, - 0x321a, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1106, 0x00c0, 0x321a, - 0x7834, 0xa005, 0x00c0, 0x321a, 0x7083, 0x000c, 0x1078, 0x3220, - 0x0078, 0x321e, 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f, 0x007c, - 0x7083, 0x000d, 0x1078, 0x35cc, 0x20a3, 0x1107, 0x20a3, 0x0000, - 0x2099, 0x7b8e, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x60c3, 0x0084, 0x1078, 0x3562, 0x007c, 0x0f7e, 0x7078, - 0xa005, 0x0040, 0x325c, 0x2011, 0x3542, 0x1078, 0x456e, 0xa086, - 0x0084, 0x00c0, 0x3258, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1107, - 0x00c0, 0x3258, 0x7834, 0xa005, 0x00c0, 0x3258, 0x707f, 0x0001, - 0x1078, 0x35be, 0x7083, 0x000e, 0x1078, 0x325e, 0x0078, 0x325c, - 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x000f, - 0x707b, 0x0000, 0x608b, 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0005, - 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x3542, 0x1078, 0x4561, - 0x007c, 0x7078, 0xa005, 0x0040, 0x3279, 0x2011, 0x3542, 0x1078, - 0x456e, 0x007c, 0x7083, 0x0011, 0x20e1, 0x9080, 0x20e1, 0x4000, - 0x2099, 0x7b80, 0x20a1, 0x020b, 0x7478, 0xa480, 0x0018, 0xa080, - 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014, - 0x1078, 0x3562, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x32bf, - 0x2011, 0x3542, 0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x32bd, - 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1103, 0x00c0, 0x32bd, 0x7834, - 0xa005, 0x00c0, 0x32bd, 0x7a38, 0xd2fc, 0x0040, 0x32b7, 0x70a4, - 0xa005, 0x00c0, 0x32b7, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x7083, - 0x0012, 0x1078, 0x32c1, 0x0078, 0x32bf, 0x707b, 0x0000, 0x0f7f, - 0x007c, 0x7083, 0x0013, 0x1078, 0x35d8, 0x20a3, 0x1103, 0x20a3, - 0x0000, 0x3430, 0x2011, 0x7b8e, 0x706c, 0xa005, 0x00c0, 0x32db, - 0x714c, 0xa186, 0xffff, 0x0040, 0x32db, 0x1078, 0x3506, 0x0040, - 0x32db, 0x1078, 0x35fb, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x3562, - 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x3315, 0x2011, 0x3542, - 0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x3313, 0x2079, 0x7b80, - 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3313, 0x7834, 0xa005, 0x00c0, - 0x3313, 0x7a38, 0xd2fc, 0x0040, 0x330d, 0x70a4, 0xa005, 0x00c0, - 0x330d, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x7083, 0x0014, 0x1078, - 0x3317, 0x0078, 0x3315, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, - 0x0015, 0x1078, 0x35d8, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, - 0x2011, 0x7b8e, 0x706c, 0xa006, 0x00c0, 0x3333, 0x7150, 0xa186, - 0xffff, 0x0040, 0x3333, 0xa180, 0x232f, 0x200c, 0xa18c, 0xff00, - 0x810f, 0x1078, 0x3506, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x3562, - 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x3382, 0x2011, 0x3542, - 0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x3380, 0x2079, 0x7b80, - 0x7a30, 0xa296, 0x1105, 0x00c0, 0x3380, 0x7834, 0x2011, 0x0100, - 0xa21e, 0x00c0, 0x3369, 0x7a38, 0xd2fc, 0x0040, 0x3367, 0x70a4, - 0xa005, 0x00c0, 0x3367, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x0078, - 0x337a, 0xa005, 0x00c0, 0x3380, 0x7a38, 0xd2fc, 0x0040, 0x3378, - 0x70a4, 0xa005, 0x00c0, 0x3378, 0x1078, 0x35fb, 0x70a7, 0x0001, - 0x707f, 0x0000, 0x7083, 0x0016, 0x1078, 0x3384, 0x0078, 0x3382, + 0xa0be, 0x0100, 0x0040, 0x2b59, 0xa0be, 0x0112, 0x0040, 0x2b59, + 0xa0be, 0x0113, 0x0040, 0x2b59, 0xa0be, 0x0114, 0x0040, 0x2b59, + 0xa0be, 0x0117, 0x0040, 0x2b59, 0xa0be, 0x011a, 0x0040, 0x2b59, + 0xa0be, 0x0121, 0x0040, 0x2b4f, 0xa0be, 0x0131, 0x0040, 0x2b4f, + 0xa0be, 0x0171, 0x0040, 0x2b59, 0xa0be, 0x0173, 0x0040, 0x2b59, + 0xa0be, 0x01a1, 0x00c0, 0x2b21, 0x6830, 0x8007, 0x6832, 0x0078, + 0x2b5f, 0xa0be, 0x0212, 0x0040, 0x2b55, 0xa0be, 0x0213, 0x0040, + 0x2b55, 0xa0be, 0x0214, 0x0040, 0x2b47, 0xa0be, 0x0217, 0x0040, + 0x2b41, 0xa0be, 0x021a, 0x00c0, 0x2b3a, 0x6838, 0x8007, 0x683a, + 0x0078, 0x2b59, 0xa0be, 0x0300, 0x0040, 0x2b59, 0x0d7f, 0x0078, + 0x253b, 0xad80, 0x0010, 0x20a9, 0x0007, 0x1078, 0x2b95, 0xad80, + 0x000e, 0x20a9, 0x0001, 0x1078, 0x2b95, 0x0078, 0x2b59, 0xad80, + 0x000c, 0x1078, 0x2ba3, 0x0078, 0x2b5f, 0xad80, 0x000e, 0x1078, + 0x2ba3, 0xad80, 0x000c, 0x20a9, 0x0001, 0x1078, 0x2b95, 0x0c7e, + 0x1078, 0x2cec, 0x0040, 0x2b8a, 0x6838, 0xc0fd, 0x683a, 0x6837, + 0x0119, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883, + 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000, + 0x0c7f, 0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, + 0x0000, 0x1078, 0x6a52, 0x0040, 0x2537, 0x7007, 0x0003, 0x701b, + 0x2b8e, 0x007c, 0x0c7f, 0x0d7f, 0x0078, 0x2537, 0x6820, 0xa086, + 0x8001, 0x0040, 0x2537, 0x0078, 0x250d, 0x017e, 0x2008, 0x2044, + 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, 0x00f0, + 0x2b97, 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, 0x00c0, 0x2537, 0x7924, 0x2140, 0xa18c, 0xff00, + 0x810f, 0xa182, 0x0080, 0x0048, 0x253b, 0xa182, 0x00ff, 0x00c8, + 0x253b, 0x7a2c, 0x7b28, 0x6064, 0xa306, 0x00c0, 0x2bd7, 0x6068, + 0xa24e, 0x0040, 0x253b, 0xa9cc, 0xff00, 0x0040, 0x253b, 0x0c7e, + 0x1078, 0x2c4b, 0x2c68, 0x0c7f, 0x0040, 0x2bfe, 0xa0c6, 0x4000, + 0x00c0, 0x2be4, 0x0078, 0x2bfb, 0xa0c6, 0x4007, 0x00c0, 0x2beb, + 0x2408, 0x0078, 0x2bfb, 0xa0c6, 0x4008, 0x00c0, 0x2bf3, 0x2708, + 0x2610, 0x0078, 0x2bfb, 0xa0c6, 0x4009, 0x00c0, 0x2bf9, 0x0078, + 0x2bfb, 0x2001, 0x4006, 0x2020, 0x0078, 0x250f, 0x017e, 0x0b7e, + 0x0c7e, 0x0e7e, 0x2c70, 0x1078, 0x5b94, 0x0040, 0x2c39, 0x2d00, + 0x601a, 0x2e58, 0x0e7f, 0x0e7e, 0x0c7e, 0x1078, 0x2cec, 0x0c7f, + 0x2b70, 0x0040, 0x2537, 0x6837, 0x0000, 0x2d00, 0x6012, 0x6833, + 0x0000, 0x6838, 0xc0fd, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, + 0x22b5, 0x127f, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x37b5, + 0x2001, 0x0002, 0x1078, 0x37c9, 0x127e, 0x2091, 0x8000, 0x7088, + 0x8000, 0x708a, 0x127f, 0x2009, 0x0002, 0x1078, 0x5c21, 0xa085, + 0x0001, 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, 0x0040, 0x2537, 0x7007, + 0x0003, 0x701b, 0x2c44, 0x007c, 0x6830, 0xa086, 0x0100, 0x00c0, + 0x250d, 0x0078, 0x2537, 0x0e7e, 0x0d7e, 0x2029, 0x0000, 0x2021, + 0x0080, 0x20a9, 0x007f, 0x2071, 0x77a0, 0x2e04, 0xa005, 0x00c0, + 0x2c5f, 0x2100, 0xa406, 0x0040, 0x2c9c, 0x0078, 0x2c90, 0x2068, + 0x6f10, 0x2700, 0xa306, 0x00c0, 0x2c81, 0x6e14, 0x2600, 0xa206, + 0x00c0, 0x2c81, 0x2400, 0xa106, 0x00c0, 0x2c7d, 0x2d60, 0xd884, + 0x0040, 0x2ca2, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, + 0x2ca2, 0x2001, 0x4000, 0x0078, 0x2ca3, 0x2001, 0x4007, 0x0078, + 0x2ca3, 0x2400, 0xa106, 0x00c0, 0x2c90, 0x6e14, 0x87ff, 0x00c0, + 0x2c8c, 0x86ff, 0x0040, 0x2c9c, 0x2001, 0x4008, 0x0078, 0x2ca3, + 0x8420, 0x8e70, 0x00f0, 0x2c55, 0x2001, 0x4009, 0x0078, 0x2ca3, + 0x2001, 0x0001, 0x0078, 0x2ca3, 0x1078, 0x37e6, 0x00c0, 0x2c98, + 0x6312, 0x6216, 0xa006, 0xa005, 0x0d7f, 0x0e7f, 0x007c, 0x81ff, + 0x00c0, 0x2537, 0x1078, 0x2cec, 0x0040, 0x2537, 0x6837, 0x0000, + 0x7824, 0xa005, 0x0040, 0x253b, 0xa096, 0x00ff, 0x0040, 0x2cbc, + 0xa092, 0x0004, 0x00c8, 0x253b, 0x2010, 0x2d18, 0x1078, 0x2277, + 0x0040, 0x2537, 0x7007, 0x0003, 0x701b, 0x2cc7, 0x007c, 0x6830, + 0xa086, 0x0100, 0x0040, 0x2537, 0x0078, 0x250d, 0x81ff, 0x00c0, + 0x2537, 0x7924, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080, 0x0048, + 0x253b, 0xa182, 0x00ff, 0x00c8, 0x253b, 0x127e, 0x2091, 0x8000, + 0x1078, 0x6979, 0x00c0, 0x2ce9, 0x1078, 0x3805, 0x127f, 0x0078, + 0x250d, 0x127f, 0x0078, 0x2537, 0x1078, 0x1327, 0x0040, 0x2d03, + 0xa006, 0x6802, 0x7010, 0xa005, 0x00c0, 0x2cfb, 0x2d00, 0x7012, + 0x7016, 0x0078, 0x2d01, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, + 0x7016, 0xad80, 0x000d, 0x007c, 0x7e24, 0x860f, 0xa18c, 0x00ff, + 0x1078, 0x381d, 0x00c0, 0x2d12, 0xa6b4, 0x00ff, 0xa682, 0x0010, + 0x0048, 0x2d13, 0xa066, 0x8cff, 0x007c, 0x017e, 0x7110, 0x81ff, + 0x0040, 0x2d20, 0x2168, 0x6904, 0x1078, 0x1340, 0x0078, 0x2d17, + 0x7112, 0x7116, 0x017f, 0x007c, 0x2031, 0x0001, 0x0078, 0x2d2a, + 0x2031, 0x0000, 0x2061, 0x76bd, 0x6606, 0x6112, 0x600e, 0x6226, + 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x1377, 0x7007, 0x0002, + 0x701b, 0x250d, 0x007c, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079, + 0x0000, 0x2001, 0x767b, 0x2004, 0xa005, 0x00c0, 0x2d56, 0x0068, + 0x2d56, 0x7818, 0xd084, 0x00c0, 0x2d56, 0x781b, 0x0001, 0x7a22, + 0x7b26, 0x7c2a, 0x2091, 0x4080, 0x0078, 0x2d7b, 0x017e, 0x0c7e, + 0x0e7e, 0x2071, 0x766d, 0x7138, 0xa182, 0x0008, 0x0048, 0x2d64, + 0x7030, 0x2060, 0x0078, 0x2d75, 0x7030, 0xa0e0, 0x0008, 0xac82, + 0x76bd, 0x0048, 0x2d6d, 0x2061, 0x767d, 0x2c00, 0x7032, 0x81ff, + 0x00c0, 0x2d73, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, + 0x0e7f, 0x0c7f, 0x017f, 0x127f, 0x0f7f, 0x007c, 0x0e7e, 0x2071, + 0x766d, 0x7038, 0xa005, 0x0040, 0x2db7, 0x127e, 0x2091, 0x8000, + 0x0068, 0x2db6, 0x0f7e, 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, + 0x2db5, 0x0c7e, 0x781b, 0x0001, 0x7034, 0x2060, 0x2c04, 0x7822, + 0x6004, 0x7826, 0x6008, 0x782a, 0x2091, 0x4080, 0x7038, 0x8001, + 0x703a, 0xa005, 0x00c0, 0x2dab, 0x7033, 0x767d, 0x7037, 0x767d, + 0x0c7f, 0x0078, 0x2db5, 0xac80, 0x0008, 0xa0fa, 0x76bd, 0x0048, + 0x2db3, 0x2001, 0x767d, 0x7036, 0x0c7f, 0x0f7f, 0x127f, 0x0e7f, + 0x007c, 0x027e, 0x2001, 0x7652, 0x2004, 0xd0c4, 0x0040, 0x2dc4, + 0x2011, 0x8014, 0x1078, 0x2d3b, 0x027f, 0x007c, 0x81ff, 0x00c0, + 0x2537, 0x127e, 0x2091, 0x8000, 0x6030, 0xc08d, 0x6032, 0x1078, + 0x3573, 0x127f, 0x0078, 0x250d, 0x7824, 0x2008, 0xa18c, 0xfffd, + 0x00c0, 0x2ddf, 0x61c8, 0xa10d, 0x61ca, 0x0078, 0x250d, 0x0078, + 0x253b, 0x81ff, 0x00c0, 0x2537, 0x6000, 0xa086, 0x0003, 0x00c0, + 0x2537, 0x2001, 0x7652, 0x2004, 0xd0a4, 0x00c0, 0x2537, 0x1078, + 0x2d04, 0x0040, 0x253b, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x00c0, 0x2dfe, 0x7828, 0xa005, 0x0040, 0x250d, 0x0c7e, 0x1078, + 0x2cec, 0x0c7f, 0x0040, 0x2537, 0x6837, 0x0000, 0x6833, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x1078, 0x6adb, 0x0040, 0x2537, 0x7007, + 0x0003, 0x701b, 0x2e14, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, + 0x2537, 0x0078, 0x250d, 0x2001, 0x7600, 0x2004, 0xa086, 0x0003, + 0x00c0, 0x2537, 0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, + 0x2cec, 0x0040, 0x2537, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, + 0x0000, 0x702f, 0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x1078, + 0x381d, 0x00c0, 0x2e61, 0x6004, 0xa0c6, 0x0707, 0x0040, 0x2e61, + 0xa084, 0x00ff, 0xa0c6, 0x0006, 0x00c0, 0x2e61, 0x87ff, 0x0040, + 0x2e54, 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, + 0x1078, 0x2ba3, 0x0078, 0x2e5d, 0xac80, 0x000a, 0x2098, 0x3400, + 0x20a9, 0x0004, 0x53a3, 0x1078, 0x2ba3, 0x21a2, 0x94a0, 0xa6b0, + 0x0005, 0x8108, 0xa186, 0x007e, 0x0040, 0x2e6c, 0xa686, 0x0028, + 0x0040, 0x2e75, 0x0078, 0x2e37, 0x86ff, 0x00c0, 0x2e73, 0x7120, + 0x810b, 0x0078, 0x250d, 0x702f, 0x0001, 0x711e, 0x7020, 0xa600, + 0x7022, 0x772a, 0x2061, 0x76bd, 0x6007, 0x0000, 0x6612, 0x7024, + 0x600e, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x1377, + 0x7007, 0x0002, 0x701b, 0x2e8d, 0x007c, 0x702c, 0xa005, 0x00c0, + 0x2e9f, 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031, 0x0000, 0x2061, + 0x76bd, 0x6224, 0x6328, 0x642c, 0x6530, 0x0078, 0x2e37, 0x7120, + 0x810b, 0x0078, 0x250d, 0x127e, 0x0c7e, 0x0e7e, 0x2061, 0x0100, + 0x2071, 0x7600, 0x6044, 0xd0a4, 0x00c0, 0x2ecc, 0xd084, 0x0040, + 0x2eb5, 0x1078, 0x2ff7, 0x0078, 0x2ec8, 0xd08c, 0x0040, 0x2ebc, + 0x1078, 0x2f0e, 0x0078, 0x2ec8, 0xd094, 0x0040, 0x2ec3, 0x1078, + 0x2ef1, 0x0078, 0x2ec8, 0xd09c, 0x0040, 0x2ec8, 0x1078, 0x2ed6, + 0x0e7f, 0x0c7f, 0x127f, 0x007c, 0x017e, 0x6128, 0xd19c, 0x00c0, + 0x2ed3, 0xc19d, 0x612a, 0x017f, 0x0078, 0x2ec8, 0x6043, 0x0040, + 0x6043, 0x0000, 0x706f, 0x0000, 0x7087, 0x0001, 0x70a7, 0x0000, + 0x70bf, 0x0000, 0x2009, 0x7cc0, 0x200b, 0x0000, 0x707f, 0x0000, + 0x7073, 0x000f, 0x2009, 0x000f, 0x2011, 0x3533, 0x1078, 0x45f6, + 0x007c, 0x7070, 0xa005, 0x00c0, 0x2f0d, 0x2011, 0x3533, 0x1078, + 0x4566, 0x6043, 0x0020, 0x6043, 0x0000, 0x6044, 0xd08c, 0x00c0, + 0x2f09, 0x7083, 0x0000, 0x6043, 0x0090, 0x6043, 0x0010, 0x0078, + 0x2f0d, 0x7077, 0x0000, 0x0078, 0x2f0d, 0x007c, 0x7074, 0xa08a, + 0x0003, 0x00c8, 0x2f17, 0x1079, 0x2f1a, 0x0078, 0x2f19, 0x1078, + 0x12cd, 0x007c, 0x2f1d, 0x2f6c, 0x2ff6, 0x0f7e, 0x7077, 0x0001, + 0x20e1, 0xa000, 0x20e1, 0x8700, 0x1078, 0x1de4, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x2079, 0x7b00, 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, 0x7b0c, 0x207b, 0x1101, + 0x7807, 0x0000, 0x2099, 0x7605, 0x20a1, 0x7b0e, 0x20a9, 0x0004, + 0x53a3, 0x2079, 0x7b12, 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, + 0x7b00, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, + 0x600f, 0x0000, 0x1078, 0x355a, 0x0f7f, 0x707b, 0x0000, 0x6043, + 0x0008, 0x6043, 0x0000, 0x007c, 0x0d7e, 0x7078, 0x707b, 0x0000, + 0xa025, 0x0040, 0x2fe0, 0x6020, 0xd0b4, 0x00c0, 0x2fde, 0x7184, + 0x81ff, 0x0040, 0x2fc7, 0xa486, 0x000c, 0x00c0, 0x2fd2, 0xa480, + 0x0018, 0x8004, 0x20a8, 0x2011, 0x7b80, 0x2019, 0x7b00, 0x220c, + 0x2304, 0xa106, 0x00c0, 0x2f9e, 0x8210, 0x8318, 0x00f0, 0x2f87, + 0x6043, 0x0004, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, + 0x7077, 0x0002, 0x7083, 0x0002, 0x0078, 0x2fde, 0x2069, 0x7b80, + 0x6930, 0xa18e, 0x1101, 0x00c0, 0x2fd2, 0x6834, 0xa005, 0x00c0, + 0x2fd2, 0x6900, 0xa18c, 0x00ff, 0x00c0, 0x2fb2, 0x6804, 0xa005, + 0x0040, 0x2fc7, 0x2011, 0x7b8e, 0x2019, 0x7605, 0x20a9, 0x0004, + 0x220c, 0x2304, 0xa102, 0x0048, 0x2fc5, 0x00c0, 0x2fd2, 0x8210, + 0x8318, 0x00f0, 0x2fb8, 0x0078, 0x2fd2, 0x7087, 0x0000, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x2099, 0x7b80, 0x20a1, 0x020b, 0x20a9, + 0x0014, 0x53a6, 0x6043, 0x0008, 0x6043, 0x0000, 0x6020, 0xd0b4, + 0x00c0, 0x2fde, 0x60c3, 0x000c, 0x1078, 0x355a, 0x0d7f, 0x007c, + 0x6020, 0xd0b4, 0x00c0, 0x2fde, 0x60c3, 0x000c, 0x2011, 0x7840, + 0x2013, 0x0000, 0x707b, 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, + 0x60a7, 0x9575, 0x1078, 0x5571, 0x0078, 0x2fde, 0x007c, 0x7080, + 0xa08a, 0x001d, 0x00c8, 0x3000, 0x1079, 0x3003, 0x0078, 0x3002, + 0x1078, 0x12cd, 0x007c, 0x3027, 0x3036, 0x3067, 0x307c, 0x30ac, + 0x30d4, 0x3104, 0x312e, 0x315e, 0x3184, 0x31cd, 0x31ef, 0x3213, + 0x3229, 0x3251, 0x3264, 0x326d, 0x3286, 0x32b4, 0x32dc, 0x330a, + 0x3334, 0x337c, 0x33ad, 0x33cf, 0x340d, 0x3433, 0x344c, 0x3459, + 0x7003, 0x0007, 0x6004, 0xa084, 0xfff9, 0x6006, 0x007c, 0x608b, + 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0002, 0x7083, 0x0001, 0x2009, + 0x07d0, 0x2011, 0x353a, 0x1078, 0x4559, 0x007c, 0x0f7e, 0x7078, + 0xa086, 0x0014, 0x00c0, 0x3065, 0x6043, 0x0000, 0x6020, 0xd0b4, + 0x00c0, 0x3065, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1102, 0x00c0, + 0x3063, 0x7834, 0xa005, 0x00c0, 0x3063, 0x7a38, 0xd2fc, 0x0040, + 0x3059, 0x70a4, 0xa005, 0x00c0, 0x3059, 0x1078, 0x35f3, 0x70a7, + 0x0001, 0x2011, 0x353a, 0x1078, 0x4566, 0x7083, 0x0010, 0x1078, + 0x326d, 0x0078, 0x3065, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, + 0x0003, 0x6043, 0x0004, 0x1078, 0x35c4, 0x20a3, 0x1102, 0x20a3, + 0x0000, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x3073, 0x60c3, + 0x0014, 0x1078, 0x355a, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, + 0x30aa, 0x2011, 0x353a, 0x1078, 0x4566, 0xa086, 0x0014, 0x00c0, + 0x30a6, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1102, 0x00c0, 0x30a6, + 0x7834, 0xa005, 0x00c0, 0x30a6, 0x7a38, 0xd2fc, 0x0040, 0x30a0, + 0x70a4, 0xa005, 0x00c0, 0x30a0, 0x1078, 0x35f3, 0x70a7, 0x0001, + 0x7083, 0x0004, 0x1078, 0x30ac, 0x0078, 0x30aa, 0x7083, 0x0002, + 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0005, 0x1078, 0x35c4, + 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0x7b8e, 0x706c, + 0xa005, 0x00c0, 0x30c6, 0x714c, 0xa186, 0xffff, 0x0040, 0x30c6, + 0x1078, 0x34fe, 0x0040, 0x30c6, 0x1078, 0x35f3, 0x20a9, 0x0008, + 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0014, 0x1078, 0x355a, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, + 0x3102, 0x2011, 0x353a, 0x1078, 0x4566, 0xa086, 0x0014, 0x00c0, + 0x30fe, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1103, 0x00c0, 0x30fe, + 0x7834, 0xa005, 0x00c0, 0x30fe, 0x7a38, 0xd2fc, 0x0040, 0x30f8, + 0x70a4, 0xa005, 0x00c0, 0x30f8, 0x1078, 0x35f3, 0x70a7, 0x0001, + 0x7083, 0x0006, 0x1078, 0x3104, 0x0078, 0x3102, 0x7083, 0x0002, + 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0007, 0x1078, 0x35c4, + 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0x7b8e, 0x706c, + 0xa005, 0x00c0, 0x3120, 0x7150, 0xa186, 0xffff, 0x0040, 0x3120, + 0xa180, 0x2329, 0x200c, 0xa18c, 0xff00, 0x810f, 0x1078, 0x34fe, + 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0014, 0x1078, 0x355a, 0x007c, 0x0f7e, 0x7078, + 0xa005, 0x0040, 0x315c, 0x2011, 0x353a, 0x1078, 0x4566, 0xa086, + 0x0014, 0x00c0, 0x3158, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1104, + 0x00c0, 0x3158, 0x7834, 0xa005, 0x00c0, 0x3158, 0x7a38, 0xd2fc, + 0x0040, 0x3152, 0x70a4, 0xa005, 0x00c0, 0x3152, 0x1078, 0x35f3, + 0x70a7, 0x0001, 0x7083, 0x0008, 0x1078, 0x315e, 0x0078, 0x315c, + 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0009, + 0x1078, 0x35c4, 0x20a3, 0x1105, 0x20a3, 0x0100, 0x3430, 0x706c, + 0xa005, 0x00c0, 0x3171, 0x1078, 0x3468, 0x0040, 0x3181, 0x0078, + 0x317b, 0x20a9, 0x0008, 0x2099, 0x7b8e, 0x26a0, 0x53a6, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x355a, 0x0078, + 0x3183, 0x1078, 0x3020, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, + 0x31cb, 0x2011, 0x353a, 0x1078, 0x4566, 0xa086, 0x0014, 0x00c0, + 0x31c7, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1105, 0x00c0, 0x31c7, + 0x7834, 0x2011, 0x0100, 0xa21e, 0x00c0, 0x31b0, 0x7a38, 0xd2fc, + 0x0040, 0x31aa, 0x70a4, 0xa005, 0x00c0, 0x31aa, 0x1078, 0x35f3, + 0x70a7, 0x0001, 0x7083, 0x000a, 0x1078, 0x31cd, 0x0078, 0x31cb, + 0xa005, 0x00c0, 0x31c7, 0x7a38, 0xd2fc, 0x0040, 0x31bf, 0x70a4, + 0xa005, 0x00c0, 0x31bf, 0x1078, 0x35f3, 0x70a7, 0x0001, 0x707f, + 0x0000, 0x7083, 0x000e, 0x1078, 0x3251, 0x0078, 0x31cb, 0x7083, + 0x0002, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x000b, 0x2011, + 0x7b0e, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, + 0x0002, 0x2009, 0x0000, 0x41a4, 0x1078, 0x35c4, 0x20a3, 0x1106, + 0x20a3, 0x0000, 0x6030, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, + 0x0042, 0x53a6, 0x60c3, 0x0084, 0x1078, 0x355a, 0x007c, 0x0f7e, + 0x7078, 0xa005, 0x0040, 0x3211, 0x2011, 0x353a, 0x1078, 0x4566, + 0xa086, 0x0084, 0x00c0, 0x320d, 0x2079, 0x7b80, 0x7a30, 0xa296, + 0x1106, 0x00c0, 0x320d, 0x7834, 0xa005, 0x00c0, 0x320d, 0x7083, + 0x000c, 0x1078, 0x3213, 0x0078, 0x3211, 0x7083, 0x0002, 0x707b, + 0x0000, 0x0f7f, 0x007c, 0x7083, 0x000d, 0x1078, 0x35c4, 0x20a3, + 0x1107, 0x20a3, 0x0000, 0x2099, 0x7b8e, 0x20a9, 0x0040, 0x53a6, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x1078, 0x355a, + 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x324f, 0x2011, 0x353a, + 0x1078, 0x4566, 0xa086, 0x0084, 0x00c0, 0x324b, 0x2079, 0x7b80, + 0x7a30, 0xa296, 0x1107, 0x00c0, 0x324b, 0x7834, 0xa005, 0x00c0, + 0x324b, 0x707f, 0x0001, 0x1078, 0x35b6, 0x7083, 0x000e, 0x1078, + 0x3251, 0x0078, 0x324f, 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f, + 0x007c, 0x7083, 0x000f, 0x707b, 0x0000, 0x608b, 0xbc85, 0x608f, + 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, + 0x353a, 0x1078, 0x4559, 0x007c, 0x7078, 0xa005, 0x0040, 0x326c, + 0x2011, 0x353a, 0x1078, 0x4566, 0x007c, 0x7083, 0x0011, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x2099, 0x7b80, 0x20a1, 0x020b, 0x7478, + 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, + 0x53a6, 0x60c3, 0x0014, 0x1078, 0x355a, 0x007c, 0x0f7e, 0x7078, + 0xa005, 0x0040, 0x32b2, 0x2011, 0x353a, 0x1078, 0x4566, 0xa086, + 0x0014, 0x00c0, 0x32b0, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1103, + 0x00c0, 0x32b0, 0x7834, 0xa005, 0x00c0, 0x32b0, 0x7a38, 0xd2fc, + 0x0040, 0x32aa, 0x70a4, 0xa005, 0x00c0, 0x32aa, 0x1078, 0x35f3, + 0x70a7, 0x0001, 0x7083, 0x0012, 0x1078, 0x32b4, 0x0078, 0x32b2, + 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0013, 0x1078, 0x35d0, + 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0x7b8e, 0x706c, + 0xa005, 0x00c0, 0x32ce, 0x714c, 0xa186, 0xffff, 0x0040, 0x32ce, + 0x1078, 0x34fe, 0x0040, 0x32ce, 0x1078, 0x35f3, 0x20a9, 0x0008, + 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0014, 0x1078, 0x355a, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, + 0x3308, 0x2011, 0x353a, 0x1078, 0x4566, 0xa086, 0x0014, 0x00c0, + 0x3306, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3306, + 0x7834, 0xa005, 0x00c0, 0x3306, 0x7a38, 0xd2fc, 0x0040, 0x3300, + 0x70a4, 0xa005, 0x00c0, 0x3300, 0x1078, 0x35f3, 0x70a7, 0x0001, + 0x7083, 0x0014, 0x1078, 0x330a, 0x0078, 0x3308, 0x707b, 0x0000, + 0x0f7f, 0x007c, 0x7083, 0x0015, 0x1078, 0x35d0, 0x20a3, 0x1104, + 0x20a3, 0x0000, 0x3430, 0x2011, 0x7b8e, 0x706c, 0xa006, 0x00c0, + 0x3326, 0x7150, 0xa186, 0xffff, 0x0040, 0x3326, 0xa180, 0x2329, + 0x200c, 0xa18c, 0xff00, 0x810f, 0x1078, 0x34fe, 0x20a9, 0x0008, + 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0014, 0x1078, 0x355a, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, + 0x337a, 0x2011, 0x353a, 0x1078, 0x4566, 0xa086, 0x0014, 0x00c0, + 0x3378, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1105, 0x00c0, 0x3378, + 0x7834, 0x2011, 0x0100, 0xa21e, 0x00c0, 0x3361, 0x7a38, 0xd2f4, + 0x0040, 0x3354, 0x70bf, 0x0008, 0xd2fc, 0x0040, 0x335f, 0x70a4, + 0xa005, 0x00c0, 0x335f, 0x1078, 0x35f3, 0x70a7, 0x0001, 0x0078, + 0x3372, 0xa005, 0x00c0, 0x3378, 0x7a38, 0xd2fc, 0x0040, 0x3370, + 0x70a4, 0xa005, 0x00c0, 0x3370, 0x1078, 0x35f3, 0x70a7, 0x0001, + 0x707f, 0x0000, 0x7083, 0x0016, 0x1078, 0x337c, 0x0078, 0x337a, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x7b80, 0x20a1, 0x020b, 0x20a9, 0x000e, 0x53a6, 0x3430, - 0x2011, 0x7b8e, 0x7083, 0x0017, 0x0078, 0x3398, 0x7083, 0x001b, - 0x706c, 0xa005, 0x00c0, 0x33a2, 0x1078, 0x3470, 0x0040, 0x33b2, - 0x0078, 0x33ac, 0x20a9, 0x0008, 0x2099, 0x7b8e, 0x26a0, 0x53a6, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x3562, - 0x0078, 0x33b4, 0x1078, 0x302d, 0x007c, 0x0f7e, 0x7078, 0xa005, - 0x0040, 0x33d5, 0x2011, 0x3542, 0x1078, 0x456e, 0xa086, 0x0084, - 0x00c0, 0x33d3, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1106, 0x00c0, - 0x33d3, 0x7834, 0xa005, 0x00c0, 0x33d3, 0x7083, 0x0018, 0x1078, - 0x33d7, 0x0078, 0x33d5, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, - 0x0019, 0x1078, 0x35d8, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430, + 0x2011, 0x7b8e, 0x7083, 0x0017, 0x0078, 0x3390, 0x7083, 0x001b, + 0x706c, 0xa005, 0x00c0, 0x339a, 0x1078, 0x3468, 0x0040, 0x33aa, + 0x0078, 0x33a4, 0x20a9, 0x0008, 0x2099, 0x7b8e, 0x26a0, 0x53a6, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x355a, + 0x0078, 0x33ac, 0x1078, 0x3020, 0x007c, 0x0f7e, 0x7078, 0xa005, + 0x0040, 0x33cd, 0x2011, 0x353a, 0x1078, 0x4566, 0xa086, 0x0084, + 0x00c0, 0x33cb, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1106, 0x00c0, + 0x33cb, 0x7834, 0xa005, 0x00c0, 0x33cb, 0x7083, 0x0018, 0x1078, + 0x33cf, 0x0078, 0x33cd, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, + 0x0019, 0x1078, 0x35d0, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430, 0x2099, 0x7b8e, 0x2039, 0x7b0e, 0x27a0, 0x20a9, 0x0040, 0x53a3, 0x2728, 0x2514, 0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, 0xa205, 0x202a, 0x6030, 0x2310, 0x8214, 0xa2a0, - 0x7b0e, 0x2414, 0xa38c, 0x0001, 0x0040, 0x3402, 0xa294, 0xff00, - 0x0078, 0x3405, 0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, 0x2798, + 0x7b0e, 0x2414, 0xa38c, 0x0001, 0x0040, 0x33fa, 0xa294, 0xff00, + 0x0078, 0x33fd, 0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x0084, 0x1078, 0x3562, 0x007c, 0x0f7e, 0x7078, 0xa005, - 0x0040, 0x3439, 0x2011, 0x3542, 0x1078, 0x456e, 0xa086, 0x0084, - 0x00c0, 0x3437, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1107, 0x00c0, - 0x3437, 0x7834, 0xa005, 0x00c0, 0x3437, 0x707f, 0x0001, 0x1078, - 0x35be, 0x7083, 0x001a, 0x1078, 0x343b, 0x0078, 0x3439, 0x707b, + 0x60c3, 0x0084, 0x1078, 0x355a, 0x007c, 0x0f7e, 0x7078, 0xa005, + 0x0040, 0x3431, 0x2011, 0x353a, 0x1078, 0x4566, 0xa086, 0x0084, + 0x00c0, 0x342f, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1107, 0x00c0, + 0x342f, 0x7834, 0xa005, 0x00c0, 0x342f, 0x707f, 0x0001, 0x1078, + 0x35b6, 0x7083, 0x001a, 0x1078, 0x3433, 0x0078, 0x3431, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x7b80, 0x20a1, 0x020b, 0x7478, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, - 0x0084, 0x1078, 0x3562, 0x007c, 0x7078, 0xa005, 0x0040, 0x3460, - 0x2011, 0x3542, 0x1078, 0x456e, 0x7083, 0x001c, 0x1078, 0x3461, + 0x0084, 0x1078, 0x355a, 0x007c, 0x7078, 0xa005, 0x0040, 0x3458, + 0x2011, 0x353a, 0x1078, 0x4566, 0x7083, 0x001c, 0x1078, 0x3459, 0x007c, 0x707b, 0x0000, 0x608b, 0xbc85, 0x608f, 0xb5b5, 0x6043, - 0x0001, 0x2009, 0x07d0, 0x2011, 0x3542, 0x1078, 0x4561, 0x007c, + 0x0001, 0x2009, 0x07d0, 0x2011, 0x353a, 0x1078, 0x4559, 0x007c, 0x087e, 0x097e, 0x2029, 0x7652, 0x252c, 0x20a9, 0x0008, 0x2041, 0x7b0e, 0x28a0, 0x2099, 0x7b8e, 0x53a3, 0x20a9, 0x0008, 0x2011, - 0x0007, 0xd5d4, 0x0040, 0x3486, 0x2011, 0x0000, 0x2800, 0xa200, - 0x200c, 0xa1a6, 0xffff, 0x00c0, 0x3498, 0xd5d4, 0x0040, 0x3493, - 0x8210, 0x0078, 0x3494, 0x8211, 0x00f0, 0x3486, 0x0078, 0x34fd, - 0x82ff, 0x00c0, 0x34aa, 0xd5d4, 0x0040, 0x34a4, 0xa1a6, 0x3fff, - 0x0040, 0x3490, 0x0078, 0x34a8, 0xa1a6, 0x3fff, 0x0040, 0x34fd, + 0x0007, 0xd5d4, 0x0040, 0x347e, 0x2011, 0x0000, 0x2800, 0xa200, + 0x200c, 0xa1a6, 0xffff, 0x00c0, 0x3490, 0xd5d4, 0x0040, 0x348b, + 0x8210, 0x0078, 0x348c, 0x8211, 0x00f0, 0x347e, 0x0078, 0x34f5, + 0x82ff, 0x00c0, 0x34a2, 0xd5d4, 0x0040, 0x349c, 0xa1a6, 0x3fff, + 0x0040, 0x3488, 0x0078, 0x34a0, 0xa1a6, 0x3fff, 0x0040, 0x34f5, 0xa18d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0040, - 0x34b3, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0040, 0x34ba, 0x8423, - 0x0078, 0x34bb, 0x8424, 0x00c8, 0x34c8, 0xd5d4, 0x0040, 0x34c3, - 0x8319, 0x0078, 0x34c4, 0x8318, 0x00f0, 0x34b4, 0x0078, 0x34fd, - 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x00f0, 0x34cc, 0x2328, - 0x8529, 0xa2be, 0x0007, 0x0040, 0x34e0, 0x007e, 0x2039, 0x0007, - 0x2200, 0xa73a, 0x007f, 0x27a8, 0xa5a8, 0x0010, 0x00f0, 0x34dc, - 0x754e, 0xa5c8, 0x232f, 0x292c, 0xa5ac, 0x00ff, 0x6532, 0x60e7, + 0x34ab, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0040, 0x34b2, 0x8423, + 0x0078, 0x34b3, 0x8424, 0x00c8, 0x34c0, 0xd5d4, 0x0040, 0x34bb, + 0x8319, 0x0078, 0x34bc, 0x8318, 0x00f0, 0x34ac, 0x0078, 0x34f5, + 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x00f0, 0x34c4, 0x2328, + 0x8529, 0xa2be, 0x0007, 0x0040, 0x34d8, 0x007e, 0x2039, 0x0007, + 0x2200, 0xa73a, 0x007f, 0x27a8, 0xa5a8, 0x0010, 0x00f0, 0x34d4, + 0x754e, 0xa5c8, 0x2329, 0x292c, 0xa5ac, 0x00ff, 0x6532, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0xa405, 0x201a, 0x706f, 0x0001, 0x26a0, 0x2898, 0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0xa085, 0x0001, 0x0078, 0x3503, 0xa006, 0x0078, 0x3503, - 0xa006, 0x1078, 0x12d5, 0x097f, 0x087f, 0x007c, 0x2118, 0x2021, - 0x0000, 0x2001, 0x0007, 0xa39a, 0x0010, 0x0048, 0x3513, 0x8420, - 0x8001, 0x0078, 0x350b, 0x2118, 0x84ff, 0x0040, 0x351c, 0xa39a, - 0x0010, 0x8421, 0x00c0, 0x3517, 0x2021, 0x0001, 0x83ff, 0x0040, - 0x3525, 0x8423, 0x8319, 0x00c0, 0x3521, 0xa238, 0x2704, 0xa42c, - 0x00c0, 0x353a, 0xa405, 0x203a, 0x714e, 0xa1a0, 0x232f, 0x242c, + 0x0000, 0xa085, 0x0001, 0x0078, 0x34fb, 0xa006, 0x0078, 0x34fb, + 0xa006, 0x1078, 0x12cd, 0x097f, 0x087f, 0x007c, 0x2118, 0x2021, + 0x0000, 0x2001, 0x0007, 0xa39a, 0x0010, 0x0048, 0x350b, 0x8420, + 0x8001, 0x0078, 0x3503, 0x2118, 0x84ff, 0x0040, 0x3514, 0xa39a, + 0x0010, 0x8421, 0x00c0, 0x350f, 0x2021, 0x0001, 0x83ff, 0x0040, + 0x351d, 0x8423, 0x8319, 0x00c0, 0x3519, 0xa238, 0x2704, 0xa42c, + 0x00c0, 0x3532, 0xa405, 0x203a, 0x714e, 0xa1a0, 0x2329, 0x242c, 0xa5ac, 0x00ff, 0x6532, 0x60e7, 0x0000, 0x65ea, 0x706f, 0x0001, 0xa084, 0x0000, 0x007c, 0x0e7e, 0x2071, 0x7600, 0x7073, 0x0000, 0x0e7f, 0x007c, 0x0e7e, 0x0f7e, 0x2079, 0x0100, 0x2071, 0x0140, - 0x1078, 0x5582, 0x7004, 0xa084, 0x4000, 0x0040, 0x3553, 0x7003, + 0x1078, 0x557a, 0x7004, 0xa084, 0x4000, 0x0040, 0x354b, 0x7003, 0x1000, 0x7003, 0x0000, 0x127e, 0x2091, 0x8000, 0x2071, 0x7620, 0x2073, 0x0000, 0x7843, 0x0090, 0x7843, 0x0010, 0x127f, 0x0f7f, 0x0e7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x2011, 0x7840, 0x2013, 0x0000, 0x707b, 0x0000, 0x127f, 0x20e1, 0x9080, 0x60a3, 0x0056, - 0x60a7, 0x9575, 0x1078, 0x5579, 0x2009, 0x07d0, 0x2011, 0x3542, - 0x1078, 0x45fe, 0x007c, 0x017e, 0x027e, 0x0c7e, 0x127e, 0x2091, - 0x8000, 0x2009, 0x00f7, 0x1078, 0x35e4, 0x2061, 0x7849, 0x601b, + 0x60a7, 0x9575, 0x1078, 0x5571, 0x2009, 0x07d0, 0x2011, 0x353a, + 0x1078, 0x45f6, 0x007c, 0x017e, 0x027e, 0x0c7e, 0x127e, 0x2091, + 0x8000, 0x2009, 0x00f7, 0x1078, 0x35dc, 0x2061, 0x7849, 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0x7600, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x001e, 0x2011, - 0x35a0, 0x1078, 0x4561, 0x127f, 0x0c7f, 0x027f, 0x017f, 0x007c, + 0x3598, 0x1078, 0x4559, 0x127f, 0x0c7f, 0x027f, 0x017f, 0x007c, 0x0e7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0x0100, 0x1078, - 0x5582, 0x2071, 0x0140, 0x7004, 0xa084, 0x4000, 0x0040, 0x35b4, - 0x7003, 0x1000, 0x7003, 0x0000, 0x2001, 0x0001, 0x1078, 0x202b, - 0x1078, 0x357b, 0x127f, 0x007f, 0x0e7f, 0x007c, 0x20a9, 0x0040, + 0x557a, 0x2071, 0x0140, 0x7004, 0xa084, 0x4000, 0x0040, 0x35ac, + 0x7003, 0x1000, 0x7003, 0x0000, 0x2001, 0x0001, 0x1078, 0x2025, + 0x1078, 0x3573, 0x127f, 0x007f, 0x0e7f, 0x007c, 0x20a9, 0x0040, 0x20a1, 0x7cc0, 0x2099, 0x7b8e, 0x3304, 0x8007, 0x20a2, 0x9398, - 0x94a0, 0x00f0, 0x35c4, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x94a0, 0x00f0, 0x35bc, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x7b00, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x7b80, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x007c, 0x0c7e, 0x007e, 0x2061, 0x0100, - 0x810f, 0x2001, 0x762c, 0x2004, 0xa005, 0x00c0, 0x35f5, 0x6030, - 0xa084, 0x00ff, 0xa105, 0x0078, 0x35f7, 0xa185, 0x00f7, 0x604a, + 0x810f, 0x2001, 0x762c, 0x2004, 0xa005, 0x00c0, 0x35ed, 0x6030, + 0xa084, 0x00ff, 0xa105, 0x0078, 0x35ef, 0xa185, 0x00f7, 0x604a, 0x007f, 0x0c7f, 0x007c, 0x017e, 0x047e, 0x2001, 0x7652, 0x2004, - 0xd0a4, 0x0040, 0x360e, 0xa006, 0x2020, 0x2009, 0x002a, 0x1078, - 0x7541, 0x2001, 0x760c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, - 0x1078, 0x2299, 0x047f, 0x017f, 0x007c, 0x157e, 0x20a9, 0x00ff, - 0x2009, 0x7720, 0xa006, 0x200a, 0x8108, 0x00f0, 0x361b, 0x157f, + 0xd0a4, 0x0040, 0x3606, 0xa006, 0x2020, 0x2009, 0x002a, 0x1078, + 0x7536, 0x2001, 0x760c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, + 0x1078, 0x2293, 0x047f, 0x017f, 0x007c, 0x157e, 0x20a9, 0x00ff, + 0x2009, 0x7720, 0xa006, 0x200a, 0x8108, 0x00f0, 0x3613, 0x157f, 0x007c, 0x0d7e, 0x037e, 0x157e, 0x137e, 0x147e, 0x2069, 0x7651, 0xa006, 0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0xa198, - 0x232f, 0x231c, 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98, + 0x2329, 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, @@ -1256,500 +1237,500 @@ 0x61a2, 0x604a, 0x6810, 0x603a, 0x680c, 0x6046, 0x6814, 0xa084, 0x00ff, 0x6042, 0x147f, 0x137f, 0x157f, 0x037f, 0x0d7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x6944, 0xa1b4, 0x00ff, 0xa682, 0x0010, - 0x00c8, 0x3715, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x00c8, - 0x371b, 0x2001, 0x760c, 0x2004, 0xa084, 0x0003, 0x00c0, 0x36fe, - 0xa188, 0x7720, 0x2104, 0xa065, 0x0040, 0x36ec, 0x6004, 0xa084, - 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x36f2, 0x6078, 0xa00d, 0x0040, - 0x3697, 0xa680, 0x75d5, 0x2004, 0xa10c, 0x00c0, 0x36e6, 0x607c, - 0xa00d, 0x0040, 0x36b3, 0xa680, 0x75d5, 0x2004, 0xa10c, 0x0040, - 0x36b3, 0x694c, 0xd1fc, 0x00c0, 0x36a9, 0x1078, 0x37ae, 0x0078, - 0x36e1, 0x1078, 0x377f, 0x694c, 0xd1ec, 0x00c0, 0x36e1, 0x1078, - 0x38c7, 0x0078, 0x36e1, 0x694c, 0xa184, 0xa000, 0x0040, 0x36d1, - 0xd1ec, 0x0040, 0x36ca, 0xd1fc, 0x0040, 0x36c2, 0x1078, 0x38de, - 0x0078, 0x36cd, 0xa680, 0x75d5, 0x200c, 0x607c, 0xa105, 0x607e, - 0x0078, 0x36d1, 0xd1fc, 0x0040, 0x36d1, 0x1078, 0x377f, 0x0078, - 0x36e1, 0x6050, 0xa00d, 0x0040, 0x36dc, 0x2d00, 0x200a, 0x6803, - 0x0000, 0x6052, 0x0078, 0x36e1, 0x2d00, 0x6052, 0x604e, 0x6803, - 0x0000, 0x1078, 0x4844, 0xa006, 0x127f, 0x007c, 0x2001, 0x0005, - 0x2009, 0x0000, 0x0078, 0x371f, 0x2001, 0x0028, 0x2009, 0x0000, - 0x0078, 0x371f, 0xa082, 0x0006, 0x00c8, 0x36fe, 0x60a0, 0xd0bc, - 0x0040, 0x368d, 0x2001, 0x0028, 0x0078, 0x3711, 0x2009, 0x760c, - 0x210c, 0xd18c, 0x0040, 0x3708, 0x2001, 0x0004, 0x0078, 0x3711, - 0xd184, 0x0040, 0x370f, 0x2001, 0x0004, 0x0078, 0x3711, 0x2001, - 0x0029, 0x2009, 0x0000, 0x0078, 0x371f, 0x2001, 0x0029, 0x2009, - 0x0000, 0x0078, 0x371f, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, + 0x00c8, 0x370d, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x00c8, + 0x3713, 0x2001, 0x760c, 0x2004, 0xa084, 0x0003, 0x00c0, 0x36f6, + 0xa188, 0x7720, 0x2104, 0xa065, 0x0040, 0x36e4, 0x6004, 0xa084, + 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x36ea, 0x6078, 0xa00d, 0x0040, + 0x368f, 0xa680, 0x75ca, 0x2004, 0xa10c, 0x00c0, 0x36de, 0x607c, + 0xa00d, 0x0040, 0x36ab, 0xa680, 0x75ca, 0x2004, 0xa10c, 0x0040, + 0x36ab, 0x694c, 0xd1fc, 0x00c0, 0x36a1, 0x1078, 0x37a6, 0x0078, + 0x36d9, 0x1078, 0x3777, 0x694c, 0xd1ec, 0x00c0, 0x36d9, 0x1078, + 0x38bf, 0x0078, 0x36d9, 0x694c, 0xa184, 0xa000, 0x0040, 0x36c9, + 0xd1ec, 0x0040, 0x36c2, 0xd1fc, 0x0040, 0x36ba, 0x1078, 0x38d6, + 0x0078, 0x36c5, 0xa680, 0x75ca, 0x200c, 0x607c, 0xa105, 0x607e, + 0x0078, 0x36c9, 0xd1fc, 0x0040, 0x36c9, 0x1078, 0x3777, 0x0078, + 0x36d9, 0x6050, 0xa00d, 0x0040, 0x36d4, 0x2d00, 0x200a, 0x6803, + 0x0000, 0x6052, 0x0078, 0x36d9, 0x2d00, 0x6052, 0x604e, 0x6803, + 0x0000, 0x1078, 0x483c, 0xa006, 0x127f, 0x007c, 0x2001, 0x0005, + 0x2009, 0x0000, 0x0078, 0x3717, 0x2001, 0x0028, 0x2009, 0x0000, + 0x0078, 0x3717, 0xa082, 0x0006, 0x00c8, 0x36f6, 0x60a0, 0xd0bc, + 0x0040, 0x3685, 0x2001, 0x0028, 0x0078, 0x3709, 0x2009, 0x760c, + 0x210c, 0xd18c, 0x0040, 0x3700, 0x2001, 0x0004, 0x0078, 0x3709, + 0xd184, 0x0040, 0x3707, 0x2001, 0x0004, 0x0078, 0x3709, 0x2001, + 0x0029, 0x2009, 0x0000, 0x0078, 0x3717, 0x2001, 0x0029, 0x2009, + 0x0000, 0x0078, 0x3717, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x127f, 0x007c, 0x6944, 0xa1b4, 0x00ff, 0xa682, 0x0010, 0x00c8, - 0x3764, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x00c8, 0x3754, - 0xa188, 0x7720, 0x2104, 0xa065, 0x0040, 0x3754, 0x6004, 0xa084, - 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x375a, 0x684c, 0xd0ec, 0x0040, - 0x3747, 0x1078, 0x38de, 0x1078, 0x377f, 0x0078, 0x374f, 0x1078, - 0x377f, 0x684c, 0xd0fc, 0x0040, 0x374f, 0x1078, 0x38c7, 0x1078, - 0x38f2, 0xa006, 0x0078, 0x3768, 0x2001, 0x0028, 0x2009, 0x0000, - 0x0078, 0x3768, 0xa082, 0x0006, 0x0048, 0x373d, 0x2001, 0x0029, - 0x2009, 0x0000, 0x0078, 0x3768, 0x2001, 0x0029, 0x2009, 0x0000, + 0x375c, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x00c8, 0x374c, + 0xa188, 0x7720, 0x2104, 0xa065, 0x0040, 0x374c, 0x6004, 0xa084, + 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x3752, 0x684c, 0xd0ec, 0x0040, + 0x373f, 0x1078, 0x38d6, 0x1078, 0x3777, 0x0078, 0x3747, 0x1078, + 0x3777, 0x684c, 0xd0fc, 0x0040, 0x3747, 0x1078, 0x38bf, 0x1078, + 0x38ea, 0xa006, 0x0078, 0x3760, 0x2001, 0x0028, 0x2009, 0x0000, + 0x0078, 0x3760, 0xa082, 0x0006, 0x0048, 0x3735, 0x2001, 0x0029, + 0x2009, 0x0000, 0x0078, 0x3760, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x007c, 0x127e, 0x2091, 0x8000, 0x6050, 0xa00d, 0x0040, - 0x3778, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x127f, 0x007c, - 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0078, 0x3776, 0x127e, - 0x2091, 0x8000, 0x604c, 0xa005, 0x0040, 0x378b, 0x6802, 0x2d00, + 0x3770, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x127f, 0x007c, + 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0078, 0x376e, 0x127e, + 0x2091, 0x8000, 0x604c, 0xa005, 0x0040, 0x3783, 0x6802, 0x2d00, 0x604e, 0x127f, 0x007c, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, - 0x0078, 0x3789, 0x127e, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0040, - 0x37a0, 0x6800, 0xa005, 0x00c0, 0x379e, 0x6052, 0x604e, 0xad05, - 0x127f, 0x007c, 0x604c, 0xa06d, 0x0040, 0x37ad, 0x6800, 0xa005, - 0x00c0, 0x37ab, 0x6052, 0x604e, 0xad05, 0x007c, 0x6803, 0x0000, - 0x6084, 0xa00d, 0x0040, 0x37b8, 0x2d00, 0x200a, 0x6086, 0x007c, - 0x2d00, 0x6086, 0x6082, 0x0078, 0x37b7, 0x127e, 0x0c7e, 0x027e, - 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0040, 0x37cb, - 0xc285, 0x0078, 0x37cc, 0xc284, 0x6202, 0x027f, 0x0c7f, 0x127f, + 0x0078, 0x3781, 0x127e, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0040, + 0x3798, 0x6800, 0xa005, 0x00c0, 0x3796, 0x6052, 0x604e, 0xad05, + 0x127f, 0x007c, 0x604c, 0xa06d, 0x0040, 0x37a5, 0x6800, 0xa005, + 0x00c0, 0x37a3, 0x6052, 0x604e, 0xad05, 0x007c, 0x6803, 0x0000, + 0x6084, 0xa00d, 0x0040, 0x37b0, 0x2d00, 0x200a, 0x6086, 0x007c, + 0x2d00, 0x6086, 0x6082, 0x0078, 0x37af, 0x127e, 0x0c7e, 0x027e, + 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0040, 0x37c3, + 0xc285, 0x0078, 0x37c4, 0xc284, 0x6202, 0x027f, 0x0c7f, 0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0xa294, 0xff00, 0xa215, 0x6206, 0x0c7f, 0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0xa294, 0x00ff, 0x8007, 0xa215, 0x6206, 0x0c7f, 0x127f, 0x007c, 0x027e, 0xa182, - 0x00ff, 0x0048, 0x37f7, 0xa085, 0x0001, 0x0078, 0x380b, 0xa190, - 0x7720, 0x2204, 0xa065, 0x00c0, 0x380a, 0x017e, 0x0d7e, 0x1078, - 0x1314, 0x2d60, 0x0d7f, 0x017f, 0x0040, 0x37f3, 0x2c00, 0x2012, - 0x1078, 0x3621, 0xa006, 0x027f, 0x007c, 0x027e, 0xa182, 0x00ff, - 0x0048, 0x3816, 0xa085, 0x0001, 0x0078, 0x3823, 0x0d7e, 0xa190, - 0x7720, 0x2204, 0xa06d, 0x0040, 0x3821, 0x2013, 0x0000, 0x1078, - 0x1348, 0x0d7f, 0xa006, 0x027f, 0x007c, 0x017e, 0xa182, 0x00ff, - 0x0048, 0x382e, 0xa085, 0x0001, 0x0078, 0x3835, 0xa188, 0x7720, - 0x2104, 0xa065, 0x0040, 0x382a, 0xa006, 0x017f, 0x007c, 0x0d7e, + 0x00ff, 0x0048, 0x37ef, 0xa085, 0x0001, 0x0078, 0x3803, 0xa190, + 0x7720, 0x2204, 0xa065, 0x00c0, 0x3802, 0x017e, 0x0d7e, 0x1078, + 0x130c, 0x2d60, 0x0d7f, 0x017f, 0x0040, 0x37eb, 0x2c00, 0x2012, + 0x1078, 0x3619, 0xa006, 0x027f, 0x007c, 0x027e, 0xa182, 0x00ff, + 0x0048, 0x380e, 0xa085, 0x0001, 0x0078, 0x381b, 0x0d7e, 0xa190, + 0x7720, 0x2204, 0xa06d, 0x0040, 0x3819, 0x2013, 0x0000, 0x1078, + 0x1340, 0x0d7f, 0xa006, 0x027f, 0x007c, 0x017e, 0xa182, 0x00ff, + 0x0048, 0x3826, 0xa085, 0x0001, 0x0078, 0x382d, 0xa188, 0x7720, + 0x2104, 0xa065, 0x0040, 0x3822, 0xa006, 0x017f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x600b, 0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, 0x6002, 0x2069, 0x7b8e, 0x6808, 0x605e, 0x6810, 0x6062, - 0x6138, 0xa10a, 0x0048, 0x384d, 0x603a, 0x6814, 0x6066, 0x2099, + 0x6138, 0xa10a, 0x0048, 0x3845, 0x603a, 0x6814, 0x6066, 0x2099, 0x7b96, 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099, 0x7b9a, 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069, 0x7bae, 0x6808, 0x606a, 0x690c, 0x616e, 0x6810, 0x6072, 0x6818, - 0x6076, 0xa182, 0x0211, 0x00c8, 0x3871, 0x2009, 0x0008, 0x0078, - 0x389b, 0xa182, 0x0259, 0x00c8, 0x3879, 0x2009, 0x0007, 0x0078, - 0x389b, 0xa182, 0x02c1, 0x00c8, 0x3881, 0x2009, 0x0006, 0x0078, - 0x389b, 0xa182, 0x0349, 0x00c8, 0x3889, 0x2009, 0x0005, 0x0078, - 0x389b, 0xa182, 0x0421, 0x00c8, 0x3891, 0x2009, 0x0004, 0x0078, - 0x389b, 0xa182, 0x0581, 0x00c8, 0x3899, 0x2009, 0x0003, 0x0078, - 0x389b, 0x2009, 0x0002, 0x6192, 0x147f, 0x137f, 0x157f, 0x0d7f, + 0x6076, 0xa182, 0x0211, 0x00c8, 0x3869, 0x2009, 0x0008, 0x0078, + 0x3893, 0xa182, 0x0259, 0x00c8, 0x3871, 0x2009, 0x0007, 0x0078, + 0x3893, 0xa182, 0x02c1, 0x00c8, 0x3879, 0x2009, 0x0006, 0x0078, + 0x3893, 0xa182, 0x0349, 0x00c8, 0x3881, 0x2009, 0x0005, 0x0078, + 0x3893, 0xa182, 0x0421, 0x00c8, 0x3889, 0x2009, 0x0004, 0x0078, + 0x3893, 0xa182, 0x0581, 0x00c8, 0x3891, 0x2009, 0x0003, 0x0078, + 0x3893, 0x2009, 0x0002, 0x6192, 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x0e7e, 0x2071, 0x7b8d, 0x2e04, 0x6896, 0x2071, 0x7b8e, - 0x7004, 0x689a, 0x701c, 0x689e, 0x0e7f, 0x007c, 0x2001, 0x75d5, + 0x7004, 0x689a, 0x701c, 0x689e, 0x0e7f, 0x007c, 0x2001, 0x75ca, 0xa600, 0x2004, 0x127e, 0x2091, 0x8000, 0x6178, 0xa10d, 0x617a, - 0x127f, 0x007c, 0x2001, 0x75d5, 0xa600, 0x2004, 0x8002, 0x127e, + 0x127f, 0x007c, 0x2001, 0x75ca, 0xa600, 0x2004, 0x8002, 0x127e, 0x2091, 0x8000, 0x6178, 0xa10c, 0x617a, 0x127f, 0x007c, 0x2001, - 0x75d5, 0xa600, 0x2004, 0x8002, 0x127e, 0x2091, 0x8000, 0x617c, - 0xa10c, 0x617e, 0x127f, 0x0078, 0x38d7, 0x1078, 0x376a, 0x1078, - 0x3938, 0x00c0, 0x38d5, 0x1078, 0x38f2, 0x007c, 0x2001, 0x75d5, + 0x75ca, 0xa600, 0x2004, 0x8002, 0x127e, 0x2091, 0x8000, 0x617c, + 0xa10c, 0x617e, 0x127f, 0x0078, 0x38cf, 0x1078, 0x3762, 0x1078, + 0x3930, 0x00c0, 0x38cd, 0x1078, 0x38ea, 0x007c, 0x2001, 0x75ca, 0xa600, 0x2004, 0x127e, 0x2091, 0x8000, 0x617c, 0xa10d, 0x617e, - 0x127f, 0x0078, 0x38ed, 0x1078, 0x37ae, 0x1078, 0x38fc, 0x00c0, - 0x38eb, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x4844, 0x127f, - 0x007c, 0xa01e, 0x0078, 0x38fe, 0x2019, 0x0001, 0xa00e, 0x127e, - 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x00c0, 0x391e, - 0x8dff, 0x0040, 0x3933, 0x83ff, 0x0040, 0x3916, 0x6844, 0xa084, - 0x00ff, 0xa606, 0x0040, 0x3923, 0x0078, 0x391e, 0x683c, 0xa406, - 0x00c0, 0x391e, 0x6840, 0xa506, 0x0040, 0x3923, 0x2d08, 0x6800, - 0x2068, 0x0078, 0x3908, 0x6a00, 0x604c, 0xad06, 0x00c0, 0x392b, - 0x624e, 0x0078, 0x392e, 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, - 0x3933, 0x6152, 0x8dff, 0x127f, 0x007c, 0xa01e, 0x0078, 0x393a, - 0x2019, 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x0040, 0x3968, - 0x83ff, 0x0040, 0x394b, 0x6844, 0xa084, 0x00ff, 0xa606, 0x0040, - 0x3958, 0x0078, 0x3953, 0x683c, 0xa406, 0x00c0, 0x3953, 0x6840, - 0xa506, 0x0040, 0x3958, 0x2d08, 0x6800, 0x2068, 0x0078, 0x393d, - 0x6a00, 0x6080, 0xad06, 0x00c0, 0x3960, 0x6282, 0x0078, 0x3963, - 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, 0x3968, 0x6186, 0x8dff, - 0x007c, 0x2001, 0x75d5, 0xa600, 0x2004, 0x6178, 0xa10c, 0x0040, - 0x3973, 0x2011, 0x0001, 0x617c, 0xa10c, 0x0040, 0x3979, 0xa295, - 0x0002, 0x007c, 0x1078, 0x39c5, 0x0040, 0x3982, 0x1078, 0x6a16, - 0x0078, 0x3984, 0xa085, 0x0001, 0x007c, 0x1078, 0x39c5, 0x0040, - 0x398d, 0x1078, 0x69a5, 0x0078, 0x398f, 0xa085, 0x0001, 0x007c, - 0x1078, 0x39c5, 0x0040, 0x3998, 0x1078, 0x69eb, 0x0078, 0x399a, - 0xa085, 0x0001, 0x007c, 0x1078, 0x39c5, 0x0040, 0x39a3, 0x1078, - 0x69c1, 0x0078, 0x39a5, 0xa085, 0x0001, 0x007c, 0x127e, 0x007e, - 0x0d7e, 0x2091, 0x8000, 0x6080, 0xa06d, 0x0040, 0x39bd, 0x6800, - 0x007e, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x6b3f, - 0x1078, 0x3a7a, 0x007f, 0x0078, 0x39ac, 0x6083, 0x0000, 0x6087, + 0x127f, 0x0078, 0x38e5, 0x1078, 0x37a6, 0x1078, 0x38f4, 0x00c0, + 0x38e3, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x483c, 0x127f, + 0x007c, 0xa01e, 0x0078, 0x38f6, 0x2019, 0x0001, 0xa00e, 0x127e, + 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x00c0, 0x3916, + 0x8dff, 0x0040, 0x392b, 0x83ff, 0x0040, 0x390e, 0x6844, 0xa084, + 0x00ff, 0xa606, 0x0040, 0x391b, 0x0078, 0x3916, 0x683c, 0xa406, + 0x00c0, 0x3916, 0x6840, 0xa506, 0x0040, 0x391b, 0x2d08, 0x6800, + 0x2068, 0x0078, 0x3900, 0x6a00, 0x604c, 0xad06, 0x00c0, 0x3923, + 0x624e, 0x0078, 0x3926, 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, + 0x392b, 0x6152, 0x8dff, 0x127f, 0x007c, 0xa01e, 0x0078, 0x3932, + 0x2019, 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x0040, 0x3960, + 0x83ff, 0x0040, 0x3943, 0x6844, 0xa084, 0x00ff, 0xa606, 0x0040, + 0x3950, 0x0078, 0x394b, 0x683c, 0xa406, 0x00c0, 0x394b, 0x6840, + 0xa506, 0x0040, 0x3950, 0x2d08, 0x6800, 0x2068, 0x0078, 0x3935, + 0x6a00, 0x6080, 0xad06, 0x00c0, 0x3958, 0x6282, 0x0078, 0x395b, + 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, 0x3960, 0x6186, 0x8dff, + 0x007c, 0x2001, 0x75ca, 0xa600, 0x2004, 0x6178, 0xa10c, 0x0040, + 0x396b, 0x2011, 0x0001, 0x617c, 0xa10c, 0x0040, 0x3971, 0xa295, + 0x0002, 0x007c, 0x1078, 0x39bd, 0x0040, 0x397a, 0x1078, 0x6a0b, + 0x0078, 0x397c, 0xa085, 0x0001, 0x007c, 0x1078, 0x39bd, 0x0040, + 0x3985, 0x1078, 0x699a, 0x0078, 0x3987, 0xa085, 0x0001, 0x007c, + 0x1078, 0x39bd, 0x0040, 0x3990, 0x1078, 0x69e0, 0x0078, 0x3992, + 0xa085, 0x0001, 0x007c, 0x1078, 0x39bd, 0x0040, 0x399b, 0x1078, + 0x69b6, 0x0078, 0x399d, 0xa085, 0x0001, 0x007c, 0x127e, 0x007e, + 0x0d7e, 0x2091, 0x8000, 0x6080, 0xa06d, 0x0040, 0x39b5, 0x6800, + 0x007e, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x6b34, + 0x1078, 0x3a72, 0x007f, 0x0078, 0x39a4, 0x6083, 0x0000, 0x6087, 0x0000, 0x0d7f, 0x007f, 0x127f, 0x007c, 0x609c, 0xd0a4, 0x007c, - 0x0f7e, 0x2079, 0x7651, 0x7804, 0xd0a4, 0x0040, 0x39f1, 0x157e, - 0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x3825, - 0x00c0, 0x39e5, 0x6004, 0xa084, 0xff00, 0x8007, 0xa086, 0x0006, - 0x00c0, 0x39e5, 0x6000, 0xc0ed, 0x6002, 0x017f, 0x8108, 0x00f0, - 0x39d5, 0x0c7f, 0x157f, 0x2009, 0x07d0, 0x2011, 0x39f3, 0x1078, - 0x45fe, 0x0f7f, 0x007c, 0x2011, 0x39f3, 0x1078, 0x456e, 0x157e, - 0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x3825, - 0x00c0, 0x3a1f, 0x6000, 0xd0ec, 0x0040, 0x3a1f, 0x047e, 0x62a0, - 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, 0x1078, 0x7541, - 0x6000, 0xc0e5, 0xc0ec, 0x6002, 0x2019, 0x0029, 0x1078, 0x4962, - 0x1078, 0x48a5, 0x2009, 0x0000, 0x1078, 0x737b, 0x047f, 0x017f, - 0x8108, 0x00f0, 0x39fd, 0x0c7f, 0x157f, 0x007c, 0x0c7e, 0x6018, + 0x0f7e, 0x2079, 0x7651, 0x7804, 0xd0a4, 0x0040, 0x39e9, 0x157e, + 0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x381d, + 0x00c0, 0x39dd, 0x6004, 0xa084, 0xff00, 0x8007, 0xa086, 0x0006, + 0x00c0, 0x39dd, 0x6000, 0xc0ed, 0x6002, 0x017f, 0x8108, 0x00f0, + 0x39cd, 0x0c7f, 0x157f, 0x2009, 0x07d0, 0x2011, 0x39eb, 0x1078, + 0x45f6, 0x0f7f, 0x007c, 0x2011, 0x39eb, 0x1078, 0x4566, 0x157e, + 0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x381d, + 0x00c0, 0x3a17, 0x6000, 0xd0ec, 0x0040, 0x3a17, 0x047e, 0x62a0, + 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, 0x1078, 0x7536, + 0x6000, 0xc0e5, 0xc0ec, 0x6002, 0x2019, 0x0029, 0x1078, 0x495a, + 0x1078, 0x489d, 0x2009, 0x0000, 0x1078, 0x7370, 0x047f, 0x017f, + 0x8108, 0x00f0, 0x39f5, 0x0c7f, 0x157f, 0x007c, 0x0c7e, 0x6018, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x0c7f, 0x007c, 0x2071, 0x76ff, 0x7003, 0x0001, 0x7007, 0x0000, 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b, 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x007c, 0x0e7e, - 0x2071, 0x76ff, 0x684c, 0xa005, 0x00c0, 0x3a55, 0x7028, 0xc085, - 0x702a, 0xa085, 0x0001, 0x0078, 0x3a78, 0x6a60, 0x7236, 0x6b64, + 0x2071, 0x76ff, 0x684c, 0xa005, 0x00c0, 0x3a4d, 0x7028, 0xc085, + 0x702a, 0xa085, 0x0001, 0x0078, 0x3a70, 0x6a60, 0x7236, 0x6b64, 0x733a, 0x6868, 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e, 0x6844, 0x7032, 0x2009, 0x000d, 0x200a, 0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006, - 0x0e7f, 0x007c, 0x0e7e, 0x6838, 0xd0fc, 0x00c0, 0x3acb, 0x6804, - 0xa00d, 0x0040, 0x3a99, 0x0d7e, 0x0e7e, 0x2071, 0x7600, 0x027e, + 0x0e7f, 0x007c, 0x0e7e, 0x6838, 0xd0fc, 0x00c0, 0x3ac3, 0x6804, + 0xa00d, 0x0040, 0x3a91, 0x0d7e, 0x0e7e, 0x2071, 0x7600, 0x027e, 0xa016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, - 0x00c0, 0x3a8a, 0x702e, 0x70a0, 0xa200, 0x70a2, 0x027f, 0x0e7f, - 0x0d7f, 0x2071, 0x76ff, 0x701c, 0xa005, 0x00c0, 0x3adc, 0x0068, - 0x3ada, 0x2071, 0x7651, 0x7004, 0xd09c, 0x0040, 0x3ada, 0x6934, - 0xa186, 0x0103, 0x00c0, 0x3aed, 0x6948, 0x6844, 0xa105, 0x00c0, - 0x3acd, 0x2009, 0x8020, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, - 0x3ada, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, + 0x00c0, 0x3a82, 0x702e, 0x70a0, 0xa200, 0x70a2, 0x027f, 0x0e7f, + 0x0d7f, 0x2071, 0x76ff, 0x701c, 0xa005, 0x00c0, 0x3ad4, 0x0068, + 0x3ad2, 0x2071, 0x7651, 0x7004, 0xd09c, 0x0040, 0x3ad2, 0x6934, + 0xa186, 0x0103, 0x00c0, 0x3ae5, 0x6948, 0x6844, 0xa105, 0x00c0, + 0x3ac5, 0x2009, 0x8020, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, + 0x3ad2, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x2071, 0x7600, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70a0, 0x8000, 0x70a2, 0x0e7f, 0x007c, 0x6844, 0xa086, 0x0100, - 0x00c0, 0x3ada, 0x6868, 0xa005, 0x00c0, 0x3ada, 0x2009, 0x8020, - 0x0078, 0x3ab3, 0x2071, 0x76ff, 0x2d08, 0x206b, 0x0000, 0x7010, - 0x8000, 0x7012, 0x7018, 0xa06d, 0x711a, 0x0040, 0x3aea, 0x6902, - 0x0078, 0x3aeb, 0x711e, 0x0078, 0x3acb, 0xa18c, 0x00ff, 0xa186, - 0x0017, 0x0040, 0x3afb, 0xa186, 0x001e, 0x0040, 0x3afb, 0xa18e, - 0x001f, 0x00c0, 0x3ada, 0x684c, 0xd0cc, 0x0040, 0x3ada, 0x6850, - 0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0, 0x3ada, 0x2009, 0x8021, - 0x0078, 0x3ab3, 0x007e, 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80, + 0x00c0, 0x3ad2, 0x6868, 0xa005, 0x00c0, 0x3ad2, 0x2009, 0x8020, + 0x0078, 0x3aab, 0x2071, 0x76ff, 0x2d08, 0x206b, 0x0000, 0x7010, + 0x8000, 0x7012, 0x7018, 0xa06d, 0x711a, 0x0040, 0x3ae2, 0x6902, + 0x0078, 0x3ae3, 0x711e, 0x0078, 0x3ac3, 0xa18c, 0x00ff, 0xa186, + 0x0017, 0x0040, 0x3af3, 0xa186, 0x001e, 0x0040, 0x3af3, 0xa18e, + 0x001f, 0x00c0, 0x3ad2, 0x684c, 0xd0cc, 0x0040, 0x3ad2, 0x6850, + 0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0, 0x3ad2, 0x2009, 0x8021, + 0x0078, 0x3aab, 0x007e, 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80, 0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x007f, 0x684a, 0x6952, - 0x007c, 0x2071, 0x76ff, 0x7004, 0x0079, 0x3b1e, 0x3b26, 0x3b35, - 0x3bc5, 0x3bc6, 0x3bd6, 0x3bdc, 0x3b27, 0x3bb3, 0x007c, 0x127e, - 0x2091, 0x8000, 0x0068, 0x3b34, 0x2009, 0x000d, 0x7030, 0x200a, + 0x007c, 0x2071, 0x76ff, 0x7004, 0x0079, 0x3b16, 0x3b1e, 0x3b2d, + 0x3bbd, 0x3bbe, 0x3bce, 0x3bd4, 0x3b1f, 0x3bab, 0x007c, 0x127e, + 0x2091, 0x8000, 0x0068, 0x3b2c, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, 0x4080, 0x7007, 0x0001, 0x127f, 0x701c, 0xa06d, 0x0040, - 0x3bb2, 0x0e7e, 0x2071, 0x7651, 0x7004, 0xd09c, 0x0040, 0x3b94, - 0x6934, 0xa186, 0x0103, 0x00c0, 0x3b6a, 0x6948, 0x6844, 0xa105, - 0x00c0, 0x3b87, 0x2009, 0x8020, 0x127e, 0x2091, 0x8000, 0x0068, - 0x3b66, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x3b66, 0x7122, + 0x3baa, 0x0e7e, 0x2071, 0x7651, 0x7004, 0xd09c, 0x0040, 0x3b8c, + 0x6934, 0xa186, 0x0103, 0x00c0, 0x3b62, 0x6948, 0x6844, 0xa105, + 0x00c0, 0x3b7f, 0x2009, 0x8020, 0x127e, 0x2091, 0x8000, 0x0068, + 0x3b5e, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x3b5e, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, - 0x127f, 0x0e7f, 0x1078, 0x3c0f, 0x0078, 0x3bb2, 0x127f, 0x0e7f, - 0x0078, 0x3bb2, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0040, 0x3b78, - 0xa186, 0x001e, 0x0040, 0x3b78, 0xa18e, 0x001f, 0x00c0, 0x3b94, - 0x684c, 0xd0cc, 0x0040, 0x3b94, 0x6850, 0xa084, 0x00ff, 0xa086, - 0x0001, 0x00c0, 0x3b94, 0x2009, 0x8021, 0x0078, 0x3b4c, 0x6844, - 0xa086, 0x0100, 0x00c0, 0x3b94, 0x6868, 0xa005, 0x00c0, 0x3b94, - 0x2009, 0x8020, 0x0078, 0x3b4c, 0x0e7f, 0x1078, 0x3c23, 0x0040, - 0x3bb2, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, - 0x00c0, 0x3ba9, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0040, 0x3ba9, - 0x710e, 0x7007, 0x0003, 0x1078, 0x3c43, 0x7050, 0xa086, 0x0100, - 0x0040, 0x3bc6, 0x007c, 0x701c, 0xa06d, 0x0040, 0x3bc4, 0x1078, - 0x3c23, 0x0040, 0x3bc4, 0x7007, 0x0003, 0x1078, 0x3c43, 0x7050, - 0xa086, 0x0100, 0x0040, 0x3bc6, 0x007c, 0x007c, 0x7050, 0xa09e, - 0x0100, 0x00c0, 0x3bcf, 0x7007, 0x0004, 0x0078, 0x3bd6, 0xa086, - 0x0200, 0x00c0, 0x3bd5, 0x7007, 0x0005, 0x007c, 0x1078, 0x3bdd, - 0x7006, 0x1078, 0x3c0f, 0x007c, 0x007c, 0x702c, 0x7130, 0x8108, - 0xa102, 0x0048, 0x3bea, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, - 0x0078, 0x3bf4, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x3bf4, + 0x127f, 0x0e7f, 0x1078, 0x3c07, 0x0078, 0x3baa, 0x127f, 0x0e7f, + 0x0078, 0x3baa, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0040, 0x3b70, + 0xa186, 0x001e, 0x0040, 0x3b70, 0xa18e, 0x001f, 0x00c0, 0x3b8c, + 0x684c, 0xd0cc, 0x0040, 0x3b8c, 0x6850, 0xa084, 0x00ff, 0xa086, + 0x0001, 0x00c0, 0x3b8c, 0x2009, 0x8021, 0x0078, 0x3b44, 0x6844, + 0xa086, 0x0100, 0x00c0, 0x3b8c, 0x6868, 0xa005, 0x00c0, 0x3b8c, + 0x2009, 0x8020, 0x0078, 0x3b44, 0x0e7f, 0x1078, 0x3c1b, 0x0040, + 0x3baa, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, + 0x00c0, 0x3ba1, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0040, 0x3ba1, + 0x710e, 0x7007, 0x0003, 0x1078, 0x3c3b, 0x7050, 0xa086, 0x0100, + 0x0040, 0x3bbe, 0x007c, 0x701c, 0xa06d, 0x0040, 0x3bbc, 0x1078, + 0x3c1b, 0x0040, 0x3bbc, 0x7007, 0x0003, 0x1078, 0x3c3b, 0x7050, + 0xa086, 0x0100, 0x0040, 0x3bbe, 0x007c, 0x007c, 0x7050, 0xa09e, + 0x0100, 0x00c0, 0x3bc7, 0x7007, 0x0004, 0x0078, 0x3bce, 0xa086, + 0x0200, 0x00c0, 0x3bcd, 0x7007, 0x0005, 0x007c, 0x1078, 0x3bd5, + 0x7006, 0x1078, 0x3c07, 0x007c, 0x007c, 0x702c, 0x7130, 0x8108, + 0xa102, 0x0048, 0x3be2, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, + 0x0078, 0x3bec, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x3bec, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, 0x8001, 0x700e, - 0x00c0, 0x3c08, 0x127e, 0x2091, 0x8000, 0x0068, 0x3c0b, 0x2001, + 0x00c0, 0x3c00, 0x127e, 0x2091, 0x8000, 0x0068, 0x3c03, 0x2001, 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x127f, 0x007c, 0x2001, 0x0007, 0x007c, 0x2001, 0x0006, 0x127f, 0x007c, 0x701c, - 0xa06d, 0x0040, 0x3c22, 0x127e, 0x2091, 0x8000, 0x7010, 0x8001, - 0x7012, 0x2d04, 0x701e, 0xa005, 0x00c0, 0x3c1f, 0x701a, 0x127f, - 0x1078, 0x1348, 0x007c, 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e, - 0x0040, 0x3c32, 0x2304, 0x230c, 0xa10e, 0x0040, 0x3c32, 0xa006, - 0x0078, 0x3c42, 0x732c, 0x8319, 0x7130, 0xa102, 0x00c0, 0x3c3c, - 0x2300, 0xa005, 0x0078, 0x3c42, 0x0048, 0x3c41, 0xa302, 0x0078, - 0x3c42, 0x8002, 0x007c, 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, + 0xa06d, 0x0040, 0x3c1a, 0x127e, 0x2091, 0x8000, 0x7010, 0x8001, + 0x7012, 0x2d04, 0x701e, 0xa005, 0x00c0, 0x3c17, 0x701a, 0x127f, + 0x1078, 0x1340, 0x007c, 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e, + 0x0040, 0x3c2a, 0x2304, 0x230c, 0xa10e, 0x0040, 0x3c2a, 0xa006, + 0x0078, 0x3c3a, 0x732c, 0x8319, 0x7130, 0xa102, 0x00c0, 0x3c34, + 0x2300, 0xa005, 0x0078, 0x3c3a, 0x0048, 0x3c39, 0xa302, 0x0078, + 0x3c3a, 0x8002, 0x007c, 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x127e, 0x2091, 0x8000, 0x2009, 0x7859, 0x2104, - 0xc08d, 0x200a, 0x127f, 0x1078, 0x1399, 0x007c, 0x2071, 0x76cd, + 0xc08d, 0x200a, 0x127f, 0x1078, 0x1391, 0x007c, 0x2071, 0x76cd, 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, 0x76cd, 0x6848, 0xa005, 0x00c0, 0x3c7f, - 0x7028, 0xc085, 0x702a, 0xa085, 0x0001, 0x0078, 0x3ca4, 0x6a50, + 0x007c, 0x0e7e, 0x2071, 0x76cd, 0x6848, 0xa005, 0x00c0, 0x3c77, + 0x7028, 0xc085, 0x702a, 0xa085, 0x0001, 0x0078, 0x3c9c, 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, - 0x76cd, 0x7004, 0x1079, 0x3d04, 0x700c, 0x0079, 0x3caf, 0x3cb4, - 0x3ca9, 0x3ca9, 0x3ca9, 0x3ca9, 0x007c, 0x700c, 0x0079, 0x3cb8, - 0x3cbd, 0x3d02, 0x3d02, 0x3d03, 0x3d03, 0x7830, 0x7930, 0xa106, - 0x0040, 0x3cc7, 0x7830, 0x7930, 0xa106, 0x00c0, 0x3ced, 0x7030, - 0xa10a, 0x0040, 0x3ced, 0x00c8, 0x3ccf, 0x712c, 0xa10a, 0xa18a, - 0x0002, 0x00c8, 0x3cee, 0x1078, 0x1314, 0x0040, 0x3ced, 0x2d00, + 0x76cd, 0x7004, 0x1079, 0x3cfc, 0x700c, 0x0079, 0x3ca7, 0x3cac, + 0x3ca1, 0x3ca1, 0x3ca1, 0x3ca1, 0x007c, 0x700c, 0x0079, 0x3cb0, + 0x3cb5, 0x3cfa, 0x3cfa, 0x3cfb, 0x3cfb, 0x7830, 0x7930, 0xa106, + 0x0040, 0x3cbf, 0x7830, 0x7930, 0xa106, 0x00c0, 0x3ce5, 0x7030, + 0xa10a, 0x0040, 0x3ce5, 0x00c8, 0x3cc7, 0x712c, 0xa10a, 0xa18a, + 0x0002, 0x00c8, 0x3ce6, 0x1078, 0x130c, 0x0040, 0x3ce5, 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001, 0x0003, 0x7057, 0x0000, 0x127e, 0x007e, 0x2091, 0x8000, 0x2009, 0x7859, 0x2104, 0xc085, 0x200a, - 0x007f, 0x700e, 0x127f, 0x1078, 0x1399, 0x007c, 0x1078, 0x1314, - 0x0040, 0x3ced, 0x2d00, 0x705a, 0x1078, 0x1314, 0x00c0, 0x3cfa, - 0x0078, 0x3cd9, 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, - 0x0078, 0x3cdd, 0x007c, 0x007c, 0x3d15, 0x3d16, 0x3d4d, 0x3d4e, - 0x3d02, 0x3d84, 0x3d89, 0x3dc0, 0x3dc1, 0x3ddc, 0x3ddd, 0x3dde, - 0x3ddf, 0x3de0, 0x3de1, 0x3e4a, 0x3e74, 0x007c, 0x700c, 0x0079, - 0x3d19, 0x3d1e, 0x3d21, 0x3d31, 0x3d4c, 0x3d4c, 0x1078, 0x3cb5, - 0x007c, 0x127e, 0x8001, 0x700e, 0x7058, 0x007e, 0x1078, 0x4153, - 0x0040, 0x3d2e, 0x2091, 0x8000, 0x1078, 0x3cb5, 0x0d7f, 0x0078, - 0x3d3a, 0x127e, 0x8001, 0x700e, 0x1078, 0x4153, 0x7058, 0x2068, + 0x007f, 0x700e, 0x127f, 0x1078, 0x1391, 0x007c, 0x1078, 0x130c, + 0x0040, 0x3ce5, 0x2d00, 0x705a, 0x1078, 0x130c, 0x00c0, 0x3cf2, + 0x0078, 0x3cd1, 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, + 0x0078, 0x3cd5, 0x007c, 0x007c, 0x3d0d, 0x3d0e, 0x3d45, 0x3d46, + 0x3cfa, 0x3d7c, 0x3d81, 0x3db8, 0x3db9, 0x3dd4, 0x3dd5, 0x3dd6, + 0x3dd7, 0x3dd8, 0x3dd9, 0x3e42, 0x3e6c, 0x007c, 0x700c, 0x0079, + 0x3d11, 0x3d16, 0x3d19, 0x3d29, 0x3d44, 0x3d44, 0x1078, 0x3cad, + 0x007c, 0x127e, 0x8001, 0x700e, 0x7058, 0x007e, 0x1078, 0x414b, + 0x0040, 0x3d26, 0x2091, 0x8000, 0x1078, 0x3cad, 0x0d7f, 0x0078, + 0x3d32, 0x127e, 0x8001, 0x700e, 0x1078, 0x414b, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, - 0x00ff, 0xa08a, 0x0020, 0x00c8, 0x3d49, 0x1079, 0x3d64, 0x127f, - 0x007c, 0x127f, 0x1078, 0x3de2, 0x007c, 0x007c, 0x007c, 0x0e7e, - 0x2071, 0x76cd, 0x700c, 0x0079, 0x3d55, 0x3d5a, 0x3d5a, 0x3d5a, - 0x3d5c, 0x3d60, 0x0e7f, 0x007c, 0x700f, 0x0001, 0x0078, 0x3d62, - 0x700f, 0x0002, 0x0e7f, 0x007c, 0x3de2, 0x3de2, 0x3dfe, 0x3de2, - 0x3ee9, 0x3de2, 0x3de2, 0x3de2, 0x3de2, 0x3de2, 0x3dfe, 0x3f2e, - 0x3f77, 0x3fcf, 0x3fe2, 0x3de2, 0x3de2, 0x3e1a, 0x3dfe, 0x3de2, - 0x3de2, 0x3e30, 0x4069, 0x4086, 0x3de2, 0x3e1a, 0x3de2, 0x3de2, - 0x3de2, 0x3de2, 0x3e30, 0x4086, 0x7020, 0x2068, 0x1078, 0x1348, - 0x007c, 0x700c, 0x0079, 0x3d8c, 0x3d91, 0x3d94, 0x3da4, 0x3dbf, - 0x3dbf, 0x1078, 0x3cb5, 0x007c, 0x127e, 0x8001, 0x700e, 0x7058, - 0x007e, 0x1078, 0x4153, 0x0040, 0x3da1, 0x2091, 0x8000, 0x1078, - 0x3cb5, 0x0d7f, 0x0078, 0x3dad, 0x127e, 0x8001, 0x700e, 0x1078, - 0x4153, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, - 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x001a, 0x00c8, 0x3dbc, - 0x1079, 0x3dc2, 0x127f, 0x007c, 0x127f, 0x1078, 0x3de2, 0x007c, - 0x007c, 0x007c, 0x3de2, 0x3dfe, 0x3ed3, 0x3de2, 0x3dfe, 0x3de2, - 0x3dfe, 0x3dfe, 0x3de2, 0x3dfe, 0x3ed3, 0x3dfe, 0x3dfe, 0x3dfe, - 0x3dfe, 0x3dfe, 0x3de2, 0x3dfe, 0x3ed3, 0x3de2, 0x3de2, 0x3dfe, - 0x3de2, 0x3de2, 0x3de2, 0x3dfe, 0x007c, 0x007c, 0x007c, 0x007c, + 0x00ff, 0xa08a, 0x0020, 0x00c8, 0x3d41, 0x1079, 0x3d5c, 0x127f, + 0x007c, 0x127f, 0x1078, 0x3dda, 0x007c, 0x007c, 0x007c, 0x0e7e, + 0x2071, 0x76cd, 0x700c, 0x0079, 0x3d4d, 0x3d52, 0x3d52, 0x3d52, + 0x3d54, 0x3d58, 0x0e7f, 0x007c, 0x700f, 0x0001, 0x0078, 0x3d5a, + 0x700f, 0x0002, 0x0e7f, 0x007c, 0x3dda, 0x3dda, 0x3df6, 0x3dda, + 0x3ee1, 0x3dda, 0x3dda, 0x3dda, 0x3dda, 0x3dda, 0x3df6, 0x3f26, + 0x3f6f, 0x3fc7, 0x3fda, 0x3dda, 0x3dda, 0x3e12, 0x3df6, 0x3dda, + 0x3dda, 0x3e28, 0x4061, 0x407e, 0x3dda, 0x3e12, 0x3dda, 0x3dda, + 0x3dda, 0x3dda, 0x3e28, 0x407e, 0x7020, 0x2068, 0x1078, 0x1340, + 0x007c, 0x700c, 0x0079, 0x3d84, 0x3d89, 0x3d8c, 0x3d9c, 0x3db7, + 0x3db7, 0x1078, 0x3cad, 0x007c, 0x127e, 0x8001, 0x700e, 0x7058, + 0x007e, 0x1078, 0x414b, 0x0040, 0x3d99, 0x2091, 0x8000, 0x1078, + 0x3cad, 0x0d7f, 0x0078, 0x3da5, 0x127e, 0x8001, 0x700e, 0x1078, + 0x414b, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, + 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x001a, 0x00c8, 0x3db4, + 0x1079, 0x3dba, 0x127f, 0x007c, 0x127f, 0x1078, 0x3dda, 0x007c, + 0x007c, 0x007c, 0x3dda, 0x3df6, 0x3ecb, 0x3dda, 0x3df6, 0x3dda, + 0x3df6, 0x3df6, 0x3dda, 0x3df6, 0x3ecb, 0x3df6, 0x3df6, 0x3df6, + 0x3df6, 0x3df6, 0x3dda, 0x3df6, 0x3ecb, 0x3dda, 0x3dda, 0x3df6, + 0x3dda, 0x3dda, 0x3dda, 0x3df6, 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0d5, - 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x3a7a, 0x127f, 0x007c, + 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x3a72, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0e5, 0x683a, 0x127e, - 0x2091, 0x8000, 0x1078, 0x3a7a, 0x127f, 0x007c, 0x7007, 0x0001, + 0x2091, 0x8000, 0x1078, 0x3a72, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0ed, 0x683a, 0x127e, 0x2091, 0x8000, - 0x1078, 0x3a7a, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, - 0x00ff, 0xc0dd, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x3a7a, - 0x127f, 0x007c, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0040, 0x3df0, - 0x8001, 0x00c0, 0x3e27, 0x7007, 0x0001, 0x0078, 0x3eb0, 0x7007, - 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x3eb0, 0x007c, + 0x1078, 0x3a72, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, + 0x00ff, 0xc0dd, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x3a72, + 0x127f, 0x007c, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0040, 0x3de8, + 0x8001, 0x00c0, 0x3e1f, 0x7007, 0x0001, 0x0078, 0x3ea8, 0x7007, + 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x3ea8, 0x007c, 0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, 0x20a1, 0x76f8, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x00c8, - 0x3e0c, 0x6884, 0xa08a, 0x0003, 0x00c8, 0x3e0c, 0xa080, 0x3ea1, - 0x2004, 0x70c6, 0x7010, 0xa015, 0x0040, 0x3e94, 0x1078, 0x1314, - 0x00c0, 0x3e55, 0x7007, 0x000f, 0x007c, 0x2d00, 0x7022, 0x70c4, + 0x3e04, 0x6884, 0xa08a, 0x0003, 0x00c8, 0x3e04, 0xa080, 0x3e99, + 0x2004, 0x70c6, 0x7010, 0xa015, 0x0040, 0x3e8c, 0x1078, 0x130c, + 0x00c0, 0x3e4d, 0x7007, 0x000f, 0x007c, 0x2d00, 0x7022, 0x70c4, 0x2060, 0x6000, 0x6836, 0x6004, 0xad00, 0x7096, 0x6008, 0xa20a, - 0x00c8, 0x3e64, 0xa00e, 0x2200, 0x7112, 0x620c, 0x8003, 0x800b, - 0xa296, 0x0004, 0x0040, 0x3e6d, 0xa108, 0x719a, 0x810b, 0x719e, - 0xae90, 0x0022, 0x1078, 0x137f, 0x7090, 0xa08e, 0x0100, 0x0040, - 0x3e88, 0xa086, 0x0200, 0x0040, 0x3e80, 0x7007, 0x0010, 0x007c, - 0x7020, 0x2068, 0x1078, 0x1348, 0x7014, 0x2068, 0x0078, 0x3e0c, + 0x00c8, 0x3e5c, 0xa00e, 0x2200, 0x7112, 0x620c, 0x8003, 0x800b, + 0xa296, 0x0004, 0x0040, 0x3e65, 0xa108, 0x719a, 0x810b, 0x719e, + 0xae90, 0x0022, 0x1078, 0x1377, 0x7090, 0xa08e, 0x0100, 0x0040, + 0x3e80, 0xa086, 0x0200, 0x0040, 0x3e78, 0x7007, 0x0010, 0x007c, + 0x7020, 0x2068, 0x1078, 0x1340, 0x7014, 0x2068, 0x0078, 0x3e04, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807, 0x0000, 0x2d08, 0x2068, - 0x6906, 0x711a, 0x0078, 0x3e4a, 0x7014, 0x2068, 0x7007, 0x0001, - 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x0040, 0x40a3, 0x0078, - 0x3eb0, 0x3ea4, 0x3ea8, 0x3eac, 0x0002, 0x0011, 0x0007, 0x0004, + 0x6906, 0x711a, 0x0078, 0x3e42, 0x7014, 0x2068, 0x7007, 0x0001, + 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x0040, 0x409b, 0x0078, + 0x3ea8, 0x3e9c, 0x3ea0, 0x3ea4, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a, 0x000f, 0x0005, 0x0006, 0x0012, 0x000f, 0x0005, 0x0006, - 0x2009, 0x762c, 0x210c, 0x81ff, 0x00c0, 0x3ecd, 0x6838, 0xa084, - 0x00ff, 0x683a, 0x6853, 0x0000, 0x1078, 0x3668, 0x00c0, 0x3ec1, - 0x007c, 0x1078, 0x3b0a, 0x127e, 0x2091, 0x8000, 0x1078, 0x6b3f, - 0x1078, 0x3a7a, 0x127f, 0x0078, 0x3ec0, 0x2001, 0x0028, 0x2009, - 0x0000, 0x0078, 0x3ec1, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, - 0x711a, 0x7010, 0x8001, 0x7012, 0x0040, 0x3ee2, 0x7007, 0x0006, - 0x0078, 0x3ee8, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x107a, + 0x2009, 0x762c, 0x210c, 0x81ff, 0x00c0, 0x3ec5, 0x6838, 0xa084, + 0x00ff, 0x683a, 0x6853, 0x0000, 0x1078, 0x3660, 0x00c0, 0x3eb9, + 0x007c, 0x1078, 0x3b02, 0x127e, 0x2091, 0x8000, 0x1078, 0x6b34, + 0x1078, 0x3a72, 0x127f, 0x0078, 0x3eb8, 0x2001, 0x0028, 0x2009, + 0x0000, 0x0078, 0x3eb9, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, + 0x711a, 0x7010, 0x8001, 0x7012, 0x0040, 0x3eda, 0x7007, 0x0006, + 0x0078, 0x3ee0, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x107a, 0x007c, 0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, - 0xa084, 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x0040, 0x3f14, - 0x2009, 0x0000, 0x20a9, 0x007e, 0xa096, 0x0002, 0x0040, 0x3f14, - 0xa005, 0x00c0, 0x3f2b, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x1078, - 0x3825, 0x00c0, 0x3f2b, 0x067e, 0x6e44, 0xa6b4, 0x000f, 0x1078, - 0x38ba, 0x067f, 0x0078, 0x3f2b, 0x047e, 0x2011, 0x760c, 0x2224, - 0xc484, 0xc48c, 0x2412, 0x047f, 0x0c7e, 0x1078, 0x3825, 0x00c0, - 0x3f27, 0x2091, 0x8000, 0x607b, 0x0000, 0x2091, 0x8001, 0x8108, - 0x00f0, 0x3f1d, 0x0c7f, 0x1078, 0x1348, 0x007c, 0x127e, 0x2091, + 0xa084, 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x0040, 0x3f0c, + 0x2009, 0x0000, 0x20a9, 0x007e, 0xa096, 0x0002, 0x0040, 0x3f0c, + 0xa005, 0x00c0, 0x3f23, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x1078, + 0x381d, 0x00c0, 0x3f23, 0x067e, 0x6e44, 0xa6b4, 0x000f, 0x1078, + 0x38b2, 0x067f, 0x0078, 0x3f23, 0x047e, 0x2011, 0x760c, 0x2224, + 0xc484, 0xc48c, 0x2412, 0x047f, 0x0c7e, 0x1078, 0x381d, 0x00c0, + 0x3f1f, 0x2091, 0x8000, 0x607b, 0x0000, 0x2091, 0x8001, 0x8108, + 0x00f0, 0x3f15, 0x0c7f, 0x1078, 0x1340, 0x007c, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0x7652, 0x2004, 0xd0a4, 0x0040, - 0x3f6e, 0x6944, 0x1078, 0x416f, 0x6100, 0xd184, 0x0040, 0x3f53, - 0x6858, 0xa084, 0x00ff, 0x00c0, 0x3f71, 0x6000, 0xd084, 0x0040, - 0x3f6e, 0x6004, 0xa005, 0x00c0, 0x3f74, 0x6003, 0x0000, 0x600b, - 0x0000, 0x0078, 0x3f6b, 0x2011, 0x0001, 0x6860, 0xa005, 0x00c0, - 0x3f5b, 0x2001, 0x001e, 0x8000, 0x6016, 0x6858, 0xa084, 0x00ff, - 0x0040, 0x3f6e, 0x6006, 0x6858, 0x8007, 0xa084, 0x00ff, 0x0040, - 0x3f6e, 0x600a, 0x6202, 0x127f, 0x0078, 0x4142, 0x127f, 0x0078, - 0x413a, 0x127f, 0x0078, 0x4132, 0x127f, 0x0078, 0x4136, 0x127e, + 0x3f66, 0x6944, 0x1078, 0x4167, 0x6100, 0xd184, 0x0040, 0x3f4b, + 0x6858, 0xa084, 0x00ff, 0x00c0, 0x3f69, 0x6000, 0xd084, 0x0040, + 0x3f66, 0x6004, 0xa005, 0x00c0, 0x3f6c, 0x6003, 0x0000, 0x600b, + 0x0000, 0x0078, 0x3f63, 0x2011, 0x0001, 0x6860, 0xa005, 0x00c0, + 0x3f53, 0x2001, 0x001e, 0x8000, 0x6016, 0x6858, 0xa084, 0x00ff, + 0x0040, 0x3f66, 0x6006, 0x6858, 0x8007, 0xa084, 0x00ff, 0x0040, + 0x3f66, 0x600a, 0x6202, 0x127f, 0x0078, 0x413a, 0x127f, 0x0078, + 0x4132, 0x127f, 0x0078, 0x412a, 0x127f, 0x0078, 0x412e, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0x7652, 0x2004, 0xd0a4, - 0x0040, 0x3fcc, 0x6944, 0x1078, 0x416f, 0x6000, 0xa084, 0x0001, - 0x0040, 0x3fcc, 0x6204, 0x6308, 0x6c48, 0xa484, 0x0003, 0x0040, - 0x3fa4, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x00c0, 0x3f9d, 0x2100, - 0xa210, 0x0048, 0x3fc9, 0x0078, 0x3fa4, 0x8001, 0x00c0, 0x3fc9, - 0x2100, 0xa212, 0x0048, 0x3fc9, 0xa484, 0x000c, 0x0040, 0x3fbe, - 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x00c0, 0x3fb6, - 0x2100, 0xa318, 0x0048, 0x3fc9, 0x0078, 0x3fbe, 0xa082, 0x0004, - 0x00c0, 0x3fc9, 0x2100, 0xa31a, 0x0048, 0x3fc9, 0x6860, 0xa005, - 0x0040, 0x3fc4, 0x8000, 0x6016, 0x6206, 0x630a, 0x127f, 0x0078, - 0x4142, 0x127f, 0x0078, 0x413e, 0x127f, 0x0078, 0x413a, 0x127e, - 0x2091, 0x8000, 0x7007, 0x0001, 0x6944, 0x1078, 0x416f, 0x6308, - 0x8318, 0x0048, 0x3fdf, 0x630a, 0x127f, 0x0078, 0x4150, 0x127f, - 0x0078, 0x413e, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x7007, 0x0001, - 0x684c, 0xd0ac, 0x0040, 0x3ff6, 0x027e, 0x2009, 0x0000, 0x2011, - 0xfcff, 0x1078, 0x46b4, 0x027f, 0x0078, 0x402c, 0x6858, 0xa005, - 0x0040, 0x4040, 0x685c, 0xa065, 0x0040, 0x403c, 0x2001, 0x762c, - 0x2004, 0xa005, 0x0040, 0x4008, 0x1078, 0x6aa1, 0x0078, 0x400e, - 0x6013, 0x0400, 0x2009, 0x0041, 0x1078, 0x5c29, 0x6958, 0xa18c, - 0xe600, 0xa186, 0x2000, 0x0040, 0x4024, 0xa186, 0x0400, 0x0040, - 0x4024, 0x6944, 0x0c7e, 0x1078, 0x460c, 0x6000, 0xa084, 0xfdff, - 0x6002, 0x0c7f, 0x0078, 0x402c, 0x027e, 0x2009, 0x0000, 0x2011, - 0xfdff, 0x1078, 0x46b4, 0x027f, 0x684c, 0xd0c4, 0x0040, 0x4038, - 0x6944, 0x1078, 0x460c, 0x6008, 0x8000, 0x0048, 0x4038, 0x600a, - 0x0c7f, 0x127f, 0x0078, 0x4142, 0x0c7f, 0x127f, 0x0078, 0x413a, - 0x6954, 0xa186, 0x002a, 0x00c0, 0x404c, 0x2001, 0x760c, 0x200c, - 0xc194, 0x2102, 0x0078, 0x402c, 0xa186, 0x0020, 0x0040, 0x4061, - 0xa186, 0x0029, 0x00c0, 0x403c, 0x6944, 0xa18c, 0xff00, 0x810f, - 0x1078, 0x3825, 0x00c0, 0x402c, 0x6000, 0xc0e4, 0x6002, 0x0078, - 0x402c, 0x685c, 0xa065, 0x0040, 0x403c, 0x6017, 0x0014, 0x0078, - 0x402c, 0x6944, 0x1078, 0x416f, 0x6000, 0xa084, 0x0001, 0x0040, - 0x4082, 0x2091, 0x8000, 0x6204, 0x8210, 0x0048, 0x407c, 0x6206, - 0x2091, 0x8001, 0x0078, 0x4150, 0x2091, 0x8001, 0x6853, 0x0016, - 0x0078, 0x4149, 0x6853, 0x0007, 0x0078, 0x4149, 0x6834, 0x8007, - 0xa084, 0x00ff, 0x00c0, 0x4090, 0x1078, 0x3df0, 0x0078, 0x40a2, - 0x2030, 0x8001, 0x00c0, 0x409a, 0x7007, 0x0001, 0x1078, 0x40a3, - 0x0078, 0x40a2, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, - 0x704b, 0x40a3, 0x007c, 0x0e7e, 0x2009, 0x762c, 0x210c, 0x81ff, - 0x00c0, 0x4124, 0x2009, 0x760c, 0x210c, 0xd194, 0x00c0, 0x412e, - 0x6848, 0x2070, 0xae82, 0x7d00, 0x0048, 0x4113, 0x2001, 0x7615, - 0x2004, 0xae02, 0x00c8, 0x4113, 0x6944, 0x1078, 0x416f, 0x6100, - 0xa184, 0x0001, 0x0040, 0x40f9, 0xa184, 0x0100, 0x00c0, 0x4117, - 0xa184, 0x0200, 0x00c0, 0x411b, 0x601c, 0xa005, 0x00c0, 0x411f, - 0x711c, 0xa186, 0x0006, 0x00c0, 0x40fe, 0x6853, 0x0000, 0x6803, + 0x0040, 0x3fc4, 0x6944, 0x1078, 0x4167, 0x6000, 0xa084, 0x0001, + 0x0040, 0x3fc4, 0x6204, 0x6308, 0x6c48, 0xa484, 0x0003, 0x0040, + 0x3f9c, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x00c0, 0x3f95, 0x2100, + 0xa210, 0x0048, 0x3fc1, 0x0078, 0x3f9c, 0x8001, 0x00c0, 0x3fc1, + 0x2100, 0xa212, 0x0048, 0x3fc1, 0xa484, 0x000c, 0x0040, 0x3fb6, + 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x00c0, 0x3fae, + 0x2100, 0xa318, 0x0048, 0x3fc1, 0x0078, 0x3fb6, 0xa082, 0x0004, + 0x00c0, 0x3fc1, 0x2100, 0xa31a, 0x0048, 0x3fc1, 0x6860, 0xa005, + 0x0040, 0x3fbc, 0x8000, 0x6016, 0x6206, 0x630a, 0x127f, 0x0078, + 0x413a, 0x127f, 0x0078, 0x4136, 0x127f, 0x0078, 0x4132, 0x127e, + 0x2091, 0x8000, 0x7007, 0x0001, 0x6944, 0x1078, 0x4167, 0x6308, + 0x8318, 0x0048, 0x3fd7, 0x630a, 0x127f, 0x0078, 0x4148, 0x127f, + 0x0078, 0x4136, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x7007, 0x0001, + 0x684c, 0xd0ac, 0x0040, 0x3fee, 0x027e, 0x2009, 0x0000, 0x2011, + 0xfcff, 0x1078, 0x46ac, 0x027f, 0x0078, 0x4024, 0x6858, 0xa005, + 0x0040, 0x4038, 0x685c, 0xa065, 0x0040, 0x4034, 0x2001, 0x762c, + 0x2004, 0xa005, 0x0040, 0x4000, 0x1078, 0x6a96, 0x0078, 0x4006, + 0x6013, 0x0400, 0x2009, 0x0041, 0x1078, 0x5c21, 0x6958, 0xa18c, + 0xe600, 0xa186, 0x2000, 0x0040, 0x401c, 0xa186, 0x0400, 0x0040, + 0x401c, 0x6944, 0x0c7e, 0x1078, 0x4604, 0x6000, 0xa084, 0xfdff, + 0x6002, 0x0c7f, 0x0078, 0x4024, 0x027e, 0x2009, 0x0000, 0x2011, + 0xfdff, 0x1078, 0x46ac, 0x027f, 0x684c, 0xd0c4, 0x0040, 0x4030, + 0x6944, 0x1078, 0x4604, 0x6008, 0x8000, 0x0048, 0x4030, 0x600a, + 0x0c7f, 0x127f, 0x0078, 0x413a, 0x0c7f, 0x127f, 0x0078, 0x4132, + 0x6954, 0xa186, 0x002a, 0x00c0, 0x4044, 0x2001, 0x760c, 0x200c, + 0xc194, 0x2102, 0x0078, 0x4024, 0xa186, 0x0020, 0x0040, 0x4059, + 0xa186, 0x0029, 0x00c0, 0x4034, 0x6944, 0xa18c, 0xff00, 0x810f, + 0x1078, 0x381d, 0x00c0, 0x4024, 0x6000, 0xc0e4, 0x6002, 0x0078, + 0x4024, 0x685c, 0xa065, 0x0040, 0x4034, 0x6017, 0x0014, 0x0078, + 0x4024, 0x6944, 0x1078, 0x4167, 0x6000, 0xa084, 0x0001, 0x0040, + 0x407a, 0x2091, 0x8000, 0x6204, 0x8210, 0x0048, 0x4074, 0x6206, + 0x2091, 0x8001, 0x0078, 0x4148, 0x2091, 0x8001, 0x6853, 0x0016, + 0x0078, 0x4141, 0x6853, 0x0007, 0x0078, 0x4141, 0x6834, 0x8007, + 0xa084, 0x00ff, 0x00c0, 0x4088, 0x1078, 0x3de8, 0x0078, 0x409a, + 0x2030, 0x8001, 0x00c0, 0x4092, 0x7007, 0x0001, 0x1078, 0x409b, + 0x0078, 0x409a, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, + 0x704b, 0x409b, 0x007c, 0x0e7e, 0x2009, 0x762c, 0x210c, 0x81ff, + 0x00c0, 0x411c, 0x2009, 0x760c, 0x210c, 0xd194, 0x00c0, 0x4126, + 0x6848, 0x2070, 0xae82, 0x7d00, 0x0048, 0x410b, 0x2001, 0x7615, + 0x2004, 0xae02, 0x00c8, 0x410b, 0x6944, 0x1078, 0x4167, 0x6100, + 0xa184, 0x0001, 0x0040, 0x40f1, 0xa184, 0x0100, 0x00c0, 0x410f, + 0xa184, 0x0200, 0x00c0, 0x4113, 0x601c, 0xa005, 0x00c0, 0x4117, + 0x711c, 0xa186, 0x0006, 0x00c0, 0x40f6, 0x6853, 0x0000, 0x6803, 0x0000, 0x2d08, 0x127e, 0x2091, 0x8000, 0x7010, 0xa005, 0x00c0, - 0x40f0, 0x7112, 0x7018, 0xa065, 0x0040, 0x4123, 0x6000, 0xd0e4, - 0x00c0, 0x4128, 0x2e60, 0x1078, 0x4615, 0x127f, 0x0e7f, 0x007c, - 0x2068, 0x6800, 0xa005, 0x00c0, 0x40f0, 0x6902, 0x127f, 0x0e7f, - 0x007c, 0x0e7f, 0x6853, 0x0006, 0x0078, 0x4149, 0x6944, 0xa18c, - 0xff00, 0x810f, 0x1078, 0x3825, 0x00c0, 0x4129, 0x6000, 0xd0e4, - 0x00c0, 0x4129, 0x711c, 0xa186, 0x0007, 0x00c0, 0x4113, 0x6853, - 0x0002, 0x0078, 0x412b, 0x6853, 0x0008, 0x0078, 0x412b, 0x6853, - 0x000e, 0x0078, 0x412b, 0x6853, 0x0017, 0x0078, 0x412b, 0x6853, - 0x0035, 0x0078, 0x412b, 0x127f, 0x6853, 0x0028, 0x0078, 0x412b, - 0x127f, 0x6853, 0x0029, 0x0e7f, 0x0078, 0x4149, 0x6853, 0x002a, - 0x0078, 0x412b, 0x2009, 0x003e, 0x0078, 0x4144, 0x2009, 0x0004, - 0x0078, 0x4144, 0x2009, 0x0006, 0x0078, 0x4144, 0x2009, 0x0016, - 0x0078, 0x4144, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00, 0xa105, - 0x6856, 0x2091, 0x8000, 0x1078, 0x3a7a, 0x2091, 0x8001, 0x007c, - 0x1078, 0x1348, 0x007c, 0x702c, 0x7130, 0x8108, 0xa102, 0x0048, - 0x4160, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0078, 0x416c, - 0x7070, 0xa080, 0x0040, 0x7072, 0x00c8, 0x416c, 0x7074, 0xa081, + 0x40e8, 0x7112, 0x7018, 0xa065, 0x0040, 0x411b, 0x6000, 0xd0e4, + 0x00c0, 0x4120, 0x2e60, 0x1078, 0x460d, 0x127f, 0x0e7f, 0x007c, + 0x2068, 0x6800, 0xa005, 0x00c0, 0x40e8, 0x6902, 0x127f, 0x0e7f, + 0x007c, 0x0e7f, 0x6853, 0x0006, 0x0078, 0x4141, 0x6944, 0xa18c, + 0xff00, 0x810f, 0x1078, 0x381d, 0x00c0, 0x4121, 0x6000, 0xd0e4, + 0x00c0, 0x4121, 0x711c, 0xa186, 0x0007, 0x00c0, 0x410b, 0x6853, + 0x0002, 0x0078, 0x4123, 0x6853, 0x0008, 0x0078, 0x4123, 0x6853, + 0x000e, 0x0078, 0x4123, 0x6853, 0x0017, 0x0078, 0x4123, 0x6853, + 0x0035, 0x0078, 0x4123, 0x127f, 0x6853, 0x0028, 0x0078, 0x4123, + 0x127f, 0x6853, 0x0029, 0x0e7f, 0x0078, 0x4141, 0x6853, 0x002a, + 0x0078, 0x4123, 0x2009, 0x003e, 0x0078, 0x413c, 0x2009, 0x0004, + 0x0078, 0x413c, 0x2009, 0x0006, 0x0078, 0x413c, 0x2009, 0x0016, + 0x0078, 0x413c, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00, 0xa105, + 0x6856, 0x2091, 0x8000, 0x1078, 0x3a72, 0x2091, 0x8001, 0x007c, + 0x1078, 0x1340, 0x007c, 0x702c, 0x7130, 0x8108, 0xa102, 0x0048, + 0x4158, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0078, 0x4164, + 0x7070, 0xa080, 0x0040, 0x7072, 0x00c8, 0x4164, 0x7074, 0xa081, 0x0000, 0x7076, 0xa085, 0x0001, 0x7932, 0x7132, 0x007c, 0x0d7e, - 0x1078, 0x460c, 0x0d7f, 0x007c, 0x0d7e, 0x2011, 0x0004, 0x2204, + 0x1078, 0x4604, 0x0d7f, 0x007c, 0x0d7e, 0x2011, 0x0004, 0x2204, 0xa085, 0x8002, 0x2012, 0x0d7f, 0x007c, 0x20e1, 0x0002, 0x3d08, - 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0040, 0x418b, 0xa086, - 0x1000, 0x00c0, 0x41a7, 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x00c0, - 0x4192, 0x3e60, 0xac84, 0x0007, 0x00c0, 0x41a7, 0xac82, 0x7d00, - 0x0048, 0x41a7, 0x6854, 0xac02, 0x00c8, 0x41a7, 0x2009, 0x0047, - 0x1078, 0x5c29, 0x7a1c, 0xd284, 0x00c0, 0x417d, 0x007c, 0xa016, - 0x1078, 0x1572, 0x0078, 0x41a2, 0x157e, 0x137e, 0x147e, 0x20e1, - 0x3000, 0x3d20, 0x3e28, 0xa584, 0x0070, 0x00c0, 0x41d5, 0xa484, - 0x7000, 0xa086, 0x1000, 0x00c0, 0x41d5, 0x1078, 0x41e2, 0x0040, - 0x41d5, 0x20e1, 0x3000, 0x7828, 0x7828, 0x1078, 0x4200, 0x147f, - 0x137f, 0x157f, 0x2009, 0x783e, 0x2104, 0xa005, 0x00c0, 0x41d1, - 0x007c, 0x1078, 0x4c7a, 0x0078, 0x41d0, 0x1078, 0x7574, 0x1078, - 0x41e2, 0x20e1, 0x3000, 0x7828, 0x7828, 0x147f, 0x137f, 0x157f, - 0x0078, 0x41d0, 0xa484, 0x01ff, 0x687a, 0xa005, 0x0040, 0x41f4, + 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0040, 0x4183, 0xa086, + 0x1000, 0x00c0, 0x419f, 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x00c0, + 0x418a, 0x3e60, 0xac84, 0x0007, 0x00c0, 0x419f, 0xac82, 0x7d00, + 0x0048, 0x419f, 0x6854, 0xac02, 0x00c8, 0x419f, 0x2009, 0x0047, + 0x1078, 0x5c21, 0x7a1c, 0xd284, 0x00c0, 0x4175, 0x007c, 0xa016, + 0x1078, 0x156a, 0x0078, 0x419a, 0x157e, 0x137e, 0x147e, 0x20e1, + 0x3000, 0x3d20, 0x3e28, 0xa584, 0x0070, 0x00c0, 0x41cd, 0xa484, + 0x7000, 0xa086, 0x1000, 0x00c0, 0x41cd, 0x1078, 0x41da, 0x0040, + 0x41cd, 0x20e1, 0x3000, 0x7828, 0x7828, 0x1078, 0x41f8, 0x147f, + 0x137f, 0x157f, 0x2009, 0x783e, 0x2104, 0xa005, 0x00c0, 0x41c9, + 0x007c, 0x1078, 0x4c72, 0x0078, 0x41c8, 0x1078, 0x7569, 0x1078, + 0x41da, 0x20e1, 0x3000, 0x7828, 0x7828, 0x147f, 0x137f, 0x157f, + 0x0078, 0x41c8, 0xa484, 0x01ff, 0x687a, 0xa005, 0x0040, 0x41ec, 0xa080, 0x001f, 0xa084, 0x03f8, 0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x007c, 0x20a9, 0x000c, 0x20e1, 0x1000, - 0x2ea0, 0x2099, 0x020a, 0x53a5, 0xa085, 0x0001, 0x0078, 0x41f3, + 0x2ea0, 0x2099, 0x020a, 0x53a5, 0xa085, 0x0001, 0x0078, 0x41eb, 0x7000, 0xa084, 0xff00, 0xa08c, 0xf000, 0x8007, 0xa196, 0x0000, - 0x00c0, 0x420d, 0x0078, 0x4381, 0x007c, 0xa196, 0x2000, 0x00c0, - 0x421e, 0x6900, 0xa18e, 0x0001, 0x00c0, 0x421a, 0x1078, 0x2eb2, - 0x0078, 0x420c, 0x1078, 0x4226, 0x0078, 0x420c, 0xa196, 0x8000, - 0x00c0, 0x420c, 0x1078, 0x4407, 0x0078, 0x420c, 0x0c7e, 0x7110, - 0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0040, 0x4233, 0xa196, - 0x0023, 0x00c0, 0x4328, 0xa08e, 0x0023, 0x00c0, 0x4264, 0x1078, - 0x447e, 0x0040, 0x4328, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, - 0x00c0, 0x424c, 0x7034, 0xa005, 0x00c0, 0x4328, 0x2009, 0x0015, - 0x1078, 0x5c29, 0x0078, 0x4328, 0xa08e, 0x0210, 0x00c0, 0x4256, - 0x2009, 0x0015, 0x1078, 0x5c29, 0x0078, 0x4328, 0xa08e, 0x0100, - 0x00c0, 0x4328, 0x7034, 0xa005, 0x00c0, 0x4328, 0x2009, 0x0016, - 0x1078, 0x5c29, 0x0078, 0x4328, 0xa08e, 0x0022, 0x00c0, 0x4328, - 0x7030, 0xa08e, 0x0300, 0x00c0, 0x4275, 0x7034, 0xa005, 0x00c0, - 0x4328, 0x2009, 0x0017, 0x0078, 0x42f4, 0xa08e, 0x0500, 0x00c0, - 0x4281, 0x7034, 0xa005, 0x00c0, 0x4328, 0x2009, 0x0018, 0x0078, - 0x42f4, 0xa08e, 0x2010, 0x00c0, 0x4289, 0x2009, 0x0019, 0x0078, - 0x42f4, 0xa08e, 0x2110, 0x00c0, 0x4291, 0x2009, 0x001a, 0x0078, - 0x42f4, 0xa08e, 0x5200, 0x00c0, 0x429d, 0x7034, 0xa005, 0x00c0, - 0x4328, 0x2009, 0x001b, 0x0078, 0x42f4, 0xa08e, 0x5000, 0x00c0, - 0x42a9, 0x7034, 0xa005, 0x00c0, 0x4328, 0x2009, 0x001c, 0x0078, - 0x42f4, 0xa08e, 0x1200, 0x00c0, 0x42b5, 0x7034, 0xa005, 0x00c0, - 0x4328, 0x2009, 0x0024, 0x0078, 0x42f4, 0xa08c, 0xff00, 0xa18e, - 0x2400, 0x00c0, 0x42bf, 0x2009, 0x002d, 0x0078, 0x42f4, 0xa08c, - 0xff00, 0xa18e, 0x5300, 0x00c0, 0x42c9, 0x2009, 0x002a, 0x0078, - 0x42f4, 0xa08e, 0x0f00, 0x00c0, 0x42d1, 0x2009, 0x0020, 0x0078, - 0x42f4, 0xa08e, 0x5300, 0x00c0, 0x42d7, 0x0078, 0x42f2, 0xa08e, - 0x6104, 0x00c0, 0x42f2, 0x2011, 0x7b8d, 0x8208, 0x2204, 0xa082, + 0x00c0, 0x4205, 0x0078, 0x4379, 0x007c, 0xa196, 0x2000, 0x00c0, + 0x4216, 0x6900, 0xa18e, 0x0001, 0x00c0, 0x4212, 0x1078, 0x2ea3, + 0x0078, 0x4204, 0x1078, 0x421e, 0x0078, 0x4204, 0xa196, 0x8000, + 0x00c0, 0x4204, 0x1078, 0x43ff, 0x0078, 0x4204, 0x0c7e, 0x7110, + 0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0040, 0x422b, 0xa196, + 0x0023, 0x00c0, 0x4320, 0xa08e, 0x0023, 0x00c0, 0x425c, 0x1078, + 0x4476, 0x0040, 0x4320, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, + 0x00c0, 0x4244, 0x7034, 0xa005, 0x00c0, 0x4320, 0x2009, 0x0015, + 0x1078, 0x5c21, 0x0078, 0x4320, 0xa08e, 0x0210, 0x00c0, 0x424e, + 0x2009, 0x0015, 0x1078, 0x5c21, 0x0078, 0x4320, 0xa08e, 0x0100, + 0x00c0, 0x4320, 0x7034, 0xa005, 0x00c0, 0x4320, 0x2009, 0x0016, + 0x1078, 0x5c21, 0x0078, 0x4320, 0xa08e, 0x0022, 0x00c0, 0x4320, + 0x7030, 0xa08e, 0x0300, 0x00c0, 0x426d, 0x7034, 0xa005, 0x00c0, + 0x4320, 0x2009, 0x0017, 0x0078, 0x42ec, 0xa08e, 0x0500, 0x00c0, + 0x4279, 0x7034, 0xa005, 0x00c0, 0x4320, 0x2009, 0x0018, 0x0078, + 0x42ec, 0xa08e, 0x2010, 0x00c0, 0x4281, 0x2009, 0x0019, 0x0078, + 0x42ec, 0xa08e, 0x2110, 0x00c0, 0x4289, 0x2009, 0x001a, 0x0078, + 0x42ec, 0xa08e, 0x5200, 0x00c0, 0x4295, 0x7034, 0xa005, 0x00c0, + 0x4320, 0x2009, 0x001b, 0x0078, 0x42ec, 0xa08e, 0x5000, 0x00c0, + 0x42a1, 0x7034, 0xa005, 0x00c0, 0x4320, 0x2009, 0x001c, 0x0078, + 0x42ec, 0xa08e, 0x1200, 0x00c0, 0x42ad, 0x7034, 0xa005, 0x00c0, + 0x4320, 0x2009, 0x0024, 0x0078, 0x42ec, 0xa08c, 0xff00, 0xa18e, + 0x2400, 0x00c0, 0x42b7, 0x2009, 0x002d, 0x0078, 0x42ec, 0xa08c, + 0xff00, 0xa18e, 0x5300, 0x00c0, 0x42c1, 0x2009, 0x002a, 0x0078, + 0x42ec, 0xa08e, 0x0f00, 0x00c0, 0x42c9, 0x2009, 0x0020, 0x0078, + 0x42ec, 0xa08e, 0x5300, 0x00c0, 0x42cf, 0x0078, 0x42ea, 0xa08e, + 0x6104, 0x00c0, 0x42ea, 0x2011, 0x7b8d, 0x8208, 0x2204, 0xa082, 0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108, - 0x2124, 0x1078, 0x2d4a, 0x8108, 0x00f0, 0x42e4, 0x2009, 0x0023, - 0x0078, 0x42f4, 0x2009, 0x001d, 0x017e, 0x2011, 0x7b83, 0x2204, - 0x8211, 0x220c, 0x1078, 0x2085, 0x00c0, 0x432a, 0x1078, 0x37ee, - 0x00c0, 0x432a, 0x6612, 0x6516, 0x86ff, 0x0040, 0x431a, 0x017f, - 0x017e, 0xa186, 0x0017, 0x00c0, 0x431a, 0x6864, 0xa606, 0x00c0, - 0x431a, 0x6868, 0xa506, 0xa084, 0xff00, 0x00c0, 0x431a, 0x6000, - 0xc0f5, 0x6002, 0x0c7e, 0x1078, 0x5b9c, 0x0040, 0x432d, 0x017f, - 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, 0x1078, 0x5c29, - 0x0c7f, 0x007c, 0x017f, 0x0078, 0x4328, 0x0c7f, 0x0078, 0x432a, - 0x0e7e, 0x0d7e, 0x2028, 0x2130, 0xa696, 0x00ff, 0x00c0, 0x4350, - 0xa596, 0xfffd, 0x00c0, 0x4340, 0x2009, 0x007f, 0x0078, 0x437d, - 0xa596, 0xfffe, 0x00c0, 0x4348, 0x2009, 0x007e, 0x0078, 0x437d, - 0xa596, 0xfffc, 0x00c0, 0x4350, 0x2009, 0x0080, 0x0078, 0x437d, + 0x2124, 0x1078, 0x2d3b, 0x8108, 0x00f0, 0x42dc, 0x2009, 0x0023, + 0x0078, 0x42ec, 0x2009, 0x001d, 0x017e, 0x2011, 0x7b83, 0x2204, + 0x8211, 0x220c, 0x1078, 0x207f, 0x00c0, 0x4322, 0x1078, 0x37e6, + 0x00c0, 0x4322, 0x6612, 0x6516, 0x86ff, 0x0040, 0x4312, 0x017f, + 0x017e, 0xa186, 0x0017, 0x00c0, 0x4312, 0x6864, 0xa606, 0x00c0, + 0x4312, 0x6868, 0xa506, 0xa084, 0xff00, 0x00c0, 0x4312, 0x6000, + 0xc0f5, 0x6002, 0x0c7e, 0x1078, 0x5b94, 0x0040, 0x4325, 0x017f, + 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, 0x1078, 0x5c21, + 0x0c7f, 0x007c, 0x017f, 0x0078, 0x4320, 0x0c7f, 0x0078, 0x4322, + 0x0e7e, 0x0d7e, 0x2028, 0x2130, 0xa696, 0x00ff, 0x00c0, 0x4348, + 0xa596, 0xfffd, 0x00c0, 0x4338, 0x2009, 0x007f, 0x0078, 0x4375, + 0xa596, 0xfffe, 0x00c0, 0x4340, 0x2009, 0x007e, 0x0078, 0x4375, + 0xa596, 0xfffc, 0x00c0, 0x4348, 0x2009, 0x0080, 0x0078, 0x4375, 0x2011, 0x0000, 0x2021, 0x007e, 0x20a9, 0x0082, 0x2071, 0x779e, - 0x2e1c, 0x83ff, 0x00c0, 0x4362, 0x82ff, 0x00c0, 0x4371, 0x2410, - 0x0078, 0x4371, 0x2368, 0x6b10, 0x007e, 0x2100, 0xa31e, 0x007f, - 0x00c0, 0x4371, 0x6b14, 0xa31e, 0x00c0, 0x4371, 0x2408, 0x0078, - 0x437d, 0x8420, 0x8e70, 0x00f0, 0x4358, 0x82ff, 0x00c0, 0x437c, - 0xa085, 0x0001, 0x0078, 0x437e, 0x2208, 0xa006, 0x0d7f, 0x0e7f, - 0x007c, 0xa084, 0x0007, 0x0079, 0x4386, 0x007c, 0x438e, 0x438e, - 0x438e, 0x438e, 0x438e, 0x438f, 0x43a8, 0x43f0, 0x007c, 0x7110, - 0xd1bc, 0x0040, 0x43a7, 0x7120, 0x2160, 0xac8c, 0x0007, 0x00c0, - 0x43a7, 0xac8a, 0x7d00, 0x0048, 0x43a7, 0x6854, 0xac02, 0x00c8, - 0x43a7, 0x7124, 0x610a, 0x2009, 0x0046, 0x1078, 0x5c29, 0x007c, - 0x0c7e, 0x7110, 0xd1bc, 0x00c0, 0x43ee, 0x2011, 0x7b83, 0x2204, - 0x8211, 0x220c, 0x1078, 0x2085, 0x00c0, 0x43ee, 0x1078, 0x3825, - 0x00c0, 0x43ee, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, - 0x00c0, 0x43d3, 0x0c7e, 0x1078, 0x5b9c, 0x017f, 0x0040, 0x43ee, + 0x2e1c, 0x83ff, 0x00c0, 0x435a, 0x82ff, 0x00c0, 0x4369, 0x2410, + 0x0078, 0x4369, 0x2368, 0x6b10, 0x007e, 0x2100, 0xa31e, 0x007f, + 0x00c0, 0x4369, 0x6b14, 0xa31e, 0x00c0, 0x4369, 0x2408, 0x0078, + 0x4375, 0x8420, 0x8e70, 0x00f0, 0x4350, 0x82ff, 0x00c0, 0x4374, + 0xa085, 0x0001, 0x0078, 0x4376, 0x2208, 0xa006, 0x0d7f, 0x0e7f, + 0x007c, 0xa084, 0x0007, 0x0079, 0x437e, 0x007c, 0x4386, 0x4386, + 0x4386, 0x4386, 0x4386, 0x4387, 0x43a0, 0x43e8, 0x007c, 0x7110, + 0xd1bc, 0x0040, 0x439f, 0x7120, 0x2160, 0xac8c, 0x0007, 0x00c0, + 0x439f, 0xac8a, 0x7d00, 0x0048, 0x439f, 0x6854, 0xac02, 0x00c8, + 0x439f, 0x7124, 0x610a, 0x2009, 0x0046, 0x1078, 0x5c21, 0x007c, + 0x0c7e, 0x7110, 0xd1bc, 0x00c0, 0x43e6, 0x2011, 0x7b83, 0x2204, + 0x8211, 0x220c, 0x1078, 0x207f, 0x00c0, 0x43e6, 0x1078, 0x381d, + 0x00c0, 0x43e6, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, + 0x00c0, 0x43cb, 0x0c7e, 0x1078, 0x5b94, 0x017f, 0x0040, 0x43e6, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x2009, 0x0044, 0x1078, - 0x5c29, 0x0078, 0x43ee, 0x0c7e, 0x1078, 0x5b9c, 0x017f, 0x0040, - 0x43ee, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004, - 0x00c0, 0x43e6, 0x6007, 0x0005, 0x0078, 0x43e8, 0x6007, 0x0001, - 0x6003, 0x0001, 0x1078, 0x4872, 0x1078, 0x4c7a, 0x0c7f, 0x007c, - 0x7110, 0xd1bc, 0x0040, 0x4406, 0x7020, 0x2060, 0xac84, 0x0007, - 0x00c0, 0x4406, 0xac82, 0x7d00, 0x0048, 0x4406, 0x6854, 0xac02, - 0x00c8, 0x4406, 0x2009, 0x0045, 0x1078, 0x5c29, 0x007c, 0x7110, - 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, 0x00c0, 0x4417, 0xa084, - 0x000f, 0xa08a, 0x0006, 0x10c8, 0x12d5, 0x1079, 0x4418, 0x007c, - 0x441e, 0x441f, 0x441e, 0x441e, 0x4460, 0x446f, 0x007c, 0x7110, - 0xd1bc, 0x00c0, 0x445f, 0x700c, 0x7108, 0x1078, 0x2085, 0x00c0, - 0x445f, 0x1078, 0x37ee, 0x00c0, 0x445f, 0x6612, 0x6516, 0x6204, - 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x00c0, 0x4448, 0x0c7e, - 0x1078, 0x5b9c, 0x017f, 0x0040, 0x445f, 0x611a, 0x601f, 0x0005, - 0x7120, 0x610a, 0x2009, 0x0088, 0x1078, 0x5c29, 0x0078, 0x445f, - 0x0c7e, 0x1078, 0x5b9c, 0x017f, 0x0040, 0x445f, 0x611a, 0x601f, - 0x0004, 0x7120, 0x610a, 0xa286, 0x0004, 0x00c0, 0x445b, 0x2009, - 0x0005, 0x0078, 0x445d, 0x2009, 0x0001, 0x1078, 0x5c29, 0x007c, - 0x7110, 0xd1bc, 0x0040, 0x446e, 0x1078, 0x447e, 0x0040, 0x446e, - 0x7124, 0x610a, 0x2009, 0x0089, 0x1078, 0x5c29, 0x007c, 0x7110, - 0xd1bc, 0x0040, 0x447d, 0x1078, 0x447e, 0x0040, 0x447d, 0x7124, - 0x610a, 0x2009, 0x008a, 0x1078, 0x5c29, 0x007c, 0x7020, 0x2060, - 0xac84, 0x0007, 0x00c0, 0x4491, 0xac82, 0x7d00, 0x0048, 0x4491, - 0x2001, 0x7615, 0x2004, 0xac02, 0x00c8, 0x4491, 0xa085, 0x0001, - 0x007c, 0xa006, 0x0078, 0x4490, 0x2071, 0x7849, 0x7003, 0x0003, + 0x5c21, 0x0078, 0x43e6, 0x0c7e, 0x1078, 0x5b94, 0x017f, 0x0040, + 0x43e6, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004, + 0x00c0, 0x43de, 0x6007, 0x0005, 0x0078, 0x43e0, 0x6007, 0x0001, + 0x6003, 0x0001, 0x1078, 0x486a, 0x1078, 0x4c72, 0x0c7f, 0x007c, + 0x7110, 0xd1bc, 0x0040, 0x43fe, 0x7020, 0x2060, 0xac84, 0x0007, + 0x00c0, 0x43fe, 0xac82, 0x7d00, 0x0048, 0x43fe, 0x6854, 0xac02, + 0x00c8, 0x43fe, 0x2009, 0x0045, 0x1078, 0x5c21, 0x007c, 0x7110, + 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, 0x00c0, 0x440f, 0xa084, + 0x000f, 0xa08a, 0x0006, 0x10c8, 0x12cd, 0x1079, 0x4410, 0x007c, + 0x4416, 0x4417, 0x4416, 0x4416, 0x4458, 0x4467, 0x007c, 0x7110, + 0xd1bc, 0x00c0, 0x4457, 0x700c, 0x7108, 0x1078, 0x207f, 0x00c0, + 0x4457, 0x1078, 0x37e6, 0x00c0, 0x4457, 0x6612, 0x6516, 0x6204, + 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x00c0, 0x4440, 0x0c7e, + 0x1078, 0x5b94, 0x017f, 0x0040, 0x4457, 0x611a, 0x601f, 0x0005, + 0x7120, 0x610a, 0x2009, 0x0088, 0x1078, 0x5c21, 0x0078, 0x4457, + 0x0c7e, 0x1078, 0x5b94, 0x017f, 0x0040, 0x4457, 0x611a, 0x601f, + 0x0004, 0x7120, 0x610a, 0xa286, 0x0004, 0x00c0, 0x4453, 0x2009, + 0x0005, 0x0078, 0x4455, 0x2009, 0x0001, 0x1078, 0x5c21, 0x007c, + 0x7110, 0xd1bc, 0x0040, 0x4466, 0x1078, 0x4476, 0x0040, 0x4466, + 0x7124, 0x610a, 0x2009, 0x0089, 0x1078, 0x5c21, 0x007c, 0x7110, + 0xd1bc, 0x0040, 0x4475, 0x1078, 0x4476, 0x0040, 0x4475, 0x7124, + 0x610a, 0x2009, 0x008a, 0x1078, 0x5c21, 0x007c, 0x7020, 0x2060, + 0xac84, 0x0007, 0x00c0, 0x4489, 0xac82, 0x7d00, 0x0048, 0x4489, + 0x2001, 0x7615, 0x2004, 0xac02, 0x00c8, 0x4489, 0xa085, 0x0001, + 0x007c, 0xa006, 0x0078, 0x4488, 0x2071, 0x7849, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a, 0x7012, 0x7017, 0x7d00, 0x7007, - 0x0000, 0x7026, 0x702b, 0x558f, 0x7032, 0x7037, 0x55d0, 0x703b, - 0x0002, 0x703f, 0x0000, 0x007c, 0x2071, 0x7849, 0x00e0, 0x455b, - 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x00c0, 0x4524, 0x700f, + 0x0000, 0x7026, 0x702b, 0x5587, 0x7032, 0x7037, 0x55c8, 0x703b, + 0x0002, 0x703f, 0x0000, 0x007c, 0x2071, 0x7849, 0x00e0, 0x4553, + 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x00c0, 0x451c, 0x700f, 0x0361, 0x7007, 0x0001, 0x127e, 0x2091, 0x8000, 0x7138, 0x8109, - 0x713a, 0x00c0, 0x4522, 0x703b, 0x0002, 0x2009, 0x0100, 0x2104, - 0xa082, 0x0003, 0x00c8, 0x4522, 0x703c, 0xa086, 0x0001, 0x00c0, - 0x44ff, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, - 0x44dd, 0x6803, 0x1000, 0x0078, 0x44e4, 0x6804, 0xa084, 0x1000, - 0x0040, 0x44e4, 0x6803, 0x0100, 0x6803, 0x0000, 0x703f, 0x0000, - 0x2069, 0x7836, 0x6804, 0xa082, 0x0006, 0x00c0, 0x44f1, 0x6807, - 0x0000, 0x6830, 0xa082, 0x0003, 0x00c0, 0x44f8, 0x6833, 0x0000, - 0x1078, 0x4c7a, 0x1078, 0x4d3a, 0x0d7f, 0x0078, 0x4522, 0x0d7e, - 0x2069, 0x7600, 0x6944, 0x6860, 0xa102, 0x00c8, 0x4521, 0x2069, - 0x7836, 0x6804, 0xa086, 0x0000, 0x00c0, 0x4521, 0x6830, 0xa086, - 0x0000, 0x00c0, 0x4521, 0x703f, 0x0001, 0x6807, 0x0006, 0x6833, + 0x713a, 0x00c0, 0x451a, 0x703b, 0x0002, 0x2009, 0x0100, 0x2104, + 0xa082, 0x0003, 0x00c8, 0x451a, 0x703c, 0xa086, 0x0001, 0x00c0, + 0x44f7, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, + 0x44d5, 0x6803, 0x1000, 0x0078, 0x44dc, 0x6804, 0xa084, 0x1000, + 0x0040, 0x44dc, 0x6803, 0x0100, 0x6803, 0x0000, 0x703f, 0x0000, + 0x2069, 0x7836, 0x6804, 0xa082, 0x0006, 0x00c0, 0x44e9, 0x6807, + 0x0000, 0x6830, 0xa082, 0x0003, 0x00c0, 0x44f0, 0x6833, 0x0000, + 0x1078, 0x4c72, 0x1078, 0x4d32, 0x0d7f, 0x0078, 0x451a, 0x0d7e, + 0x2069, 0x7600, 0x6944, 0x6860, 0xa102, 0x00c8, 0x4519, 0x2069, + 0x7836, 0x6804, 0xa086, 0x0000, 0x00c0, 0x4519, 0x6830, 0xa086, + 0x0000, 0x00c0, 0x4519, 0x703f, 0x0001, 0x6807, 0x0006, 0x6833, 0x0003, 0x2069, 0x0100, 0x6830, 0x689e, 0x2069, 0x0140, 0x6803, - 0x0600, 0x0d7f, 0x0078, 0x4527, 0x127e, 0x2091, 0x8000, 0x7024, - 0xa00d, 0x0040, 0x4538, 0x7020, 0x8001, 0x7022, 0x00c0, 0x4538, - 0x7023, 0x0009, 0x8109, 0x7126, 0x00c0, 0x4538, 0x7028, 0x107a, - 0x7030, 0xa00d, 0x0040, 0x4549, 0x702c, 0x8001, 0x702e, 0x00c0, - 0x4549, 0x702f, 0x0009, 0x8109, 0x7132, 0x00c0, 0x4549, 0x7034, - 0x107a, 0x7018, 0xa00d, 0x0040, 0x455a, 0x7008, 0x8001, 0x700a, - 0x00c0, 0x455a, 0x700b, 0x0009, 0x8109, 0x711a, 0x00c0, 0x455a, - 0x701c, 0x107a, 0x127f, 0x7004, 0x0079, 0x455e, 0x4585, 0x4586, - 0x45a2, 0x0e7e, 0x2071, 0x7849, 0x7018, 0xa005, 0x00c0, 0x456c, + 0x0600, 0x0d7f, 0x0078, 0x451f, 0x127e, 0x2091, 0x8000, 0x7024, + 0xa00d, 0x0040, 0x4530, 0x7020, 0x8001, 0x7022, 0x00c0, 0x4530, + 0x7023, 0x0009, 0x8109, 0x7126, 0x00c0, 0x4530, 0x7028, 0x107a, + 0x7030, 0xa00d, 0x0040, 0x4541, 0x702c, 0x8001, 0x702e, 0x00c0, + 0x4541, 0x702f, 0x0009, 0x8109, 0x7132, 0x00c0, 0x4541, 0x7034, + 0x107a, 0x7018, 0xa00d, 0x0040, 0x4552, 0x7008, 0x8001, 0x700a, + 0x00c0, 0x4552, 0x700b, 0x0009, 0x8109, 0x711a, 0x00c0, 0x4552, + 0x701c, 0x107a, 0x127f, 0x7004, 0x0079, 0x4556, 0x457d, 0x457e, + 0x459a, 0x0e7e, 0x2071, 0x7849, 0x7018, 0xa005, 0x00c0, 0x4564, 0x711a, 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x0e7e, 0x007e, - 0x2071, 0x7849, 0x701c, 0xa206, 0x00c0, 0x4578, 0x701a, 0x701e, + 0x2071, 0x7849, 0x701c, 0xa206, 0x00c0, 0x4570, 0x701a, 0x701e, 0x007f, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0x7849, 0x6088, 0xa102, - 0x0048, 0x4583, 0x618a, 0x0e7f, 0x007c, 0x007c, 0x7110, 0x1078, - 0x3825, 0x00c0, 0x4598, 0x6088, 0x8001, 0x0048, 0x4598, 0x608a, - 0x00c0, 0x4598, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c7a, 0x127f, - 0x8108, 0xa182, 0x00ff, 0x0048, 0x45a0, 0xa00e, 0x7007, 0x0002, + 0x0048, 0x457b, 0x618a, 0x0e7f, 0x007c, 0x007c, 0x7110, 0x1078, + 0x381d, 0x00c0, 0x4590, 0x6088, 0x8001, 0x0048, 0x4590, 0x608a, + 0x00c0, 0x4590, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c72, 0x127f, + 0x8108, 0xa182, 0x00ff, 0x0048, 0x4598, 0xa00e, 0x7007, 0x0002, 0x7112, 0x007c, 0x7014, 0x2060, 0x127e, 0x2091, 0x8000, 0x6014, - 0xa005, 0x0040, 0x45d1, 0x8001, 0x6016, 0x00c0, 0x45d1, 0x611c, - 0xa186, 0x0003, 0x0040, 0x45b8, 0xa186, 0x0006, 0x00c0, 0x45cf, - 0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, 0x0048, 0x45cf, 0xa082, - 0x1999, 0x6856, 0xa08a, 0x199a, 0x0048, 0x45c8, 0x2001, 0x1999, - 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x0078, 0x45d1, 0x1078, - 0x67c9, 0x127f, 0xac88, 0x0008, 0x7116, 0x2001, 0x7616, 0x2004, - 0xa102, 0x0048, 0x45df, 0x7017, 0x7d00, 0x7007, 0x0000, 0x007c, + 0xa005, 0x0040, 0x45c9, 0x8001, 0x6016, 0x00c0, 0x45c9, 0x611c, + 0xa186, 0x0003, 0x0040, 0x45b0, 0xa186, 0x0006, 0x00c0, 0x45c7, + 0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, 0x0048, 0x45c7, 0xa082, + 0x1999, 0x6856, 0xa08a, 0x199a, 0x0048, 0x45c0, 0x2001, 0x1999, + 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x0078, 0x45c9, 0x1078, + 0x67c3, 0x127f, 0xac88, 0x0008, 0x7116, 0x2001, 0x7616, 0x2004, + 0xa102, 0x0048, 0x45d7, 0x7017, 0x7d00, 0x7007, 0x0000, 0x007c, 0x0e7e, 0x2071, 0x7849, 0x7027, 0x07d0, 0x7023, 0x0009, 0x703b, 0x0002, 0x0e7f, 0x007c, 0x2001, 0x7852, 0x2003, 0x0000, 0x007c, 0x0e7e, 0x2071, 0x7849, 0x7033, 0x07d0, 0x702f, 0x0009, 0x0e7f, @@ -1757,1536 +1738,5694 @@ 0x7849, 0x711a, 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x0c7e, 0x2061, 0x78da, 0x0c7f, 0x007c, 0xa184, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x78da, 0x2060, 0x007c, 0x6854, 0xa08a, 0x199a, - 0x0048, 0x461c, 0x2001, 0x1999, 0xa005, 0x00c0, 0x462c, 0x6944, - 0x0c7e, 0x1078, 0x460c, 0x6014, 0x0c7f, 0xa005, 0x00c0, 0x4631, - 0x2001, 0x001e, 0x0078, 0x4631, 0xa08e, 0xffff, 0x00c0, 0x4631, + 0x0048, 0x4614, 0x2001, 0x1999, 0xa005, 0x00c0, 0x4624, 0x6944, + 0x0c7e, 0x1078, 0x4604, 0x6014, 0x0c7f, 0xa005, 0x00c0, 0x4629, + 0x2001, 0x001e, 0x0078, 0x4629, 0xa08e, 0xffff, 0x00c0, 0x4629, 0xa006, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c, - 0x00c0, 0xa18e, 0x00c0, 0x0040, 0x466c, 0xd0b4, 0x00c0, 0x4648, - 0xd0bc, 0x00c0, 0x465a, 0x2009, 0x0006, 0x1078, 0x468f, 0x007c, - 0xd0fc, 0x0040, 0x4655, 0xa084, 0x0003, 0xa08e, 0x0003, 0x0040, - 0x4688, 0xa08e, 0x0000, 0x00c0, 0x4688, 0x2009, 0x0043, 0x1078, - 0x5c29, 0x007c, 0xd0fc, 0x0040, 0x4667, 0xa084, 0x0003, 0xa08e, - 0x0003, 0x0040, 0x4688, 0xa08e, 0x0000, 0x00c0, 0x4688, 0x2009, - 0x0042, 0x1078, 0x5c29, 0x007c, 0xd0fc, 0x0040, 0x467e, 0xa084, - 0x0003, 0xa08e, 0x0003, 0x0040, 0x4688, 0xa08e, 0x0002, 0x0040, - 0x4682, 0x2009, 0x0041, 0x1078, 0x5c29, 0x007c, 0x1078, 0x468d, - 0x0078, 0x467d, 0x2009, 0x0043, 0x1078, 0x5c29, 0x0078, 0x467d, - 0x2009, 0x0004, 0x1078, 0x468f, 0x007c, 0x2009, 0x0001, 0x6010, - 0xa0ec, 0xf000, 0x0040, 0x46b3, 0x2068, 0x6952, 0x6800, 0x6012, - 0xa186, 0x0001, 0x00c0, 0x46ad, 0x694c, 0xa18c, 0x8100, 0xa18e, - 0x8100, 0x00c0, 0x46ad, 0x0c7e, 0x6944, 0x1078, 0x460c, 0x6204, - 0x8210, 0x0048, 0x46ac, 0x6206, 0x0c7f, 0x1078, 0x3a7a, 0x6010, - 0xa06d, 0x10c0, 0x4615, 0x007c, 0x157e, 0x0c7e, 0x20a9, 0x0010, - 0x2061, 0x78da, 0x6000, 0x81ff, 0x0040, 0x46c1, 0xa205, 0x0078, - 0x46c2, 0xa204, 0x6002, 0xace0, 0x0008, 0x00f0, 0x46ba, 0x0c7f, - 0x157f, 0x007c, 0x6808, 0xa005, 0x0040, 0x46d2, 0x8001, 0x680a, + 0x00c0, 0xa18e, 0x00c0, 0x0040, 0x4664, 0xd0b4, 0x00c0, 0x4640, + 0xd0bc, 0x00c0, 0x4652, 0x2009, 0x0006, 0x1078, 0x4687, 0x007c, + 0xd0fc, 0x0040, 0x464d, 0xa084, 0x0003, 0xa08e, 0x0003, 0x0040, + 0x4680, 0xa08e, 0x0000, 0x00c0, 0x4680, 0x2009, 0x0043, 0x1078, + 0x5c21, 0x007c, 0xd0fc, 0x0040, 0x465f, 0xa084, 0x0003, 0xa08e, + 0x0003, 0x0040, 0x4680, 0xa08e, 0x0000, 0x00c0, 0x4680, 0x2009, + 0x0042, 0x1078, 0x5c21, 0x007c, 0xd0fc, 0x0040, 0x4676, 0xa084, + 0x0003, 0xa08e, 0x0003, 0x0040, 0x4680, 0xa08e, 0x0002, 0x0040, + 0x467a, 0x2009, 0x0041, 0x1078, 0x5c21, 0x007c, 0x1078, 0x4685, + 0x0078, 0x4675, 0x2009, 0x0043, 0x1078, 0x5c21, 0x0078, 0x4675, + 0x2009, 0x0004, 0x1078, 0x4687, 0x007c, 0x2009, 0x0001, 0x6010, + 0xa0ec, 0xf000, 0x0040, 0x46ab, 0x2068, 0x6952, 0x6800, 0x6012, + 0xa186, 0x0001, 0x00c0, 0x46a5, 0x694c, 0xa18c, 0x8100, 0xa18e, + 0x8100, 0x00c0, 0x46a5, 0x0c7e, 0x6944, 0x1078, 0x4604, 0x6204, + 0x8210, 0x0048, 0x46a4, 0x6206, 0x0c7f, 0x1078, 0x3a72, 0x6010, + 0xa06d, 0x10c0, 0x460d, 0x007c, 0x157e, 0x0c7e, 0x20a9, 0x0010, + 0x2061, 0x78da, 0x6000, 0x81ff, 0x0040, 0x46b9, 0xa205, 0x0078, + 0x46ba, 0xa204, 0x6002, 0xace0, 0x0008, 0x00f0, 0x46b2, 0x0c7f, + 0x157f, 0x007c, 0x6808, 0xa005, 0x0040, 0x46ca, 0x8001, 0x680a, 0xa085, 0x0001, 0x007c, 0x127e, 0x2091, 0x2200, 0x2079, 0x7836, 0x127f, 0x0d7e, 0x2069, 0x7836, 0x6803, 0x0005, 0x2069, 0x0004, 0x2d04, 0xa085, 0x8001, 0x206a, 0x0d7f, 0x007c, 0x0c7e, 0x6027, - 0x0001, 0x7804, 0xa084, 0x0007, 0x0079, 0x46ee, 0x46f8, 0x471d, - 0x4778, 0x46fe, 0x471d, 0x46f6, 0x46f6, 0x46f6, 0x1078, 0x12d5, - 0x1078, 0x45eb, 0x1078, 0x4c7a, 0x0c7f, 0x007c, 0x62c0, 0x82ff, - 0x00c0, 0x4704, 0x0c7f, 0x007c, 0x2011, 0x3542, 0x1078, 0x456e, - 0x7828, 0xa092, 0x0002, 0x00c8, 0x4713, 0x8000, 0x782a, 0x1078, - 0x3572, 0x0078, 0x4702, 0x1078, 0x3542, 0x7807, 0x0003, 0x7827, - 0x0000, 0x782b, 0x0000, 0x0078, 0x4702, 0x1078, 0x45eb, 0x3c00, + 0x0001, 0x7804, 0xa084, 0x0007, 0x0079, 0x46e6, 0x46f0, 0x4715, + 0x4770, 0x46f6, 0x4715, 0x46ee, 0x46ee, 0x46ee, 0x1078, 0x12cd, + 0x1078, 0x45e3, 0x1078, 0x4c72, 0x0c7f, 0x007c, 0x62c0, 0x82ff, + 0x00c0, 0x46fc, 0x0c7f, 0x007c, 0x2011, 0x353a, 0x1078, 0x4566, + 0x7828, 0xa092, 0x0002, 0x00c8, 0x470b, 0x8000, 0x782a, 0x1078, + 0x356a, 0x0078, 0x46fa, 0x1078, 0x353a, 0x7807, 0x0003, 0x7827, + 0x0000, 0x782b, 0x0000, 0x0078, 0x46fa, 0x1078, 0x45e3, 0x3c00, 0x007e, 0x2011, 0x0209, 0x20e1, 0x4000, 0x2214, 0x007f, 0x20e0, - 0x82ff, 0x0040, 0x473b, 0x62c0, 0x82ff, 0x00c0, 0x473b, 0x782b, - 0x0000, 0x7824, 0xa065, 0x1040, 0x12d5, 0x2009, 0x0013, 0x1078, - 0x5c29, 0x0c7f, 0x007c, 0x3900, 0xa082, 0x797a, 0x00c8, 0x4742, - 0x1078, 0x5b2c, 0x0c7e, 0x7824, 0xa065, 0x1040, 0x12d5, 0x7804, - 0xa086, 0x0004, 0x0040, 0x47bd, 0x7828, 0xa092, 0x2710, 0x00c8, - 0x4758, 0x8000, 0x782a, 0x0c7f, 0x1078, 0x5574, 0x0078, 0x4739, - 0x6104, 0xa186, 0x0003, 0x00c0, 0x476f, 0x0e7e, 0x2071, 0x7600, - 0x70c8, 0x0e7f, 0xd08c, 0x0040, 0x476f, 0x0c7e, 0x0e7e, 0x2061, - 0x0100, 0x2071, 0x7600, 0x1078, 0x357b, 0x0e7f, 0x0c7f, 0x1078, - 0x75c7, 0x2009, 0x0014, 0x1078, 0x5c29, 0x0c7f, 0x0078, 0x4739, - 0x2001, 0x7852, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x00c0, 0x478c, - 0x782b, 0x0000, 0x7824, 0xa065, 0x1040, 0x12d5, 0x2009, 0x0013, - 0x1078, 0x5c77, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x3900, 0xa082, - 0x797a, 0x00c8, 0x4795, 0x1078, 0x5b2c, 0x7824, 0xa005, 0x1040, - 0x12d5, 0x781c, 0xa06d, 0x1040, 0x12d5, 0x6800, 0xc0dc, 0x6802, - 0x7924, 0x2160, 0x1078, 0x5c02, 0x693c, 0x81ff, 0x1040, 0x12d5, - 0x8109, 0x693e, 0x6854, 0xa015, 0x0040, 0x47b1, 0x7a1e, 0x0078, - 0x47b3, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x0d7f, - 0x0c7f, 0x1078, 0x4c7a, 0x0078, 0x478a, 0x6104, 0xa186, 0x0002, - 0x0040, 0x47c8, 0xa186, 0x0004, 0x0040, 0x47c8, 0x0078, 0x474c, - 0x7808, 0xac06, 0x0040, 0x474c, 0x1078, 0x4b81, 0x1078, 0x4872, - 0x0c7f, 0x1078, 0x4c7a, 0x0078, 0x4739, 0x0c7e, 0x6027, 0x0002, - 0x2011, 0x7855, 0x2013, 0x0000, 0x62c8, 0x82ff, 0x00c0, 0x47ef, - 0x62c4, 0x82ff, 0x00c0, 0x47ef, 0x793c, 0xa1e5, 0x0000, 0x0040, - 0x47ed, 0x2009, 0x0049, 0x1078, 0x5c29, 0x0c7f, 0x007c, 0x3908, - 0xa192, 0x797a, 0x00c8, 0x47f6, 0x1078, 0x5b2c, 0x6017, 0x0010, - 0x793c, 0x81ff, 0x0040, 0x47ed, 0x7944, 0xa192, 0x7530, 0x00c8, - 0x4815, 0x8108, 0x7946, 0x1078, 0x45f0, 0x793c, 0xa188, 0x0007, - 0x210c, 0xa18e, 0x0006, 0x00c0, 0x4811, 0x6017, 0x0012, 0x0078, - 0x47ed, 0x6017, 0x0016, 0x0078, 0x47ed, 0x037e, 0x2019, 0x0001, - 0x1078, 0x5768, 0x037f, 0x1078, 0x75c7, 0x793c, 0x2160, 0x2009, - 0x004a, 0x1078, 0x5c29, 0x0078, 0x47ed, 0x007e, 0x017e, 0x0c7e, + 0x82ff, 0x0040, 0x4733, 0x62c0, 0x82ff, 0x00c0, 0x4733, 0x782b, + 0x0000, 0x7824, 0xa065, 0x1040, 0x12cd, 0x2009, 0x0013, 0x1078, + 0x5c21, 0x0c7f, 0x007c, 0x3900, 0xa082, 0x797a, 0x00c8, 0x473a, + 0x1078, 0x5b24, 0x0c7e, 0x7824, 0xa065, 0x1040, 0x12cd, 0x7804, + 0xa086, 0x0004, 0x0040, 0x47b5, 0x7828, 0xa092, 0x2710, 0x00c8, + 0x4750, 0x8000, 0x782a, 0x0c7f, 0x1078, 0x556c, 0x0078, 0x4731, + 0x6104, 0xa186, 0x0003, 0x00c0, 0x4767, 0x0e7e, 0x2071, 0x7600, + 0x70c8, 0x0e7f, 0xd08c, 0x0040, 0x4767, 0x0c7e, 0x0e7e, 0x2061, + 0x0100, 0x2071, 0x7600, 0x1078, 0x3573, 0x0e7f, 0x0c7f, 0x1078, + 0x75bc, 0x2009, 0x0014, 0x1078, 0x5c21, 0x0c7f, 0x0078, 0x4731, + 0x2001, 0x7852, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x00c0, 0x4784, + 0x782b, 0x0000, 0x7824, 0xa065, 0x1040, 0x12cd, 0x2009, 0x0013, + 0x1078, 0x5c6f, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x3900, 0xa082, + 0x797a, 0x00c8, 0x478d, 0x1078, 0x5b24, 0x7824, 0xa005, 0x1040, + 0x12cd, 0x781c, 0xa06d, 0x1040, 0x12cd, 0x6800, 0xc0dc, 0x6802, + 0x7924, 0x2160, 0x1078, 0x5bfa, 0x693c, 0x81ff, 0x1040, 0x12cd, + 0x8109, 0x693e, 0x6854, 0xa015, 0x0040, 0x47a9, 0x7a1e, 0x0078, + 0x47ab, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x0d7f, + 0x0c7f, 0x1078, 0x4c72, 0x0078, 0x4782, 0x6104, 0xa186, 0x0002, + 0x0040, 0x47c0, 0xa186, 0x0004, 0x0040, 0x47c0, 0x0078, 0x4744, + 0x7808, 0xac06, 0x0040, 0x4744, 0x1078, 0x4b79, 0x1078, 0x486a, + 0x0c7f, 0x1078, 0x4c72, 0x0078, 0x4731, 0x0c7e, 0x6027, 0x0002, + 0x2011, 0x7855, 0x2013, 0x0000, 0x62c8, 0x82ff, 0x00c0, 0x47e7, + 0x62c4, 0x82ff, 0x00c0, 0x47e7, 0x793c, 0xa1e5, 0x0000, 0x0040, + 0x47e5, 0x2009, 0x0049, 0x1078, 0x5c21, 0x0c7f, 0x007c, 0x3908, + 0xa192, 0x797a, 0x00c8, 0x47ee, 0x1078, 0x5b24, 0x6017, 0x0010, + 0x793c, 0x81ff, 0x0040, 0x47e5, 0x7944, 0xa192, 0x7530, 0x00c8, + 0x480d, 0x8108, 0x7946, 0x1078, 0x45e8, 0x793c, 0xa188, 0x0007, + 0x210c, 0xa18e, 0x0006, 0x00c0, 0x4809, 0x6017, 0x0012, 0x0078, + 0x47e5, 0x6017, 0x0016, 0x0078, 0x47e5, 0x037e, 0x2019, 0x0001, + 0x1078, 0x5760, 0x037f, 0x1078, 0x75bc, 0x793c, 0x2160, 0x2009, + 0x004a, 0x1078, 0x5c21, 0x0078, 0x47e5, 0x007e, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0x7836, - 0x6020, 0x8000, 0x6022, 0x6010, 0xa005, 0x0040, 0x4840, 0xa080, + 0x6020, 0x8000, 0x6022, 0x6010, 0xa005, 0x0040, 0x4838, 0xa080, 0x0003, 0x2102, 0x6112, 0x127f, 0x0c7f, 0x017f, 0x007f, 0x007c, - 0x6116, 0x6112, 0x0078, 0x483b, 0x0d7e, 0x2069, 0x7836, 0x6000, - 0xd0d4, 0x0040, 0x4859, 0x6820, 0x8000, 0x6822, 0xa086, 0x0001, - 0x00c0, 0x4854, 0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, 0x0079, - 0x4c82, 0xc0d5, 0x6002, 0x6818, 0xa005, 0x0040, 0x486b, 0x6056, + 0x6116, 0x6112, 0x0078, 0x4833, 0x0d7e, 0x2069, 0x7836, 0x6000, + 0xd0d4, 0x0040, 0x4851, 0x6820, 0x8000, 0x6822, 0xa086, 0x0001, + 0x00c0, 0x484c, 0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, 0x0079, + 0x4c7a, 0xc0d5, 0x6002, 0x6818, 0xa005, 0x0040, 0x4863, 0x6056, 0x605b, 0x0000, 0x007e, 0x2c00, 0x681a, 0x0d7f, 0x685a, 0x2069, - 0x7836, 0x0078, 0x484b, 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, - 0x0078, 0x484b, 0x007e, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, + 0x7836, 0x0078, 0x4843, 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, + 0x0078, 0x4843, 0x007e, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0x7836, 0x6020, 0x8000, 0x6022, - 0x6008, 0xa005, 0x0040, 0x488d, 0xa080, 0x0003, 0x2102, 0x610a, + 0x6008, 0xa005, 0x0040, 0x4885, 0xa080, 0x0003, 0x2102, 0x610a, 0x127f, 0x0c7f, 0x017f, 0x007f, 0x007c, 0x610e, 0x610a, 0x0078, - 0x4888, 0x0c7e, 0x600f, 0x0000, 0x2c08, 0x2061, 0x7836, 0x6034, - 0xa005, 0x0040, 0x48a1, 0xa080, 0x0003, 0x2102, 0x6136, 0x0c7f, - 0x007c, 0x613a, 0x6136, 0x0078, 0x489f, 0x0f7e, 0x0e7e, 0x0d7e, + 0x4880, 0x0c7e, 0x600f, 0x0000, 0x2c08, 0x2061, 0x7836, 0x6034, + 0xa005, 0x0040, 0x4899, 0xa080, 0x0003, 0x2102, 0x6136, 0x0c7f, + 0x007c, 0x613a, 0x6136, 0x0078, 0x4897, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x027e, 0x007e, 0x127e, 0x2071, 0x7836, 0x7638, - 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0040, 0x4907, 0x6018, - 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x4902, 0x703c, 0xac06, - 0x00c0, 0x48c7, 0x6003, 0x000a, 0x630a, 0x0078, 0x4902, 0x7038, - 0xac36, 0x00c0, 0x48cd, 0x660c, 0x763a, 0x7034, 0xac36, 0x00c0, - 0x48db, 0x2c00, 0xaf36, 0x0040, 0x48d9, 0x2f00, 0x7036, 0x0078, - 0x48db, 0x7037, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, - 0x48e4, 0x7e0e, 0x0078, 0x48e5, 0x2678, 0x600f, 0x0000, 0x1078, - 0x693e, 0x0040, 0x48fd, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, - 0x00c0, 0x4910, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, - 0x6b3f, 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x1078, 0x6aa1, 0x0c7f, - 0x0078, 0x48b4, 0x2c78, 0x600c, 0x2060, 0x0078, 0x48b4, 0x127f, + 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0040, 0x48ff, 0x6018, + 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x48fa, 0x703c, 0xac06, + 0x00c0, 0x48bf, 0x6003, 0x000a, 0x630a, 0x0078, 0x48fa, 0x7038, + 0xac36, 0x00c0, 0x48c5, 0x660c, 0x763a, 0x7034, 0xac36, 0x00c0, + 0x48d3, 0x2c00, 0xaf36, 0x0040, 0x48d1, 0x2f00, 0x7036, 0x0078, + 0x48d3, 0x7037, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, + 0x48dc, 0x7e0e, 0x0078, 0x48dd, 0x2678, 0x600f, 0x0000, 0x1078, + 0x6938, 0x0040, 0x48f5, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, + 0x00c0, 0x4908, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, + 0x6b34, 0x1078, 0x3a72, 0x1078, 0x6a89, 0x1078, 0x6a96, 0x0c7f, + 0x0078, 0x48ac, 0x2c78, 0x600c, 0x2060, 0x0078, 0x48ac, 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, - 0x601c, 0xa086, 0x0006, 0x00c0, 0x48f2, 0x1078, 0x74fd, 0x0078, - 0x48fd, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x0f7e, 0x2031, 0x0000, + 0x601c, 0xa086, 0x0006, 0x00c0, 0x48ea, 0x1078, 0x74f2, 0x0078, + 0x48f5, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x0f7e, 0x2031, 0x0000, 0x127e, 0x2091, 0x8000, 0x2079, 0x7836, 0x7838, 0xa065, 0x0040, - 0x4950, 0x600c, 0x007e, 0x600f, 0x0000, 0x783c, 0xac06, 0x00c0, - 0x4937, 0x6003, 0x000a, 0x630a, 0x2c30, 0x0078, 0x494d, 0x1078, - 0x693e, 0x0040, 0x494b, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, - 0x00c0, 0x4959, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, - 0x3a7a, 0x1078, 0x6a94, 0x1078, 0x6aa1, 0x007f, 0x0078, 0x4926, + 0x4948, 0x600c, 0x007e, 0x600f, 0x0000, 0x783c, 0xac06, 0x00c0, + 0x492f, 0x6003, 0x000a, 0x630a, 0x2c30, 0x0078, 0x4945, 0x1078, + 0x6938, 0x0040, 0x4943, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, + 0x00c0, 0x4951, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, + 0x3a72, 0x1078, 0x6a89, 0x1078, 0x6a96, 0x007f, 0x0078, 0x491e, 0x7e3a, 0x7e36, 0x127f, 0x0f7f, 0x0d7f, 0x0c7f, 0x067f, 0x007f, - 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x4942, 0x1078, 0x74fd, - 0x0078, 0x494b, 0x027e, 0x1078, 0x4976, 0x1078, 0x4a0f, 0x027f, + 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x493a, 0x1078, 0x74f2, + 0x0078, 0x4943, 0x027e, 0x1078, 0x496e, 0x1078, 0x4a07, 0x027f, 0x007c, 0x0f7e, 0x127e, 0x2079, 0x7836, 0x2091, 0x8000, 0x1078, - 0x4aa6, 0x1078, 0x4b0e, 0x127f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e, + 0x4a9e, 0x1078, 0x4b06, 0x127f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, - 0x7836, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0040, 0x49fe, 0x6018, - 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x49f9, 0x7024, 0xac06, - 0x00c0, 0x49bc, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x49b7, - 0x1078, 0x5582, 0x68c3, 0x0000, 0x1078, 0x5a32, 0x7027, 0x0000, - 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x49ac, + 0x7836, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0040, 0x49f6, 0x6018, + 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x49f1, 0x7024, 0xac06, + 0x00c0, 0x49b4, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x49af, + 0x1078, 0x557a, 0x68c3, 0x0000, 0x1078, 0x5a2a, 0x7027, 0x0000, + 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x49a4, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, - 0x0040, 0x49b4, 0x6827, 0x0001, 0x037f, 0x0078, 0x49bc, 0x6003, - 0x0009, 0x630a, 0x0078, 0x49f9, 0x7014, 0xac36, 0x00c0, 0x49c2, - 0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x49d0, 0x2c00, 0xaf36, - 0x0040, 0x49ce, 0x2f00, 0x7012, 0x0078, 0x49d0, 0x7013, 0x0000, - 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x49d9, 0x7e0e, 0x0078, - 0x49da, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x693e, - 0x0040, 0x49f2, 0x601c, 0xa086, 0x0003, 0x00c0, 0x4a06, 0x6837, - 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x6b3f, 0x1078, 0x3a7a, - 0x1078, 0x6a94, 0x1078, 0x6aa1, 0x1078, 0x5902, 0x0c7f, 0x0078, - 0x4984, 0x2c78, 0x600c, 0x2060, 0x0078, 0x4984, 0x127f, 0x007f, + 0x0040, 0x49ac, 0x6827, 0x0001, 0x037f, 0x0078, 0x49b4, 0x6003, + 0x0009, 0x630a, 0x0078, 0x49f1, 0x7014, 0xac36, 0x00c0, 0x49ba, + 0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x49c8, 0x2c00, 0xaf36, + 0x0040, 0x49c6, 0x2f00, 0x7012, 0x0078, 0x49c8, 0x7013, 0x0000, + 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x49d1, 0x7e0e, 0x0078, + 0x49d2, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x6938, + 0x0040, 0x49ea, 0x601c, 0xa086, 0x0003, 0x00c0, 0x49fe, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x6b34, 0x1078, 0x3a72, + 0x1078, 0x6a89, 0x1078, 0x6a96, 0x1078, 0x58fa, 0x0c7f, 0x0078, + 0x497c, 0x2c78, 0x600c, 0x2060, 0x0078, 0x497c, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, - 0x0006, 0x00c0, 0x49e7, 0x1078, 0x74fd, 0x0078, 0x49f2, 0x0c7e, + 0x0006, 0x00c0, 0x49df, 0x1078, 0x74f2, 0x0078, 0x49ea, 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, 0xa280, 0x7720, 0x2004, 0xa065, - 0x0040, 0x4aa2, 0x0f7e, 0x0e7e, 0x0d7e, 0x067e, 0x2071, 0x7836, - 0x6654, 0x7018, 0xac06, 0x00c0, 0x4a26, 0x761a, 0x701c, 0xac06, - 0x00c0, 0x4a32, 0x86ff, 0x00c0, 0x4a31, 0x7018, 0x701e, 0x0078, - 0x4a32, 0x761e, 0x6058, 0xa07d, 0x0040, 0x4a37, 0x7e56, 0xa6ed, - 0x0000, 0x0040, 0x4a3d, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b, - 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x37a2, 0x0040, - 0x4a9e, 0x7624, 0x86ff, 0x0040, 0x4a8e, 0xa680, 0x0004, 0x2004, - 0xad06, 0x00c0, 0x4a8e, 0x0d7e, 0x2069, 0x0100, 0x68c0, 0xa005, - 0x0040, 0x4a85, 0x1078, 0x5582, 0x68c3, 0x0000, 0x1078, 0x5a32, + 0x0040, 0x4a9a, 0x0f7e, 0x0e7e, 0x0d7e, 0x067e, 0x2071, 0x7836, + 0x6654, 0x7018, 0xac06, 0x00c0, 0x4a1e, 0x761a, 0x701c, 0xac06, + 0x00c0, 0x4a2a, 0x86ff, 0x00c0, 0x4a29, 0x7018, 0x701e, 0x0078, + 0x4a2a, 0x761e, 0x6058, 0xa07d, 0x0040, 0x4a2f, 0x7e56, 0xa6ed, + 0x0000, 0x0040, 0x4a35, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b, + 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x379a, 0x0040, + 0x4a96, 0x7624, 0x86ff, 0x0040, 0x4a86, 0xa680, 0x0004, 0x2004, + 0xad06, 0x00c0, 0x4a86, 0x0d7e, 0x2069, 0x0100, 0x68c0, 0xa005, + 0x0040, 0x4a7d, 0x1078, 0x557a, 0x68c3, 0x0000, 0x1078, 0x5a2a, 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, - 0x0040, 0x4a6e, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0040, 0x4a76, 0x6827, 0x0001, 0x037f, 0x0d7f, - 0x0c7e, 0x603c, 0xa005, 0x0040, 0x4a7f, 0x8001, 0x603e, 0x2660, - 0x1078, 0x6aa1, 0x0c7f, 0x0078, 0x4a8e, 0x0d7f, 0x0c7e, 0x2660, - 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, 0x4a45, 0x8dff, 0x0040, - 0x4a9a, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x6b3f, - 0x1078, 0x3a7a, 0x1078, 0x5902, 0x0078, 0x4a45, 0x067f, 0x0d7f, + 0x0040, 0x4a66, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, + 0x6824, 0xd084, 0x0040, 0x4a6e, 0x6827, 0x0001, 0x037f, 0x0d7f, + 0x0c7e, 0x603c, 0xa005, 0x0040, 0x4a77, 0x8001, 0x603e, 0x2660, + 0x1078, 0x6a96, 0x0c7f, 0x0078, 0x4a86, 0x0d7f, 0x0c7e, 0x2660, + 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, 0x4a3d, 0x8dff, 0x0040, + 0x4a92, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x6b34, + 0x1078, 0x3a72, 0x1078, 0x58fa, 0x0078, 0x4a3d, 0x067f, 0x0d7f, 0x0e7f, 0x0f7f, 0x127f, 0x007f, 0x0c7f, 0x007c, 0x007e, 0x067e, - 0x0c7e, 0x0d7e, 0x2031, 0x0000, 0x7814, 0xa065, 0x0040, 0x4afe, - 0x600c, 0x007e, 0x600f, 0x0000, 0x7824, 0xac06, 0x00c0, 0x4ae3, - 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x4add, 0x1078, 0x5582, - 0x68c3, 0x0000, 0x1078, 0x5a32, 0x7827, 0x0000, 0x037e, 0x2069, - 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x4ad2, 0x6803, 0x0100, - 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x4ada, - 0x6827, 0x0001, 0x037f, 0x0078, 0x4ae3, 0x6003, 0x0009, 0x630a, - 0x2c30, 0x0078, 0x4afb, 0x6010, 0x2068, 0x1078, 0x693e, 0x0040, - 0x4af7, 0x601c, 0xa086, 0x0003, 0x00c0, 0x4b05, 0x6837, 0x0103, - 0x6b4a, 0x6847, 0x0000, 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x1078, - 0x6aa1, 0x1078, 0x5902, 0x007f, 0x0078, 0x4aad, 0x7e16, 0x7e12, + 0x0c7e, 0x0d7e, 0x2031, 0x0000, 0x7814, 0xa065, 0x0040, 0x4af6, + 0x600c, 0x007e, 0x600f, 0x0000, 0x7824, 0xac06, 0x00c0, 0x4adb, + 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x4ad5, 0x1078, 0x557a, + 0x68c3, 0x0000, 0x1078, 0x5a2a, 0x7827, 0x0000, 0x037e, 0x2069, + 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x4aca, 0x6803, 0x0100, + 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x4ad2, + 0x6827, 0x0001, 0x037f, 0x0078, 0x4adb, 0x6003, 0x0009, 0x630a, + 0x2c30, 0x0078, 0x4af3, 0x6010, 0x2068, 0x1078, 0x6938, 0x0040, + 0x4aef, 0x601c, 0xa086, 0x0003, 0x00c0, 0x4afd, 0x6837, 0x0103, + 0x6b4a, 0x6847, 0x0000, 0x1078, 0x3a72, 0x1078, 0x6a89, 0x1078, + 0x6a96, 0x1078, 0x58fa, 0x007f, 0x0078, 0x4aa5, 0x7e16, 0x7e12, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x601c, 0xa086, 0x0006, - 0x00c0, 0x4aee, 0x1078, 0x74fd, 0x0078, 0x4af7, 0x007e, 0x067e, - 0x0c7e, 0x0d7e, 0x7818, 0xa065, 0x0040, 0x4b7a, 0x6054, 0x007e, + 0x00c0, 0x4ae6, 0x1078, 0x74f2, 0x0078, 0x4aef, 0x007e, 0x067e, + 0x0c7e, 0x0d7e, 0x7818, 0xa065, 0x0040, 0x4b72, 0x6054, 0x007e, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, - 0x1078, 0x37a2, 0x0040, 0x4b77, 0x7e24, 0x86ff, 0x0040, 0x4b69, - 0xa680, 0x0004, 0x2004, 0xad06, 0x00c0, 0x4b69, 0x0d7e, 0x2069, - 0x0100, 0x68c0, 0xa005, 0x0040, 0x4b60, 0x1078, 0x5582, 0x68c3, - 0x0000, 0x1078, 0x5a32, 0x7827, 0x0000, 0x037e, 0x2069, 0x0140, - 0x6b04, 0xa384, 0x1000, 0x0040, 0x4b49, 0x6803, 0x0100, 0x6803, - 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x4b51, 0x6827, - 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040, 0x4b5a, - 0x8001, 0x603e, 0x2660, 0x1078, 0x6aa1, 0x0c7f, 0x0078, 0x4b69, + 0x1078, 0x379a, 0x0040, 0x4b6f, 0x7e24, 0x86ff, 0x0040, 0x4b61, + 0xa680, 0x0004, 0x2004, 0xad06, 0x00c0, 0x4b61, 0x0d7e, 0x2069, + 0x0100, 0x68c0, 0xa005, 0x0040, 0x4b58, 0x1078, 0x557a, 0x68c3, + 0x0000, 0x1078, 0x5a2a, 0x7827, 0x0000, 0x037e, 0x2069, 0x0140, + 0x6b04, 0xa384, 0x1000, 0x0040, 0x4b41, 0x6803, 0x0100, 0x6803, + 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x4b49, 0x6827, + 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040, 0x4b52, + 0x8001, 0x603e, 0x2660, 0x1078, 0x6a96, 0x0c7f, 0x0078, 0x4b61, 0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, - 0x4b20, 0x8dff, 0x0040, 0x4b73, 0x6837, 0x0103, 0x6b4a, 0x6847, - 0x0000, 0x1078, 0x3a7a, 0x1078, 0x5902, 0x0078, 0x4b20, 0x007f, - 0x0078, 0x4b13, 0x781e, 0x781a, 0x0d7f, 0x0c7f, 0x067f, 0x007f, + 0x4b18, 0x8dff, 0x0040, 0x4b6b, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x1078, 0x3a72, 0x1078, 0x58fa, 0x0078, 0x4b18, 0x007f, + 0x0078, 0x4b0b, 0x781e, 0x781a, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x0e7e, 0x0c7e, 0x2071, 0x7836, 0x7004, 0xa084, 0x0007, - 0x0079, 0x4b8a, 0x4b94, 0x4b97, 0x4bb0, 0x4bcc, 0x4c11, 0x4b94, - 0x4b94, 0x4b92, 0x1078, 0x12d5, 0x0c7f, 0x0e7f, 0x007c, 0x7024, - 0xa065, 0x0040, 0x4ba5, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015, - 0x0040, 0x4bac, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, - 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7216, 0x7212, 0x0078, 0x4ba5, - 0x6018, 0x2060, 0x1078, 0x37a2, 0x6000, 0xc0dc, 0x6002, 0x7020, - 0x8001, 0x7022, 0x0040, 0x4bc1, 0x6054, 0xa015, 0x0040, 0x4bc8, + 0x0079, 0x4b82, 0x4b8c, 0x4b8f, 0x4ba8, 0x4bc4, 0x4c09, 0x4b8c, + 0x4b8c, 0x4b8a, 0x1078, 0x12cd, 0x0c7f, 0x0e7f, 0x007c, 0x7024, + 0xa065, 0x0040, 0x4b9d, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015, + 0x0040, 0x4ba4, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, + 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7216, 0x7212, 0x0078, 0x4b9d, + 0x6018, 0x2060, 0x1078, 0x379a, 0x6000, 0xc0dc, 0x6002, 0x7020, + 0x8001, 0x7022, 0x0040, 0x4bb9, 0x6054, 0xa015, 0x0040, 0x4bc0, 0x721e, 0x7007, 0x0000, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, - 0x7218, 0x721e, 0x0078, 0x4bc1, 0x7024, 0xa065, 0x0040, 0x4c0e, - 0x700c, 0xac06, 0x00c0, 0x4be3, 0x1078, 0x5902, 0x600c, 0xa015, - 0x0040, 0x4bdf, 0x720e, 0x600f, 0x0000, 0x0078, 0x4c0c, 0x720e, - 0x720a, 0x0078, 0x4c0c, 0x7014, 0xac06, 0x00c0, 0x4bf6, 0x1078, - 0x5902, 0x600c, 0xa015, 0x0040, 0x4bf2, 0x7216, 0x600f, 0x0000, - 0x0078, 0x4c0c, 0x7216, 0x7212, 0x0078, 0x4c0c, 0x6018, 0x2060, - 0x1078, 0x37a2, 0x6000, 0xc0dc, 0x6002, 0x1078, 0x5902, 0x701c, - 0xa065, 0x0040, 0x4c0c, 0x6054, 0xa015, 0x0040, 0x4c0a, 0x721e, - 0x0078, 0x4c0c, 0x7218, 0x721e, 0x7027, 0x0000, 0x0c7f, 0x0e7f, - 0x007c, 0x7024, 0xa065, 0x0040, 0x4c1e, 0x1078, 0x5902, 0x600c, - 0xa015, 0x0040, 0x4c25, 0x720e, 0x600f, 0x0000, 0x1078, 0x5a32, + 0x7218, 0x721e, 0x0078, 0x4bb9, 0x7024, 0xa065, 0x0040, 0x4c06, + 0x700c, 0xac06, 0x00c0, 0x4bdb, 0x1078, 0x58fa, 0x600c, 0xa015, + 0x0040, 0x4bd7, 0x720e, 0x600f, 0x0000, 0x0078, 0x4c04, 0x720e, + 0x720a, 0x0078, 0x4c04, 0x7014, 0xac06, 0x00c0, 0x4bee, 0x1078, + 0x58fa, 0x600c, 0xa015, 0x0040, 0x4bea, 0x7216, 0x600f, 0x0000, + 0x0078, 0x4c04, 0x7216, 0x7212, 0x0078, 0x4c04, 0x6018, 0x2060, + 0x1078, 0x379a, 0x6000, 0xc0dc, 0x6002, 0x1078, 0x58fa, 0x701c, + 0xa065, 0x0040, 0x4c04, 0x6054, 0xa015, 0x0040, 0x4c02, 0x721e, + 0x0078, 0x4c04, 0x7218, 0x721e, 0x7027, 0x0000, 0x0c7f, 0x0e7f, + 0x007c, 0x7024, 0xa065, 0x0040, 0x4c16, 0x1078, 0x58fa, 0x600c, + 0xa015, 0x0040, 0x4c1d, 0x720e, 0x600f, 0x0000, 0x1078, 0x5a2a, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x720e, 0x720a, 0x0078, - 0x4c1e, 0x0d7e, 0x2069, 0x7836, 0x6830, 0xa084, 0x0003, 0x0079, - 0x4c31, 0x4c37, 0x4c39, 0x4c5f, 0x4c37, 0x1078, 0x12d5, 0x0d7f, - 0x007c, 0x0c7e, 0x6840, 0xa086, 0x0001, 0x0040, 0x4c55, 0x683c, - 0xa065, 0x0040, 0x4c4a, 0x600c, 0xa015, 0x0040, 0x4c51, 0x6a3a, + 0x4c16, 0x0d7e, 0x2069, 0x7836, 0x6830, 0xa084, 0x0003, 0x0079, + 0x4c29, 0x4c2f, 0x4c31, 0x4c57, 0x4c2f, 0x1078, 0x12cd, 0x0d7f, + 0x007c, 0x0c7e, 0x6840, 0xa086, 0x0001, 0x0040, 0x4c4d, 0x683c, + 0xa065, 0x0040, 0x4c42, 0x600c, 0xa015, 0x0040, 0x4c49, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c7f, 0x0d7f, - 0x007c, 0x683a, 0x6836, 0x0078, 0x4c4a, 0x6843, 0x0000, 0x6838, - 0xa065, 0x0040, 0x4c4a, 0x6003, 0x0003, 0x0078, 0x4c4a, 0x0c7e, - 0x6843, 0x0000, 0x6847, 0x0000, 0x683c, 0xa065, 0x0040, 0x4c77, - 0x600c, 0xa015, 0x0040, 0x4c73, 0x6a3a, 0x600f, 0x0000, 0x683f, - 0x0000, 0x0078, 0x4c77, 0x683f, 0x0000, 0x683a, 0x6836, 0x0c7f, + 0x007c, 0x683a, 0x6836, 0x0078, 0x4c42, 0x6843, 0x0000, 0x6838, + 0xa065, 0x0040, 0x4c42, 0x6003, 0x0003, 0x0078, 0x4c42, 0x0c7e, + 0x6843, 0x0000, 0x6847, 0x0000, 0x683c, 0xa065, 0x0040, 0x4c6f, + 0x600c, 0xa015, 0x0040, 0x4c6b, 0x6a3a, 0x600f, 0x0000, 0x683f, + 0x0000, 0x0078, 0x4c6f, 0x683f, 0x0000, 0x683a, 0x6836, 0x0c7f, 0x0d7f, 0x007c, 0x0d7e, 0x2069, 0x7836, 0x6804, 0xa084, 0x0007, - 0x0079, 0x4c82, 0x4c8c, 0x4d29, 0x4d29, 0x4d29, 0x4d29, 0x4d2b, - 0x4d29, 0x4c8a, 0x1078, 0x12d5, 0x6820, 0xa005, 0x00c0, 0x4c92, - 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x4ca1, 0x6807, - 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x4d71, 0x0c7f, 0x0d7f, - 0x007c, 0x6814, 0xa065, 0x0040, 0x4caf, 0x6807, 0x0001, 0x6826, - 0x682b, 0x0000, 0x1078, 0x4d71, 0x0c7f, 0x0d7f, 0x007c, 0x0e7e, - 0x037e, 0x6a1c, 0xa2f5, 0x0000, 0x0040, 0x4d24, 0x704c, 0xa00d, - 0x0040, 0x4cbe, 0x7088, 0xa005, 0x0040, 0x4cd6, 0x7054, 0xa075, - 0x0040, 0x4cc7, 0xa20e, 0x0040, 0x4d24, 0x0078, 0x4ccc, 0x6818, - 0xa20e, 0x0040, 0x4d24, 0x2070, 0x704c, 0xa00d, 0x0040, 0x4cbe, - 0x7088, 0xa005, 0x00c0, 0x4cbe, 0x2e00, 0x681e, 0x733c, 0x7038, - 0xa302, 0x00c8, 0x4cbe, 0x1078, 0x5bd1, 0x0040, 0x4d24, 0x8318, + 0x0079, 0x4c7a, 0x4c84, 0x4d21, 0x4d21, 0x4d21, 0x4d21, 0x4d23, + 0x4d21, 0x4c82, 0x1078, 0x12cd, 0x6820, 0xa005, 0x00c0, 0x4c8a, + 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x4c99, 0x6807, + 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x4d69, 0x0c7f, 0x0d7f, + 0x007c, 0x6814, 0xa065, 0x0040, 0x4ca7, 0x6807, 0x0001, 0x6826, + 0x682b, 0x0000, 0x1078, 0x4d69, 0x0c7f, 0x0d7f, 0x007c, 0x0e7e, + 0x037e, 0x6a1c, 0xa2f5, 0x0000, 0x0040, 0x4d1c, 0x704c, 0xa00d, + 0x0040, 0x4cb6, 0x7088, 0xa005, 0x0040, 0x4cce, 0x7054, 0xa075, + 0x0040, 0x4cbf, 0xa20e, 0x0040, 0x4d1c, 0x0078, 0x4cc4, 0x6818, + 0xa20e, 0x0040, 0x4d1c, 0x2070, 0x704c, 0xa00d, 0x0040, 0x4cb6, + 0x7088, 0xa005, 0x00c0, 0x4cb6, 0x2e00, 0x681e, 0x733c, 0x7038, + 0xa302, 0x00c8, 0x4cb6, 0x1078, 0x5bc9, 0x0040, 0x4d1c, 0x8318, 0x733e, 0x6112, 0x2e10, 0x621a, 0xa180, 0x0015, 0x2004, 0xa08a, - 0x199a, 0x0048, 0x4ced, 0x2001, 0x1999, 0x8003, 0x801b, 0x831b, + 0x199a, 0x0048, 0x4ce5, 0x2001, 0x1999, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x037f, 0x0f7e, 0x2c78, 0x71a0, 0xd1bc, 0x0040, - 0x4d06, 0x7100, 0xd1f4, 0x0040, 0x4d02, 0x7114, 0xa18c, 0x00ff, - 0x0078, 0x4d0b, 0x2009, 0x0000, 0x0078, 0x4d0b, 0xa1e0, 0x232f, - 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x1078, 0x51c2, + 0x4cfe, 0x7100, 0xd1f4, 0x0040, 0x4cfa, 0x7114, 0xa18c, 0x00ff, + 0x0078, 0x4d03, 0x2009, 0x0000, 0x0078, 0x4d03, 0xa1e0, 0x2329, + 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x1078, 0x51ba, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, 0x0f7f, 0x0e7f, 0x0c7f, 0x0d7f, 0x007c, 0x037f, 0x0e7f, 0x0c7f, 0x0078, - 0x4d22, 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x4d37, - 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x4d71, 0x0c7f, + 0x4d1a, 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x4d2f, + 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x4d69, 0x0c7f, 0x0d7f, 0x007c, 0x0f7e, 0x0d7e, 0x2069, 0x7836, 0x6830, 0xa086, - 0x0000, 0x00c0, 0x4d58, 0x6838, 0xa07d, 0x0040, 0x4d58, 0x6833, + 0x0000, 0x00c0, 0x4d50, 0x6838, 0xa07d, 0x0040, 0x4d50, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x127e, 0x0f7e, 0x2091, 0x2200, - 0x027f, 0x1078, 0x1a4c, 0x00c0, 0x4d5b, 0x127f, 0x1078, 0x5457, + 0x027f, 0x1078, 0x1a44, 0x00c0, 0x4d53, 0x127f, 0x1078, 0x544f, 0x0d7f, 0x0f7f, 0x007c, 0x127f, 0x6843, 0x0000, 0x7803, 0x0002, - 0x780c, 0xa015, 0x0040, 0x4d6d, 0x6a3a, 0x780f, 0x0000, 0x6833, - 0x0000, 0x683f, 0x0000, 0x0078, 0x4d58, 0x683a, 0x6836, 0x0078, - 0x4d67, 0x601c, 0xa084, 0x000f, 0x1079, 0x4d77, 0x007c, 0x4d80, - 0x4d85, 0x508c, 0x5182, 0x4d85, 0x508c, 0x5182, 0x4d80, 0x4d85, - 0x1078, 0x4b81, 0x1078, 0x4c7a, 0x007c, 0x157e, 0x137e, 0x147e, - 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0030, 0x10c8, 0x12d5, 0x6118, - 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x4da2, 0x7900, 0xd1f4, 0x0040, - 0x4d9e, 0x7914, 0xa18c, 0x00ff, 0x0078, 0x4da7, 0x2009, 0x0000, - 0x0078, 0x4da7, 0xa1f8, 0x232f, 0x2f0c, 0xa18c, 0x00ff, 0x2c78, - 0x2061, 0x0100, 0x619a, 0x1079, 0x4db3, 0x0f7f, 0x0c7f, 0x147f, - 0x137f, 0x157f, 0x007c, 0x4de5, 0x4e1d, 0x4e35, 0x4eb4, 0x4ee1, - 0x4ee9, 0x4f0a, 0x4f1b, 0x4f2c, 0x4f34, 0x4f45, 0x4f34, 0x4f8d, - 0x4f1b, 0x4fae, 0x4fb6, 0x4f2c, 0x4fb6, 0x4fc7, 0x4de3, 0x4de3, - 0x4de3, 0x4de3, 0x4de3, 0x4de3, 0x4de3, 0x4de3, 0x4de3, 0x4de3, - 0x4de3, 0x4de3, 0x5640, 0x5655, 0x5678, 0x569c, 0x4f0a, 0x4de3, - 0x4f0a, 0x4f34, 0x4de3, 0x4e35, 0x4eb4, 0x4de3, 0x5b4c, 0x4f34, - 0x4de3, 0x5b6f, 0x4f34, 0x1078, 0x12d5, 0x20a1, 0x020b, 0x1078, - 0x4fdc, 0x20a3, 0x5200, 0x20a3, 0x0000, 0x0d7e, 0x2069, 0x7651, - 0x6804, 0xd084, 0x0040, 0x4dff, 0x6828, 0x20a3, 0x0000, 0x017e, - 0x1078, 0x209a, 0x21a2, 0x017f, 0x0d7f, 0x0078, 0x4e04, 0x0d7f, + 0x780c, 0xa015, 0x0040, 0x4d65, 0x6a3a, 0x780f, 0x0000, 0x6833, + 0x0000, 0x683f, 0x0000, 0x0078, 0x4d50, 0x683a, 0x6836, 0x0078, + 0x4d5f, 0x601c, 0xa084, 0x000f, 0x1079, 0x4d6f, 0x007c, 0x4d78, + 0x4d7d, 0x5084, 0x517a, 0x4d7d, 0x5084, 0x517a, 0x4d78, 0x4d7d, + 0x1078, 0x4b79, 0x1078, 0x4c72, 0x007c, 0x157e, 0x137e, 0x147e, + 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0030, 0x10c8, 0x12cd, 0x6118, + 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x4d9a, 0x7900, 0xd1f4, 0x0040, + 0x4d96, 0x7914, 0xa18c, 0x00ff, 0x0078, 0x4d9f, 0x2009, 0x0000, + 0x0078, 0x4d9f, 0xa1f8, 0x2329, 0x2f0c, 0xa18c, 0x00ff, 0x2c78, + 0x2061, 0x0100, 0x619a, 0x1079, 0x4dab, 0x0f7f, 0x0c7f, 0x147f, + 0x137f, 0x157f, 0x007c, 0x4ddd, 0x4e15, 0x4e2d, 0x4eac, 0x4ed9, + 0x4ee1, 0x4f02, 0x4f13, 0x4f24, 0x4f2c, 0x4f3d, 0x4f2c, 0x4f85, + 0x4f13, 0x4fa6, 0x4fae, 0x4f24, 0x4fae, 0x4fbf, 0x4ddb, 0x4ddb, + 0x4ddb, 0x4ddb, 0x4ddb, 0x4ddb, 0x4ddb, 0x4ddb, 0x4ddb, 0x4ddb, + 0x4ddb, 0x4ddb, 0x5638, 0x564d, 0x5670, 0x5694, 0x4f02, 0x4ddb, + 0x4f02, 0x4f2c, 0x4ddb, 0x4e2d, 0x4eac, 0x4ddb, 0x5b44, 0x4f2c, + 0x4ddb, 0x5b67, 0x4f2c, 0x1078, 0x12cd, 0x20a1, 0x020b, 0x1078, + 0x4fd4, 0x20a3, 0x5200, 0x20a3, 0x0000, 0x0d7e, 0x2069, 0x7651, + 0x6804, 0xd084, 0x0040, 0x4df7, 0x6828, 0x20a3, 0x0000, 0x017e, + 0x1078, 0x2094, 0x21a2, 0x017f, 0x0d7f, 0x0078, 0x4dfc, 0x0d7f, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0x7605, 0x53a6, 0x20a9, 0x0004, 0x2099, 0x7601, 0x53a6, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x60c3, 0x001c, 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b, 0x1078, - 0x4fdc, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x6030, + 0x60c3, 0x001c, 0x1078, 0x5566, 0x007c, 0x20a1, 0x020b, 0x1078, + 0x4fd4, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2, 0x20a9, 0x0004, 0x2099, 0x7605, 0x53a6, - 0x60c3, 0x0010, 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b, 0x1078, - 0x4fdc, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, - 0x4e48, 0x20a3, 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0078, 0x4e4a, + 0x60c3, 0x0010, 0x1078, 0x5566, 0x007c, 0x20a1, 0x020b, 0x1078, + 0x4fd4, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, + 0x4e40, 0x20a3, 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0078, 0x4e42, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x7818, 0xa080, 0x0028, 0x2004, - 0xa086, 0x007e, 0x00c0, 0x4e83, 0x2099, 0x7820, 0x33a6, 0x9398, + 0xa086, 0x007e, 0x00c0, 0x4e7b, 0x2099, 0x7820, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304, 0xa084, 0x3fff, 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0x7605, 0x53a6, 0x20a9, 0x0004, 0x2099, - 0x7601, 0x53a6, 0x20a9, 0x0010, 0x20a3, 0x0000, 0x00f0, 0x4e74, + 0x7601, 0x53a6, 0x20a9, 0x0010, 0x20a3, 0x0000, 0x00f0, 0x4e6c, 0x2099, 0x7828, 0x33a6, 0x20a9, 0x0007, 0x20a3, 0x0000, 0x00f0, - 0x4e7d, 0x0078, 0x4ea3, 0x2099, 0x7820, 0x20a9, 0x0008, 0x53a6, + 0x4e75, 0x0078, 0x4e9b, 0x2099, 0x7820, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0004, 0x2099, 0x7605, 0x53a6, 0x20a9, 0x0004, 0x2099, - 0x7601, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x4e94, - 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x4e9a, 0x2099, 0x7828, + 0x7601, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x4e8c, + 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x4e92, 0x2099, 0x7828, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, - 0x4ea5, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x4eab, 0x60c3, - 0x0074, 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b, 0x1078, 0x4fdc, + 0x4e9d, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x4ea3, 0x60c3, + 0x0074, 0x1078, 0x5566, 0x007c, 0x20a1, 0x020b, 0x1078, 0x4fd4, 0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079, - 0x7651, 0x7904, 0x0f7f, 0xd1ac, 0x00c0, 0x4ed0, 0xa085, 0x0020, - 0xd1a4, 0x0040, 0x4ed5, 0xa085, 0x0010, 0xa085, 0x0002, 0x20a2, - 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x556e, - 0x007c, 0x20a1, 0x020b, 0x1078, 0x4fdc, 0x20a3, 0x5000, 0x0078, - 0x4e4a, 0x20a1, 0x020b, 0x1078, 0x4fdc, 0x20a3, 0x2110, 0x20a3, + 0x7651, 0x7904, 0x0f7f, 0xd1ac, 0x00c0, 0x4ec8, 0xa085, 0x0020, + 0xd1a4, 0x0040, 0x4ecd, 0xa085, 0x0010, 0xa085, 0x0002, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x5566, + 0x007c, 0x20a1, 0x020b, 0x1078, 0x4fd4, 0x20a3, 0x5000, 0x0078, + 0x4e42, 0x20a1, 0x020b, 0x1078, 0x4fd4, 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, - 0x556e, 0x007c, 0x20a1, 0x020b, 0x1078, 0x5053, 0x20a3, 0x0200, + 0x5566, 0x007c, 0x20a1, 0x020b, 0x1078, 0x504b, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, - 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b, 0x1078, 0x5053, 0x20a3, + 0x1078, 0x5566, 0x007c, 0x20a1, 0x020b, 0x1078, 0x504b, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, - 0x0008, 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b, 0x1078, 0x5053, - 0x20a3, 0x0200, 0x0078, 0x4e4a, 0x20a1, 0x020b, 0x1078, 0x5053, + 0x0008, 0x1078, 0x5566, 0x007c, 0x20a1, 0x020b, 0x1078, 0x504b, + 0x20a3, 0x0200, 0x0078, 0x4e42, 0x20a1, 0x020b, 0x1078, 0x504b, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x7810, 0x20a2, - 0x60c3, 0x0008, 0x1078, 0x556e, 0x007c, 0x0d7e, 0x20a1, 0x020b, - 0x1078, 0x5053, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800, - 0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x00c0, 0x4f6b, 0x6998, - 0xa184, 0xc000, 0x00c0, 0x4f67, 0xd1ec, 0x0040, 0x4f63, 0x20a3, - 0x2100, 0x0078, 0x4f6d, 0x20a3, 0x0100, 0x0078, 0x4f6d, 0x20a3, - 0x0400, 0x0078, 0x4f6d, 0x20a3, 0x0700, 0xa006, 0x20a2, 0x20a2, + 0x60c3, 0x0008, 0x1078, 0x5566, 0x007c, 0x0d7e, 0x20a1, 0x020b, + 0x1078, 0x504b, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800, + 0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x00c0, 0x4f63, 0x6998, + 0xa184, 0xc000, 0x00c0, 0x4f5f, 0xd1ec, 0x0040, 0x4f5b, 0x20a3, + 0x2100, 0x0078, 0x4f65, 0x20a3, 0x0100, 0x0078, 0x4f65, 0x20a3, + 0x0400, 0x0078, 0x4f65, 0x20a3, 0x0700, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079, 0x7651, 0x7904, 0x0f7f, - 0xd1ac, 0x00c0, 0x4f7d, 0xa085, 0x0020, 0xd1a4, 0x0040, 0x4f82, + 0xd1ac, 0x00c0, 0x4f75, 0xa085, 0x0020, 0xd1a4, 0x0040, 0x4f7a, 0xa085, 0x0010, 0xa085, 0x0002, 0x20a2, 0x20a2, 0x20a2, 0x60c3, - 0x0014, 0x1078, 0x556e, 0x0d7f, 0x007c, 0x20a1, 0x020b, 0x1078, - 0x5053, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, + 0x0014, 0x1078, 0x5566, 0x0d7f, 0x007c, 0x20a1, 0x020b, 0x1078, + 0x504b, 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, 0x556e, 0x007c, 0x20a1, 0x020b, - 0x1078, 0x5053, 0x20a3, 0x0200, 0x0078, 0x4deb, 0x20a1, 0x020b, - 0x1078, 0x5053, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, - 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x1078, 0x556e, 0x007c, 0x20e1, - 0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, 0x1078, 0x5053, 0x20a3, + 0x0000, 0x60c3, 0x0014, 0x1078, 0x5566, 0x007c, 0x20a1, 0x020b, + 0x1078, 0x504b, 0x20a3, 0x0200, 0x0078, 0x4de3, 0x20a1, 0x020b, + 0x1078, 0x504b, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, + 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x1078, 0x5566, 0x007c, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, 0x1078, 0x504b, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3, 0x0000, 0x60c3, - 0x0008, 0x1078, 0x556e, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, + 0x0008, 0x1078, 0x5566, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x00c0, - 0x4fef, 0x20a3, 0x22ff, 0x20a3, 0xfffe, 0x0078, 0x501d, 0xa286, - 0x007f, 0x00c0, 0x4ffa, 0x0d7e, 0x20a3, 0x22ff, 0x20a3, 0xfffd, - 0x0078, 0x5011, 0xd2bc, 0x0040, 0x5019, 0xa286, 0x0080, 0x0d7e, - 0x00c0, 0x5008, 0x20a3, 0x22ff, 0x20a3, 0xfffc, 0x0078, 0x5011, + 0x4fe7, 0x20a3, 0x22ff, 0x20a3, 0xfffe, 0x0078, 0x5015, 0xa286, + 0x007f, 0x00c0, 0x4ff2, 0x0d7e, 0x20a3, 0x22ff, 0x20a3, 0xfffd, + 0x0078, 0x5009, 0xd2bc, 0x0040, 0x5011, 0xa286, 0x0080, 0x0d7e, + 0x00c0, 0x5000, 0x20a3, 0x22ff, 0x20a3, 0xfffc, 0x0078, 0x5009, 0xa2e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x2200, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, - 0x5021, 0x20a3, 0x2200, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, - 0x22a2, 0x20a3, 0x0129, 0x20a3, 0x0000, 0x1078, 0x555d, 0x22a2, + 0x5019, 0x20a3, 0x2200, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, + 0x22a2, 0x20a3, 0x0129, 0x20a3, 0x0000, 0x1078, 0x5555, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, 0x2011, 0xfffc, 0x22a2, 0x0d7e, 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x20a3, 0x2029, 0x20a3, 0x0000, - 0x0078, 0x5025, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02, + 0x0078, 0x501d, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, - 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x5072, + 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x506a, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x2300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, - 0x0078, 0x507a, 0x20a3, 0x2300, 0x6298, 0x22a2, 0x20a3, 0x0000, - 0x6230, 0x22a2, 0x20a3, 0x0198, 0x20a3, 0x0000, 0x1078, 0x555d, + 0x0078, 0x5072, 0x20a3, 0x2300, 0x6298, 0x22a2, 0x20a3, 0x0000, + 0x6230, 0x22a2, 0x20a3, 0x0198, 0x20a3, 0x0000, 0x1078, 0x5555, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0c7e, 0x0f7e, 0x6004, 0xa08a, - 0x0085, 0x1048, 0x12d5, 0xa08a, 0x008c, 0x10c8, 0x12d5, 0x6118, - 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x50aa, 0x7900, 0xd1f4, 0x0040, - 0x50a6, 0x7914, 0xa18c, 0x00ff, 0x0078, 0x50af, 0x2009, 0x0000, - 0x0078, 0x50af, 0xa1f8, 0x232f, 0x2f0c, 0xa18c, 0x00ff, 0x2c78, - 0x2061, 0x0100, 0x619a, 0xa082, 0x0085, 0x1079, 0x50ba, 0x0f7f, - 0x0c7f, 0x007c, 0x50c3, 0x50ce, 0x50e8, 0x50c1, 0x50c1, 0x50c1, - 0x50c3, 0x1078, 0x12d5, 0x147e, 0x20a1, 0x020b, 0x1078, 0x50fb, - 0x60c3, 0x0000, 0x1078, 0x556e, 0x147f, 0x007c, 0x147e, 0x20a1, - 0x020b, 0x1078, 0x5128, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, + 0x0085, 0x1048, 0x12cd, 0xa08a, 0x008c, 0x10c8, 0x12cd, 0x6118, + 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x50a2, 0x7900, 0xd1f4, 0x0040, + 0x509e, 0x7914, 0xa18c, 0x00ff, 0x0078, 0x50a7, 0x2009, 0x0000, + 0x0078, 0x50a7, 0xa1f8, 0x2329, 0x2f0c, 0xa18c, 0x00ff, 0x2c78, + 0x2061, 0x0100, 0x619a, 0xa082, 0x0085, 0x1079, 0x50b2, 0x0f7f, + 0x0c7f, 0x007c, 0x50bb, 0x50c6, 0x50e0, 0x50b9, 0x50b9, 0x50b9, + 0x50bb, 0x1078, 0x12cd, 0x147e, 0x20a1, 0x020b, 0x1078, 0x50f3, + 0x60c3, 0x0000, 0x1078, 0x5566, 0x147f, 0x007c, 0x147e, 0x20a1, + 0x020b, 0x1078, 0x5120, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3, 0x0000, - 0x20a3, 0x0000, 0x60c3, 0x000c, 0x1078, 0x556e, 0x147f, 0x007c, - 0x147e, 0x20a1, 0x020b, 0x1078, 0x5155, 0x20a3, 0x0003, 0x20a3, + 0x20a3, 0x0000, 0x60c3, 0x000c, 0x1078, 0x5566, 0x147f, 0x007c, + 0x147e, 0x20a1, 0x020b, 0x1078, 0x514d, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, 0x1078, - 0x556e, 0x147f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, - 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x511a, + 0x5566, 0x147f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x5112, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, - 0x0078, 0x5122, 0x20a3, 0x8100, 0x6298, 0x22a2, 0x20a3, 0x0000, - 0x6230, 0x22a2, 0x20a3, 0x0009, 0x20a3, 0x0000, 0x0078, 0x5025, + 0x0078, 0x511a, 0x20a3, 0x8100, 0x6298, 0x22a2, 0x20a3, 0x0000, + 0x6230, 0x22a2, 0x20a3, 0x0009, 0x20a3, 0x0000, 0x0078, 0x501d, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, - 0x2004, 0xa092, 0x007e, 0x0048, 0x5147, 0x0d7e, 0xa0e8, 0x7720, + 0x2004, 0xa092, 0x007e, 0x0048, 0x513f, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, 0x2069, - 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x514f, 0x20a3, + 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x5147, 0x20a3, 0x8400, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, - 0x00d1, 0x20a3, 0x0000, 0x0078, 0x507e, 0x027e, 0x20e1, 0x9080, + 0x00d1, 0x20a3, 0x0000, 0x0078, 0x5076, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, - 0x0048, 0x5174, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085, + 0x0048, 0x516c, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x7619, 0x2da6, 0x8d68, - 0x2da6, 0x0d7f, 0x0078, 0x517c, 0x20a3, 0x8500, 0x6298, 0x22a2, + 0x2da6, 0x0d7f, 0x0078, 0x5174, 0x20a3, 0x8500, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x00d1, 0x20a3, 0x0000, - 0x0078, 0x507e, 0x0c7e, 0x0f7e, 0x2c78, 0x7804, 0xa08a, 0x0040, - 0x1048, 0x12d5, 0xa08a, 0x0050, 0x10c8, 0x12d5, 0x7918, 0x2160, - 0x61a0, 0xd1bc, 0x0040, 0x51a1, 0x6100, 0xd1f4, 0x0040, 0x519d, - 0x6114, 0xa18c, 0x00ff, 0x0078, 0x51a6, 0x2009, 0x0000, 0x0078, - 0x51a6, 0xa1e0, 0x232f, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, - 0x619a, 0xa082, 0x0040, 0x1079, 0x51b0, 0x0f7f, 0x0c7f, 0x007c, - 0x51c2, 0x52aa, 0x5252, 0x53d2, 0x51c0, 0x51c0, 0x51c0, 0x51c0, - 0x51c0, 0x51c0, 0x51c0, 0x581b, 0x582c, 0x583d, 0x584e, 0x51c0, - 0x1078, 0x12d5, 0x0d7e, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, - 0x5215, 0x7910, 0x2168, 0x6944, 0xa18c, 0x00ff, 0x21a2, 0xa016, + 0x0078, 0x5076, 0x0c7e, 0x0f7e, 0x2c78, 0x7804, 0xa08a, 0x0040, + 0x1048, 0x12cd, 0xa08a, 0x0050, 0x10c8, 0x12cd, 0x7918, 0x2160, + 0x61a0, 0xd1bc, 0x0040, 0x5199, 0x6100, 0xd1f4, 0x0040, 0x5195, + 0x6114, 0xa18c, 0x00ff, 0x0078, 0x519e, 0x2009, 0x0000, 0x0078, + 0x519e, 0xa1e0, 0x2329, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, + 0x619a, 0xa082, 0x0040, 0x1079, 0x51a8, 0x0f7f, 0x0c7f, 0x007c, + 0x51ba, 0x52a2, 0x524a, 0x53ca, 0x51b8, 0x51b8, 0x51b8, 0x51b8, + 0x51b8, 0x51b8, 0x51b8, 0x5813, 0x5824, 0x5835, 0x5846, 0x51b8, + 0x1078, 0x12cd, 0x0d7e, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, + 0x520d, 0x7910, 0x2168, 0x6944, 0xa18c, 0x00ff, 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, 0x0006, 0x8004, 0x20a2, - 0xd1ac, 0x0040, 0x51df, 0x20a3, 0x0002, 0x0078, 0x51eb, 0xd1b4, - 0x0040, 0x51e6, 0x20a3, 0x0001, 0x0078, 0x51eb, 0x20a3, 0x0000, - 0x2230, 0x0078, 0x51ed, 0x6a80, 0x6e7c, 0x20a9, 0x0008, 0xad80, - 0x0017, 0x200c, 0x810f, 0x21a2, 0x8000, 0x00f0, 0x51f1, 0x22a2, + 0xd1ac, 0x0040, 0x51d7, 0x20a3, 0x0002, 0x0078, 0x51e3, 0xd1b4, + 0x0040, 0x51de, 0x20a3, 0x0001, 0x0078, 0x51e3, 0x20a3, 0x0000, + 0x2230, 0x0078, 0x51e5, 0x6a80, 0x6e7c, 0x20a9, 0x0008, 0xad80, + 0x0017, 0x200c, 0x810f, 0x21a2, 0x8000, 0x00f0, 0x51e9, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0x7852, 0x2003, 0x07d0, 0x2001, 0x7851, 0x2003, 0x0009, 0x2001, 0x7857, 0x2003, 0x0002, 0x1078, - 0x1504, 0x147f, 0x157f, 0x0d7f, 0x007c, 0x20e1, 0x9080, 0x20e1, + 0x14fc, 0x147f, 0x157f, 0x0d7f, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, - 0x523b, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x0600, + 0x5233, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, - 0x0d7f, 0x0078, 0x5243, 0x20a3, 0x0600, 0x6198, 0x21a2, 0x20a3, + 0x0d7f, 0x0078, 0x523b, 0x20a3, 0x0600, 0x6198, 0x21a2, 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, 0x5272, 0x7810, 0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2, + 0x1078, 0x526a, 0x7810, 0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, - 0x20a2, 0x60c3, 0x000c, 0x1078, 0x556e, 0x147f, 0x137f, 0x157f, + 0x20a2, 0x60c3, 0x000c, 0x1078, 0x5566, 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, - 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x5290, 0x0d7e, 0xa0e8, + 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x5288, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, - 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x5298, + 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x5290, 0x20a3, 0x0500, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, - 0x20a3, 0x0889, 0x20a3, 0x0000, 0x1078, 0x555d, 0x22a2, 0x20a3, + 0x20a3, 0x0889, 0x20a3, 0x0000, 0x1078, 0x5555, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x20a1, 0x020b, - 0x1078, 0x539a, 0x7810, 0x2068, 0xa016, 0x22a2, 0x22a2, 0x22a2, - 0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, 0x00c0, 0x52c7, 0x7810, - 0xa084, 0x0700, 0x8007, 0x1079, 0x52cf, 0x0078, 0x52ca, 0xa006, - 0x1079, 0x52cf, 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x52d9, - 0x533b, 0x533f, 0x5362, 0x536f, 0x5381, 0x5385, 0x52d7, 0x1078, - 0x12d5, 0x017e, 0x037e, 0x694c, 0xa18c, 0x0003, 0xa186, 0x0000, - 0x00c0, 0x52ec, 0x6b78, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, - 0x037f, 0x017f, 0x0078, 0x5366, 0xa186, 0x0001, 0x00c0, 0x5336, + 0x1078, 0x5392, 0x7810, 0x2068, 0xa016, 0x22a2, 0x22a2, 0x22a2, + 0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, 0x00c0, 0x52bf, 0x7810, + 0xa084, 0x0700, 0x8007, 0x1079, 0x52c7, 0x0078, 0x52c2, 0xa006, + 0x1079, 0x52c7, 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x52d1, + 0x5333, 0x5337, 0x535a, 0x5367, 0x5379, 0x537d, 0x52cf, 0x1078, + 0x12cd, 0x017e, 0x037e, 0x694c, 0xa18c, 0x0003, 0xa186, 0x0000, + 0x00c0, 0x52e4, 0x6b78, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, + 0x037f, 0x017f, 0x0078, 0x535e, 0xa186, 0x0001, 0x00c0, 0x532e, 0x6b78, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, 0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, 0x0300, - 0x0040, 0x5335, 0xd3c4, 0x0040, 0x5307, 0x687c, 0xa108, 0xd3cc, - 0x0040, 0x530c, 0x6874, 0xa108, 0x157e, 0x20a9, 0x000d, 0xad80, - 0x0020, 0x201c, 0x831f, 0x23a2, 0x8000, 0x00f0, 0x5311, 0x157f, - 0x22a2, 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0040, 0x5335, 0x20a1, + 0x0040, 0x532d, 0xd3c4, 0x0040, 0x52ff, 0x687c, 0xa108, 0xd3cc, + 0x0040, 0x5304, 0x6874, 0xa108, 0x157e, 0x20a9, 0x000d, 0xad80, + 0x0020, 0x201c, 0x831f, 0x23a2, 0x8000, 0x00f0, 0x5309, 0x157f, + 0x22a2, 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0040, 0x532d, 0x20a1, 0x020b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x0700, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0898, 0x20a2, - 0x1078, 0x555d, 0x22a2, 0x20a3, 0x0000, 0x61c2, 0x037f, 0x017f, - 0x1078, 0x556e, 0x007c, 0x20a3, 0x0008, 0x0078, 0x5364, 0x20a3, + 0x1078, 0x5555, 0x22a2, 0x20a3, 0x0000, 0x61c2, 0x037f, 0x017f, + 0x1078, 0x5566, 0x007c, 0x20a3, 0x0008, 0x0078, 0x535c, 0x20a3, 0x0302, 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, - 0x556e, 0x007c, 0x20a3, 0x0028, 0x22a2, 0x22a2, 0x22a2, 0x22a2, - 0x22a2, 0x22a2, 0x60c3, 0x0018, 0x1078, 0x556e, 0x007c, 0x20a3, + 0x5566, 0x007c, 0x20a3, 0x0028, 0x22a2, 0x22a2, 0x22a2, 0x22a2, + 0x22a2, 0x22a2, 0x60c3, 0x0018, 0x1078, 0x5566, 0x007c, 0x20a3, 0x0100, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0008, - 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x1078, 0x556e, - 0x007c, 0x20a3, 0x0008, 0x0078, 0x5364, 0x037e, 0x7b10, 0xa384, - 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, 0x00c0, 0x5393, 0x22a2, - 0x037f, 0x0078, 0x5364, 0x20a3, 0x0800, 0x22a2, 0x20a2, 0x037f, - 0x0078, 0x5366, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, - 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x53b8, 0x0d7e, 0xa0e8, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x1078, 0x5566, + 0x007c, 0x20a3, 0x0008, 0x0078, 0x535c, 0x037e, 0x7b10, 0xa384, + 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, 0x00c0, 0x538b, 0x22a2, + 0x037f, 0x0078, 0x535c, 0x20a3, 0x0800, 0x22a2, 0x20a2, 0x037f, + 0x0078, 0x535e, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, + 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x53b0, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, - 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x53c0, + 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x53b8, 0x20a3, 0x0700, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, - 0x20a3, 0x0898, 0x20a3, 0x0000, 0x1078, 0x555d, 0x22a2, 0x20a3, + 0x20a3, 0x0898, 0x20a3, 0x0000, 0x1078, 0x5555, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x017e, 0x037e, - 0x7810, 0xa084, 0x0700, 0x8007, 0x1079, 0x53e5, 0x037f, 0x017f, - 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x53ed, 0x53ed, 0x53ef, - 0x53ed, 0x53ed, 0x53ed, 0x5414, 0x53ed, 0x1078, 0x12d5, 0x7910, + 0x7810, 0xa084, 0x0700, 0x8007, 0x1079, 0x53dd, 0x037f, 0x017f, + 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x53e5, 0x53e5, 0x53e7, + 0x53e5, 0x53e5, 0x53e5, 0x540c, 0x53e5, 0x1078, 0x12cd, 0x7910, 0xa18c, 0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, - 0x0003, 0x1078, 0x541e, 0x0d7e, 0x2069, 0x7651, 0x6804, 0xd0bc, - 0x0040, 0x5409, 0x682c, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0078, - 0x540b, 0x20a3, 0x3f00, 0x0d7f, 0x22a2, 0x22a2, 0x22a2, 0x60c3, - 0x0001, 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b, 0x2009, 0x0003, - 0x1078, 0x541e, 0x20a3, 0x7f00, 0x0078, 0x540c, 0x027e, 0x20e1, + 0x0003, 0x1078, 0x5416, 0x0d7e, 0x2069, 0x7651, 0x6804, 0xd0bc, + 0x0040, 0x5401, 0x682c, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0078, + 0x5403, 0x20a3, 0x3f00, 0x0d7f, 0x22a2, 0x22a2, 0x22a2, 0x60c3, + 0x0001, 0x1078, 0x5566, 0x007c, 0x20a1, 0x020b, 0x2009, 0x0003, + 0x1078, 0x5416, 0x20a3, 0x7f00, 0x0078, 0x5404, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, - 0x0040, 0x543c, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085, + 0x0040, 0x5434, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x7619, 0x2da6, 0x8d68, - 0x2da6, 0x0d7f, 0x0078, 0x5444, 0x20a3, 0x0100, 0x6298, 0x22a2, + 0x2da6, 0x0d7f, 0x0078, 0x543c, 0x20a3, 0x0100, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, - 0x21a2, 0x1078, 0x555d, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, + 0x21a2, 0x1078, 0x5555, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x0c7e, 0x057e, 0x047e, 0x037e, 0x2061, 0x0100, 0x2071, 0x7600, 0x6130, 0x7818, 0x2068, 0x68a0, 0x2028, 0xd0bc, 0x00c0, - 0x5470, 0xa080, 0x232f, 0x2014, 0xa294, 0x00ff, 0x0078, 0x5474, + 0x5468, 0xa080, 0x2329, 0x2014, 0xa294, 0x00ff, 0x0078, 0x546c, 0x6910, 0x6a14, 0x7364, 0x7468, 0x781c, 0xa086, 0x0006, 0x0040, - 0x54c8, 0xd5bc, 0x0040, 0x5484, 0xa185, 0x0100, 0x6062, 0x6266, - 0x636a, 0x646e, 0x0078, 0x548a, 0x6063, 0x0100, 0x6266, 0x606b, + 0x54c0, 0xd5bc, 0x0040, 0x547c, 0xa185, 0x0100, 0x6062, 0x6266, + 0x636a, 0x646e, 0x0078, 0x5482, 0x6063, 0x0100, 0x6266, 0x606b, 0x0000, 0x616e, 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, - 0x54bc, 0x6a00, 0xd2f4, 0x0040, 0x54ba, 0x6a14, 0xa294, 0x00ff, - 0x0078, 0x54bc, 0x2011, 0x0000, 0x629e, 0x6017, 0x0016, 0x1078, - 0x45f0, 0x037f, 0x047f, 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, + 0x54b4, 0x6a00, 0xd2f4, 0x0040, 0x54b2, 0x6a14, 0xa294, 0x00ff, + 0x0078, 0x54b4, 0x2011, 0x0000, 0x629e, 0x6017, 0x0016, 0x1078, + 0x45e8, 0x037f, 0x047f, 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x7810, 0x2070, 0x704c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0040, - 0x5517, 0xd5bc, 0x0040, 0x54dc, 0xa185, 0x0100, 0x6062, 0x6266, - 0x636a, 0x646e, 0x0078, 0x54e2, 0x6063, 0x0100, 0x6266, 0x606b, + 0x550f, 0xd5bc, 0x0040, 0x54d4, 0xa185, 0x0100, 0x6062, 0x6266, + 0x636a, 0x646e, 0x0078, 0x54da, 0x6063, 0x0100, 0x6266, 0x606b, 0x0000, 0x616e, 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, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, - 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0048, 0x5512, 0x6a00, - 0xd2f4, 0x0040, 0x5510, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x5512, - 0x2011, 0x0000, 0x629e, 0x6017, 0x0012, 0x0078, 0x54bf, 0xd5bc, - 0x0040, 0x5522, 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, - 0x0078, 0x5528, 0x6063, 0x0700, 0x6266, 0x606b, 0x0000, 0x616e, + 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0048, 0x550a, 0x6a00, + 0xd2f4, 0x0040, 0x5508, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x550a, + 0x2011, 0x0000, 0x629e, 0x6017, 0x0012, 0x0078, 0x54b7, 0xd5bc, + 0x0040, 0x551a, 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, + 0x0078, 0x5520, 0x6063, 0x0700, 0x6266, 0x606b, 0x0000, 0x616e, 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, 0x5558, 0x6a00, 0xd2f4, 0x0040, - 0x5556, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x5558, 0x2011, 0x0000, - 0x629e, 0x6017, 0x0016, 0x0078, 0x54bf, 0x7a18, 0xa280, 0x0023, + 0x0000, 0xa582, 0x0080, 0x0048, 0x5550, 0x6a00, 0xd2f4, 0x0040, + 0x554e, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x5550, 0x2011, 0x0000, + 0x629e, 0x6017, 0x0016, 0x0078, 0x54b7, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, 0x007c, 0x0d7e, 0x2069, 0x7836, 0x6843, 0x0001, 0x0d7f, 0x007c, 0x20e1, 0x9080, - 0x60a3, 0x0056, 0x60a7, 0x9575, 0x1078, 0x5579, 0x1078, 0x45e0, + 0x60a3, 0x0056, 0x60a7, 0x9575, 0x1078, 0x5571, 0x1078, 0x45d8, 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, 0x1078, 0x45eb, 0x2061, 0x0100, 0x2069, - 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x55cc, 0x1078, 0x5582, + 0x0d7e, 0x017e, 0x027e, 0x1078, 0x45e3, 0x2061, 0x0100, 0x2069, + 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x55c4, 0x1078, 0x557a, 0x6803, 0x1000, 0x6803, 0x0000, 0x0c7e, 0x2061, 0x7836, 0x6128, - 0xa192, 0x0002, 0x00c8, 0x55b9, 0x8108, 0x612a, 0x6124, 0x0c7f, - 0x81ff, 0x0040, 0x55c7, 0x1078, 0x45e0, 0x1078, 0x5579, 0x0078, - 0x55c7, 0x6124, 0xa1e5, 0x0000, 0x0040, 0x55c4, 0x1078, 0x75c7, - 0x2009, 0x0014, 0x1078, 0x5c29, 0x0c7f, 0x0078, 0x55c7, 0x027f, - 0x017f, 0x0d7f, 0x0c7f, 0x007c, 0x1078, 0x357b, 0x0078, 0x55c7, - 0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x027e, 0x1078, 0x45f9, 0x2071, - 0x7836, 0x713c, 0x81ff, 0x0040, 0x55fa, 0x2061, 0x0100, 0x2069, - 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x5600, 0x6803, 0x1000, - 0x6803, 0x0000, 0x037e, 0x2019, 0x0001, 0x1078, 0x5768, 0x037f, - 0x713c, 0x2160, 0x1078, 0x75c7, 0x2009, 0x004a, 0x1078, 0x5c29, - 0x0078, 0x55fa, 0x027f, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c, - 0x7144, 0xa192, 0x0002, 0x00c8, 0x55ea, 0x8108, 0x7146, 0x1078, - 0x45f0, 0x0078, 0x55fa, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x057e, + 0xa192, 0x0002, 0x00c8, 0x55b1, 0x8108, 0x612a, 0x6124, 0x0c7f, + 0x81ff, 0x0040, 0x55bf, 0x1078, 0x45d8, 0x1078, 0x5571, 0x0078, + 0x55bf, 0x6124, 0xa1e5, 0x0000, 0x0040, 0x55bc, 0x1078, 0x75bc, + 0x2009, 0x0014, 0x1078, 0x5c21, 0x0c7f, 0x0078, 0x55bf, 0x027f, + 0x017f, 0x0d7f, 0x0c7f, 0x007c, 0x1078, 0x3573, 0x0078, 0x55bf, + 0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x027e, 0x1078, 0x45f1, 0x2071, + 0x7836, 0x713c, 0x81ff, 0x0040, 0x55f2, 0x2061, 0x0100, 0x2069, + 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x55f8, 0x6803, 0x1000, + 0x6803, 0x0000, 0x037e, 0x2019, 0x0001, 0x1078, 0x5760, 0x037f, + 0x713c, 0x2160, 0x1078, 0x75bc, 0x2009, 0x004a, 0x1078, 0x5c21, + 0x0078, 0x55f2, 0x027f, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c, + 0x7144, 0xa192, 0x0002, 0x00c8, 0x55e2, 0x8108, 0x7146, 0x1078, + 0x45e8, 0x0078, 0x55f2, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x057e, 0x047e, 0x007e, 0x127e, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0, - 0x2071, 0x7836, 0x7018, 0x2068, 0x8dff, 0x0040, 0x5637, 0x68a0, - 0xa406, 0x0040, 0x5627, 0x6854, 0x2068, 0x0078, 0x561c, 0x6010, + 0x2071, 0x7836, 0x7018, 0x2068, 0x8dff, 0x0040, 0x562f, 0x68a0, + 0xa406, 0x0040, 0x561f, 0x6854, 0x2068, 0x0078, 0x5614, 0x6010, 0x2060, 0x643c, 0x6540, 0x6644, 0xa6b4, 0x000f, 0x2d60, 0x1078, - 0x38f9, 0x0040, 0x5637, 0x1078, 0x5902, 0xa085, 0x0001, 0x127f, + 0x38f1, 0x0040, 0x562f, 0x1078, 0x58fa, 0xa085, 0x0001, 0x127f, 0x007f, 0x047f, 0x057f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, - 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x4fdc, 0x20a3, 0x0f00, + 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x4fd4, 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, - 0x1078, 0x556e, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1, - 0x020b, 0x1078, 0x5053, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a9, + 0x1078, 0x5566, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1, + 0x020b, 0x1078, 0x504b, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a9, 0x0006, 0x2011, 0x7640, 0x2019, 0x7641, 0x23a6, 0x22a6, 0xa398, - 0x0002, 0xa290, 0x0002, 0x00f0, 0x5665, 0x20a3, 0x0000, 0x20a3, - 0x0000, 0x60c3, 0x001c, 0x1078, 0x556e, 0x147f, 0x157f, 0x007c, - 0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b, 0x1078, 0x5033, - 0x1078, 0x504a, 0x7810, 0x007e, 0xa080, 0x0015, 0x2098, 0x7808, + 0x0002, 0xa290, 0x0002, 0x00f0, 0x565d, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x001c, 0x1078, 0x5566, 0x147f, 0x157f, 0x007c, + 0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b, 0x1078, 0x502b, + 0x1078, 0x5042, 0x7810, 0x007e, 0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0xa080, 0x0004, 0x8003, 0x60c2, - 0x007f, 0xa080, 0x0001, 0x2004, 0x7812, 0x1078, 0x556e, 0x027f, + 0x007f, 0xa080, 0x0001, 0x2004, 0x7812, 0x1078, 0x5566, 0x027f, 0x017f, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, - 0x1078, 0x4fdc, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, - 0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x556e, 0x147f, 0x157f, + 0x1078, 0x4fd4, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x5566, 0x147f, 0x157f, 0x007c, 0x0e7e, 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, - 0x7836, 0x700c, 0x2060, 0x8cff, 0x0040, 0x56cd, 0x1078, 0x6ace, - 0x00c0, 0x56c4, 0x1078, 0x5e57, 0x600c, 0x007e, 0x1078, 0x5c02, - 0x1078, 0x5902, 0x0c7f, 0x0078, 0x56bb, 0x700f, 0x0000, 0x700b, + 0x7836, 0x700c, 0x2060, 0x8cff, 0x0040, 0x56c5, 0x1078, 0x6ac3, + 0x00c0, 0x56bc, 0x1078, 0x5e4d, 0x600c, 0x007e, 0x1078, 0x5bfa, + 0x1078, 0x58fa, 0x0c7f, 0x0078, 0x56b3, 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, 0x7836, 0x7024, - 0x2060, 0x8cff, 0x0040, 0x5726, 0x1078, 0x5582, 0x68c3, 0x0000, - 0x1078, 0x45eb, 0x2009, 0x0013, 0x1078, 0x5c29, 0x20a9, 0x01f4, - 0x6824, 0xd094, 0x0040, 0x5709, 0x6827, 0x0004, 0x7804, 0xa084, - 0x4000, 0x0040, 0x571b, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, - 0x571b, 0xd084, 0x0040, 0x5710, 0x6827, 0x0001, 0x0078, 0x5712, - 0x00f0, 0x56f8, 0x7804, 0xa084, 0x1000, 0x0040, 0x571b, 0x7803, + 0x2060, 0x8cff, 0x0040, 0x571e, 0x1078, 0x557a, 0x68c3, 0x0000, + 0x1078, 0x45e3, 0x2009, 0x0013, 0x1078, 0x5c21, 0x20a9, 0x01f4, + 0x6824, 0xd094, 0x0040, 0x5701, 0x6827, 0x0004, 0x7804, 0xa084, + 0x4000, 0x0040, 0x5713, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, + 0x5713, 0xd084, 0x0040, 0x5708, 0x6827, 0x0001, 0x0078, 0x570a, + 0x00f0, 0x56f0, 0x7804, 0xa084, 0x1000, 0x0040, 0x5713, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c, 0x2001, 0x7600, - 0x2004, 0xa096, 0x0001, 0x0040, 0x575e, 0xa096, 0x0004, 0x0040, - 0x575e, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x3542, 0x1078, - 0x456e, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040, 0x574c, 0x6827, - 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x575e, 0x7803, 0x1000, - 0x7803, 0x0000, 0x0078, 0x575e, 0xd084, 0x0040, 0x5753, 0x6827, - 0x0001, 0x0078, 0x5755, 0x00f0, 0x573b, 0x7804, 0xa084, 0x1000, - 0x0040, 0x575e, 0x7803, 0x0100, 0x7803, 0x0000, 0x007f, 0x017f, + 0x2004, 0xa096, 0x0001, 0x0040, 0x5756, 0xa096, 0x0004, 0x0040, + 0x5756, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x353a, 0x1078, + 0x4566, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040, 0x5744, 0x6827, + 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x5756, 0x7803, 0x1000, + 0x7803, 0x0000, 0x0078, 0x5756, 0xd084, 0x0040, 0x574b, 0x6827, + 0x0001, 0x0078, 0x574d, 0x00f0, 0x5733, 0x7804, 0xa084, 0x1000, + 0x0040, 0x5756, 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, - 0x7836, 0x703c, 0x2060, 0x8cff, 0x0040, 0x57b6, 0x6817, 0x0010, - 0x68cb, 0x0000, 0x68c7, 0x0000, 0x1078, 0x45f9, 0x1078, 0x1c19, - 0xa39d, 0x0000, 0x00c0, 0x5790, 0x2009, 0x0049, 0x1078, 0x5c29, - 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0040, 0x57a3, 0x6827, 0x0004, - 0x7804, 0xa084, 0x4000, 0x0040, 0x57b5, 0x7803, 0x1000, 0x7803, - 0x0000, 0x0078, 0x57b5, 0xd094, 0x0040, 0x57aa, 0x6827, 0x0002, - 0x0078, 0x57ac, 0x00f0, 0x5792, 0x7804, 0xa084, 0x1000, 0x0040, - 0x57b5, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x007f, 0x017f, + 0x7836, 0x703c, 0x2060, 0x8cff, 0x0040, 0x57ae, 0x6817, 0x0010, + 0x68cb, 0x0000, 0x68c7, 0x0000, 0x1078, 0x45f1, 0x1078, 0x1c13, + 0xa39d, 0x0000, 0x00c0, 0x5788, 0x2009, 0x0049, 0x1078, 0x5c21, + 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0040, 0x579b, 0x6827, 0x0004, + 0x7804, 0xa084, 0x4000, 0x0040, 0x57ad, 0x7803, 0x1000, 0x7803, + 0x0000, 0x0078, 0x57ad, 0xd094, 0x0040, 0x57a2, 0x6827, 0x0002, + 0x0078, 0x57a4, 0x00f0, 0x578a, 0x7804, 0xa084, 0x1000, 0x0040, + 0x57ad, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0x7836, 0x6a06, 0x127f, 0x0d7f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0x7836, 0x6a32, 0x127f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2071, 0x7836, 0x7614, 0x2660, 0x2678, 0x2091, - 0x8000, 0x8cff, 0x0040, 0x5814, 0x601c, 0xa206, 0x00c0, 0x580f, - 0x7014, 0xac36, 0x00c0, 0x57ee, 0x660c, 0x7616, 0x7010, 0xac36, - 0x00c0, 0x57fc, 0x2c00, 0xaf36, 0x0040, 0x57fa, 0x2f00, 0x7012, - 0x0078, 0x57fc, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, - 0x0040, 0x5805, 0x7e0e, 0x0078, 0x5806, 0x2678, 0x600f, 0x0000, - 0x1078, 0x6aa1, 0x1078, 0x5902, 0x0c7f, 0x0078, 0x57e1, 0x2c78, - 0x600c, 0x2060, 0x0078, 0x57e1, 0x127f, 0x007f, 0x067f, 0x0c7f, + 0x8000, 0x8cff, 0x0040, 0x580c, 0x601c, 0xa206, 0x00c0, 0x5807, + 0x7014, 0xac36, 0x00c0, 0x57e6, 0x660c, 0x7616, 0x7010, 0xac36, + 0x00c0, 0x57f4, 0x2c00, 0xaf36, 0x0040, 0x57f2, 0x2f00, 0x7012, + 0x0078, 0x57f4, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, + 0x0040, 0x57fd, 0x7e0e, 0x0078, 0x57fe, 0x2678, 0x600f, 0x0000, + 0x1078, 0x6a96, 0x1078, 0x58fa, 0x0c7f, 0x0078, 0x57d9, 0x2c78, + 0x600c, 0x2060, 0x0078, 0x57d9, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, - 0x5215, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, - 0x20a3, 0x4000, 0x0078, 0x585d, 0x157e, 0x147e, 0x20a1, 0x020b, - 0x1078, 0x5215, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, - 0x20a2, 0x20a3, 0x2000, 0x0078, 0x585d, 0x157e, 0x147e, 0x20a1, - 0x020b, 0x1078, 0x5215, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, - 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, 0x585d, 0x157e, 0x147e, - 0x20a1, 0x020b, 0x1078, 0x5215, 0x7810, 0x20a2, 0xa006, 0x20a2, - 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x1078, 0x590d, 0x60c3, - 0x0020, 0x1078, 0x556e, 0x147f, 0x157f, 0x007c, 0x127e, 0x0c7e, - 0x2091, 0x8000, 0x2061, 0x0100, 0x6120, 0xd1b4, 0x00c0, 0x5875, - 0xd1bc, 0x00c0, 0x58bf, 0x0078, 0x58ff, 0x2009, 0x017f, 0x200b, + 0x520d, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, + 0x20a3, 0x4000, 0x0078, 0x5855, 0x157e, 0x147e, 0x20a1, 0x020b, + 0x1078, 0x520d, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, + 0x20a2, 0x20a3, 0x2000, 0x0078, 0x5855, 0x157e, 0x147e, 0x20a1, + 0x020b, 0x1078, 0x520d, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, + 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, 0x5855, 0x157e, 0x147e, + 0x20a1, 0x020b, 0x1078, 0x520d, 0x7810, 0x20a2, 0xa006, 0x20a2, + 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x1078, 0x5905, 0x60c3, + 0x0020, 0x1078, 0x5566, 0x147f, 0x157f, 0x007c, 0x127e, 0x0c7e, + 0x2091, 0x8000, 0x2061, 0x0100, 0x6120, 0xd1b4, 0x00c0, 0x586d, + 0xd1bc, 0x00c0, 0x58b7, 0x0078, 0x58f7, 0x2009, 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, 0x0140, 0x20a9, 0x001e, - 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, 0x0040, 0x58b6, 0x6020, - 0xd0b4, 0x0040, 0x58b6, 0x6024, 0xd094, 0x00c0, 0x58b6, 0x2104, - 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x58b6, 0x00f0, 0x5882, + 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, 0x0040, 0x58ae, 0x6020, + 0xd0b4, 0x0040, 0x58ae, 0x6024, 0xd094, 0x00c0, 0x58ae, 0x2104, + 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x58ae, 0x00f0, 0x587a, 0x027e, 0x6198, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, 0x00ff, 0xa10d, 0x6088, 0x628c, 0x618e, 0x608b, 0xbc91, 0x6043, 0x0001, - 0x6043, 0x0000, 0x608a, 0x628e, 0x6024, 0xd094, 0x00c0, 0x58b5, - 0x6a04, 0xa294, 0x4000, 0x00c0, 0x58ac, 0x027f, 0x0d7f, 0x007f, - 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, 0x0078, 0x58ff, 0x2009, + 0x6043, 0x0000, 0x608a, 0x628e, 0x6024, 0xd094, 0x00c0, 0x58ad, + 0x6a04, 0xa294, 0x4000, 0x00c0, 0x58a4, 0x027f, 0x0d7f, 0x007f, + 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, 0x0078, 0x58f7, 0x2009, 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, 0x0140, 0x20a9, 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, 0x0040, - 0x58f8, 0x6020, 0xd0bc, 0x0040, 0x58f8, 0x2104, 0xa084, 0x000f, - 0xa086, 0x0004, 0x00c0, 0x58f8, 0x00f0, 0x58cc, 0x027e, 0x6164, + 0x58f0, 0x6020, 0xd0bc, 0x0040, 0x58f0, 0x2104, 0xa084, 0x000f, + 0xa086, 0x0004, 0x00c0, 0x58f0, 0x00f0, 0x58c4, 0x027e, 0x6164, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, 0x00ff, 0xa10d, 0x6088, 0x628c, 0x608b, 0xbc91, 0x618e, 0x6043, 0x0001, 0x6043, 0x0000, - 0x608a, 0x628e, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x58f2, 0x027f, + 0x608a, 0x628e, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x58ea, 0x027f, 0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, 0x0c7f, 0x127f, 0x007c, 0x0e7e, 0x2071, 0x7836, 0x7020, 0xa005, 0x0040, - 0x590b, 0x8001, 0x7022, 0x0e7f, 0x007c, 0x20a9, 0x0008, 0x20a2, - 0x00f0, 0x590f, 0x20a2, 0x20a2, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, + 0x5903, 0x8001, 0x7022, 0x0e7f, 0x007c, 0x20a9, 0x0008, 0x20a2, + 0x00f0, 0x5907, 0x20a2, 0x20a2, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x077e, 0x067e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0x7836, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, 0x0040, - 0x59a5, 0x8cff, 0x0040, 0x59a5, 0x601c, 0xa086, 0x0006, 0x00c0, - 0x59a0, 0x88ff, 0x0040, 0x593c, 0x2800, 0xac06, 0x00c0, 0x59a0, - 0x2039, 0x0000, 0x0078, 0x5940, 0x6018, 0xa206, 0x00c0, 0x59a0, - 0x7024, 0xac06, 0x00c0, 0x596e, 0x2069, 0x0100, 0x68c0, 0xa005, - 0x0040, 0x5969, 0x6817, 0x0008, 0x68c3, 0x0000, 0x1078, 0x5a32, + 0x599d, 0x8cff, 0x0040, 0x599d, 0x601c, 0xa086, 0x0006, 0x00c0, + 0x5998, 0x88ff, 0x0040, 0x5934, 0x2800, 0xac06, 0x00c0, 0x5998, + 0x2039, 0x0000, 0x0078, 0x5938, 0x6018, 0xa206, 0x00c0, 0x5998, + 0x7024, 0xac06, 0x00c0, 0x5966, 0x2069, 0x0100, 0x68c0, 0xa005, + 0x0040, 0x5961, 0x6817, 0x0008, 0x68c3, 0x0000, 0x1078, 0x5a2a, 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, - 0x0040, 0x595e, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, - 0x6824, 0xd084, 0x0040, 0x5966, 0x6827, 0x0001, 0x037f, 0x0078, - 0x596e, 0x6003, 0x0009, 0x630a, 0x0078, 0x59a0, 0x7014, 0xac36, - 0x00c0, 0x5974, 0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x5982, - 0x2c00, 0xaf36, 0x0040, 0x5980, 0x2f00, 0x7012, 0x0078, 0x5982, - 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x598b, - 0x7e0e, 0x0078, 0x598c, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, - 0x1078, 0x693e, 0x0040, 0x5996, 0x1078, 0x74fd, 0x1078, 0x6aa1, - 0x1078, 0x5902, 0x88ff, 0x00c0, 0x59af, 0x0c7f, 0x0078, 0x5926, - 0x2c78, 0x600c, 0x2060, 0x0078, 0x5926, 0xa006, 0x127f, 0x007f, + 0x0040, 0x5956, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, + 0x6824, 0xd084, 0x0040, 0x595e, 0x6827, 0x0001, 0x037f, 0x0078, + 0x5966, 0x6003, 0x0009, 0x630a, 0x0078, 0x5998, 0x7014, 0xac36, + 0x00c0, 0x596c, 0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x597a, + 0x2c00, 0xaf36, 0x0040, 0x5978, 0x2f00, 0x7012, 0x0078, 0x597a, + 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5983, + 0x7e0e, 0x0078, 0x5984, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, + 0x1078, 0x6938, 0x0040, 0x598e, 0x1078, 0x74f2, 0x1078, 0x6a96, + 0x1078, 0x58fa, 0x88ff, 0x00c0, 0x59a7, 0x0c7f, 0x0078, 0x591e, + 0x2c78, 0x600c, 0x2060, 0x0078, 0x591e, 0xa006, 0x127f, 0x007f, 0x067f, 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x6017, - 0x0000, 0x0c7f, 0xa8c5, 0x0001, 0x0078, 0x59a6, 0x0f7e, 0x0e7e, + 0x0000, 0x0c7f, 0xa8c5, 0x0001, 0x0078, 0x599e, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x027e, 0x007e, 0x127e, 0x2091, 0x8000, - 0x2071, 0x7836, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x5a21, - 0x601c, 0xa086, 0x0006, 0x00c0, 0x5a1c, 0x88ff, 0x0040, 0x59d6, - 0x2800, 0xac06, 0x00c0, 0x5a1c, 0x0078, 0x59da, 0x6018, 0xa206, - 0x00c0, 0x5a1c, 0x703c, 0xac06, 0x00c0, 0x59ec, 0x037e, 0x2019, - 0x0001, 0x1078, 0x5768, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, - 0x0000, 0x7047, 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x59f2, - 0x660c, 0x763a, 0x7034, 0xac36, 0x00c0, 0x5a00, 0x2c00, 0xaf36, - 0x0040, 0x59fe, 0x2f00, 0x7036, 0x0078, 0x5a00, 0x7037, 0x0000, - 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5a09, 0x7e0e, 0x0078, - 0x5a0a, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x693e, - 0x0040, 0x5a14, 0x1078, 0x74fd, 0x1078, 0x6aa1, 0x88ff, 0x00c0, - 0x5a2b, 0x0c7f, 0x0078, 0x59c5, 0x2c78, 0x600c, 0x2060, 0x0078, - 0x59c5, 0xa006, 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f, + 0x2071, 0x7836, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x5a19, + 0x601c, 0xa086, 0x0006, 0x00c0, 0x5a14, 0x88ff, 0x0040, 0x59ce, + 0x2800, 0xac06, 0x00c0, 0x5a14, 0x0078, 0x59d2, 0x6018, 0xa206, + 0x00c0, 0x5a14, 0x703c, 0xac06, 0x00c0, 0x59e4, 0x037e, 0x2019, + 0x0001, 0x1078, 0x5760, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, + 0x0000, 0x7047, 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x59ea, + 0x660c, 0x763a, 0x7034, 0xac36, 0x00c0, 0x59f8, 0x2c00, 0xaf36, + 0x0040, 0x59f6, 0x2f00, 0x7036, 0x0078, 0x59f8, 0x7037, 0x0000, + 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5a01, 0x7e0e, 0x0078, + 0x5a02, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x6938, + 0x0040, 0x5a0c, 0x1078, 0x74f2, 0x1078, 0x6a96, 0x88ff, 0x00c0, + 0x5a23, 0x0c7f, 0x0078, 0x59bd, 0x2c78, 0x600c, 0x2060, 0x0078, + 0x59bd, 0xa006, 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x6017, 0x0000, 0x0c7f, 0xa8c5, 0x0001, - 0x0078, 0x5a22, 0x0e7e, 0x2071, 0x7836, 0x2001, 0x7600, 0x2004, - 0xa086, 0x0002, 0x00c0, 0x5a40, 0x7007, 0x0005, 0x0078, 0x5a42, + 0x0078, 0x5a1a, 0x0e7e, 0x2071, 0x7836, 0x2001, 0x7600, 0x2004, + 0xa086, 0x0002, 0x00c0, 0x5a38, 0x7007, 0x0005, 0x0078, 0x5a3a, 0x7007, 0x0000, 0x0e7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e, 0x027e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0x7836, 0x2c10, - 0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x5a82, 0x2200, 0xac06, - 0x00c0, 0x5a7d, 0x7038, 0xac36, 0x00c0, 0x5a60, 0x660c, 0x763a, - 0x7034, 0xac36, 0x00c0, 0x5a6e, 0x2c00, 0xaf36, 0x0040, 0x5a6c, - 0x2f00, 0x7036, 0x0078, 0x5a6e, 0x7037, 0x0000, 0x660c, 0x2c00, - 0xaf06, 0x0040, 0x5a76, 0x7e0e, 0x0078, 0x5a77, 0x2678, 0x600f, - 0x0000, 0xa085, 0x0001, 0x0078, 0x5a82, 0x2c78, 0x600c, 0x2060, - 0x0078, 0x5a53, 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0e7f, + 0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x5a7a, 0x2200, 0xac06, + 0x00c0, 0x5a75, 0x7038, 0xac36, 0x00c0, 0x5a58, 0x660c, 0x763a, + 0x7034, 0xac36, 0x00c0, 0x5a66, 0x2c00, 0xaf36, 0x0040, 0x5a64, + 0x2f00, 0x7036, 0x0078, 0x5a66, 0x7037, 0x0000, 0x660c, 0x2c00, + 0xaf06, 0x0040, 0x5a6e, 0x7e0e, 0x0078, 0x5a6f, 0x2678, 0x600f, + 0x0000, 0xa085, 0x0001, 0x0078, 0x5a7a, 0x2c78, 0x600c, 0x2060, + 0x0078, 0x5a4b, 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0x7836, 0x760c, 0x2660, 0x2678, - 0x8cff, 0x0040, 0x5b1b, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, - 0x00c0, 0x5b16, 0x7024, 0xac06, 0x00c0, 0x5ac9, 0x2069, 0x0100, - 0x68c0, 0xa005, 0x0040, 0x5ac9, 0x1078, 0x5582, 0x68c3, 0x0000, - 0x1078, 0x5a32, 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, - 0xa384, 0x1000, 0x0040, 0x5ac0, 0x6803, 0x0100, 0x6803, 0x0000, - 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x5ac8, 0x6827, 0x0001, - 0x037f, 0x700c, 0xac36, 0x00c0, 0x5acf, 0x660c, 0x760e, 0x7008, - 0xac36, 0x00c0, 0x5add, 0x2c00, 0xaf36, 0x0040, 0x5adb, 0x2f00, - 0x700a, 0x0078, 0x5add, 0x700b, 0x0000, 0x660c, 0x067e, 0x2c00, - 0xaf06, 0x0040, 0x5ae6, 0x7e0e, 0x0078, 0x5ae7, 0x2678, 0x600f, - 0x0000, 0x1078, 0x6aba, 0x00c0, 0x5af1, 0x1078, 0x22dd, 0x0078, - 0x5b0d, 0x1078, 0x6ace, 0x00c0, 0x5af9, 0x1078, 0x5e57, 0x0078, - 0x5b0d, 0x6010, 0x2068, 0x1078, 0x693e, 0x0040, 0x5b0d, 0x601c, - 0xa086, 0x0003, 0x00c0, 0x5b23, 0x6837, 0x0103, 0x6b4a, 0x6847, - 0x0000, 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x6003, 0x0000, 0x1078, - 0x6aa1, 0x1078, 0x5902, 0x0c7f, 0x0078, 0x5a98, 0x2c78, 0x600c, - 0x2060, 0x0078, 0x5a98, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0d7f, - 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x5b04, - 0x1078, 0x74fd, 0x0078, 0x5b0d, 0x037e, 0x157e, 0x137e, 0x147e, - 0x3908, 0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x214f, 0x00c0, - 0x5b3d, 0x8210, 0x8000, 0x0078, 0x5b34, 0xa005, 0x0040, 0x5b47, + 0x8cff, 0x0040, 0x5b13, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, + 0x00c0, 0x5b0e, 0x7024, 0xac06, 0x00c0, 0x5ac1, 0x2069, 0x0100, + 0x68c0, 0xa005, 0x0040, 0x5ac1, 0x1078, 0x557a, 0x68c3, 0x0000, + 0x1078, 0x5a2a, 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, + 0xa384, 0x1000, 0x0040, 0x5ab8, 0x6803, 0x0100, 0x6803, 0x0000, + 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x5ac0, 0x6827, 0x0001, + 0x037f, 0x700c, 0xac36, 0x00c0, 0x5ac7, 0x660c, 0x760e, 0x7008, + 0xac36, 0x00c0, 0x5ad5, 0x2c00, 0xaf36, 0x0040, 0x5ad3, 0x2f00, + 0x700a, 0x0078, 0x5ad5, 0x700b, 0x0000, 0x660c, 0x067e, 0x2c00, + 0xaf06, 0x0040, 0x5ade, 0x7e0e, 0x0078, 0x5adf, 0x2678, 0x600f, + 0x0000, 0x1078, 0x6aaf, 0x00c0, 0x5ae9, 0x1078, 0x22d7, 0x0078, + 0x5b05, 0x1078, 0x6ac3, 0x00c0, 0x5af1, 0x1078, 0x5e4d, 0x0078, + 0x5b05, 0x6010, 0x2068, 0x1078, 0x6938, 0x0040, 0x5b05, 0x601c, + 0xa086, 0x0003, 0x00c0, 0x5b1b, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x1078, 0x3a72, 0x1078, 0x6a89, 0x6003, 0x0000, 0x1078, + 0x6a96, 0x1078, 0x58fa, 0x0c7f, 0x0078, 0x5a90, 0x2c78, 0x600c, + 0x2060, 0x0078, 0x5a90, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0d7f, + 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x5afc, + 0x1078, 0x74f2, 0x0078, 0x5b05, 0x037e, 0x157e, 0x137e, 0x147e, + 0x3908, 0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x2149, 0x00c0, + 0x5b35, 0x8210, 0x8000, 0x0078, 0x5b2c, 0xa005, 0x0040, 0x5b3f, 0x20a9, 0x0020, 0x2198, 0xa110, 0x22a0, 0x22c8, 0x53a3, 0x147f, 0x137f, 0x157f, 0x037f, 0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078, - 0x5053, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, + 0x504b, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x514c, 0x20a3, 0x4f47, 0x20a3, 0x4943, 0x20a3, 0x2020, 0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3, - 0x0000, 0x20a3, 0x0000, 0x1078, 0x556e, 0x0d7f, 0x007c, 0x20a1, - 0x020b, 0x1078, 0x5053, 0x20a3, 0x0210, 0x20a3, 0x0018, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x1078, 0x5566, 0x0d7f, 0x007c, 0x20a1, + 0x020b, 0x1078, 0x504b, 0x20a3, 0x0210, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, 0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7810, 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, - 0x0018, 0x1078, 0x556e, 0x007c, 0x2061, 0x7d00, 0x2a70, 0x7060, + 0x0018, 0x1078, 0x5566, 0x007c, 0x2061, 0x7d00, 0x2a70, 0x7060, 0x7046, 0x704b, 0x7d00, 0x007c, 0x0e7e, 0x127e, 0x2071, 0x7600, - 0x2091, 0x8000, 0x7544, 0xa582, 0x0001, 0x0048, 0x5bce, 0x7048, - 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, 0x5bba, 0xace0, 0x0008, - 0x7054, 0xac02, 0x00c8, 0x5bb6, 0x0078, 0x5ba9, 0x2061, 0x7d00, - 0x0078, 0x5ba9, 0x6003, 0x0008, 0x8529, 0x7546, 0xaca8, 0x0008, - 0x7054, 0xa502, 0x00c8, 0x5bca, 0x754a, 0xa085, 0x0001, 0x127f, - 0x0e7f, 0x007c, 0x704b, 0x7d00, 0x0078, 0x5bc5, 0xa006, 0x0078, - 0x5bc7, 0x0e7e, 0x2071, 0x7600, 0x7544, 0xa582, 0x0001, 0x0048, - 0x5bff, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, 0x5bec, - 0xace0, 0x0008, 0x7054, 0xac02, 0x00c8, 0x5be8, 0x0078, 0x5bdb, - 0x2061, 0x7d00, 0x0078, 0x5bdb, 0x6003, 0x0008, 0x8529, 0x7546, - 0xaca8, 0x0008, 0x7054, 0xa502, 0x00c8, 0x5bfb, 0x754a, 0xa085, - 0x0001, 0x0e7f, 0x007c, 0x704b, 0x7d00, 0x0078, 0x5bf7, 0xa006, - 0x0078, 0x5bf9, 0xac82, 0x7d00, 0x1048, 0x12d5, 0x2001, 0x7615, - 0x2004, 0xac02, 0x10c8, 0x12d5, 0xa006, 0x6006, 0x600a, 0x600e, + 0x2091, 0x8000, 0x7544, 0xa582, 0x0001, 0x0048, 0x5bc6, 0x7048, + 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, 0x5bb2, 0xace0, 0x0008, + 0x7054, 0xac02, 0x00c8, 0x5bae, 0x0078, 0x5ba1, 0x2061, 0x7d00, + 0x0078, 0x5ba1, 0x6003, 0x0008, 0x8529, 0x7546, 0xaca8, 0x0008, + 0x7054, 0xa502, 0x00c8, 0x5bc2, 0x754a, 0xa085, 0x0001, 0x127f, + 0x0e7f, 0x007c, 0x704b, 0x7d00, 0x0078, 0x5bbd, 0xa006, 0x0078, + 0x5bbf, 0x0e7e, 0x2071, 0x7600, 0x7544, 0xa582, 0x0001, 0x0048, + 0x5bf7, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, 0x5be4, + 0xace0, 0x0008, 0x7054, 0xac02, 0x00c8, 0x5be0, 0x0078, 0x5bd3, + 0x2061, 0x7d00, 0x0078, 0x5bd3, 0x6003, 0x0008, 0x8529, 0x7546, + 0xaca8, 0x0008, 0x7054, 0xa502, 0x00c8, 0x5bf3, 0x754a, 0xa085, + 0x0001, 0x0e7f, 0x007c, 0x704b, 0x7d00, 0x0078, 0x5bef, 0xa006, + 0x0078, 0x5bf1, 0xac82, 0x7d00, 0x1048, 0x12cd, 0x2001, 0x7615, + 0x2004, 0xac02, 0x10c8, 0x12cd, 0xa006, 0x6006, 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, 0x601f, 0x0000, 0x6003, 0x0000, 0x2061, - 0x7600, 0x6044, 0x8000, 0x6046, 0xa086, 0x0001, 0x0040, 0x5c21, - 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c7a, 0x127f, 0x0078, - 0x5c20, 0x601c, 0xa084, 0x000f, 0x0079, 0x5c2e, 0x5c37, 0x5c3f, - 0x5c5b, 0x5c77, 0x6b4b, 0x6b67, 0x6b83, 0x5c37, 0x5c3f, 0xa18e, - 0x0047, 0x00c0, 0x5c3e, 0xa016, 0x1078, 0x1572, 0x007c, 0x067e, - 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12d5, 0x1079, 0x5c49, 0x067f, - 0x007c, 0x5c59, 0x5d40, 0x5e72, 0x5c59, 0x5ec9, 0x5c59, 0x5c59, - 0x5c59, 0x5cef, 0x6182, 0x5c59, 0x5c59, 0x5c59, 0x5c59, 0x5c59, - 0x5c59, 0x1078, 0x12d5, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, - 0x12d5, 0x1079, 0x5c65, 0x067f, 0x007c, 0x5c75, 0x5c75, 0x5c75, - 0x5c75, 0x5c75, 0x5c75, 0x5c75, 0x5c75, 0x65f2, 0x66b8, 0x5c75, - 0x660b, 0x6664, 0x660b, 0x6664, 0x5c75, 0x1078, 0x12d5, 0x067e, - 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12d5, 0x1079, 0x5c81, 0x067f, - 0x007c, 0x5c91, 0x61c0, 0x6266, 0x6328, 0x647c, 0x5c91, 0x5c91, - 0x5c91, 0x619e, 0x65a7, 0x65ab, 0x5c91, 0x5c91, 0x5c91, 0x5c91, - 0x65d1, 0x1078, 0x12d5, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, + 0x7600, 0x6044, 0x8000, 0x6046, 0xa086, 0x0001, 0x0040, 0x5c19, + 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c72, 0x127f, 0x0078, + 0x5c18, 0x601c, 0xa084, 0x000f, 0x0079, 0x5c26, 0x5c2f, 0x5c37, + 0x5c53, 0x5c6f, 0x6b40, 0x6b5c, 0x6b78, 0x5c2f, 0x5c37, 0xa18e, + 0x0047, 0x00c0, 0x5c36, 0xa016, 0x1078, 0x156a, 0x007c, 0x067e, + 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12cd, 0x1079, 0x5c41, 0x067f, + 0x007c, 0x5c51, 0x5d38, 0x5e68, 0x5c51, 0x5ebf, 0x5c51, 0x5c51, + 0x5c51, 0x5ce7, 0x6178, 0x5c51, 0x5c51, 0x5c51, 0x5c51, 0x5c51, + 0x5c51, 0x1078, 0x12cd, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, + 0x12cd, 0x1079, 0x5c5d, 0x067f, 0x007c, 0x5c6d, 0x5c6d, 0x5c6d, + 0x5c6d, 0x5c6d, 0x5c6d, 0x5c6d, 0x5c6d, 0x65ec, 0x66b2, 0x5c6d, + 0x6605, 0x665e, 0x6605, 0x665e, 0x5c6d, 0x1078, 0x12cd, 0x067e, + 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12cd, 0x1079, 0x5c79, 0x067f, + 0x007c, 0x5c89, 0x61b6, 0x625c, 0x631e, 0x6476, 0x5c89, 0x5c89, + 0x5c89, 0x6194, 0x65a1, 0x65a5, 0x5c89, 0x5c89, 0x5c89, 0x5c89, + 0x65cb, 0x1078, 0x12cd, 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, 0x5ca1, 0x0e7e, 0x1078, 0x693e, - 0x0040, 0x5cb8, 0x6010, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, - 0x0e7f, 0x1078, 0x5c02, 0x007c, 0x0d7e, 0x037e, 0x7330, 0xa386, - 0x0200, 0x00c0, 0x5cc9, 0x6018, 0x2068, 0x6813, 0x00ff, 0x6817, - 0xfffd, 0x6010, 0xa005, 0x0040, 0x5cd3, 0x2068, 0x6807, 0x0000, - 0x6837, 0x0103, 0x6b32, 0x1078, 0x5c02, 0x037f, 0x0d7f, 0x007c, + 0x0002, 0xa4a0, 0x0002, 0x00f0, 0x5c99, 0x0e7e, 0x1078, 0x6938, + 0x0040, 0x5cb0, 0x6010, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, + 0x0e7f, 0x1078, 0x5bfa, 0x007c, 0x0d7e, 0x037e, 0x7330, 0xa386, + 0x0200, 0x00c0, 0x5cc1, 0x6018, 0x2068, 0x6813, 0x00ff, 0x6817, + 0xfffd, 0x6010, 0xa005, 0x0040, 0x5ccb, 0x2068, 0x6807, 0x0000, + 0x6837, 0x0103, 0x6b32, 0x1078, 0x5bfa, 0x037f, 0x0d7f, 0x007c, 0x0d7e, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0xa1b6, - 0x0015, 0x00c0, 0x5cec, 0x6018, 0x2068, 0x7038, 0x680a, 0x703c, - 0x680e, 0x6800, 0xc08d, 0x6802, 0x0d7f, 0x0078, 0x5cad, 0x2100, - 0xa1b2, 0x0030, 0x10c8, 0x12d5, 0x0079, 0x5cf6, 0x5d28, 0x5d34, - 0x5d28, 0x5d28, 0x5d28, 0x5d28, 0x5d26, 0x5d26, 0x5d26, 0x5d26, - 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, - 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, - 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d28, 0x5d26, 0x5d28, - 0x5d28, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d28, 0x5d26, - 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x1078, 0x12d5, - 0x6003, 0x0001, 0x6106, 0x1078, 0x4872, 0x127e, 0x2091, 0x8000, - 0x1078, 0x4c7a, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, - 0x4872, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c7a, 0x127f, 0x007c, - 0x6004, 0xa0b2, 0x0030, 0x10c8, 0x12d5, 0xa1b6, 0x0013, 0x00c0, - 0x5d4c, 0x2008, 0x0079, 0x5dd5, 0xa1b6, 0x0027, 0x00c0, 0x5da2, - 0x1078, 0x4b81, 0x6004, 0x1078, 0x6aba, 0x0040, 0x5d65, 0x1078, - 0x6ace, 0x0040, 0x5d9a, 0xa08e, 0x0021, 0x0040, 0x5d9e, 0xa08e, - 0x0022, 0x0040, 0x5d9a, 0x0078, 0x5d95, 0x1078, 0x22dd, 0x2001, - 0x0007, 0x1078, 0x37d1, 0x6018, 0xa080, 0x0028, 0x200c, 0x1078, - 0x5e57, 0xa186, 0x007e, 0x00c0, 0x5d7b, 0x2001, 0x762f, 0x2014, - 0xa295, 0x0001, 0x2202, 0x017e, 0x027e, 0x037e, 0x2110, 0x2019, - 0x0028, 0x1078, 0x4962, 0x1078, 0x48a5, 0x0c7e, 0x6018, 0xa065, - 0x0040, 0x5d8c, 0x1078, 0x39a6, 0x0c7f, 0x2c08, 0x1078, 0x737b, - 0x037f, 0x027f, 0x017f, 0x1078, 0x380d, 0x1078, 0x5c02, 0x1078, - 0x4c7a, 0x007c, 0x1078, 0x5e57, 0x0078, 0x5d95, 0x1078, 0x5e66, - 0x0078, 0x5d95, 0xa186, 0x0014, 0x00c0, 0x5d99, 0x1078, 0x4b81, - 0x1078, 0x22bb, 0x1078, 0x6aba, 0x00c0, 0x5dc2, 0x1078, 0x22dd, - 0x6018, 0xa080, 0x0028, 0x200c, 0x1078, 0x5e57, 0xa186, 0x007e, - 0x00c0, 0x5dc0, 0x2001, 0x762f, 0x200c, 0xa18d, 0x0001, 0x2102, - 0x0078, 0x5d95, 0x1078, 0x6ace, 0x00c0, 0x5dca, 0x1078, 0x5e57, - 0x0078, 0x5d95, 0x6004, 0xa08e, 0x0021, 0x0040, 0x5dc6, 0xa08e, - 0x0022, 0x1040, 0x5e66, 0x0078, 0x5d95, 0x5e07, 0x5e09, 0x5e0d, - 0x5e11, 0x5e15, 0x5e19, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, - 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, - 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, - 0x5e05, 0x5e05, 0x5e05, 0x5e1d, 0x5e23, 0x5e05, 0x5e2d, 0x5e23, - 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e23, 0x5e23, 0x5e05, - 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x1078, 0x12d5, 0x0078, - 0x5e23, 0x2001, 0x000b, 0x0078, 0x5e36, 0x2001, 0x0003, 0x0078, - 0x5e36, 0x2001, 0x0005, 0x0078, 0x5e36, 0x2001, 0x0001, 0x0078, - 0x5e36, 0x2001, 0x0009, 0x0078, 0x5e36, 0x1078, 0x12d5, 0x0078, - 0x5e35, 0x1078, 0x37d1, 0x1078, 0x4b81, 0x6003, 0x0002, 0x6017, - 0x0028, 0x1078, 0x4c7a, 0x0078, 0x5e35, 0x1078, 0x4b81, 0x6003, - 0x0004, 0x6017, 0x0028, 0x1078, 0x4c7a, 0x007c, 0x1078, 0x37d1, - 0x1078, 0x4b81, 0x6003, 0x0002, 0x037e, 0x2019, 0x765c, 0x2304, - 0xa084, 0xff00, 0x00c0, 0x5e48, 0x2019, 0x0028, 0x0078, 0x5e51, - 0x8007, 0xa09a, 0x0004, 0x0048, 0x5e44, 0x8003, 0x801b, 0x831b, - 0xa318, 0x6316, 0x037f, 0x1078, 0x4c7a, 0x0078, 0x5e35, 0x0e7e, - 0x1078, 0x693e, 0x0040, 0x5e64, 0x6010, 0x2070, 0x7007, 0x0000, - 0x7037, 0x0103, 0x7033, 0x0100, 0x0e7f, 0x007c, 0x0e7e, 0xacf0, - 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x7023, 0x8001, - 0x0e7f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, 0x00ff, - 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x12d5, 0x6604, 0xa6b6, 0x0028, - 0x00c0, 0x5e86, 0x1078, 0x6b03, 0x0078, 0x5eb8, 0x6604, 0xa6b6, - 0x0029, 0x00c0, 0x5e8f, 0x1078, 0x6b1d, 0x0078, 0x5eb8, 0x6604, - 0xa6b6, 0x001f, 0x00c0, 0x5e98, 0x1078, 0x5c93, 0x0078, 0x5eb8, - 0x6604, 0xa6b6, 0x0000, 0x00c0, 0x5ea1, 0x1078, 0x5cd8, 0x0078, - 0x5eb8, 0x6604, 0xa6b6, 0x0022, 0x00c0, 0x5eaa, 0x1078, 0x5cbc, - 0x0078, 0x5eb8, 0xa1b6, 0x0015, 0x00c0, 0x5eb2, 0x1079, 0x5ebd, - 0x0078, 0x5eb8, 0xa1b6, 0x0016, 0x00c0, 0x5eb9, 0x1079, 0x5ffa, - 0x007c, 0x1078, 0x5c37, 0x0078, 0x5eb8, 0x5ee1, 0x5ee4, 0x5ee1, - 0x5f25, 0x5ee1, 0x5f96, 0x5ee1, 0x5ee1, 0x5ee1, 0x5fd2, 0x5ee1, - 0x5fe8, 0xa1b6, 0x0048, 0x0040, 0x5ed5, 0x20e1, 0x0005, 0x3d18, - 0x3e20, 0x2c10, 0x1078, 0x1572, 0x007c, 0x0e7e, 0xacf0, 0x0004, - 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x5c02, - 0x007c, 0x0005, 0x0005, 0x007c, 0x0e7e, 0x2071, 0x7600, 0x7078, - 0xa086, 0x0074, 0x00c0, 0x5f0e, 0x1078, 0x734f, 0x00c0, 0x5f00, - 0x0d7e, 0x6018, 0x2068, 0x1078, 0x5f12, 0x0d7f, 0x2001, 0x0006, - 0x1078, 0x37d1, 0x1078, 0x22dd, 0x1078, 0x5c02, 0x0078, 0x5f10, - 0x2001, 0x000a, 0x1078, 0x37d1, 0x1078, 0x22dd, 0x6003, 0x0001, - 0x6007, 0x0001, 0x1078, 0x4872, 0x0078, 0x5f10, 0x1078, 0x5f86, - 0x0e7f, 0x007c, 0x6800, 0xd084, 0x0040, 0x5f24, 0x2001, 0x0000, - 0x1078, 0x37bd, 0x2069, 0x7651, 0x6804, 0xd0a4, 0x0040, 0x5f24, - 0x2001, 0x0006, 0x1078, 0x37df, 0x007c, 0x0d7e, 0x2011, 0x761e, - 0x2204, 0xa086, 0x0074, 0x00c0, 0x5f82, 0x1078, 0x60d4, 0x6018, - 0x2068, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x0040, 0x5f4d, - 0xa286, 0x0080, 0x00c0, 0x5f76, 0x6813, 0x00ff, 0x6817, 0xfffc, - 0x6010, 0xa005, 0x0040, 0x5f6c, 0x2068, 0x6807, 0x0000, 0x6837, - 0x0103, 0x6833, 0x0200, 0x0078, 0x5f6c, 0x0e7e, 0x0f7e, 0x6813, - 0x00ff, 0x6817, 0xfffe, 0x2071, 0x762f, 0x2e04, 0xa085, 0x0003, - 0x2072, 0x2071, 0x7b80, 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, - 0x2069, 0x7619, 0x206a, 0x78e6, 0x8e70, 0x2e04, 0x2069, 0x761a, - 0x206a, 0x78ea, 0x0f7f, 0x0e7f, 0x2001, 0x0006, 0x1078, 0x37d1, - 0x1078, 0x22dd, 0x1078, 0x5c02, 0x0078, 0x5f84, 0x2001, 0x0004, - 0x1078, 0x37d1, 0x6003, 0x0001, 0x6007, 0x0003, 0x1078, 0x4872, - 0x0078, 0x5f84, 0x1078, 0x5f86, 0x0d7f, 0x007c, 0x2001, 0x7600, - 0x2004, 0xa086, 0x0003, 0x0040, 0x5f91, 0x2001, 0x0007, 0x1078, - 0x37d1, 0x1078, 0x22dd, 0x1078, 0x5c02, 0x007c, 0x0e7e, 0x2071, - 0x7600, 0x7078, 0xa086, 0x0014, 0x00c0, 0x5fcc, 0x7000, 0xa086, - 0x0003, 0x00c0, 0x5fa9, 0x6010, 0xa005, 0x00c0, 0x5fa9, 0x1078, - 0x2dc8, 0x0d7e, 0x6018, 0x2068, 0x1078, 0x38a1, 0x1078, 0x5f12, - 0x0d7f, 0x1078, 0x60de, 0x00c0, 0x5fcc, 0x2001, 0x0006, 0x1078, - 0x37d1, 0x0e7e, 0x6010, 0xa005, 0x0040, 0x5fc5, 0x2070, 0x7007, - 0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x0e7f, 0x1078, 0x22dd, - 0x1078, 0x5c02, 0x0078, 0x5fd0, 0x1078, 0x5e57, 0x1078, 0x5f86, - 0x0e7f, 0x007c, 0x2011, 0x761e, 0x2204, 0xa086, 0x0014, 0x00c0, - 0x5fe5, 0x2001, 0x0002, 0x1078, 0x37d1, 0x6003, 0x0001, 0x6007, - 0x0001, 0x1078, 0x4872, 0x0078, 0x5fe7, 0x1078, 0x5f86, 0x007c, - 0x2011, 0x761e, 0x2204, 0xa086, 0x0004, 0x00c0, 0x5ff7, 0x2001, - 0x0007, 0x1078, 0x37d1, 0x1078, 0x5c02, 0x0078, 0x5ff9, 0x1078, - 0x5f86, 0x007c, 0x5ee1, 0x6006, 0x5ee1, 0x602c, 0x5ee1, 0x6087, - 0x5ee1, 0x5ee1, 0x5ee1, 0x609c, 0x5ee1, 0x60af, 0x0c7e, 0x1078, - 0x60c2, 0x00c0, 0x601b, 0x2001, 0x0000, 0x1078, 0x37bd, 0x2001, - 0x0002, 0x1078, 0x37d1, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, - 0x4872, 0x0078, 0x602a, 0x2009, 0x7b8f, 0x2104, 0xa084, 0xff00, - 0xa086, 0x1900, 0x00c0, 0x6028, 0x1078, 0x5c02, 0x0078, 0x602a, - 0x1078, 0x5f86, 0x0c7f, 0x007c, 0x1078, 0x60d1, 0x00c0, 0x6040, - 0x2001, 0x0000, 0x1078, 0x37bd, 0x2001, 0x0002, 0x1078, 0x37d1, - 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x4872, 0x0078, 0x6062, - 0x1078, 0x5e57, 0x2009, 0x7b8e, 0x2134, 0xa6b4, 0x00ff, 0xa686, - 0x0005, 0x0040, 0x6063, 0x2009, 0x7b8f, 0x2104, 0xa084, 0xff00, - 0xa086, 0x1900, 0x00c0, 0x6060, 0xa686, 0x0009, 0x0040, 0x6063, - 0x2001, 0x0004, 0x1078, 0x37d1, 0x1078, 0x5c02, 0x0078, 0x6062, - 0x1078, 0x5f86, 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x693e, - 0x0040, 0x6071, 0x6838, 0xd0fc, 0x0040, 0x6071, 0x0d7f, 0x0078, - 0x6060, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, - 0x6082, 0x8001, 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x0d7f, - 0x0078, 0x6062, 0x1078, 0x22bb, 0x0d7f, 0x0078, 0x6060, 0x1078, - 0x60d1, 0x00c0, 0x6097, 0x2001, 0x0004, 0x1078, 0x37d1, 0x6003, - 0x0001, 0x6007, 0x0003, 0x1078, 0x4872, 0x0078, 0x609b, 0x1078, - 0x5e57, 0x1078, 0x5f86, 0x007c, 0x1078, 0x60d1, 0x00c0, 0x60ac, - 0x2001, 0x0008, 0x1078, 0x37d1, 0x6003, 0x0001, 0x6007, 0x0005, - 0x1078, 0x4872, 0x0078, 0x60ae, 0x1078, 0x5f86, 0x007c, 0x1078, - 0x60d1, 0x00c0, 0x60bf, 0x2001, 0x000a, 0x1078, 0x37d1, 0x6003, - 0x0001, 0x6007, 0x0001, 0x1078, 0x4872, 0x0078, 0x60c1, 0x1078, - 0x5f86, 0x007c, 0x2009, 0x7b8e, 0x2104, 0xa086, 0x0003, 0x00c0, - 0x60d0, 0x2009, 0x7b8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, - 0x007c, 0xa085, 0x0001, 0x007c, 0x0c7e, 0x017e, 0xac88, 0x0006, - 0x2164, 0x1078, 0x3837, 0x017f, 0x0c7f, 0x007c, 0x0e7e, 0x2071, - 0x7b8c, 0x7004, 0xa086, 0x0014, 0x00c0, 0x6101, 0x7008, 0xa086, - 0x0800, 0x00c0, 0x6101, 0x700c, 0xd0ec, 0x0040, 0x60ff, 0xa084, - 0x0f00, 0xa086, 0x0100, 0x00c0, 0x60ff, 0x7024, 0xd0a4, 0x0040, - 0x60ff, 0xd08c, 0x0040, 0x60ff, 0xa006, 0x0078, 0x6101, 0xa085, - 0x0001, 0x0e7f, 0x007c, 0x0e7e, 0x0d7e, 0x0c7e, 0x077e, 0x057e, - 0x047e, 0x027e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2029, 0x783f, - 0x252c, 0x2021, 0x7845, 0x2424, 0x2061, 0x7d00, 0x2071, 0x7600, - 0x7244, 0x7060, 0xa202, 0x00c8, 0x6158, 0x1078, 0x7559, 0x0040, - 0x6150, 0x671c, 0xa786, 0x0001, 0x0040, 0x6150, 0xa786, 0x0007, - 0x0040, 0x6150, 0x2500, 0xac06, 0x0040, 0x6150, 0x2400, 0xac06, - 0x0040, 0x6150, 0x0c7e, 0x6000, 0xa086, 0x0004, 0x00c0, 0x613a, - 0x1078, 0x1676, 0x6010, 0x2068, 0x1078, 0x693e, 0x0040, 0x614d, - 0xa786, 0x0003, 0x00c0, 0x6162, 0x6837, 0x0103, 0x6b4a, 0x6847, - 0x0000, 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x1078, 0x6aa1, 0x0c7f, - 0xace0, 0x0008, 0x7054, 0xac02, 0x00c8, 0x6158, 0x0078, 0x6118, - 0x127f, 0x007f, 0x027f, 0x047f, 0x057f, 0x077f, 0x0c7f, 0x0d7f, - 0x0e7f, 0x007c, 0xa786, 0x0006, 0x00c0, 0x6144, 0x1078, 0x74fd, - 0x0078, 0x614d, 0x220c, 0x2304, 0xa106, 0x00c0, 0x6175, 0x8210, - 0x8318, 0x00f0, 0x616a, 0xa006, 0x007c, 0x2304, 0xa102, 0x0048, - 0x617d, 0x2001, 0x0001, 0x0078, 0x617f, 0x2001, 0x0000, 0xa18d, - 0x0001, 0x007c, 0x6004, 0xa08a, 0x0030, 0x10c8, 0x12d5, 0x1078, - 0x6aba, 0x0040, 0x6191, 0x1078, 0x6ace, 0x0040, 0x619a, 0x0078, - 0x6193, 0x1078, 0x22dd, 0x1078, 0x4b81, 0x1078, 0x5c02, 0x1078, - 0x4c7a, 0x007c, 0x1078, 0x5e57, 0x0078, 0x6193, 0xa182, 0x0040, - 0x0079, 0x61a2, 0x61b2, 0x61b2, 0x61b2, 0x61b2, 0x61b2, 0x61b2, - 0x61b2, 0x61b2, 0x61b2, 0x61b2, 0x61b2, 0x61b4, 0x61b4, 0x61b4, - 0x61b4, 0x61b2, 0x1078, 0x12d5, 0x6003, 0x0001, 0x6106, 0x1078, - 0x4825, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c7a, 0x127f, 0x007c, - 0xa186, 0x0013, 0x00c0, 0x61c9, 0x6004, 0xa082, 0x0040, 0x0079, - 0x623f, 0xa186, 0x0027, 0x00c0, 0x61e6, 0x1078, 0x4b81, 0x1078, - 0x22bb, 0x0d7e, 0x6110, 0x2168, 0x1078, 0x693e, 0x0040, 0x61e0, - 0x6837, 0x0103, 0x684b, 0x0029, 0x1078, 0x3a7a, 0x1078, 0x6a94, - 0x0d7f, 0x1078, 0x5c02, 0x1078, 0x4c7a, 0x007c, 0xa186, 0x0014, - 0x00c0, 0x61ef, 0x6004, 0xa082, 0x0040, 0x0079, 0x620f, 0xa186, - 0x0047, 0x10c0, 0x12d5, 0x2001, 0x0109, 0x2004, 0xd084, 0x0040, - 0x620c, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x027e, 0x1078, - 0x46e6, 0x027f, 0x017f, 0x007f, 0x127f, 0x6000, 0xa086, 0x0002, - 0x00c0, 0x620c, 0x0078, 0x6266, 0x1078, 0x5c37, 0x007c, 0x6221, - 0x621f, 0x621f, 0x621f, 0x621f, 0x621f, 0x621f, 0x621f, 0x621f, - 0x621f, 0x621f, 0x6238, 0x6238, 0x6238, 0x6238, 0x621f, 0x1078, - 0x12d5, 0x1078, 0x4b81, 0x0d7e, 0x6110, 0x2168, 0x1078, 0x693e, - 0x0040, 0x6232, 0x6837, 0x0103, 0x684b, 0x0006, 0x1078, 0x3a7a, - 0x1078, 0x6a94, 0x0d7f, 0x1078, 0x5c02, 0x1078, 0x4c7a, 0x007c, - 0x1078, 0x4b81, 0x1078, 0x5c02, 0x1078, 0x4c7a, 0x007c, 0x6251, - 0x624f, 0x624f, 0x624f, 0x624f, 0x624f, 0x624f, 0x624f, 0x624f, - 0x624f, 0x624f, 0x625f, 0x625f, 0x625f, 0x625f, 0x624f, 0x1078, - 0x12d5, 0x1078, 0x4b81, 0x6003, 0x0002, 0x1078, 0x4c7a, 0x6010, - 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x007c, 0x1078, - 0x4b81, 0x6003, 0x000f, 0x1078, 0x4c7a, 0x007c, 0xa182, 0x0040, - 0x0079, 0x626a, 0x627a, 0x627a, 0x627a, 0x627a, 0x627a, 0x627c, - 0x6305, 0x631d, 0x627a, 0x627a, 0x627a, 0x627a, 0x627a, 0x627a, - 0x627a, 0x627a, 0x1078, 0x12d5, 0x0e7e, 0x0d7e, 0x2071, 0x7b8c, - 0x6110, 0x2168, 0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0040, 0x62e9, - 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040, 0x62ae, 0xa186, 0x0028, - 0x00c0, 0x6298, 0x1078, 0x6aa8, 0x684b, 0x001c, 0x0078, 0x62b0, - 0xd6dc, 0x0040, 0x62a3, 0x684b, 0x0015, 0x7318, 0x6b62, 0x731c, - 0x6b5e, 0x0078, 0x62b0, 0xd6d4, 0x0040, 0x62ae, 0x684b, 0x0007, - 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x62b0, 0x684b, 0x0000, - 0x6837, 0x0103, 0x6e46, 0xa01e, 0xd6c4, 0x0040, 0x62c3, 0x7328, - 0x732c, 0x6b56, 0x037e, 0x2308, 0x2019, 0x7b98, 0xad90, 0x0019, - 0x1078, 0x6727, 0x037f, 0xd6cc, 0x0040, 0x62f9, 0x7124, 0x695a, - 0xa192, 0x0021, 0x00c8, 0x62d7, 0x2071, 0x7b98, 0x831c, 0x2300, - 0xae18, 0xad90, 0x001d, 0x1078, 0x6727, 0x0078, 0x62f9, 0x6838, - 0xd0fc, 0x0040, 0x62e0, 0x2009, 0x0020, 0x695a, 0x0078, 0x62cc, - 0x0f7e, 0x2d78, 0x1078, 0x66bf, 0x0f7f, 0x1078, 0x6714, 0x0078, - 0x62fb, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac, - 0x0040, 0x62f9, 0x6810, 0x6914, 0xa115, 0x0040, 0x62f9, 0x1078, - 0x646d, 0x1078, 0x3a7a, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, - 0x0d7f, 0x0e7f, 0x1078, 0x5c02, 0x007c, 0x0f7e, 0x6003, 0x0003, - 0x2079, 0x7b8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, - 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x19cf, - 0x1078, 0x4891, 0x1078, 0x4d3a, 0x007c, 0x6003, 0x0004, 0x6110, - 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x1572, 0x007c, - 0xa182, 0x0040, 0x0079, 0x632c, 0x633c, 0x633c, 0x633c, 0x633c, - 0x633c, 0x633e, 0x63d5, 0x633c, 0x633c, 0x63eb, 0x644d, 0x633c, - 0x633c, 0x633c, 0x633c, 0x6454, 0x1078, 0x12d5, 0x077e, 0x0f7e, - 0x0e7e, 0x0d7e, 0x2071, 0x7b8c, 0x6110, 0x2178, 0x7614, 0xa6b4, - 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, - 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x63d0, 0xa694, 0xff00, 0xa284, - 0x0c00, 0x0040, 0x635f, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, - 0x0300, 0x0040, 0x63d0, 0x1078, 0x132f, 0x1040, 0x12d5, 0x2d00, - 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, - 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x00ff, 0xa186, - 0x0002, 0x0040, 0x6399, 0xa186, 0x0028, 0x00c0, 0x6383, 0x684b, - 0x001c, 0x0078, 0x639b, 0xd6dc, 0x0040, 0x638e, 0x684b, 0x0015, - 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x639b, 0xd6d4, 0x0040, - 0x6399, 0x684b, 0x0007, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, - 0x639b, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, - 0xa01e, 0xd6c4, 0x0040, 0x63b0, 0x7328, 0x732c, 0x6b56, 0x037e, - 0x2308, 0x2019, 0x7b98, 0xad90, 0x0019, 0x1078, 0x6727, 0x037f, - 0xd6cc, 0x0040, 0x63d0, 0x7124, 0x695a, 0xa192, 0x0021, 0x00c8, - 0x63c4, 0x2071, 0x7b98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, - 0x1078, 0x6727, 0x0078, 0x63d0, 0x7838, 0xd0fc, 0x0040, 0x63cd, - 0x2009, 0x0020, 0x695a, 0x0078, 0x63b9, 0x2d78, 0x1078, 0x66bf, - 0x0d7f, 0x0e7f, 0x0f7f, 0x077f, 0x007c, 0x0f7e, 0x6003, 0x0003, - 0x2079, 0x7b8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, - 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x19cf, - 0x1078, 0x5567, 0x007c, 0x0d7e, 0x6003, 0x0002, 0x1078, 0x4c29, - 0x1078, 0x4d3a, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, 0x644b, - 0xd1cc, 0x0040, 0x6426, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x641e, - 0x017e, 0x684c, 0x007e, 0x6850, 0x007e, 0xad90, 0x000d, 0xa198, - 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318, - 0x8210, 0x00f0, 0x640d, 0x157f, 0x007f, 0x6852, 0x007f, 0x684e, - 0x017f, 0x2168, 0x1078, 0x1358, 0x0078, 0x6449, 0x017e, 0x1078, - 0x1358, 0x0d7f, 0x1078, 0x6714, 0x0078, 0x6449, 0x6837, 0x0103, - 0x6944, 0xa184, 0x00ff, 0xa186, 0x0002, 0x0040, 0x6445, 0xa086, - 0x0028, 0x00c0, 0x6437, 0x684b, 0x001c, 0x0078, 0x6447, 0xd1dc, - 0x0040, 0x643e, 0x684b, 0x0015, 0x0078, 0x6447, 0xd1d4, 0x0040, - 0x6445, 0x684b, 0x0007, 0x0078, 0x6447, 0x684b, 0x0000, 0x1078, - 0x3a7a, 0x1078, 0x5c02, 0x0d7f, 0x007c, 0x6003, 0x0002, 0x1078, - 0x4c29, 0x1078, 0x4d3a, 0x007c, 0x1078, 0x4c29, 0x1078, 0x22bb, - 0x0d7e, 0x6110, 0x2168, 0x1078, 0x693e, 0x0040, 0x6467, 0x6837, - 0x0103, 0x684b, 0x0029, 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x0d7f, - 0x1078, 0x5c02, 0x1078, 0x4d3a, 0x007c, 0x684b, 0x0015, 0xd1fc, - 0x0040, 0x6479, 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, - 0x0000, 0x6962, 0x685e, 0x007c, 0xa182, 0x0040, 0x0079, 0x6480, - 0x6490, 0x6490, 0x6490, 0x6490, 0x6490, 0x6492, 0x6490, 0x6536, - 0x653e, 0x6490, 0x6490, 0x6490, 0x6490, 0x6490, 0x6490, 0x6490, - 0x1078, 0x12d5, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071, 0x7b8c, - 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, - 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0040, - 0x6528, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0040, 0x64b3, 0x7018, - 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0040, 0x6525, 0x1078, - 0x132f, 0x1040, 0x12d5, 0x2d00, 0x784a, 0x7f4c, 0xa7bd, 0x0200, - 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, 0x683e, 0x7840, - 0x6842, 0x6e46, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040, 0x64ee, - 0xa186, 0x0028, 0x00c0, 0x64d8, 0x684b, 0x001c, 0x0078, 0x64f0, - 0xd6dc, 0x0040, 0x64e3, 0x684b, 0x0015, 0x7318, 0x6b62, 0x731c, - 0x6b5e, 0x0078, 0x64f0, 0xd6d4, 0x0040, 0x64ee, 0x684b, 0x0007, - 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x64f0, 0x684b, 0x0000, - 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0040, - 0x6505, 0x7328, 0x732c, 0x6b56, 0x037e, 0x2308, 0x2019, 0x7b98, - 0xad90, 0x0019, 0x1078, 0x6727, 0x037f, 0xd6cc, 0x0040, 0x6525, - 0x7124, 0x695a, 0xa192, 0x0021, 0x00c8, 0x6519, 0x2071, 0x7b98, - 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x6727, 0x0078, - 0x6525, 0x7838, 0xd0fc, 0x0040, 0x6522, 0x2009, 0x0020, 0x695a, - 0x0078, 0x650e, 0x2d78, 0x1078, 0x66bf, 0xd6dc, 0x00c0, 0x652b, - 0xa006, 0x0078, 0x652f, 0x2001, 0x0001, 0x7218, 0x731c, 0x1078, - 0x15b6, 0x0d7f, 0x0e7f, 0x0f7f, 0x077f, 0x007c, 0x20e1, 0x0005, - 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x1572, 0x007c, 0x0d7e, 0x6003, - 0x0002, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, 0x65a5, 0xd1cc, - 0x0040, 0x6575, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x656d, 0x017e, - 0x684c, 0x007e, 0x6850, 0x007e, 0xad90, 0x000d, 0xa198, 0x000d, - 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, - 0x00f0, 0x655c, 0x157f, 0x007f, 0x6852, 0x007f, 0x684e, 0x017f, - 0x2168, 0x1078, 0x1358, 0x0078, 0x65a3, 0x017e, 0x1078, 0x1358, - 0x0d7f, 0x1078, 0x6714, 0x0078, 0x65a3, 0x6837, 0x0103, 0x6944, - 0xa184, 0x00ff, 0xa186, 0x0002, 0x0040, 0x6594, 0xa086, 0x0028, - 0x00c0, 0x6586, 0x684b, 0x001c, 0x0078, 0x65a1, 0xd1dc, 0x0040, - 0x658d, 0x684b, 0x0015, 0x0078, 0x65a1, 0xd1d4, 0x0040, 0x6594, - 0x684b, 0x0007, 0x0078, 0x65a1, 0x684b, 0x0000, 0x684c, 0xd0ac, - 0x0040, 0x65a1, 0x6810, 0x6914, 0xa115, 0x0040, 0x65a1, 0x1078, - 0x646d, 0x1078, 0x3a7a, 0x1078, 0x5c02, 0x0d7f, 0x007c, 0x1078, - 0x4b81, 0x0078, 0x65ad, 0x1078, 0x4c29, 0x1078, 0x693e, 0x0040, - 0x65c4, 0x0d7e, 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0x760c, - 0x210c, 0xd18c, 0x00c0, 0x65cd, 0xd184, 0x00c0, 0x65c9, 0x6108, - 0x694a, 0x1078, 0x3a7a, 0x0d7f, 0x1078, 0x5c02, 0x1078, 0x4c7a, - 0x007c, 0x684b, 0x0004, 0x0078, 0x65c1, 0x684b, 0x0004, 0x0078, - 0x65c1, 0xa182, 0x0040, 0x0079, 0x65d5, 0x65e5, 0x65e5, 0x65e5, - 0x65e5, 0x65e5, 0x65e7, 0x65e5, 0x65ea, 0x65e5, 0x65e5, 0x65e5, - 0x65e5, 0x65e5, 0x65e5, 0x65e5, 0x65e5, 0x1078, 0x12d5, 0x1078, - 0x5c02, 0x007c, 0x007e, 0x027e, 0xa016, 0x1078, 0x1572, 0x027f, - 0x007f, 0x007c, 0xa182, 0x0085, 0x0079, 0x65f6, 0x65ff, 0x65fd, - 0x65fd, 0x65fd, 0x65fd, 0x65fd, 0x65fd, 0x1078, 0x12d5, 0x6003, - 0x0001, 0x6106, 0x1078, 0x4825, 0x127e, 0x2091, 0x8000, 0x1078, - 0x4c7a, 0x127f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x6615, 0x6004, - 0xa082, 0x0085, 0x2008, 0x0079, 0x6649, 0xa186, 0x0027, 0x00c0, - 0x6636, 0x1078, 0x4b81, 0x1078, 0x22bb, 0x0d7e, 0x6010, 0x2068, - 0x1078, 0x693e, 0x0040, 0x662c, 0x6837, 0x0103, 0x684b, 0x0029, - 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x0d7f, 0x1078, 0x5c02, 0x1078, - 0x4c7a, 0x007c, 0x1078, 0x5c37, 0x0078, 0x6631, 0xa186, 0x0014, - 0x00c0, 0x6632, 0x1078, 0x4b81, 0x0d7e, 0x6010, 0x2068, 0x1078, - 0x693e, 0x0040, 0x662c, 0x6837, 0x0103, 0x684b, 0x0006, 0x0078, - 0x6628, 0x6652, 0x6650, 0x6650, 0x6650, 0x6650, 0x6650, 0x665b, - 0x1078, 0x12d5, 0x1078, 0x4b81, 0x6017, 0x0014, 0x6003, 0x000c, - 0x1078, 0x4c7a, 0x007c, 0x1078, 0x4b81, 0x6017, 0x0014, 0x6003, - 0x000e, 0x1078, 0x4c7a, 0x007c, 0xa182, 0x008c, 0x00c8, 0x666e, - 0xa182, 0x0085, 0x0048, 0x666e, 0x0079, 0x6671, 0x1078, 0x5c37, - 0x007c, 0x6678, 0x6678, 0x6678, 0x6678, 0x667a, 0x6699, 0x6678, - 0x1078, 0x12d5, 0x0d7e, 0x1078, 0x6a94, 0x1078, 0x693e, 0x0040, - 0x6695, 0x6010, 0x2068, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, - 0x668d, 0x684b, 0x0006, 0x0078, 0x6691, 0x684b, 0x0005, 0x1078, - 0x6b47, 0x6847, 0x0000, 0x1078, 0x3a7a, 0x1078, 0x5c02, 0x0d7f, - 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x693e, 0x0040, 0x66b4, - 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, 0x66aa, 0x684b, 0x0006, - 0x0078, 0x66ae, 0x684b, 0x0005, 0x1078, 0x6b47, 0x6847, 0x0000, - 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x0d7f, 0x1078, 0x5c02, 0x007c, - 0x1078, 0x4b81, 0x1078, 0x5c02, 0x1078, 0x4c7a, 0x007c, 0x057e, - 0x067e, 0x0d7e, 0x0f7e, 0x2029, 0x0001, 0xa182, 0x0101, 0x00c8, - 0x66cb, 0x0078, 0x66cd, 0x2009, 0x0100, 0x2130, 0x2069, 0x7b98, - 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90, 0x001d, 0x1078, - 0x6727, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0040, 0x66e1, 0x1078, - 0x1358, 0x1078, 0x132f, 0x0040, 0x670b, 0x8528, 0x6837, 0x0110, - 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d, 0x00c8, 0x66f7, - 0x2608, 0xad90, 0x000f, 0x1078, 0x6727, 0x0078, 0x670b, 0xa6b2, - 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, 0x000f, 0x1078, 0x6727, - 0x0078, 0x66e1, 0x0f7f, 0x852f, 0xa5ad, 0x0003, 0x7d36, 0xa5ac, - 0x0000, 0x0078, 0x6710, 0x0f7f, 0x852f, 0xa5ad, 0x0003, 0x7d36, - 0x0d7f, 0x067f, 0x057f, 0x007c, 0x0f7e, 0x8dff, 0x0040, 0x6725, - 0x6804, 0xa07d, 0x0040, 0x6723, 0x6807, 0x0000, 0x1078, 0x3a7a, - 0x2f68, 0x0078, 0x6718, 0x1078, 0x3a7a, 0x0f7f, 0x007c, 0x157e, - 0xa184, 0x0001, 0x0040, 0x672d, 0x8108, 0x810c, 0x21a8, 0x2304, - 0x8007, 0x2012, 0x8318, 0x8210, 0x00f0, 0x672f, 0x157f, 0x007c, - 0x127e, 0x2091, 0x8000, 0x601c, 0xa084, 0x000f, 0x1079, 0x6742, - 0x127f, 0x007c, 0x6751, 0x674a, 0x674c, 0x676a, 0x674a, 0x674c, - 0x674c, 0x674c, 0x1078, 0x12d5, 0xa006, 0x007c, 0xa085, 0x0001, - 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x693e, 0x0040, 0x6767, - 0xa00e, 0x2001, 0x0005, 0x1078, 0x3b0a, 0x1078, 0x6b47, 0x1078, - 0x3a7a, 0x1078, 0x5c02, 0xa085, 0x0001, 0x0d7f, 0x007c, 0xa006, - 0x0078, 0x6765, 0x6000, 0xa08a, 0x0010, 0x10c8, 0x12d5, 0x1079, - 0x6772, 0x007c, 0x6782, 0x679f, 0x6784, 0x67b0, 0x679b, 0x6782, - 0x674c, 0x6751, 0x6751, 0x674c, 0x674c, 0x674c, 0x674c, 0x674c, - 0x674c, 0x674c, 0x1078, 0x12d5, 0x0d7e, 0x6010, 0x2068, 0x1078, - 0x693e, 0x0040, 0x678d, 0x1078, 0x6b47, 0x0d7f, 0x6007, 0x0085, - 0x6003, 0x000b, 0x601f, 0x0002, 0x1078, 0x4825, 0x1078, 0x4c7a, - 0xa085, 0x0001, 0x007c, 0x1078, 0x1676, 0x0078, 0x6784, 0x0e7e, - 0x2071, 0x7836, 0x7024, 0xac06, 0x00c0, 0x67a8, 0x1078, 0x56d6, - 0x1078, 0x560b, 0x0e7f, 0x00c0, 0x6784, 0x1078, 0x674c, 0x007c, - 0x037e, 0x0e7e, 0x2071, 0x7836, 0x703c, 0xac06, 0x00c0, 0x67c0, - 0x2019, 0x0000, 0x1078, 0x5768, 0x0e7f, 0x037f, 0x0078, 0x6784, - 0x1078, 0x5a44, 0x0e7f, 0x037f, 0x00c0, 0x6784, 0x1078, 0x674c, - 0x007c, 0x0c7e, 0x601c, 0xa084, 0x000f, 0x1079, 0x67d1, 0x0c7f, - 0x007c, 0x67e0, 0x683d, 0x68e2, 0x67e4, 0x67e0, 0x67e0, 0x71dd, - 0x5c02, 0x683d, 0x1078, 0x6ace, 0x00c0, 0x67e0, 0x1078, 0x5e57, - 0x007c, 0x6017, 0x0001, 0x007c, 0x6000, 0xa08a, 0x0010, 0x10c8, - 0x12d5, 0x1079, 0x67ec, 0x007c, 0x67fc, 0x67fe, 0x681e, 0x6830, - 0x6830, 0x67fc, 0x67e0, 0x67e0, 0x67e0, 0x6830, 0x6830, 0x67fc, - 0x67fc, 0x67fc, 0x67fc, 0x683a, 0x1078, 0x12d5, 0x0e7e, 0x6010, - 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071, 0x7836, 0x7024, 0xac06, - 0x0040, 0x681a, 0x1078, 0x560b, 0x6007, 0x0085, 0x6003, 0x000b, - 0x601f, 0x0002, 0x6017, 0x0014, 0x1078, 0x4825, 0x1078, 0x4c7a, - 0x0e7f, 0x007c, 0x6017, 0x0001, 0x0078, 0x6818, 0x0d7e, 0x6010, - 0x2068, 0x6850, 0xc0b5, 0x6852, 0x0d7f, 0x6007, 0x0085, 0x6003, - 0x000b, 0x601f, 0x0002, 0x1078, 0x4825, 0x1078, 0x4c7a, 0x007c, - 0x0d7e, 0x6017, 0x0001, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, - 0x0d7f, 0x007c, 0x1078, 0x5c02, 0x007c, 0x6000, 0xa08a, 0x0010, - 0x10c8, 0x12d5, 0x1079, 0x6845, 0x007c, 0x6855, 0x67e1, 0x6857, - 0x6855, 0x6857, 0x6855, 0x6855, 0x6855, 0x67da, 0x67da, 0x6855, - 0x6855, 0x6855, 0x6855, 0x6855, 0x6855, 0x1078, 0x12d5, 0x0d7e, - 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f, 0xa08a, 0x000c, - 0x10c8, 0x12d5, 0x1079, 0x6865, 0x007c, 0x6871, 0x6890, 0x6871, - 0x6890, 0x6871, 0x6890, 0x6873, 0x687c, 0x6871, 0x6890, 0x6871, - 0x6889, 0x1078, 0x12d5, 0x6004, 0xa08e, 0x0004, 0x0040, 0x688b, - 0xa08e, 0x0002, 0x0040, 0x688b, 0x6004, 0x1078, 0x6ace, 0x0040, - 0x68da, 0xa08e, 0x0021, 0x0040, 0x68de, 0xa08e, 0x0022, 0x0040, - 0x68da, 0x1078, 0x22bb, 0x1078, 0x5e57, 0x1078, 0x5c02, 0x007c, - 0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016, 0x0040, 0x68ca, 0xa186, - 0x0002, 0x00c0, 0x68b9, 0x6018, 0x2068, 0x68a0, 0xd0bc, 0x00c0, - 0x68b9, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, 0x68b9, 0x8001, - 0x6842, 0x6013, 0x0000, 0x601f, 0x0007, 0x6017, 0x0398, 0x1078, - 0x5b9c, 0x0040, 0x68b9, 0x2d00, 0x601a, 0x601f, 0x0001, 0x0078, - 0x68ca, 0x0d7f, 0x0c7f, 0x1078, 0x5e57, 0x1078, 0x22bb, 0x0e7e, - 0x127e, 0x2091, 0x8000, 0x1078, 0x22dd, 0x127f, 0x0e7f, 0x1078, - 0x5c02, 0x007c, 0x2001, 0x0002, 0x1078, 0x37d1, 0x6003, 0x0001, - 0x6007, 0x0002, 0x1078, 0x4872, 0x1078, 0x4c7a, 0x0d7f, 0x0c7f, - 0x0078, 0x68c9, 0x1078, 0x5e57, 0x0078, 0x688d, 0x1078, 0x5e66, - 0x0078, 0x688d, 0x6000, 0xa08a, 0x0010, 0x10c8, 0x12d5, 0x1079, - 0x68ea, 0x007c, 0x68fa, 0x68fa, 0x68fa, 0x68fa, 0x68fa, 0x68fa, - 0x68fa, 0x68fa, 0x68fa, 0x67e0, 0x68fa, 0x67e1, 0x68fc, 0x67e1, - 0x6905, 0x68fa, 0x1078, 0x12d5, 0x6007, 0x008b, 0x6003, 0x000d, - 0x1078, 0x4825, 0x1078, 0x4c7a, 0x007c, 0x1078, 0x6a94, 0x1078, - 0x693e, 0x0040, 0x6927, 0x1078, 0x22bb, 0x0d7e, 0x1078, 0x693e, - 0x0040, 0x691a, 0x6010, 0x2068, 0x6837, 0x0103, 0x684b, 0x0006, - 0x1078, 0x3a7a, 0x0d7f, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, - 0x0001, 0x1078, 0x4872, 0x1078, 0x4c7a, 0x0078, 0x6929, 0x1078, - 0x5c02, 0x007c, 0xa284, 0x0007, 0x00c0, 0x693b, 0xa282, 0x7d00, - 0x0048, 0x693b, 0x2001, 0x7615, 0x2004, 0xa202, 0x00c8, 0x693b, - 0xa085, 0x0001, 0x007c, 0xa006, 0x0078, 0x693a, 0x027e, 0x0e7e, - 0x2071, 0x7600, 0x6210, 0x7058, 0xa202, 0x0048, 0x6950, 0x705c, - 0xa202, 0x00c8, 0x6950, 0xa085, 0x0001, 0x0e7f, 0x027f, 0x007c, - 0xa006, 0x0078, 0x694d, 0x0e7e, 0x0c7e, 0x037e, 0x007e, 0x127e, - 0x2091, 0x8000, 0x2061, 0x7d00, 0x2071, 0x7600, 0x7344, 0x7060, - 0xa302, 0x00c8, 0x6979, 0x601c, 0xa206, 0x00c0, 0x6971, 0x1078, - 0x6ace, 0x00c0, 0x696d, 0x1078, 0x5e57, 0x0c7e, 0x1078, 0x5c02, - 0x0c7f, 0xace0, 0x0008, 0x7054, 0xac02, 0x00c8, 0x6979, 0x0078, - 0x695e, 0x127f, 0x007f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, - 0x0c7e, 0x017e, 0xa188, 0x7720, 0x210c, 0x81ff, 0x0040, 0x699c, - 0x2061, 0x7d00, 0x2071, 0x7600, 0x7344, 0x7060, 0xa302, 0x00c8, - 0x699c, 0x017e, 0x1078, 0x5b9c, 0x017f, 0x0040, 0x699f, 0x611a, - 0x1078, 0x22bb, 0x1078, 0x5c02, 0xa006, 0x0078, 0x69a1, 0xa085, - 0x0001, 0x017f, 0x0c7f, 0x0e7f, 0x007c, 0x0c7e, 0x057e, 0x127e, - 0x2091, 0x8000, 0x0c7e, 0x1078, 0x5b9c, 0x057f, 0x0040, 0x69be, - 0x6612, 0x651a, 0x601f, 0x0003, 0x2009, 0x004b, 0x1078, 0x5c29, - 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, - 0x69ba, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, - 0x1078, 0x5b9c, 0x057f, 0x0040, 0x69e8, 0x6013, 0x0000, 0x651a, - 0x601f, 0x0003, 0x0c7e, 0x2560, 0x1078, 0x39a6, 0x0c7f, 0x1078, - 0x4962, 0x1078, 0x48a5, 0x2c08, 0x1078, 0x737b, 0x2009, 0x004c, - 0x1078, 0x5c29, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c, - 0xa006, 0x0078, 0x69e4, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, - 0x62a0, 0x0c7e, 0x1078, 0x5b9c, 0x057f, 0x0040, 0x6a13, 0x6612, + 0x0015, 0x00c0, 0x5ce4, 0x6018, 0x2068, 0x7038, 0x680a, 0x703c, + 0x680e, 0x6800, 0xc08d, 0x6802, 0x0d7f, 0x0078, 0x5ca5, 0x2100, + 0xa1b2, 0x0030, 0x10c8, 0x12cd, 0x0079, 0x5cee, 0x5d20, 0x5d2c, + 0x5d20, 0x5d20, 0x5d20, 0x5d20, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, + 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, + 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, + 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d20, 0x5d1e, 0x5d20, + 0x5d20, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d20, 0x5d1e, + 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x1078, 0x12cd, + 0x6003, 0x0001, 0x6106, 0x1078, 0x486a, 0x127e, 0x2091, 0x8000, + 0x1078, 0x4c72, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, + 0x486a, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c72, 0x127f, 0x007c, + 0x6004, 0xa0b2, 0x0030, 0x10c8, 0x12cd, 0xa1b6, 0x0013, 0x00c0, + 0x5d44, 0x2008, 0x0079, 0x5dcb, 0xa1b6, 0x0027, 0x00c0, 0x5d99, + 0x1078, 0x4b79, 0x6004, 0x1078, 0x6aaf, 0x0040, 0x5d5d, 0x1078, + 0x6ac3, 0x0040, 0x5d91, 0xa08e, 0x0021, 0x0040, 0x5d95, 0xa08e, + 0x0022, 0x0040, 0x5d91, 0x0078, 0x5d8c, 0x1078, 0x22d7, 0x2001, + 0x0007, 0x1078, 0x37c9, 0x6018, 0xa080, 0x0028, 0x200c, 0x1078, + 0x5e4d, 0xa186, 0x007e, 0x00c0, 0x5d72, 0x2001, 0x762f, 0x2014, + 0xc285, 0x2202, 0x017e, 0x027e, 0x037e, 0x2110, 0x2019, 0x0028, + 0x1078, 0x495a, 0x1078, 0x489d, 0x0c7e, 0x6018, 0xa065, 0x0040, + 0x5d83, 0x1078, 0x399e, 0x0c7f, 0x2c08, 0x1078, 0x7370, 0x037f, + 0x027f, 0x017f, 0x1078, 0x3805, 0x1078, 0x5bfa, 0x1078, 0x4c72, + 0x007c, 0x1078, 0x5e4d, 0x0078, 0x5d8c, 0x1078, 0x5e5c, 0x0078, + 0x5d8c, 0xa186, 0x0014, 0x00c0, 0x5d90, 0x1078, 0x4b79, 0x1078, + 0x22b5, 0x1078, 0x6aaf, 0x00c0, 0x5db8, 0x1078, 0x22d7, 0x6018, + 0xa080, 0x0028, 0x200c, 0x1078, 0x5e4d, 0xa186, 0x007e, 0x00c0, + 0x5db6, 0x2001, 0x762f, 0x200c, 0xc185, 0x2102, 0x0078, 0x5d8c, + 0x1078, 0x6ac3, 0x00c0, 0x5dc0, 0x1078, 0x5e4d, 0x0078, 0x5d8c, + 0x6004, 0xa08e, 0x0021, 0x0040, 0x5dbc, 0xa08e, 0x0022, 0x1040, + 0x5e5c, 0x0078, 0x5d8c, 0x5dfd, 0x5dff, 0x5e03, 0x5e07, 0x5e0b, + 0x5e0f, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, + 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, + 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, + 0x5dfb, 0x5e13, 0x5e19, 0x5dfb, 0x5e23, 0x5e19, 0x5dfb, 0x5dfb, + 0x5dfb, 0x5dfb, 0x5dfb, 0x5e19, 0x5e19, 0x5dfb, 0x5dfb, 0x5dfb, + 0x5dfb, 0x5dfb, 0x5dfb, 0x1078, 0x12cd, 0x0078, 0x5e19, 0x2001, + 0x000b, 0x0078, 0x5e2c, 0x2001, 0x0003, 0x0078, 0x5e2c, 0x2001, + 0x0005, 0x0078, 0x5e2c, 0x2001, 0x0001, 0x0078, 0x5e2c, 0x2001, + 0x0009, 0x0078, 0x5e2c, 0x1078, 0x12cd, 0x0078, 0x5e2b, 0x1078, + 0x37c9, 0x1078, 0x4b79, 0x6003, 0x0002, 0x6017, 0x0028, 0x1078, + 0x4c72, 0x0078, 0x5e2b, 0x1078, 0x4b79, 0x6003, 0x0004, 0x6017, + 0x0028, 0x1078, 0x4c72, 0x007c, 0x1078, 0x37c9, 0x1078, 0x4b79, + 0x6003, 0x0002, 0x037e, 0x2019, 0x765c, 0x2304, 0xa084, 0xff00, + 0x00c0, 0x5e3e, 0x2019, 0x0028, 0x0078, 0x5e47, 0x8007, 0xa09a, + 0x0004, 0x0048, 0x5e3a, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, + 0x037f, 0x1078, 0x4c72, 0x0078, 0x5e2b, 0x0e7e, 0x1078, 0x6938, + 0x0040, 0x5e5a, 0x6010, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, + 0x7033, 0x0100, 0x0e7f, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74, + 0x7000, 0x2070, 0x7037, 0x0103, 0x7023, 0x8001, 0x0e7f, 0x007c, + 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, 0x00ff, 0x0d7f, 0xa0b2, + 0x000c, 0x10c8, 0x12cd, 0x6604, 0xa6b6, 0x0028, 0x00c0, 0x5e7c, + 0x1078, 0x6af8, 0x0078, 0x5eae, 0x6604, 0xa6b6, 0x0029, 0x00c0, + 0x5e85, 0x1078, 0x6b12, 0x0078, 0x5eae, 0x6604, 0xa6b6, 0x001f, + 0x00c0, 0x5e8e, 0x1078, 0x5c8b, 0x0078, 0x5eae, 0x6604, 0xa6b6, + 0x0000, 0x00c0, 0x5e97, 0x1078, 0x5cd0, 0x0078, 0x5eae, 0x6604, + 0xa6b6, 0x0022, 0x00c0, 0x5ea0, 0x1078, 0x5cb4, 0x0078, 0x5eae, + 0xa1b6, 0x0015, 0x00c0, 0x5ea8, 0x1079, 0x5eb3, 0x0078, 0x5eae, + 0xa1b6, 0x0016, 0x00c0, 0x5eaf, 0x1079, 0x5ff0, 0x007c, 0x1078, + 0x5c2f, 0x0078, 0x5eae, 0x5ed7, 0x5eda, 0x5ed7, 0x5f1b, 0x5ed7, + 0x5f8c, 0x5ed7, 0x5ed7, 0x5ed7, 0x5fc8, 0x5ed7, 0x5fde, 0xa1b6, + 0x0048, 0x0040, 0x5ecb, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, + 0x1078, 0x156a, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74, 0x7000, + 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x5bfa, 0x007c, 0x0005, + 0x0005, 0x007c, 0x0e7e, 0x2071, 0x7600, 0x7078, 0xa086, 0x0074, + 0x00c0, 0x5f04, 0x1078, 0x7344, 0x00c0, 0x5ef6, 0x0d7e, 0x6018, + 0x2068, 0x1078, 0x5f08, 0x0d7f, 0x2001, 0x0006, 0x1078, 0x37c9, + 0x1078, 0x22d7, 0x1078, 0x5bfa, 0x0078, 0x5f06, 0x2001, 0x000a, + 0x1078, 0x37c9, 0x1078, 0x22d7, 0x6003, 0x0001, 0x6007, 0x0001, + 0x1078, 0x486a, 0x0078, 0x5f06, 0x1078, 0x5f7c, 0x0e7f, 0x007c, + 0x6800, 0xd084, 0x0040, 0x5f1a, 0x2001, 0x0000, 0x1078, 0x37b5, + 0x2069, 0x7651, 0x6804, 0xd0a4, 0x0040, 0x5f1a, 0x2001, 0x0006, + 0x1078, 0x37d7, 0x007c, 0x0d7e, 0x2011, 0x761e, 0x2204, 0xa086, + 0x0074, 0x00c0, 0x5f78, 0x1078, 0x60ca, 0x6018, 0x2068, 0xa080, + 0x0028, 0x2014, 0xa286, 0x007e, 0x0040, 0x5f43, 0xa286, 0x0080, + 0x00c0, 0x5f6c, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005, + 0x0040, 0x5f62, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833, + 0x0200, 0x0078, 0x5f62, 0x0e7e, 0x0f7e, 0x6813, 0x00ff, 0x6817, + 0xfffe, 0x2071, 0x762f, 0x2e04, 0xa085, 0x0003, 0x2072, 0x2071, + 0x7b80, 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0x7619, + 0x206a, 0x78e6, 0x8e70, 0x2e04, 0x2069, 0x761a, 0x206a, 0x78ea, + 0x0f7f, 0x0e7f, 0x2001, 0x0006, 0x1078, 0x37c9, 0x1078, 0x22d7, + 0x1078, 0x5bfa, 0x0078, 0x5f7a, 0x2001, 0x0004, 0x1078, 0x37c9, + 0x6003, 0x0001, 0x6007, 0x0003, 0x1078, 0x486a, 0x0078, 0x5f7a, + 0x1078, 0x5f7c, 0x0d7f, 0x007c, 0x2001, 0x7600, 0x2004, 0xa086, + 0x0003, 0x0040, 0x5f87, 0x2001, 0x0007, 0x1078, 0x37c9, 0x1078, + 0x22d7, 0x1078, 0x5bfa, 0x007c, 0x0e7e, 0x2071, 0x7600, 0x7078, + 0xa086, 0x0014, 0x00c0, 0x5fc2, 0x7000, 0xa086, 0x0003, 0x00c0, + 0x5f9f, 0x6010, 0xa005, 0x00c0, 0x5f9f, 0x1078, 0x2db9, 0x0d7e, + 0x6018, 0x2068, 0x1078, 0x3899, 0x1078, 0x5f08, 0x0d7f, 0x1078, + 0x60d4, 0x00c0, 0x5fc2, 0x2001, 0x0006, 0x1078, 0x37c9, 0x0e7e, + 0x6010, 0xa005, 0x0040, 0x5fbb, 0x2070, 0x7007, 0x0000, 0x7037, + 0x0103, 0x7033, 0x0200, 0x0e7f, 0x1078, 0x22d7, 0x1078, 0x5bfa, + 0x0078, 0x5fc6, 0x1078, 0x5e4d, 0x1078, 0x5f7c, 0x0e7f, 0x007c, + 0x2011, 0x761e, 0x2204, 0xa086, 0x0014, 0x00c0, 0x5fdb, 0x2001, + 0x0002, 0x1078, 0x37c9, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, + 0x486a, 0x0078, 0x5fdd, 0x1078, 0x5f7c, 0x007c, 0x2011, 0x761e, + 0x2204, 0xa086, 0x0004, 0x00c0, 0x5fed, 0x2001, 0x0007, 0x1078, + 0x37c9, 0x1078, 0x5bfa, 0x0078, 0x5fef, 0x1078, 0x5f7c, 0x007c, + 0x5ed7, 0x5ffc, 0x5ed7, 0x6022, 0x5ed7, 0x607d, 0x5ed7, 0x5ed7, + 0x5ed7, 0x6092, 0x5ed7, 0x60a5, 0x0c7e, 0x1078, 0x60b8, 0x00c0, + 0x6011, 0x2001, 0x0000, 0x1078, 0x37b5, 0x2001, 0x0002, 0x1078, + 0x37c9, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x486a, 0x0078, + 0x6020, 0x2009, 0x7b8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x1900, + 0x00c0, 0x601e, 0x1078, 0x5bfa, 0x0078, 0x6020, 0x1078, 0x5f7c, + 0x0c7f, 0x007c, 0x1078, 0x60c7, 0x00c0, 0x6036, 0x2001, 0x0000, + 0x1078, 0x37b5, 0x2001, 0x0002, 0x1078, 0x37c9, 0x6003, 0x0001, + 0x6007, 0x0002, 0x1078, 0x486a, 0x0078, 0x6058, 0x1078, 0x5e4d, + 0x2009, 0x7b8e, 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x0040, + 0x6059, 0x2009, 0x7b8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x1900, + 0x00c0, 0x6056, 0xa686, 0x0009, 0x0040, 0x6059, 0x2001, 0x0004, + 0x1078, 0x37c9, 0x1078, 0x5bfa, 0x0078, 0x6058, 0x1078, 0x5f7c, + 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x6938, 0x0040, 0x6067, + 0x6838, 0xd0fc, 0x0040, 0x6067, 0x0d7f, 0x0078, 0x6056, 0x6018, + 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, 0x6078, 0x8001, + 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x0d7f, 0x0078, 0x6058, + 0x1078, 0x22b5, 0x0d7f, 0x0078, 0x6056, 0x1078, 0x60c7, 0x00c0, + 0x608d, 0x2001, 0x0004, 0x1078, 0x37c9, 0x6003, 0x0001, 0x6007, + 0x0003, 0x1078, 0x486a, 0x0078, 0x6091, 0x1078, 0x5e4d, 0x1078, + 0x5f7c, 0x007c, 0x1078, 0x60c7, 0x00c0, 0x60a2, 0x2001, 0x0008, + 0x1078, 0x37c9, 0x6003, 0x0001, 0x6007, 0x0005, 0x1078, 0x486a, + 0x0078, 0x60a4, 0x1078, 0x5f7c, 0x007c, 0x1078, 0x60c7, 0x00c0, + 0x60b5, 0x2001, 0x000a, 0x1078, 0x37c9, 0x6003, 0x0001, 0x6007, + 0x0001, 0x1078, 0x486a, 0x0078, 0x60b7, 0x1078, 0x5f7c, 0x007c, + 0x2009, 0x7b8e, 0x2104, 0xa086, 0x0003, 0x00c0, 0x60c6, 0x2009, + 0x7b8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, 0x007c, 0xa085, + 0x0001, 0x007c, 0x0c7e, 0x017e, 0xac88, 0x0006, 0x2164, 0x1078, + 0x382f, 0x017f, 0x0c7f, 0x007c, 0x0e7e, 0x2071, 0x7b8c, 0x7004, + 0xa086, 0x0014, 0x00c0, 0x60f7, 0x7008, 0xa086, 0x0800, 0x00c0, + 0x60f7, 0x700c, 0xd0ec, 0x0040, 0x60f5, 0xa084, 0x0f00, 0xa086, + 0x0100, 0x00c0, 0x60f5, 0x7024, 0xd0a4, 0x0040, 0x60f5, 0xd08c, + 0x0040, 0x60f5, 0xa006, 0x0078, 0x60f7, 0xa085, 0x0001, 0x0e7f, + 0x007c, 0x0e7e, 0x0d7e, 0x0c7e, 0x077e, 0x057e, 0x047e, 0x027e, + 0x007e, 0x127e, 0x2091, 0x8000, 0x2029, 0x783f, 0x252c, 0x2021, + 0x7845, 0x2424, 0x2061, 0x7d00, 0x2071, 0x7600, 0x7244, 0x7060, + 0xa202, 0x00c8, 0x614e, 0x1078, 0x754e, 0x0040, 0x6146, 0x671c, + 0xa786, 0x0001, 0x0040, 0x6146, 0xa786, 0x0007, 0x0040, 0x6146, + 0x2500, 0xac06, 0x0040, 0x6146, 0x2400, 0xac06, 0x0040, 0x6146, + 0x0c7e, 0x6000, 0xa086, 0x0004, 0x00c0, 0x6130, 0x1078, 0x166e, + 0x6010, 0x2068, 0x1078, 0x6938, 0x0040, 0x6143, 0xa786, 0x0003, + 0x00c0, 0x6158, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, + 0x3a72, 0x1078, 0x6a89, 0x1078, 0x6a96, 0x0c7f, 0xace0, 0x0008, + 0x7054, 0xac02, 0x00c8, 0x614e, 0x0078, 0x610e, 0x127f, 0x007f, + 0x027f, 0x047f, 0x057f, 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, + 0xa786, 0x0006, 0x00c0, 0x613a, 0x1078, 0x74f2, 0x0078, 0x6143, + 0x220c, 0x2304, 0xa106, 0x00c0, 0x616b, 0x8210, 0x8318, 0x00f0, + 0x6160, 0xa006, 0x007c, 0x2304, 0xa102, 0x0048, 0x6173, 0x2001, + 0x0001, 0x0078, 0x6175, 0x2001, 0x0000, 0xa18d, 0x0001, 0x007c, + 0x6004, 0xa08a, 0x0030, 0x10c8, 0x12cd, 0x1078, 0x6aaf, 0x0040, + 0x6187, 0x1078, 0x6ac3, 0x0040, 0x6190, 0x0078, 0x6189, 0x1078, + 0x22d7, 0x1078, 0x4b79, 0x1078, 0x5bfa, 0x1078, 0x4c72, 0x007c, + 0x1078, 0x5e4d, 0x0078, 0x6189, 0xa182, 0x0040, 0x0079, 0x6198, + 0x61a8, 0x61a8, 0x61a8, 0x61a8, 0x61a8, 0x61a8, 0x61a8, 0x61a8, + 0x61a8, 0x61a8, 0x61a8, 0x61aa, 0x61aa, 0x61aa, 0x61aa, 0x61a8, + 0x1078, 0x12cd, 0x6003, 0x0001, 0x6106, 0x1078, 0x481d, 0x127e, + 0x2091, 0x8000, 0x1078, 0x4c72, 0x127f, 0x007c, 0xa186, 0x0013, + 0x00c0, 0x61bf, 0x6004, 0xa082, 0x0040, 0x0079, 0x6235, 0xa186, + 0x0027, 0x00c0, 0x61dc, 0x1078, 0x4b79, 0x1078, 0x22b5, 0x0d7e, + 0x6110, 0x2168, 0x1078, 0x6938, 0x0040, 0x61d6, 0x6837, 0x0103, + 0x684b, 0x0029, 0x1078, 0x3a72, 0x1078, 0x6a89, 0x0d7f, 0x1078, + 0x5bfa, 0x1078, 0x4c72, 0x007c, 0xa186, 0x0014, 0x00c0, 0x61e5, + 0x6004, 0xa082, 0x0040, 0x0079, 0x6205, 0xa186, 0x0047, 0x10c0, + 0x12cd, 0x2001, 0x0109, 0x2004, 0xd084, 0x0040, 0x6202, 0x127e, + 0x2091, 0x2200, 0x007e, 0x017e, 0x027e, 0x1078, 0x46de, 0x027f, + 0x017f, 0x007f, 0x127f, 0x6000, 0xa086, 0x0002, 0x00c0, 0x6202, + 0x0078, 0x625c, 0x1078, 0x5c2f, 0x007c, 0x6217, 0x6215, 0x6215, + 0x6215, 0x6215, 0x6215, 0x6215, 0x6215, 0x6215, 0x6215, 0x6215, + 0x622e, 0x622e, 0x622e, 0x622e, 0x6215, 0x1078, 0x12cd, 0x1078, + 0x4b79, 0x0d7e, 0x6110, 0x2168, 0x1078, 0x6938, 0x0040, 0x6228, + 0x6837, 0x0103, 0x684b, 0x0006, 0x1078, 0x3a72, 0x1078, 0x6a89, + 0x0d7f, 0x1078, 0x5bfa, 0x1078, 0x4c72, 0x007c, 0x1078, 0x4b79, + 0x1078, 0x5bfa, 0x1078, 0x4c72, 0x007c, 0x6247, 0x6245, 0x6245, + 0x6245, 0x6245, 0x6245, 0x6245, 0x6245, 0x6245, 0x6245, 0x6245, + 0x6255, 0x6255, 0x6255, 0x6255, 0x6245, 0x1078, 0x12cd, 0x1078, + 0x4b79, 0x6003, 0x0002, 0x1078, 0x4c72, 0x6010, 0xa088, 0x0013, + 0x2104, 0xa085, 0x0400, 0x200a, 0x007c, 0x1078, 0x4b79, 0x6003, + 0x000f, 0x1078, 0x4c72, 0x007c, 0xa182, 0x0040, 0x0079, 0x6260, + 0x6270, 0x6270, 0x6270, 0x6270, 0x6270, 0x6272, 0x62fb, 0x6313, + 0x6270, 0x6270, 0x6270, 0x6270, 0x6270, 0x6270, 0x6270, 0x6270, + 0x1078, 0x12cd, 0x0e7e, 0x0d7e, 0x2071, 0x7b8c, 0x6110, 0x2168, + 0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0040, 0x62df, 0xa68c, 0x00ff, + 0xa186, 0x0002, 0x0040, 0x62a4, 0xa186, 0x0028, 0x00c0, 0x628e, + 0x1078, 0x6a9d, 0x684b, 0x001c, 0x0078, 0x62a6, 0xd6dc, 0x0040, + 0x6299, 0x684b, 0x0015, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, + 0x62a6, 0xd6d4, 0x0040, 0x62a4, 0x684b, 0x0007, 0x7318, 0x6b62, + 0x731c, 0x6b5e, 0x0078, 0x62a6, 0x684b, 0x0000, 0x6837, 0x0103, + 0x6e46, 0xa01e, 0xd6c4, 0x0040, 0x62b9, 0x7328, 0x732c, 0x6b56, + 0x037e, 0x2308, 0x2019, 0x7b98, 0xad90, 0x0019, 0x1078, 0x6721, + 0x037f, 0xd6cc, 0x0040, 0x62ef, 0x7124, 0x695a, 0xa192, 0x0021, + 0x00c8, 0x62cd, 0x2071, 0x7b98, 0x831c, 0x2300, 0xae18, 0xad90, + 0x001d, 0x1078, 0x6721, 0x0078, 0x62ef, 0x6838, 0xd0fc, 0x0040, + 0x62d6, 0x2009, 0x0020, 0x695a, 0x0078, 0x62c2, 0x0f7e, 0x2d78, + 0x1078, 0x66b9, 0x0f7f, 0x1078, 0x670e, 0x0078, 0x62f1, 0x684b, + 0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0040, 0x62ef, + 0x6810, 0x6914, 0xa115, 0x0040, 0x62ef, 0x1078, 0x6467, 0x1078, + 0x3a72, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x0d7f, 0x0e7f, + 0x1078, 0x5bfa, 0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, 0x7b8c, + 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, + 0x7e0a, 0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x19c7, 0x1078, 0x4889, + 0x1078, 0x4d32, 0x007c, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, + 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x156a, 0x007c, 0xa182, 0x0040, + 0x0079, 0x6322, 0x6332, 0x6332, 0x6332, 0x6332, 0x6332, 0x6334, + 0x63cb, 0x6332, 0x6332, 0x63e1, 0x6443, 0x6332, 0x6332, 0x6332, + 0x6332, 0x644e, 0x1078, 0x12cd, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, + 0x2071, 0x7b8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46, + 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, + 0x86ff, 0x0040, 0x63c6, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0040, + 0x6355, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0040, + 0x63c6, 0x1078, 0x1327, 0x1040, 0x12cd, 0x2d00, 0x784a, 0x7f4c, + 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, 0x683e, + 0x7840, 0x6842, 0x6e46, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040, + 0x638f, 0xa186, 0x0028, 0x00c0, 0x6379, 0x684b, 0x001c, 0x0078, + 0x6391, 0xd6dc, 0x0040, 0x6384, 0x684b, 0x0015, 0x7318, 0x6b62, + 0x731c, 0x6b5e, 0x0078, 0x6391, 0xd6d4, 0x0040, 0x638f, 0x684b, + 0x0007, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x6391, 0x684b, + 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4, + 0x0040, 0x63a6, 0x7328, 0x732c, 0x6b56, 0x037e, 0x2308, 0x2019, + 0x7b98, 0xad90, 0x0019, 0x1078, 0x6721, 0x037f, 0xd6cc, 0x0040, + 0x63c6, 0x7124, 0x695a, 0xa192, 0x0021, 0x00c8, 0x63ba, 0x2071, + 0x7b98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x6721, + 0x0078, 0x63c6, 0x7838, 0xd0fc, 0x0040, 0x63c3, 0x2009, 0x0020, + 0x695a, 0x0078, 0x63af, 0x2d78, 0x1078, 0x66b9, 0x0d7f, 0x0e7f, + 0x0f7f, 0x077f, 0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, 0x7b8c, + 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, + 0x7e0a, 0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x19c7, 0x1078, 0x555f, + 0x007c, 0x0d7e, 0x6003, 0x0002, 0x1078, 0x4c21, 0x1078, 0x4d32, + 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, 0x6441, 0xd1cc, 0x0040, + 0x641c, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x6414, 0x017e, 0x684c, + 0x007e, 0x6850, 0x007e, 0xad90, 0x000d, 0xa198, 0x000d, 0x2009, + 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x00f0, + 0x6403, 0x157f, 0x007f, 0x6852, 0x007f, 0x684e, 0x017f, 0x2168, + 0x1078, 0x1350, 0x0078, 0x643f, 0x017e, 0x1078, 0x1350, 0x0d7f, + 0x1078, 0x670e, 0x0078, 0x643f, 0x6837, 0x0103, 0x6944, 0xa184, + 0x00ff, 0xa186, 0x0002, 0x0040, 0x643b, 0xa086, 0x0028, 0x00c0, + 0x642d, 0x684b, 0x001c, 0x0078, 0x643d, 0xd1dc, 0x0040, 0x6434, + 0x684b, 0x0015, 0x0078, 0x643d, 0xd1d4, 0x0040, 0x643b, 0x684b, + 0x0007, 0x0078, 0x643d, 0x684b, 0x0000, 0x1078, 0x3a72, 0x1078, + 0x5bfa, 0x0d7f, 0x007c, 0x2019, 0x0001, 0x1078, 0x5760, 0x6003, + 0x0002, 0x1078, 0x4c21, 0x1078, 0x4d32, 0x007c, 0x1078, 0x4c21, + 0x1078, 0x22b5, 0x0d7e, 0x6110, 0x2168, 0x1078, 0x6938, 0x0040, + 0x6461, 0x6837, 0x0103, 0x684b, 0x0029, 0x1078, 0x3a72, 0x1078, + 0x6a89, 0x0d7f, 0x1078, 0x5bfa, 0x1078, 0x4d32, 0x007c, 0x684b, + 0x0015, 0xd1fc, 0x0040, 0x6473, 0x684b, 0x0007, 0x8002, 0x8000, + 0x810a, 0xa189, 0x0000, 0x6962, 0x685e, 0x007c, 0xa182, 0x0040, + 0x0079, 0x647a, 0x648a, 0x648a, 0x648a, 0x648a, 0x648a, 0x648c, + 0x648a, 0x6530, 0x6538, 0x648a, 0x648a, 0x648a, 0x648a, 0x648a, + 0x648a, 0x648a, 0x1078, 0x12cd, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, + 0x2071, 0x7b8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46, + 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, + 0x86ff, 0x0040, 0x6522, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0040, + 0x64ad, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0040, + 0x651f, 0x1078, 0x1327, 0x1040, 0x12cd, 0x2d00, 0x784a, 0x7f4c, + 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, + 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x00ff, 0xa186, 0x0002, + 0x0040, 0x64e8, 0xa186, 0x0028, 0x00c0, 0x64d2, 0x684b, 0x001c, + 0x0078, 0x64ea, 0xd6dc, 0x0040, 0x64dd, 0x684b, 0x0015, 0x7318, + 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x64ea, 0xd6d4, 0x0040, 0x64e8, + 0x684b, 0x0007, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x64ea, + 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, + 0xd6c4, 0x0040, 0x64ff, 0x7328, 0x732c, 0x6b56, 0x037e, 0x2308, + 0x2019, 0x7b98, 0xad90, 0x0019, 0x1078, 0x6721, 0x037f, 0xd6cc, + 0x0040, 0x651f, 0x7124, 0x695a, 0xa192, 0x0021, 0x00c8, 0x6513, + 0x2071, 0x7b98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, + 0x6721, 0x0078, 0x651f, 0x7838, 0xd0fc, 0x0040, 0x651c, 0x2009, + 0x0020, 0x695a, 0x0078, 0x6508, 0x2d78, 0x1078, 0x66b9, 0xd6dc, + 0x00c0, 0x6525, 0xa006, 0x0078, 0x6529, 0x2001, 0x0001, 0x7218, + 0x731c, 0x1078, 0x15ae, 0x0d7f, 0x0e7f, 0x0f7f, 0x077f, 0x007c, + 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x156a, 0x007c, + 0x0d7e, 0x6003, 0x0002, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, + 0x659f, 0xd1cc, 0x0040, 0x656f, 0x6948, 0x6838, 0xd0fc, 0x0040, + 0x6567, 0x017e, 0x684c, 0x007e, 0x6850, 0x007e, 0xad90, 0x000d, + 0xa198, 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, + 0x8318, 0x8210, 0x00f0, 0x6556, 0x157f, 0x007f, 0x6852, 0x007f, + 0x684e, 0x017f, 0x2168, 0x1078, 0x1350, 0x0078, 0x659d, 0x017e, + 0x1078, 0x1350, 0x0d7f, 0x1078, 0x670e, 0x0078, 0x659d, 0x6837, + 0x0103, 0x6944, 0xa184, 0x00ff, 0xa186, 0x0002, 0x0040, 0x658e, + 0xa086, 0x0028, 0x00c0, 0x6580, 0x684b, 0x001c, 0x0078, 0x659b, + 0xd1dc, 0x0040, 0x6587, 0x684b, 0x0015, 0x0078, 0x659b, 0xd1d4, + 0x0040, 0x658e, 0x684b, 0x0007, 0x0078, 0x659b, 0x684b, 0x0000, + 0x684c, 0xd0ac, 0x0040, 0x659b, 0x6810, 0x6914, 0xa115, 0x0040, + 0x659b, 0x1078, 0x6467, 0x1078, 0x3a72, 0x1078, 0x5bfa, 0x0d7f, + 0x007c, 0x1078, 0x4b79, 0x0078, 0x65a7, 0x1078, 0x4c21, 0x1078, + 0x6938, 0x0040, 0x65be, 0x0d7e, 0x6110, 0x2168, 0x6837, 0x0103, + 0x2009, 0x760c, 0x210c, 0xd18c, 0x00c0, 0x65c7, 0xd184, 0x00c0, + 0x65c3, 0x6108, 0x694a, 0x1078, 0x3a72, 0x0d7f, 0x1078, 0x5bfa, + 0x1078, 0x4c72, 0x007c, 0x684b, 0x0004, 0x0078, 0x65bb, 0x684b, + 0x0004, 0x0078, 0x65bb, 0xa182, 0x0040, 0x0079, 0x65cf, 0x65df, + 0x65df, 0x65df, 0x65df, 0x65df, 0x65e1, 0x65df, 0x65e4, 0x65df, + 0x65df, 0x65df, 0x65df, 0x65df, 0x65df, 0x65df, 0x65df, 0x1078, + 0x12cd, 0x1078, 0x5bfa, 0x007c, 0x007e, 0x027e, 0xa016, 0x1078, + 0x156a, 0x027f, 0x007f, 0x007c, 0xa182, 0x0085, 0x0079, 0x65f0, + 0x65f9, 0x65f7, 0x65f7, 0x65f7, 0x65f7, 0x65f7, 0x65f7, 0x1078, + 0x12cd, 0x6003, 0x0001, 0x6106, 0x1078, 0x481d, 0x127e, 0x2091, + 0x8000, 0x1078, 0x4c72, 0x127f, 0x007c, 0xa186, 0x0013, 0x00c0, + 0x660f, 0x6004, 0xa082, 0x0085, 0x2008, 0x0079, 0x6643, 0xa186, + 0x0027, 0x00c0, 0x6630, 0x1078, 0x4b79, 0x1078, 0x22b5, 0x0d7e, + 0x6010, 0x2068, 0x1078, 0x6938, 0x0040, 0x6626, 0x6837, 0x0103, + 0x684b, 0x0029, 0x1078, 0x3a72, 0x1078, 0x6a89, 0x0d7f, 0x1078, + 0x5bfa, 0x1078, 0x4c72, 0x007c, 0x1078, 0x5c2f, 0x0078, 0x662b, + 0xa186, 0x0014, 0x00c0, 0x662c, 0x1078, 0x4b79, 0x0d7e, 0x6010, + 0x2068, 0x1078, 0x6938, 0x0040, 0x6626, 0x6837, 0x0103, 0x684b, + 0x0006, 0x0078, 0x6622, 0x664c, 0x664a, 0x664a, 0x664a, 0x664a, + 0x664a, 0x6655, 0x1078, 0x12cd, 0x1078, 0x4b79, 0x6017, 0x0014, + 0x6003, 0x000c, 0x1078, 0x4c72, 0x007c, 0x1078, 0x4b79, 0x6017, + 0x0014, 0x6003, 0x000e, 0x1078, 0x4c72, 0x007c, 0xa182, 0x008c, + 0x00c8, 0x6668, 0xa182, 0x0085, 0x0048, 0x6668, 0x0079, 0x666b, + 0x1078, 0x5c2f, 0x007c, 0x6672, 0x6672, 0x6672, 0x6672, 0x6674, + 0x6693, 0x6672, 0x1078, 0x12cd, 0x0d7e, 0x1078, 0x6a89, 0x1078, + 0x6938, 0x0040, 0x668f, 0x6010, 0x2068, 0x6837, 0x0103, 0x6850, + 0xd0b4, 0x0040, 0x6687, 0x684b, 0x0006, 0x0078, 0x668b, 0x684b, + 0x0005, 0x1078, 0x6b3c, 0x6847, 0x0000, 0x1078, 0x3a72, 0x1078, + 0x5bfa, 0x0d7f, 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x6938, + 0x0040, 0x66ae, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, 0x66a4, + 0x684b, 0x0006, 0x0078, 0x66a8, 0x684b, 0x0005, 0x1078, 0x6b3c, + 0x6847, 0x0000, 0x1078, 0x3a72, 0x1078, 0x6a89, 0x0d7f, 0x1078, + 0x5bfa, 0x007c, 0x1078, 0x4b79, 0x1078, 0x5bfa, 0x1078, 0x4c72, + 0x007c, 0x057e, 0x067e, 0x0d7e, 0x0f7e, 0x2029, 0x0001, 0xa182, + 0x0101, 0x00c8, 0x66c5, 0x0078, 0x66c7, 0x2009, 0x0100, 0x2130, + 0x2069, 0x7b98, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90, + 0x001d, 0x1078, 0x6721, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0040, + 0x66db, 0x1078, 0x1350, 0x1078, 0x1327, 0x0040, 0x6705, 0x8528, + 0x6837, 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d, + 0x00c8, 0x66f1, 0x2608, 0xad90, 0x000f, 0x1078, 0x6721, 0x0078, + 0x6705, 0xa6b2, 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, 0x000f, + 0x1078, 0x6721, 0x0078, 0x66db, 0x0f7f, 0x852f, 0xa5ad, 0x0003, + 0x7d36, 0xa5ac, 0x0000, 0x0078, 0x670a, 0x0f7f, 0x852f, 0xa5ad, + 0x0003, 0x7d36, 0x0d7f, 0x067f, 0x057f, 0x007c, 0x0f7e, 0x8dff, + 0x0040, 0x671f, 0x6804, 0xa07d, 0x0040, 0x671d, 0x6807, 0x0000, + 0x1078, 0x3a72, 0x2f68, 0x0078, 0x6712, 0x1078, 0x3a72, 0x0f7f, + 0x007c, 0x157e, 0xa184, 0x0001, 0x0040, 0x6727, 0x8108, 0x810c, + 0x21a8, 0x2304, 0x8007, 0x2012, 0x8318, 0x8210, 0x00f0, 0x6729, + 0x157f, 0x007c, 0x127e, 0x2091, 0x8000, 0x601c, 0xa084, 0x000f, + 0x1079, 0x673c, 0x127f, 0x007c, 0x674b, 0x6744, 0x6746, 0x6764, + 0x6744, 0x6746, 0x6746, 0x6746, 0x1078, 0x12cd, 0xa006, 0x007c, + 0xa085, 0x0001, 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x6938, + 0x0040, 0x6761, 0xa00e, 0x2001, 0x0005, 0x1078, 0x3b02, 0x1078, + 0x6b3c, 0x1078, 0x3a72, 0x1078, 0x5bfa, 0xa085, 0x0001, 0x0d7f, + 0x007c, 0xa006, 0x0078, 0x675f, 0x6000, 0xa08a, 0x0010, 0x10c8, + 0x12cd, 0x1079, 0x676c, 0x007c, 0x677c, 0x6799, 0x677e, 0x67aa, + 0x6795, 0x677c, 0x6746, 0x674b, 0x674b, 0x6746, 0x6746, 0x6746, + 0x6746, 0x6746, 0x6746, 0x6746, 0x1078, 0x12cd, 0x0d7e, 0x6010, + 0x2068, 0x1078, 0x6938, 0x0040, 0x6787, 0x1078, 0x6b3c, 0x0d7f, + 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x1078, 0x481d, + 0x1078, 0x4c72, 0xa085, 0x0001, 0x007c, 0x1078, 0x166e, 0x0078, + 0x677e, 0x0e7e, 0x2071, 0x7836, 0x7024, 0xac06, 0x00c0, 0x67a2, + 0x1078, 0x56ce, 0x1078, 0x5603, 0x0e7f, 0x00c0, 0x677e, 0x1078, + 0x6746, 0x007c, 0x037e, 0x0e7e, 0x2071, 0x7836, 0x703c, 0xac06, + 0x00c0, 0x67ba, 0x2019, 0x0000, 0x1078, 0x5760, 0x0e7f, 0x037f, + 0x0078, 0x677e, 0x1078, 0x5a3c, 0x0e7f, 0x037f, 0x00c0, 0x677e, + 0x1078, 0x6746, 0x007c, 0x0c7e, 0x601c, 0xa084, 0x000f, 0x1079, + 0x67cb, 0x0c7f, 0x007c, 0x67da, 0x6837, 0x68dc, 0x67de, 0x67da, + 0x67da, 0x71d2, 0x5bfa, 0x6837, 0x1078, 0x6ac3, 0x00c0, 0x67da, + 0x1078, 0x5e4d, 0x007c, 0x6017, 0x0001, 0x007c, 0x6000, 0xa08a, + 0x0010, 0x10c8, 0x12cd, 0x1079, 0x67e6, 0x007c, 0x67f6, 0x67f8, + 0x6818, 0x682a, 0x682a, 0x67f6, 0x67da, 0x67da, 0x67da, 0x682a, + 0x682a, 0x67f6, 0x67f6, 0x67f6, 0x67f6, 0x6834, 0x1078, 0x12cd, + 0x0e7e, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071, 0x7836, + 0x7024, 0xac06, 0x0040, 0x6814, 0x1078, 0x5603, 0x6007, 0x0085, + 0x6003, 0x000b, 0x601f, 0x0002, 0x6017, 0x0014, 0x1078, 0x481d, + 0x1078, 0x4c72, 0x0e7f, 0x007c, 0x6017, 0x0001, 0x0078, 0x6812, + 0x0d7e, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x0d7f, 0x6007, + 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x1078, 0x481d, 0x1078, + 0x4c72, 0x007c, 0x0d7e, 0x6017, 0x0001, 0x6010, 0x2068, 0x6850, + 0xc0b5, 0x6852, 0x0d7f, 0x007c, 0x1078, 0x5bfa, 0x007c, 0x6000, + 0xa08a, 0x0010, 0x10c8, 0x12cd, 0x1079, 0x683f, 0x007c, 0x684f, + 0x67db, 0x6851, 0x684f, 0x6851, 0x684f, 0x684f, 0x684f, 0x67d4, + 0x67d4, 0x684f, 0x684f, 0x684f, 0x684f, 0x684f, 0x684f, 0x1078, + 0x12cd, 0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f, + 0xa08a, 0x000c, 0x10c8, 0x12cd, 0x1079, 0x685f, 0x007c, 0x686b, + 0x688a, 0x686b, 0x688a, 0x686b, 0x688a, 0x686d, 0x6876, 0x686b, + 0x688a, 0x686b, 0x6883, 0x1078, 0x12cd, 0x6004, 0xa08e, 0x0004, + 0x0040, 0x6885, 0xa08e, 0x0002, 0x0040, 0x6885, 0x6004, 0x1078, + 0x6ac3, 0x0040, 0x68d4, 0xa08e, 0x0021, 0x0040, 0x68d8, 0xa08e, + 0x0022, 0x0040, 0x68d4, 0x1078, 0x22b5, 0x1078, 0x5e4d, 0x1078, + 0x5bfa, 0x007c, 0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016, 0x0040, + 0x68c4, 0xa186, 0x0002, 0x00c0, 0x68b3, 0x6018, 0x2068, 0x68a0, + 0xd0bc, 0x00c0, 0x68b3, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, + 0x68b3, 0x8001, 0x6842, 0x6013, 0x0000, 0x601f, 0x0007, 0x6017, + 0x0398, 0x1078, 0x5b94, 0x0040, 0x68b3, 0x2d00, 0x601a, 0x601f, + 0x0001, 0x0078, 0x68c4, 0x0d7f, 0x0c7f, 0x1078, 0x5e4d, 0x1078, + 0x22b5, 0x0e7e, 0x127e, 0x2091, 0x8000, 0x1078, 0x22d7, 0x127f, + 0x0e7f, 0x1078, 0x5bfa, 0x007c, 0x2001, 0x0002, 0x1078, 0x37c9, + 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x486a, 0x1078, 0x4c72, + 0x0d7f, 0x0c7f, 0x0078, 0x68c3, 0x1078, 0x5e4d, 0x0078, 0x6887, + 0x1078, 0x5e5c, 0x0078, 0x6887, 0x6000, 0xa08a, 0x0010, 0x10c8, + 0x12cd, 0x1079, 0x68e4, 0x007c, 0x68f4, 0x68f4, 0x68f4, 0x68f4, + 0x68f4, 0x68f4, 0x68f4, 0x68f4, 0x68f4, 0x67da, 0x68f4, 0x67db, + 0x68f6, 0x67db, 0x68ff, 0x68f4, 0x1078, 0x12cd, 0x6007, 0x008b, + 0x6003, 0x000d, 0x1078, 0x481d, 0x1078, 0x4c72, 0x007c, 0x1078, + 0x6a89, 0x1078, 0x6938, 0x0040, 0x6921, 0x1078, 0x22b5, 0x0d7e, + 0x1078, 0x6938, 0x0040, 0x6914, 0x6010, 0x2068, 0x6837, 0x0103, + 0x684b, 0x0006, 0x1078, 0x3a72, 0x0d7f, 0x601f, 0x0001, 0x6007, + 0x0001, 0x6003, 0x0001, 0x1078, 0x486a, 0x1078, 0x4c72, 0x0078, + 0x6923, 0x1078, 0x5bfa, 0x007c, 0xa284, 0x0007, 0x00c0, 0x6935, + 0xa282, 0x7d00, 0x0048, 0x6935, 0x2001, 0x7615, 0x2004, 0xa202, + 0x00c8, 0x6935, 0xa085, 0x0001, 0x007c, 0xa006, 0x0078, 0x6934, + 0x027e, 0x0e7e, 0x2071, 0x7600, 0x6210, 0x7058, 0xa202, 0x0048, + 0x694a, 0x705c, 0xa202, 0x00c8, 0x694a, 0xa085, 0x0001, 0x0e7f, + 0x027f, 0x007c, 0xa006, 0x0078, 0x6947, 0x0e7e, 0x0c7e, 0x037e, + 0x007e, 0x127e, 0x2091, 0x8000, 0x2061, 0x7d00, 0x2071, 0x7600, + 0x7344, 0x7060, 0xa302, 0x00c8, 0x6973, 0x601c, 0xa206, 0x00c0, + 0x696b, 0x1078, 0x6ac3, 0x00c0, 0x6967, 0x1078, 0x5e4d, 0x0c7e, + 0x1078, 0x5bfa, 0x0c7f, 0xace0, 0x0008, 0x7054, 0xac02, 0x00c8, + 0x6973, 0x0078, 0x6958, 0x127f, 0x007f, 0x037f, 0x0c7f, 0x0e7f, + 0x007c, 0x0e7e, 0x0c7e, 0x017e, 0xa188, 0x7720, 0x210c, 0x81ff, + 0x0040, 0x6991, 0x2061, 0x7d00, 0x2071, 0x7600, 0x017e, 0x1078, + 0x5b94, 0x017f, 0x0040, 0x6994, 0x611a, 0x1078, 0x22b5, 0x1078, + 0x5bfa, 0xa006, 0x0078, 0x6996, 0xa085, 0x0001, 0x017f, 0x0c7f, + 0x0e7f, 0x007c, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x0c7e, + 0x1078, 0x5b94, 0x057f, 0x0040, 0x69b3, 0x6612, 0x651a, 0x601f, + 0x0003, 0x2009, 0x004b, 0x1078, 0x5c21, 0xa085, 0x0001, 0x127f, + 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x69af, 0x0c7e, 0x057e, + 0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, 0x5b94, 0x057f, + 0x0040, 0x69dd, 0x6013, 0x0000, 0x651a, 0x601f, 0x0003, 0x0c7e, + 0x2560, 0x1078, 0x399e, 0x0c7f, 0x1078, 0x495a, 0x1078, 0x489d, + 0x2c08, 0x1078, 0x7370, 0x2009, 0x004c, 0x1078, 0x5c21, 0xa085, + 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x69d9, + 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, + 0x5b94, 0x057f, 0x0040, 0x6a08, 0x6612, 0x651a, 0x601f, 0x0003, + 0x2019, 0x0005, 0x0c7e, 0x2560, 0x1078, 0x399e, 0x0c7f, 0x1078, + 0x495a, 0x1078, 0x489d, 0x2c08, 0x1078, 0x7370, 0x2009, 0x004d, + 0x1078, 0x5c21, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c, + 0xa006, 0x0078, 0x6a04, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, + 0x62a0, 0x0c7e, 0x1078, 0x5b94, 0x057f, 0x0040, 0x6a33, 0x6612, 0x651a, 0x601f, 0x0003, 0x2019, 0x0005, 0x0c7e, 0x2560, 0x1078, - 0x39a6, 0x0c7f, 0x1078, 0x4962, 0x1078, 0x48a5, 0x2c08, 0x1078, - 0x737b, 0x2009, 0x004d, 0x1078, 0x5c29, 0xa085, 0x0001, 0x127f, - 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6a0f, 0x0c7e, 0x057e, - 0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, 0x5b9c, 0x057f, - 0x0040, 0x6a3e, 0x6612, 0x651a, 0x601f, 0x0003, 0x2019, 0x0005, - 0x0c7e, 0x2560, 0x1078, 0x39a6, 0x0c7f, 0x1078, 0x4962, 0x1078, - 0x48a5, 0x2c08, 0x1078, 0x737b, 0x2009, 0x004e, 0x1078, 0x5c29, - 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, - 0x6a3a, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x5b9c, - 0x017f, 0x0040, 0x6a5a, 0x660a, 0x611a, 0x601f, 0x0001, 0x2d00, - 0x6012, 0x2009, 0x001f, 0x1078, 0x5c29, 0xa085, 0x0001, 0x127f, - 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6a57, 0x0c7e, 0x127e, 0x2091, - 0x8000, 0x0c7e, 0x1078, 0x5b9c, 0x017f, 0x0040, 0x6a76, 0x660a, - 0x611a, 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, 0x0021, 0x1078, - 0x5c29, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, - 0x6a73, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x5b9c, - 0x017f, 0x0040, 0x6a91, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, - 0x2009, 0x0000, 0x1078, 0x5c29, 0xa085, 0x0001, 0x127f, 0x0c7f, - 0x007c, 0xa006, 0x0078, 0x6a8e, 0x027e, 0x0d7e, 0x6218, 0x2268, - 0x6a3c, 0x82ff, 0x0040, 0x6a9e, 0x8211, 0x6a3e, 0x0d7f, 0x027f, - 0x007c, 0x6013, 0x0000, 0x601f, 0x0007, 0x6017, 0x0014, 0x007c, - 0x067e, 0x0c7e, 0x0d7e, 0x2031, 0x7652, 0x2634, 0xd6e4, 0x0040, - 0x6ab6, 0x6618, 0x2660, 0x6e44, 0x1078, 0x38de, 0x0d7f, 0x0c7f, - 0x067f, 0x007c, 0x007e, 0x017e, 0x6004, 0xa08e, 0x0002, 0x0040, - 0x6acb, 0xa08e, 0x0003, 0x0040, 0x6acb, 0xa08e, 0x0004, 0x0040, - 0x6acb, 0xa085, 0x0001, 0x017f, 0x007f, 0x007c, 0x007e, 0x017e, - 0x6004, 0xa08e, 0x0000, 0x0040, 0x6ae3, 0xa08e, 0x001f, 0x0040, - 0x6ae3, 0xa08e, 0x0028, 0x0040, 0x6ae3, 0xa08e, 0x0029, 0x0040, - 0x6ae3, 0xa085, 0x0001, 0x017f, 0x007f, 0x007c, 0x0c7e, 0x127e, - 0x2091, 0x8000, 0x0c7e, 0x1078, 0x5b9c, 0x017f, 0x0040, 0x6b00, - 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x1078, 0x22bb, 0x2009, - 0x0028, 0x1078, 0x5c29, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, - 0xa006, 0x0078, 0x6afd, 0xa186, 0x0015, 0x00c0, 0x6b18, 0x2011, - 0x761e, 0x2204, 0xa086, 0x0074, 0x00c0, 0x6b18, 0x1078, 0x60d4, - 0x6003, 0x0001, 0x6007, 0x0029, 0x1078, 0x4872, 0x0078, 0x6b1c, - 0x1078, 0x5e57, 0x1078, 0x5c02, 0x007c, 0xa186, 0x0015, 0x00c0, - 0x6b3a, 0x2011, 0x761e, 0x2204, 0xa086, 0x0014, 0x00c0, 0x6b3a, - 0x0d7e, 0x6018, 0x2068, 0x1078, 0x38a1, 0x0d7f, 0x1078, 0x60de, - 0x00c0, 0x6b3a, 0x2001, 0x0006, 0x1078, 0x37d1, 0x1078, 0x5cad, - 0x0078, 0x6b3e, 0x1078, 0x5e57, 0x1078, 0x5c02, 0x007c, 0x6848, - 0xa086, 0x0005, 0x00c0, 0x6b46, 0x1078, 0x6b47, 0x007c, 0x6850, - 0xc0ad, 0x6852, 0x007c, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, - 0x12d5, 0x1079, 0x6b55, 0x067f, 0x007c, 0x6b65, 0x6d3c, 0x6e1d, - 0x6b65, 0x6b65, 0x6b65, 0x6b65, 0x6b65, 0x6b9f, 0x6e8b, 0x6b65, - 0x6b65, 0x6b65, 0x6b65, 0x6b65, 0x6b65, 0x1078, 0x12d5, 0x067e, - 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12d5, 0x1079, 0x6b71, 0x067f, - 0x007c, 0x6b81, 0x718c, 0x6b81, 0x6b81, 0x6b81, 0x6b81, 0x6b81, - 0x6b81, 0x7167, 0x71d6, 0x6b81, 0x6b81, 0x6b81, 0x6b81, 0x6b81, - 0x6b81, 0x1078, 0x12d5, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, - 0x12d5, 0x1079, 0x6b8d, 0x067f, 0x007c, 0x6b9d, 0x6fd8, 0x704a, - 0x706c, 0x70b8, 0x6b9d, 0x6b9d, 0x7112, 0x6e97, 0x714f, 0x7153, - 0x6b9d, 0x6b9d, 0x6b9d, 0x6b9d, 0x6b9d, 0x1078, 0x12d5, 0xa1b2, - 0x0030, 0x10c8, 0x12d5, 0x2100, 0x0079, 0x6ba6, 0x6bd6, 0x6cb3, - 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, - 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, - 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd8, 0x6c07, 0x6c12, - 0x6c3a, 0x6c40, 0x6c74, 0x6cac, 0x6bd6, 0x6bd6, 0x6cbb, 0x6bd6, - 0x6bd6, 0x6cc2, 0x6cc9, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, - 0x6ce6, 0x6bd6, 0x6bd6, 0x6cf1, 0x6bd6, 0x6bd6, 0x1078, 0x12d5, - 0x1078, 0x3a26, 0x6618, 0x0c7e, 0x2660, 0x1078, 0x3837, 0x0c7f, + 0x399e, 0x0c7f, 0x1078, 0x495a, 0x1078, 0x489d, 0x2c08, 0x1078, + 0x7370, 0x2009, 0x004e, 0x1078, 0x5c21, 0xa085, 0x0001, 0x127f, + 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6a2f, 0x0c7e, 0x127e, + 0x2091, 0x8000, 0x0c7e, 0x1078, 0x5b94, 0x017f, 0x0040, 0x6a4f, + 0x660a, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x001f, + 0x1078, 0x5c21, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, + 0x0078, 0x6a4c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, + 0x5b94, 0x017f, 0x0040, 0x6a6b, 0x660a, 0x611a, 0x601f, 0x0008, + 0x2d00, 0x6012, 0x2009, 0x0021, 0x1078, 0x5c21, 0xa085, 0x0001, + 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6a68, 0x0c7e, 0x127e, + 0x2091, 0x8000, 0x0c7e, 0x1078, 0x5b94, 0x017f, 0x0040, 0x6a86, + 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x1078, + 0x5c21, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, + 0x6a83, 0x027e, 0x0d7e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0040, + 0x6a93, 0x8211, 0x6a3e, 0x0d7f, 0x027f, 0x007c, 0x6013, 0x0000, + 0x601f, 0x0007, 0x6017, 0x0014, 0x007c, 0x067e, 0x0c7e, 0x0d7e, + 0x2031, 0x7652, 0x2634, 0xd6e4, 0x0040, 0x6aab, 0x6618, 0x2660, + 0x6e44, 0x1078, 0x38d6, 0x0d7f, 0x0c7f, 0x067f, 0x007c, 0x007e, + 0x017e, 0x6004, 0xa08e, 0x0002, 0x0040, 0x6ac0, 0xa08e, 0x0003, + 0x0040, 0x6ac0, 0xa08e, 0x0004, 0x0040, 0x6ac0, 0xa085, 0x0001, + 0x017f, 0x007f, 0x007c, 0x007e, 0x017e, 0x6004, 0xa08e, 0x0000, + 0x0040, 0x6ad8, 0xa08e, 0x001f, 0x0040, 0x6ad8, 0xa08e, 0x0028, + 0x0040, 0x6ad8, 0xa08e, 0x0029, 0x0040, 0x6ad8, 0xa085, 0x0001, + 0x017f, 0x007f, 0x007c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, + 0x1078, 0x5b94, 0x017f, 0x0040, 0x6af5, 0x611a, 0x601f, 0x0001, + 0x2d00, 0x6012, 0x1078, 0x22b5, 0x2009, 0x0028, 0x1078, 0x5c21, + 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6af2, + 0xa186, 0x0015, 0x00c0, 0x6b0d, 0x2011, 0x761e, 0x2204, 0xa086, + 0x0074, 0x00c0, 0x6b0d, 0x1078, 0x60ca, 0x6003, 0x0001, 0x6007, + 0x0029, 0x1078, 0x486a, 0x0078, 0x6b11, 0x1078, 0x5e4d, 0x1078, + 0x5bfa, 0x007c, 0xa186, 0x0015, 0x00c0, 0x6b2f, 0x2011, 0x761e, + 0x2204, 0xa086, 0x0014, 0x00c0, 0x6b2f, 0x0d7e, 0x6018, 0x2068, + 0x1078, 0x3899, 0x0d7f, 0x1078, 0x60d4, 0x00c0, 0x6b2f, 0x2001, + 0x0006, 0x1078, 0x37c9, 0x1078, 0x5ca5, 0x0078, 0x6b33, 0x1078, + 0x5e4d, 0x1078, 0x5bfa, 0x007c, 0x6848, 0xa086, 0x0005, 0x00c0, + 0x6b3b, 0x1078, 0x6b3c, 0x007c, 0x6850, 0xc0ad, 0x6852, 0x007c, + 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12cd, 0x1079, 0x6b4a, + 0x067f, 0x007c, 0x6b5a, 0x6d31, 0x6e12, 0x6b5a, 0x6b5a, 0x6b5a, + 0x6b5a, 0x6b5a, 0x6b94, 0x6e80, 0x6b5a, 0x6b5a, 0x6b5a, 0x6b5a, + 0x6b5a, 0x6b5a, 0x1078, 0x12cd, 0x067e, 0x6000, 0xa0b2, 0x0010, + 0x10c8, 0x12cd, 0x1079, 0x6b66, 0x067f, 0x007c, 0x6b76, 0x7181, + 0x6b76, 0x6b76, 0x6b76, 0x6b76, 0x6b76, 0x6b76, 0x715c, 0x71cb, + 0x6b76, 0x6b76, 0x6b76, 0x6b76, 0x6b76, 0x6b76, 0x1078, 0x12cd, + 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12cd, 0x1079, 0x6b82, + 0x067f, 0x007c, 0x6b92, 0x6fcd, 0x703f, 0x7061, 0x70ad, 0x6b92, + 0x6b92, 0x7107, 0x6e8c, 0x7144, 0x7148, 0x6b92, 0x6b92, 0x6b92, + 0x6b92, 0x6b92, 0x1078, 0x12cd, 0xa1b2, 0x0030, 0x10c8, 0x12cd, + 0x2100, 0x0079, 0x6b9b, 0x6bcb, 0x6ca8, 0x6bcb, 0x6bcb, 0x6bcb, + 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, + 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, + 0x6bcb, 0x6bcb, 0x6bcd, 0x6bfc, 0x6c07, 0x6c2f, 0x6c35, 0x6c69, + 0x6ca1, 0x6bcb, 0x6bcb, 0x6cb0, 0x6bcb, 0x6bcb, 0x6cb7, 0x6cbe, + 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6cdb, 0x6bcb, 0x6bcb, + 0x6ce6, 0x6bcb, 0x6bcb, 0x1078, 0x12cd, 0x1078, 0x3a1e, 0x6618, + 0x0c7e, 0x2660, 0x1078, 0x382f, 0x0c7f, 0xa6b0, 0x0001, 0x2634, + 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x6bee, 0x1078, 0x72ac, + 0x00c0, 0x6c29, 0x1078, 0x724a, 0x00c0, 0x6bea, 0x6007, 0x0008, + 0x0078, 0x6ca3, 0x6007, 0x0009, 0x0078, 0x6ca3, 0x1078, 0x7441, + 0x0040, 0x6bf8, 0x1078, 0x72ac, 0x0040, 0x6be2, 0x0078, 0x6c29, + 0x6013, 0x1900, 0x0078, 0x6bea, 0x6106, 0x1078, 0x720c, 0x6007, + 0x0006, 0x0078, 0x6ca3, 0x6007, 0x0007, 0x0078, 0x6ca3, 0x0d7e, + 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, + 0x0040, 0x6c19, 0xa686, 0x0004, 0x0040, 0x6c19, 0x0d7f, 0x0078, + 0x6c29, 0x1078, 0x730a, 0x00c0, 0x6c24, 0x1078, 0x3899, 0x6007, + 0x000a, 0x0d7f, 0x0078, 0x6ca3, 0x6007, 0x000b, 0x0d7f, 0x0078, + 0x6ca3, 0x1078, 0x22b5, 0x6007, 0x0001, 0x0078, 0x6ca3, 0x1078, + 0x22b5, 0x6007, 0x000c, 0x0078, 0x6ca3, 0x1078, 0x3a1e, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, - 0x6bf9, 0x1078, 0x72b7, 0x00c0, 0x6c34, 0x1078, 0x7255, 0x00c0, - 0x6bf5, 0x6007, 0x0008, 0x0078, 0x6cae, 0x6007, 0x0009, 0x0078, - 0x6cae, 0x1078, 0x744c, 0x0040, 0x6c03, 0x1078, 0x72b7, 0x0040, - 0x6bed, 0x0078, 0x6c34, 0x6013, 0x1900, 0x0078, 0x6bf5, 0x6106, - 0x1078, 0x7217, 0x6007, 0x0006, 0x0078, 0x6cae, 0x6007, 0x0007, - 0x0078, 0x6cae, 0x0d7e, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, - 0x8637, 0xa686, 0x0006, 0x0040, 0x6c24, 0xa686, 0x0004, 0x0040, - 0x6c24, 0x0d7f, 0x0078, 0x6c34, 0x1078, 0x7315, 0x00c0, 0x6c2f, - 0x1078, 0x38a1, 0x6007, 0x000a, 0x0d7f, 0x0078, 0x6cae, 0x6007, - 0x000b, 0x0d7f, 0x0078, 0x6cae, 0x1078, 0x22bb, 0x6007, 0x0001, - 0x0078, 0x6cae, 0x1078, 0x22bb, 0x6007, 0x000c, 0x0078, 0x6cae, - 0x1078, 0x3a26, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, - 0xa082, 0x0006, 0x0048, 0x6c61, 0xa6b4, 0xff00, 0x8637, 0xa686, - 0x0006, 0x00c0, 0x6c34, 0x1078, 0x7324, 0x00c0, 0x6c5b, 0x6007, - 0x000e, 0x0078, 0x6cae, 0x1078, 0x22bb, 0x6007, 0x000f, 0x0078, - 0x6cae, 0x1078, 0x744c, 0x0040, 0x6c6e, 0xa6b4, 0xff00, 0x8637, - 0xa686, 0x0006, 0x0040, 0x6c53, 0x0078, 0x6c34, 0x6013, 0x1900, - 0x6007, 0x0009, 0x0078, 0x6cae, 0x1078, 0x3a26, 0x6618, 0xa6b0, - 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x6c99, - 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x00c0, 0x6c34, 0x1078, - 0x734f, 0x00c0, 0x6c93, 0x1078, 0x7255, 0x00c0, 0x6c93, 0x6007, - 0x0010, 0x0078, 0x6cae, 0x1078, 0x22bb, 0x6007, 0x0011, 0x0078, - 0x6cae, 0x1078, 0x744c, 0x0040, 0x6ca6, 0xa6b4, 0xff00, 0x8637, - 0xa686, 0x0006, 0x0040, 0x6c87, 0x0078, 0x6c34, 0x6013, 0x1900, - 0x6007, 0x0009, 0x0078, 0x6cae, 0x6007, 0x0012, 0x6003, 0x0001, - 0x1078, 0x4872, 0x007c, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, - 0x4872, 0x0078, 0x6cb2, 0x6007, 0x0020, 0x6003, 0x0001, 0x1078, - 0x4872, 0x007c, 0x6007, 0x0023, 0x6003, 0x0001, 0x1078, 0x4872, - 0x007c, 0x017e, 0x027e, 0x2011, 0x7b88, 0x2214, 0x2c08, 0x1078, - 0x7514, 0x00c0, 0x6cda, 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, - 0x0078, 0x6cdf, 0x1078, 0x5c02, 0x2160, 0x6007, 0x0025, 0x6003, - 0x0001, 0x1078, 0x4872, 0x027f, 0x017f, 0x007c, 0x6106, 0x1078, - 0x6cf8, 0x6007, 0x002b, 0x0078, 0x6cae, 0x6007, 0x002c, 0x0078, - 0x6cae, 0x6106, 0x1078, 0x6cfd, 0x6007, 0x002e, 0x0078, 0x6cae, - 0x0d7e, 0x1078, 0x6d23, 0x0d7f, 0x007c, 0x0d7e, 0x1078, 0x6d32, - 0x00c0, 0x6d1c, 0x680c, 0xa08c, 0xff00, 0x6824, 0xa084, 0x00ff, - 0xa115, 0x6212, 0xd1e4, 0x0040, 0x6d11, 0x2009, 0x0001, 0x0078, - 0x6d18, 0xd1ec, 0x0040, 0x6d1c, 0x2009, 0x0000, 0xa294, 0x00ff, - 0x1078, 0x22ff, 0x0078, 0x6d20, 0xa085, 0x0001, 0x0078, 0x6d21, - 0xa006, 0x0d7f, 0x007c, 0x2069, 0x7b8d, 0x6800, 0xa082, 0x0010, - 0x00c8, 0x6d30, 0x6013, 0x0000, 0xa085, 0x0001, 0x0078, 0x6d31, - 0xa006, 0x007c, 0x6013, 0x0000, 0x2069, 0x7b8c, 0x6808, 0xa084, - 0xff00, 0xa086, 0x0800, 0x007c, 0x6004, 0xa0b2, 0x0030, 0x10c8, - 0x12d5, 0xa1b6, 0x0013, 0x00c0, 0x6d48, 0x2008, 0x0079, 0x6d5b, - 0xa1b6, 0x0027, 0x0040, 0x6d50, 0xa1b6, 0x0014, 0x10c0, 0x12d5, - 0x2001, 0x0007, 0x1078, 0x37df, 0x1078, 0x4b81, 0x1078, 0x6aa1, - 0x1078, 0x4c7a, 0x007c, 0x6d8b, 0x6d8d, 0x6d8b, 0x6d8b, 0x6d8b, - 0x6d8d, 0x6d95, 0x6df8, 0x6dbb, 0x6df8, 0x6dcf, 0x6df8, 0x6d95, - 0x6df8, 0x6df0, 0x6df8, 0x6df0, 0x6df8, 0x6df8, 0x6d8b, 0x6d8b, - 0x6d8b, 0x6d8b, 0x6d8b, 0x6d8b, 0x6d8b, 0x6d8b, 0x6d8b, 0x6d8b, - 0x6d8b, 0x6d8b, 0x6d8b, 0x6df8, 0x6d8b, 0x6d8b, 0x6df8, 0x6d8b, - 0x6df8, 0x6df8, 0x6d8b, 0x6d8b, 0x6d8b, 0x6d8b, 0x6df8, 0x6df8, - 0x6d8b, 0x6df8, 0x6df8, 0x1078, 0x12d5, 0x1078, 0x4b81, 0x6003, - 0x0002, 0x1078, 0x4c7a, 0x0078, 0x6dfe, 0x0f7e, 0x2079, 0x7651, - 0x7804, 0x0f7f, 0xd0ac, 0x00c0, 0x6df8, 0x2001, 0x0000, 0x1078, - 0x37bd, 0x2001, 0x0002, 0x1078, 0x37d1, 0x1078, 0x4b81, 0x601f, - 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x4872, 0x1078, - 0x4c7a, 0x0c7e, 0x6118, 0x2160, 0x2009, 0x0001, 0x1078, 0x457b, - 0x0c7f, 0x0078, 0x6dfe, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, - 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x6df8, 0xa686, - 0x0004, 0x0040, 0x6df8, 0x2001, 0x0004, 0x0078, 0x6df6, 0x2001, - 0x7600, 0x2004, 0xa086, 0x0003, 0x00c0, 0x6dd8, 0x1078, 0x2dc8, - 0x2001, 0x0006, 0x1078, 0x6dff, 0x6618, 0x0d7e, 0x2668, 0x6e04, - 0x0d7f, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x6df8, - 0x2001, 0x0006, 0x0078, 0x6df6, 0x2001, 0x0004, 0x0078, 0x6df6, - 0x2001, 0x0006, 0x1078, 0x6dff, 0x0078, 0x6df8, 0x1078, 0x37df, - 0x1078, 0x4b81, 0x1078, 0x5c02, 0x1078, 0x4c7a, 0x007c, 0x017e, - 0x0d7e, 0x6118, 0x2168, 0x6900, 0xd184, 0x0040, 0x6e1a, 0x6104, - 0xa18e, 0x000a, 0x00c0, 0x6e12, 0x699c, 0xd1a4, 0x00c0, 0x6e12, - 0x2001, 0x0007, 0x1078, 0x37d1, 0x2001, 0x0000, 0x1078, 0x37bd, - 0x1078, 0x22dd, 0x0d7f, 0x017f, 0x007c, 0x0d7e, 0x6618, 0x2668, - 0x6804, 0xa084, 0xff00, 0x8007, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, - 0x12d5, 0xa1b6, 0x0015, 0x00c0, 0x6e31, 0x1079, 0x6e38, 0x0078, - 0x6e37, 0xa1b6, 0x0016, 0x10c0, 0x12d5, 0x1079, 0x6e70, 0x007c, - 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x6e44, - 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x0f7e, 0x2079, 0x7651, 0x7804, - 0x0f7f, 0xd0ac, 0x00c0, 0x6e60, 0x2001, 0x0000, 0x1078, 0x37bd, - 0x2001, 0x0002, 0x1078, 0x37d1, 0x601f, 0x0001, 0x6003, 0x0001, - 0x6007, 0x0002, 0x1078, 0x4872, 0x1078, 0x4c7a, 0x0078, 0x6e6f, - 0x2011, 0x7b83, 0x220c, 0x017e, 0x0c7e, 0x1078, 0x3825, 0x00c0, - 0x6e6f, 0x1078, 0x3621, 0x0c7f, 0x017f, 0x1078, 0x5c02, 0x007c, - 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x6e7c, - 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x1078, 0x60d1, 0x00c0, 0x6e88, - 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x4872, 0x0078, 0x6e8a, - 0x1078, 0x5c02, 0x007c, 0x6004, 0xa08a, 0x0030, 0x10c8, 0x12d5, - 0x1078, 0x4b81, 0x1078, 0x6aa1, 0x1078, 0x4c7a, 0x007c, 0xa182, - 0x0040, 0x0079, 0x6e9b, 0x6eab, 0x6eab, 0x6eab, 0x6eab, 0x6ead, - 0x6eab, 0x6eab, 0x6eab, 0x6eab, 0x6eab, 0x6eab, 0x6eab, 0x6eab, - 0x6eab, 0x6eab, 0x6eab, 0x1078, 0x12d5, 0x0d7e, 0x0e7e, 0x0f7e, - 0x157e, 0x047e, 0x027e, 0x6106, 0x2071, 0x7b80, 0x7444, 0xa4a4, - 0xe600, 0x0040, 0x6f1e, 0xa486, 0x2000, 0x0040, 0x6edd, 0xa486, - 0x0400, 0x0040, 0x6edd, 0x7130, 0xa18c, 0x00ff, 0xa182, 0x0010, - 0x00c8, 0x6fb0, 0x0c7e, 0x1078, 0x460c, 0x2c68, 0x0c7f, 0x6a00, - 0xa284, 0x0001, 0x0040, 0x6f91, 0x1078, 0x46ca, 0x0040, 0x6fbc, - 0xa295, 0x0200, 0x6a02, 0x0078, 0x6ee3, 0x2009, 0x0001, 0x2011, - 0x0200, 0x1078, 0x46b4, 0x1078, 0x132f, 0x1040, 0x12d5, 0x6003, - 0x0007, 0x2d00, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, - 0x6c5a, 0x2c00, 0x685e, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, - 0xa18c, 0x00ff, 0xa10d, 0x6946, 0x684f, 0x0000, 0x6857, 0x0036, - 0x1078, 0x3a7a, 0xa486, 0x2000, 0x00c0, 0x6f0c, 0x2019, 0x0017, - 0x1078, 0x74d9, 0x0078, 0x6f7e, 0xa486, 0x0400, 0x00c0, 0x6f16, - 0x2019, 0x0002, 0x1078, 0x74d9, 0x0078, 0x6f7e, 0xa486, 0x0200, - 0x00c0, 0x6f1c, 0x1078, 0x74ca, 0x0078, 0x6f7e, 0x7130, 0xa184, - 0xff00, 0x00c0, 0x6fd0, 0xa18c, 0x00ff, 0xa182, 0x0010, 0x00c8, - 0x6fd0, 0x0c7e, 0x1078, 0x460c, 0x2c68, 0x0c7f, 0x6a00, 0xa284, - 0x0001, 0x0040, 0x6fd4, 0xa284, 0x0300, 0x00c0, 0x6fcc, 0x6804, - 0xa005, 0x0040, 0x6fbc, 0x8001, 0x6806, 0x6003, 0x0007, 0x1078, - 0x1314, 0x0040, 0x6f85, 0x6013, 0x0000, 0x6803, 0x0000, 0x6837, - 0x0116, 0x683b, 0x0000, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, - 0x8007, 0xa10d, 0x6946, 0x6853, 0x003d, 0x7044, 0xa084, 0x0003, - 0xa086, 0x0002, 0x00c0, 0x6f60, 0x684f, 0x0040, 0x0078, 0x6f6a, - 0xa086, 0x0001, 0x00c0, 0x6f68, 0x684f, 0x0080, 0x0078, 0x6f6a, - 0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, 0x7b90, 0xad90, 0x0015, - 0x200c, 0x810f, 0x2112, 0x8000, 0x8210, 0x00f0, 0x6f70, 0x200c, - 0x6982, 0x8000, 0x200c, 0x697e, 0x1078, 0x3a7a, 0x027f, 0x047f, - 0x157f, 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x6013, 0x0100, 0x6003, - 0x0001, 0x6007, 0x0041, 0x1078, 0x4825, 0x1078, 0x4c7a, 0x0078, - 0x6f7e, 0x2069, 0x7b92, 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200, - 0x00c0, 0x6fb0, 0x2069, 0x7b80, 0x686c, 0xa084, 0x00ff, 0x017e, - 0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, 0x017f, 0x6003, 0x0001, - 0x6007, 0x0043, 0x1078, 0x4825, 0x1078, 0x4c7a, 0x0078, 0x6f7e, - 0x6013, 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x4825, - 0x1078, 0x4c7a, 0x0078, 0x6f7e, 0x6013, 0x0300, 0x0078, 0x6fc2, - 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x4825, - 0x1078, 0x4c7a, 0x0078, 0x6f7e, 0x6013, 0x0500, 0x0078, 0x6fc2, - 0x6013, 0x0600, 0x0078, 0x6f91, 0x6013, 0x0200, 0x0078, 0x6f91, - 0xa186, 0x0013, 0x00c0, 0x6fea, 0x6004, 0xa08a, 0x0040, 0x1048, - 0x12d5, 0xa08a, 0x0050, 0x10c8, 0x12d5, 0xa082, 0x0040, 0x2008, - 0x0079, 0x701b, 0xa186, 0x0047, 0x00c0, 0x6ff0, 0x0078, 0x704a, - 0xa186, 0x0027, 0x0040, 0x6ff8, 0xa186, 0x0014, 0x10c0, 0x12d5, - 0x6004, 0xa082, 0x0040, 0x2008, 0x0079, 0x6ffe, 0x700e, 0x7010, - 0x7010, 0x700e, 0x700e, 0x700e, 0x700e, 0x700e, 0x700e, 0x700e, - 0x700e, 0x700e, 0x700e, 0x700e, 0x700e, 0x700e, 0x1078, 0x12d5, - 0x2001, 0x0007, 0x1078, 0x37df, 0x1078, 0x4b81, 0x1078, 0x6aa1, - 0x1078, 0x4c7a, 0x007c, 0x702b, 0x703b, 0x7034, 0x7044, 0x702b, - 0x702b, 0x702b, 0x702b, 0x702b, 0x702b, 0x702b, 0x702b, 0x702b, - 0x702b, 0x702b, 0x702b, 0x1078, 0x12d5, 0x6010, 0xa088, 0x0013, - 0x2104, 0xa085, 0x0400, 0x200a, 0x1078, 0x4b81, 0x6003, 0x0002, - 0x1078, 0x4c7a, 0x007c, 0x1078, 0x4b81, 0x1078, 0x468d, 0x1078, - 0x5c02, 0x1078, 0x4c7a, 0x007c, 0x1078, 0x4b81, 0x2009, 0x0041, - 0x0078, 0x7112, 0xa182, 0x0040, 0x0079, 0x704e, 0x705e, 0x7060, - 0x705e, 0x705e, 0x705e, 0x705e, 0x705e, 0x7061, 0x705e, 0x705e, - 0x705e, 0x705e, 0x705e, 0x705e, 0x705e, 0x705e, 0x1078, 0x12d5, - 0x007c, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, - 0x2c10, 0x1078, 0x1572, 0x007c, 0xa182, 0x0040, 0x0079, 0x7070, - 0x7080, 0x7080, 0x7080, 0x7080, 0x7080, 0x7080, 0x7080, 0x7080, - 0x7080, 0x7082, 0x70a5, 0x7080, 0x7080, 0x7080, 0x7080, 0x70a5, - 0x1078, 0x12d5, 0x1078, 0x4c29, 0x1078, 0x4d3a, 0x6010, 0x0d7e, - 0x2068, 0x684c, 0xd0fc, 0x0040, 0x7098, 0xa08c, 0x0003, 0xa18e, - 0x0002, 0x0040, 0x709e, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x7112, - 0x6003, 0x0007, 0x1078, 0x468d, 0x0d7f, 0x007c, 0x1078, 0x468d, - 0x1078, 0x5c02, 0x0d7f, 0x0078, 0x709d, 0x037e, 0x1078, 0x4c29, - 0x1078, 0x4d3a, 0x6010, 0x0d7e, 0x2068, 0x2019, 0x0004, 0x1078, - 0x74fd, 0x1078, 0x6aa1, 0x6017, 0x0028, 0x0d7f, 0x037f, 0x007c, - 0xa186, 0x0013, 0x00c0, 0x70c6, 0x6004, 0xa086, 0x0042, 0x10c0, - 0x12d5, 0x1078, 0x4b81, 0x1078, 0x4c7a, 0x007c, 0xa186, 0x0027, - 0x0040, 0x70ce, 0xa186, 0x0014, 0x00c0, 0x70de, 0x6004, 0xa086, - 0x0042, 0x10c0, 0x12d5, 0x2001, 0x0007, 0x1078, 0x37df, 0x1078, - 0x4b81, 0x1078, 0x6aa1, 0x1078, 0x4c7a, 0x007c, 0xa182, 0x0040, - 0x0079, 0x70e2, 0x70f2, 0x70f2, 0x70f2, 0x70f2, 0x70f2, 0x70f2, - 0x70f2, 0x70f4, 0x7100, 0x70f2, 0x70f2, 0x70f2, 0x70f2, 0x70f2, - 0x70f2, 0x70f2, 0x1078, 0x12d5, 0x037e, 0x047e, 0x20e1, 0x0005, - 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x1572, 0x047f, 0x037f, 0x007c, - 0x6010, 0x0d7e, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x710c, 0x2009, - 0x0041, 0x0d7f, 0x0078, 0x7112, 0x6003, 0x0007, 0x1078, 0x468d, - 0x0d7f, 0x007c, 0xa182, 0x0040, 0x0079, 0x7116, 0x7126, 0x7128, - 0x7134, 0x7140, 0x7126, 0x7126, 0x7126, 0x7126, 0x7126, 0x7126, - 0x7126, 0x7126, 0x7126, 0x7126, 0x7126, 0x7126, 0x1078, 0x12d5, - 0x6003, 0x0001, 0x6106, 0x1078, 0x4825, 0x127e, 0x2091, 0x8000, - 0x1078, 0x4c7a, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, - 0x4825, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c7a, 0x127f, 0x007c, - 0x6003, 0x0003, 0x6106, 0x2c10, 0x1078, 0x19cf, 0x127e, 0x2091, - 0x8000, 0x1078, 0x4891, 0x1078, 0x4d3a, 0x127f, 0x007c, 0x1078, - 0x4b81, 0x0078, 0x7155, 0x1078, 0x4c29, 0x6110, 0x81ff, 0x0040, - 0x7162, 0x0d7e, 0x2168, 0x037e, 0x2019, 0x0029, 0x1078, 0x74fd, - 0x037f, 0x0d7f, 0x1078, 0x6aa1, 0x1078, 0x4c7a, 0x007c, 0xa182, - 0x0085, 0x0079, 0x716b, 0x7172, 0x7172, 0x7172, 0x7174, 0x7172, - 0x7172, 0x7172, 0x1078, 0x12d5, 0x027e, 0x0e7e, 0x2071, 0x7b80, - 0x7220, 0x1078, 0x7417, 0x0040, 0x7181, 0x6007, 0x0086, 0x0078, - 0x7183, 0x6007, 0x0087, 0x6003, 0x0001, 0x1078, 0x4825, 0x1078, - 0x4c7a, 0x0e7f, 0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x719d, - 0x6004, 0xa08a, 0x0085, 0x1048, 0x12d5, 0xa08a, 0x008c, 0x10c8, - 0x12d5, 0xa082, 0x0085, 0x0079, 0x71b0, 0xa186, 0x0027, 0x0040, - 0x71a5, 0xa186, 0x0014, 0x10c0, 0x12d5, 0x2001, 0x0007, 0x1078, - 0x37df, 0x1078, 0x4b81, 0x1078, 0x6aa1, 0x1078, 0x4c7a, 0x007c, - 0x71b7, 0x71b9, 0x71b9, 0x71b7, 0x71b7, 0x71b7, 0x71b7, 0x1078, - 0x12d5, 0x1078, 0x4b81, 0x1078, 0x5c02, 0x1078, 0x4c7a, 0x007c, - 0xa182, 0x0085, 0x1048, 0x12d5, 0xa182, 0x008c, 0x10c8, 0x12d5, - 0xa182, 0x0085, 0x0079, 0x71cc, 0x71d3, 0x71d3, 0x71d3, 0x71d5, - 0x71d3, 0x71d3, 0x71d3, 0x1078, 0x12d5, 0x007c, 0x1078, 0x4b81, - 0x1078, 0x6aa1, 0x1078, 0x4c7a, 0x007c, 0x037e, 0x2019, 0x000b, - 0x1078, 0x71e6, 0x601f, 0x0006, 0x037f, 0x007c, 0x127e, 0x037e, - 0x087e, 0x2091, 0x8000, 0x2c40, 0x1078, 0x5915, 0x00c0, 0x7213, - 0x1078, 0x59b6, 0x00c0, 0x7213, 0x6000, 0xa086, 0x0000, 0x0040, - 0x7213, 0x601c, 0xa086, 0x0007, 0x0040, 0x7213, 0x0d7e, 0x6000, - 0xa086, 0x0004, 0x00c0, 0x7206, 0x1078, 0x1676, 0x6010, 0x2068, - 0x1078, 0x693e, 0x0040, 0x720e, 0x1078, 0x74fd, 0x0d7f, 0x6013, - 0x0000, 0x601f, 0x0007, 0x087f, 0x037f, 0x127f, 0x007c, 0x0f7e, - 0x0c7e, 0x037e, 0x157e, 0x2079, 0x7b80, 0x7838, 0xa08c, 0x00ff, - 0x783c, 0x1078, 0x2085, 0x00c0, 0x724e, 0x017e, 0x0c7e, 0x1078, - 0x3825, 0x00c0, 0x724e, 0x2011, 0x7b90, 0xac98, 0x000a, 0x20a9, - 0x0004, 0x1078, 0x616a, 0x00c0, 0x724e, 0x017f, 0x027f, 0x027e, - 0x017e, 0x2019, 0x0029, 0x1078, 0x5a8a, 0x1078, 0x4962, 0x1078, - 0x48a5, 0x017f, 0x1078, 0x737b, 0x1078, 0x39a6, 0x017f, 0x1078, - 0x3621, 0x6612, 0x6516, 0xa006, 0x0078, 0x7250, 0x0c7f, 0x017f, - 0x157f, 0x037f, 0x0c7f, 0x0f7f, 0x007c, 0x0c7e, 0x0d7e, 0x017e, - 0x2009, 0x761e, 0x2104, 0xa086, 0x0074, 0x00c0, 0x72ac, 0x2069, - 0x7b8e, 0x690c, 0xa182, 0x0100, 0x0048, 0x729c, 0x6908, 0xa184, - 0x8000, 0x0040, 0x72a8, 0xa184, 0x0800, 0x0040, 0x72a8, 0x6910, - 0xa18a, 0x0001, 0x0048, 0x72a0, 0x6914, 0x2069, 0x7bae, 0x6904, - 0x81ff, 0x00c0, 0x7294, 0x690c, 0xa182, 0x0100, 0x0048, 0x729c, - 0x6908, 0x81ff, 0x00c0, 0x7298, 0x6910, 0xa18a, 0x0001, 0x0048, - 0x72a0, 0x6918, 0xa18a, 0x0001, 0x0048, 0x72a8, 0x0078, 0x72b2, - 0x6013, 0x0100, 0x0078, 0x72ae, 0x6013, 0x0300, 0x0078, 0x72ae, - 0x6013, 0x0500, 0x0078, 0x72ae, 0x6013, 0x0700, 0x0078, 0x72ae, - 0x6013, 0x0900, 0x0078, 0x72ae, 0x6013, 0x0b00, 0x0078, 0x72ae, - 0x6013, 0x0f00, 0x0078, 0x72ae, 0x6013, 0x2d00, 0xa085, 0x0001, - 0x0078, 0x72b3, 0xa006, 0x017f, 0x0d7f, 0x0c7f, 0x007c, 0x0c7e, - 0x0d7e, 0x027e, 0x037e, 0x157e, 0x6218, 0x2268, 0x6b04, 0xa394, - 0x00ff, 0xa286, 0x0006, 0x0040, 0x72db, 0xa286, 0x0004, 0x0040, - 0x72db, 0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0040, 0x72db, - 0xa286, 0x0004, 0x0040, 0x72db, 0x0c7e, 0x2d60, 0x1078, 0x3837, - 0x0c7f, 0x0078, 0x730e, 0x2011, 0x7b96, 0xad98, 0x000a, 0x20a9, - 0x0004, 0x1078, 0x616a, 0x00c0, 0x730f, 0x2011, 0x7b9a, 0xad98, - 0x0006, 0x20a9, 0x0004, 0x1078, 0x616a, 0x00c0, 0x730f, 0x047e, - 0x017e, 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0x7652, - 0x210c, 0xd1a4, 0x0040, 0x7303, 0x2009, 0x0029, 0x1078, 0x7541, - 0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, 0x1078, 0x4962, 0x1078, - 0x48a5, 0x2c08, 0x1078, 0x737b, 0x017f, 0x047f, 0xa006, 0x157f, - 0x037f, 0x027f, 0x0d7f, 0x0c7f, 0x007c, 0x0d7e, 0x2069, 0x7b8e, - 0x6800, 0xa086, 0x0800, 0x0040, 0x7321, 0x6013, 0x0000, 0x0078, - 0x7322, 0xa006, 0x0d7f, 0x007c, 0x0c7e, 0x0f7e, 0x017e, 0x027e, - 0x037e, 0x157e, 0x2079, 0x7b8c, 0x7930, 0x7834, 0x1078, 0x2085, - 0x00c0, 0x7348, 0x1078, 0x3825, 0x00c0, 0x7348, 0x2011, 0x7b90, - 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x616a, 0x00c0, 0x7348, - 0x2011, 0x7b94, 0xac98, 0x0006, 0x20a9, 0x0004, 0x1078, 0x616a, - 0x157f, 0x037f, 0x027f, 0x017f, 0x0f7f, 0x0c7f, 0x007c, 0x0c7e, - 0x007e, 0x017e, 0x027e, 0x037e, 0x157e, 0x2011, 0x7b83, 0x2204, - 0x8211, 0x220c, 0x1078, 0x2085, 0x00c0, 0x7374, 0x1078, 0x3825, - 0x00c0, 0x7374, 0x2011, 0x7b96, 0xac98, 0x000a, 0x20a9, 0x0004, - 0x1078, 0x616a, 0x00c0, 0x7374, 0x2011, 0x7b9a, 0xac98, 0x0006, - 0x20a9, 0x0004, 0x1078, 0x616a, 0x157f, 0x037f, 0x027f, 0x017f, - 0x007f, 0x0c7f, 0x007c, 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x057e, - 0x047e, 0x027e, 0x127e, 0x2091, 0x8000, 0x2029, 0x783f, 0x252c, - 0x2021, 0x7845, 0x2424, 0x2061, 0x7d00, 0x2071, 0x7600, 0x7644, - 0x7060, 0x8001, 0xa602, 0x00c8, 0x73e0, 0x2100, 0xac06, 0x0040, - 0x73d6, 0x1078, 0x7559, 0x0040, 0x73d6, 0x671c, 0xa786, 0x0001, - 0x0040, 0x73f5, 0xa786, 0x0007, 0x0040, 0x73d6, 0x2500, 0xac06, - 0x0040, 0x73d6, 0x2400, 0xac06, 0x0040, 0x73d6, 0x1078, 0x756d, - 0x00c0, 0x73d6, 0x0d7e, 0x6000, 0xa086, 0x0004, 0x00c0, 0x73bc, - 0x017e, 0x1078, 0x1676, 0x017f, 0x6010, 0x2068, 0x1078, 0x693e, - 0x0040, 0x73d3, 0xa786, 0x0003, 0x00c0, 0x73e9, 0x6837, 0x0103, - 0x6b4a, 0x6847, 0x0000, 0x017e, 0x1078, 0x6b3f, 0x1078, 0x3a7a, - 0x017f, 0x1078, 0x6a94, 0x0d7f, 0x1078, 0x6aa1, 0xace0, 0x0008, - 0x2001, 0x7615, 0x2004, 0xac02, 0x00c8, 0x73e0, 0x0078, 0x738d, - 0x127f, 0x027f, 0x047f, 0x057f, 0x067f, 0x077f, 0x0c7f, 0x0e7f, - 0x007c, 0xa786, 0x0006, 0x00c0, 0x73c6, 0xa386, 0x0005, 0x0040, - 0x73d6, 0x1078, 0x74fd, 0x0078, 0x73d3, 0x1078, 0x756d, 0x00c0, - 0x73d6, 0xa180, 0x0001, 0x2004, 0xa086, 0x0018, 0x00c0, 0x73d6, - 0x6000, 0xa086, 0x0002, 0x00c0, 0x73d6, 0x1078, 0x6aba, 0x0040, - 0x7411, 0x1078, 0x6ace, 0x00c0, 0x73d6, 0x1078, 0x5e57, 0x0078, - 0x7413, 0x1078, 0x22dd, 0x1078, 0x6aa1, 0x0078, 0x73d6, 0x0c7e, - 0x0e7e, 0x017e, 0x2c08, 0x2170, 0x1078, 0x7514, 0x017f, 0x0040, - 0x7426, 0x601c, 0xa084, 0x000f, 0x1079, 0x7429, 0x0e7f, 0x0c7f, - 0x007c, 0x7431, 0x7431, 0x7431, 0x7431, 0x7431, 0x7431, 0x7433, - 0x7431, 0xa006, 0x007c, 0x047e, 0x017e, 0x7018, 0xa080, 0x0028, - 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009, 0x0020, 0x1078, - 0x7541, 0x017f, 0x047f, 0x037e, 0x2019, 0x0002, 0x1078, 0x71e6, - 0x037f, 0xa085, 0x0001, 0x007c, 0x2001, 0x0001, 0x1078, 0x37bd, - 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, 0x0004, 0x2019, 0x7605, - 0x2011, 0x7b96, 0x1078, 0x616a, 0x037f, 0x027f, 0x017f, 0x157f, - 0xa005, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x027e, - 0x127e, 0x2091, 0x8000, 0x2061, 0x7d00, 0x2079, 0x0001, 0x8fff, - 0x0040, 0x74bd, 0x2071, 0x7600, 0x7644, 0x7060, 0x8001, 0xa602, - 0x00c8, 0x74bd, 0x88ff, 0x0040, 0x7483, 0x2800, 0xac06, 0x00c0, - 0x74b3, 0x2079, 0x0000, 0x1078, 0x7559, 0x0040, 0x74b3, 0x2400, - 0xac06, 0x0040, 0x74b3, 0x671c, 0xa786, 0x0006, 0x00c0, 0x74b3, - 0xa786, 0x0007, 0x0040, 0x74b3, 0x88ff, 0x00c0, 0x749b, 0x6018, - 0xa206, 0x00c0, 0x74b3, 0x0d7e, 0x6000, 0xa086, 0x0004, 0x00c0, - 0x74a3, 0x1078, 0x1676, 0x6010, 0x2068, 0x1078, 0x693e, 0x0040, - 0x74ad, 0x047e, 0x1078, 0x74fd, 0x047f, 0x0d7f, 0x1078, 0x6aa1, - 0x88ff, 0x00c0, 0x74c6, 0xace0, 0x0008, 0x2001, 0x7615, 0x2004, - 0xac02, 0x00c8, 0x74bd, 0x0078, 0x746f, 0xa006, 0x127f, 0x027f, - 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0xa8c5, 0x0001, - 0x0078, 0x74be, 0x087e, 0x2041, 0x0000, 0x2c20, 0x2019, 0x0002, - 0x6218, 0x1078, 0x5915, 0x1078, 0x59b6, 0x1078, 0x7462, 0x087f, - 0x007c, 0x027e, 0x047e, 0x087e, 0x0c7e, 0x157e, 0x2c20, 0x20a9, - 0x007f, 0x2009, 0x0000, 0x017e, 0x037e, 0x1078, 0x3825, 0x00c0, - 0x74f2, 0x2c10, 0x2041, 0x0000, 0x1078, 0x5915, 0x1078, 0x59b6, - 0x1078, 0x7462, 0x037f, 0x017f, 0x8108, 0x00f0, 0x74e3, 0x157f, - 0x0c7f, 0x087f, 0x047f, 0x027f, 0x007c, 0x017e, 0x0f7e, 0x8dff, - 0x0040, 0x7511, 0x6800, 0xa07d, 0x0040, 0x750e, 0x6803, 0x0000, - 0x6b52, 0x1078, 0x3a7a, 0x2f68, 0x0078, 0x7502, 0x6b52, 0x1078, - 0x3a7a, 0x0f7f, 0x017f, 0x007c, 0x0e7e, 0x047e, 0x037e, 0x2061, - 0x7d00, 0x2071, 0x7600, 0x7444, 0x7060, 0x8001, 0xa402, 0x00c8, - 0x753c, 0x2100, 0xac06, 0x0040, 0x752e, 0x6000, 0xa086, 0x0000, - 0x0040, 0x752e, 0x6008, 0xa206, 0x0040, 0x7538, 0xace0, 0x0008, - 0x2001, 0x7615, 0x2004, 0xac02, 0x00c8, 0x753c, 0x0078, 0x7519, - 0xa085, 0x0001, 0x0078, 0x753d, 0xa006, 0x037f, 0x047f, 0x0e7f, - 0x007c, 0x0d7e, 0x007e, 0x1078, 0x132f, 0x007f, 0x1040, 0x12d5, - 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x685b, 0x0000, - 0x685e, 0x6956, 0x6c46, 0x684f, 0x0000, 0x1078, 0x3a7a, 0x0d7f, - 0x007c, 0x6700, 0xa786, 0x0000, 0x0040, 0x756c, 0xa786, 0x0001, - 0x0040, 0x756c, 0xa786, 0x000a, 0x0040, 0x756c, 0xa786, 0x0009, - 0x0040, 0x756c, 0xa085, 0x0001, 0x007c, 0x0e7e, 0x6018, 0x2070, - 0x70a0, 0xa206, 0x0e7f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, - 0x8000, 0x2071, 0x7640, 0xd5a4, 0x0040, 0x7581, 0x7034, 0x8000, - 0x7036, 0xd5b4, 0x0040, 0x7587, 0x7030, 0x8000, 0x7032, 0xd5ac, - 0x0040, 0x758e, 0x2071, 0x764a, 0x1078, 0x75bd, 0x0e7f, 0x007f, - 0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071, - 0x7640, 0xd5a4, 0x0040, 0x759f, 0x7034, 0x8000, 0x7036, 0xd5b4, - 0x0040, 0x75a5, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0040, 0x75ac, - 0x2071, 0x764a, 0x1078, 0x75bd, 0x0e7f, 0x007f, 0x127f, 0x007c, - 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x7642, 0x1078, - 0x75bd, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x2e04, 0x8000, 0x2072, - 0x00c8, 0x75c6, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x007c, 0x0e7e, - 0x2071, 0x7640, 0x1078, 0x75bd, 0x0e7f, 0x007c, 0x0e7e, 0x2071, - 0x7644, 0x1078, 0x75bd, 0x0e7f, 0x007c, 0x0001, 0x0002, 0x0004, - 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, - 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0xaaff + 0x6c56, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x00c0, 0x6c29, + 0x1078, 0x7319, 0x00c0, 0x6c50, 0x6007, 0x000e, 0x0078, 0x6ca3, + 0x1078, 0x22b5, 0x6007, 0x000f, 0x0078, 0x6ca3, 0x1078, 0x7441, + 0x0040, 0x6c63, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, + 0x6c48, 0x0078, 0x6c29, 0x6013, 0x1900, 0x6007, 0x0009, 0x0078, + 0x6ca3, 0x1078, 0x3a1e, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, + 0x00ff, 0xa082, 0x0006, 0x0048, 0x6c8e, 0xa6b4, 0xff00, 0x8637, + 0xa686, 0x0006, 0x00c0, 0x6c29, 0x1078, 0x7344, 0x00c0, 0x6c88, + 0x1078, 0x724a, 0x00c0, 0x6c88, 0x6007, 0x0010, 0x0078, 0x6ca3, + 0x1078, 0x22b5, 0x6007, 0x0011, 0x0078, 0x6ca3, 0x1078, 0x7441, + 0x0040, 0x6c9b, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, + 0x6c7c, 0x0078, 0x6c29, 0x6013, 0x1900, 0x6007, 0x0009, 0x0078, + 0x6ca3, 0x6007, 0x0012, 0x6003, 0x0001, 0x1078, 0x486a, 0x007c, + 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, 0x486a, 0x0078, 0x6ca7, + 0x6007, 0x0020, 0x6003, 0x0001, 0x1078, 0x486a, 0x007c, 0x6007, + 0x0023, 0x6003, 0x0001, 0x1078, 0x486a, 0x007c, 0x017e, 0x027e, + 0x2011, 0x7b88, 0x2214, 0x2c08, 0x1078, 0x7509, 0x00c0, 0x6ccf, + 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x0078, 0x6cd4, 0x1078, + 0x5bfa, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x1078, 0x486a, + 0x027f, 0x017f, 0x007c, 0x6106, 0x1078, 0x6ced, 0x6007, 0x002b, + 0x0078, 0x6ca3, 0x6007, 0x002c, 0x0078, 0x6ca3, 0x6106, 0x1078, + 0x6cf2, 0x6007, 0x002e, 0x0078, 0x6ca3, 0x0d7e, 0x1078, 0x6d18, + 0x0d7f, 0x007c, 0x0d7e, 0x1078, 0x6d27, 0x00c0, 0x6d11, 0x680c, + 0xa08c, 0xff00, 0x6824, 0xa084, 0x00ff, 0xa115, 0x6212, 0xd1e4, + 0x0040, 0x6d06, 0x2009, 0x0001, 0x0078, 0x6d0d, 0xd1ec, 0x0040, + 0x6d11, 0x2009, 0x0000, 0xa294, 0x00ff, 0x1078, 0x22f9, 0x0078, + 0x6d15, 0xa085, 0x0001, 0x0078, 0x6d16, 0xa006, 0x0d7f, 0x007c, + 0x2069, 0x7b8d, 0x6800, 0xa082, 0x0010, 0x00c8, 0x6d25, 0x6013, + 0x0000, 0xa085, 0x0001, 0x0078, 0x6d26, 0xa006, 0x007c, 0x6013, + 0x0000, 0x2069, 0x7b8c, 0x6808, 0xa084, 0xff00, 0xa086, 0x0800, + 0x007c, 0x6004, 0xa0b2, 0x0030, 0x10c8, 0x12cd, 0xa1b6, 0x0013, + 0x00c0, 0x6d3d, 0x2008, 0x0079, 0x6d50, 0xa1b6, 0x0027, 0x0040, + 0x6d45, 0xa1b6, 0x0014, 0x10c0, 0x12cd, 0x2001, 0x0007, 0x1078, + 0x37d7, 0x1078, 0x4b79, 0x1078, 0x6a96, 0x1078, 0x4c72, 0x007c, + 0x6d80, 0x6d82, 0x6d80, 0x6d80, 0x6d80, 0x6d82, 0x6d8a, 0x6ded, + 0x6db0, 0x6ded, 0x6dc4, 0x6ded, 0x6d8a, 0x6ded, 0x6de5, 0x6ded, + 0x6de5, 0x6ded, 0x6ded, 0x6d80, 0x6d80, 0x6d80, 0x6d80, 0x6d80, + 0x6d80, 0x6d80, 0x6d80, 0x6d80, 0x6d80, 0x6d80, 0x6d80, 0x6d80, + 0x6ded, 0x6d80, 0x6d80, 0x6ded, 0x6d80, 0x6ded, 0x6ded, 0x6d80, + 0x6d80, 0x6d80, 0x6d80, 0x6ded, 0x6ded, 0x6d80, 0x6ded, 0x6ded, + 0x1078, 0x12cd, 0x1078, 0x4b79, 0x6003, 0x0002, 0x1078, 0x4c72, + 0x0078, 0x6df3, 0x0f7e, 0x2079, 0x7651, 0x7804, 0x0f7f, 0xd0ac, + 0x00c0, 0x6ded, 0x2001, 0x0000, 0x1078, 0x37b5, 0x2001, 0x0002, + 0x1078, 0x37c9, 0x1078, 0x4b79, 0x601f, 0x0001, 0x6003, 0x0001, + 0x6007, 0x0002, 0x1078, 0x486a, 0x1078, 0x4c72, 0x0c7e, 0x6118, + 0x2160, 0x2009, 0x0001, 0x1078, 0x4573, 0x0c7f, 0x0078, 0x6df3, + 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, 0xff00, 0x8637, + 0xa686, 0x0006, 0x0040, 0x6ded, 0xa686, 0x0004, 0x0040, 0x6ded, + 0x2001, 0x0004, 0x0078, 0x6deb, 0x2001, 0x7600, 0x2004, 0xa086, + 0x0003, 0x00c0, 0x6dcd, 0x1078, 0x2db9, 0x2001, 0x0006, 0x1078, + 0x6df4, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0006, 0x0040, 0x6ded, 0x2001, 0x0006, 0x0078, + 0x6deb, 0x2001, 0x0004, 0x0078, 0x6deb, 0x2001, 0x0006, 0x1078, + 0x6df4, 0x0078, 0x6ded, 0x1078, 0x37d7, 0x1078, 0x4b79, 0x1078, + 0x5bfa, 0x1078, 0x4c72, 0x007c, 0x017e, 0x0d7e, 0x6118, 0x2168, + 0x6900, 0xd184, 0x0040, 0x6e0f, 0x6104, 0xa18e, 0x000a, 0x00c0, + 0x6e07, 0x699c, 0xd1a4, 0x00c0, 0x6e07, 0x2001, 0x0007, 0x1078, + 0x37c9, 0x2001, 0x0000, 0x1078, 0x37b5, 0x1078, 0x22d7, 0x0d7f, + 0x017f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, 0xff00, + 0x8007, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x12cd, 0xa1b6, 0x0015, + 0x00c0, 0x6e26, 0x1079, 0x6e2d, 0x0078, 0x6e2c, 0xa1b6, 0x0016, + 0x10c0, 0x12cd, 0x1079, 0x6e65, 0x007c, 0x5ed7, 0x5ed7, 0x5ed7, + 0x5ed7, 0x5ed7, 0x5ed7, 0x5ed7, 0x6e39, 0x5ed7, 0x5ed7, 0x5ed7, + 0x5ed7, 0x0f7e, 0x2079, 0x7651, 0x7804, 0x0f7f, 0xd0ac, 0x00c0, + 0x6e55, 0x2001, 0x0000, 0x1078, 0x37b5, 0x2001, 0x0002, 0x1078, + 0x37c9, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, + 0x486a, 0x1078, 0x4c72, 0x0078, 0x6e64, 0x2011, 0x7b83, 0x220c, + 0x017e, 0x0c7e, 0x1078, 0x381d, 0x00c0, 0x6e64, 0x1078, 0x3619, + 0x0c7f, 0x017f, 0x1078, 0x5bfa, 0x007c, 0x5ed7, 0x5ed7, 0x5ed7, + 0x5ed7, 0x5ed7, 0x5ed7, 0x5ed7, 0x6e71, 0x5ed7, 0x5ed7, 0x5ed7, + 0x5ed7, 0x1078, 0x60c7, 0x00c0, 0x6e7d, 0x6003, 0x0001, 0x6007, + 0x0001, 0x1078, 0x486a, 0x0078, 0x6e7f, 0x1078, 0x5bfa, 0x007c, + 0x6004, 0xa08a, 0x0030, 0x10c8, 0x12cd, 0x1078, 0x4b79, 0x1078, + 0x6a96, 0x1078, 0x4c72, 0x007c, 0xa182, 0x0040, 0x0079, 0x6e90, + 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea2, 0x6ea0, 0x6ea0, 0x6ea0, + 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0, + 0x1078, 0x12cd, 0x0d7e, 0x0e7e, 0x0f7e, 0x157e, 0x047e, 0x027e, + 0x6106, 0x2071, 0x7b80, 0x7444, 0xa4a4, 0xe600, 0x0040, 0x6f13, + 0xa486, 0x2000, 0x0040, 0x6ed2, 0xa486, 0x0400, 0x0040, 0x6ed2, + 0x7130, 0xa18c, 0x00ff, 0xa182, 0x0010, 0x00c8, 0x6fa5, 0x0c7e, + 0x1078, 0x4604, 0x2c68, 0x0c7f, 0x6a00, 0xa284, 0x0001, 0x0040, + 0x6f86, 0x1078, 0x46c2, 0x0040, 0x6fb1, 0xa295, 0x0200, 0x6a02, + 0x0078, 0x6ed8, 0x2009, 0x0001, 0x2011, 0x0200, 0x1078, 0x46ac, + 0x1078, 0x1327, 0x1040, 0x12cd, 0x6003, 0x0007, 0x2d00, 0x6837, + 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e, + 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0xa18c, 0x00ff, 0xa10d, + 0x6946, 0x684f, 0x0000, 0x6857, 0x0036, 0x1078, 0x3a72, 0xa486, + 0x2000, 0x00c0, 0x6f01, 0x2019, 0x0017, 0x1078, 0x74ce, 0x0078, + 0x6f73, 0xa486, 0x0400, 0x00c0, 0x6f0b, 0x2019, 0x0002, 0x1078, + 0x74ce, 0x0078, 0x6f73, 0xa486, 0x0200, 0x00c0, 0x6f11, 0x1078, + 0x74bf, 0x0078, 0x6f73, 0x7130, 0xa184, 0xff00, 0x00c0, 0x6fc5, + 0xa18c, 0x00ff, 0xa182, 0x0010, 0x00c8, 0x6fc5, 0x0c7e, 0x1078, + 0x4604, 0x2c68, 0x0c7f, 0x6a00, 0xa284, 0x0001, 0x0040, 0x6fc9, + 0xa284, 0x0300, 0x00c0, 0x6fc1, 0x6804, 0xa005, 0x0040, 0x6fb1, + 0x8001, 0x6806, 0x6003, 0x0007, 0x1078, 0x130c, 0x0040, 0x6f7a, + 0x6013, 0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, + 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, 0xa10d, 0x6946, + 0x6853, 0x003d, 0x7044, 0xa084, 0x0003, 0xa086, 0x0002, 0x00c0, + 0x6f55, 0x684f, 0x0040, 0x0078, 0x6f5f, 0xa086, 0x0001, 0x00c0, + 0x6f5d, 0x684f, 0x0080, 0x0078, 0x6f5f, 0x684f, 0x0000, 0x20a9, + 0x000a, 0x2001, 0x7b90, 0xad90, 0x0015, 0x200c, 0x810f, 0x2112, + 0x8000, 0x8210, 0x00f0, 0x6f65, 0x200c, 0x6982, 0x8000, 0x200c, + 0x697e, 0x1078, 0x3a72, 0x027f, 0x047f, 0x157f, 0x0f7f, 0x0e7f, + 0x0d7f, 0x007c, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, + 0x1078, 0x481d, 0x1078, 0x4c72, 0x0078, 0x6f73, 0x2069, 0x7b92, + 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200, 0x00c0, 0x6fa5, 0x2069, + 0x7b80, 0x686c, 0xa084, 0x00ff, 0x017e, 0x6110, 0xa18c, 0x0700, + 0xa10d, 0x6112, 0x017f, 0x6003, 0x0001, 0x6007, 0x0043, 0x1078, + 0x481d, 0x1078, 0x4c72, 0x0078, 0x6f73, 0x6013, 0x0200, 0x6003, + 0x0001, 0x6007, 0x0041, 0x1078, 0x481d, 0x1078, 0x4c72, 0x0078, + 0x6f73, 0x6013, 0x0300, 0x0078, 0x6fb7, 0x6013, 0x0100, 0x6003, + 0x0001, 0x6007, 0x0041, 0x1078, 0x481d, 0x1078, 0x4c72, 0x0078, + 0x6f73, 0x6013, 0x0500, 0x0078, 0x6fb7, 0x6013, 0x0600, 0x0078, + 0x6f86, 0x6013, 0x0200, 0x0078, 0x6f86, 0xa186, 0x0013, 0x00c0, + 0x6fdf, 0x6004, 0xa08a, 0x0040, 0x1048, 0x12cd, 0xa08a, 0x0050, + 0x10c8, 0x12cd, 0xa082, 0x0040, 0x2008, 0x0079, 0x7010, 0xa186, + 0x0047, 0x00c0, 0x6fe5, 0x0078, 0x703f, 0xa186, 0x0027, 0x0040, + 0x6fed, 0xa186, 0x0014, 0x10c0, 0x12cd, 0x6004, 0xa082, 0x0040, + 0x2008, 0x0079, 0x6ff3, 0x7003, 0x7005, 0x7005, 0x7003, 0x7003, + 0x7003, 0x7003, 0x7003, 0x7003, 0x7003, 0x7003, 0x7003, 0x7003, + 0x7003, 0x7003, 0x7003, 0x1078, 0x12cd, 0x2001, 0x0007, 0x1078, + 0x37d7, 0x1078, 0x4b79, 0x1078, 0x6a96, 0x1078, 0x4c72, 0x007c, + 0x7020, 0x7030, 0x7029, 0x7039, 0x7020, 0x7020, 0x7020, 0x7020, + 0x7020, 0x7020, 0x7020, 0x7020, 0x7020, 0x7020, 0x7020, 0x7020, + 0x1078, 0x12cd, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, + 0x200a, 0x1078, 0x4b79, 0x6003, 0x0002, 0x1078, 0x4c72, 0x007c, + 0x1078, 0x4b79, 0x1078, 0x4685, 0x1078, 0x5bfa, 0x1078, 0x4c72, + 0x007c, 0x1078, 0x4b79, 0x2009, 0x0041, 0x0078, 0x7107, 0xa182, + 0x0040, 0x0079, 0x7043, 0x7053, 0x7055, 0x7053, 0x7053, 0x7053, + 0x7053, 0x7053, 0x7056, 0x7053, 0x7053, 0x7053, 0x7053, 0x7053, + 0x7053, 0x7053, 0x7053, 0x1078, 0x12cd, 0x007c, 0x6003, 0x0004, + 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x156a, + 0x007c, 0xa182, 0x0040, 0x0079, 0x7065, 0x7075, 0x7075, 0x7075, + 0x7075, 0x7075, 0x7075, 0x7075, 0x7075, 0x7075, 0x7077, 0x709a, + 0x7075, 0x7075, 0x7075, 0x7075, 0x709a, 0x1078, 0x12cd, 0x1078, + 0x4c21, 0x1078, 0x4d32, 0x6010, 0x0d7e, 0x2068, 0x684c, 0xd0fc, + 0x0040, 0x708d, 0xa08c, 0x0003, 0xa18e, 0x0002, 0x0040, 0x7093, + 0x2009, 0x0041, 0x0d7f, 0x0078, 0x7107, 0x6003, 0x0007, 0x1078, + 0x4685, 0x0d7f, 0x007c, 0x1078, 0x4685, 0x1078, 0x5bfa, 0x0d7f, + 0x0078, 0x7092, 0x037e, 0x1078, 0x4c21, 0x1078, 0x4d32, 0x6010, + 0x0d7e, 0x2068, 0x2019, 0x0004, 0x1078, 0x74f2, 0x1078, 0x6a96, + 0x6017, 0x0028, 0x0d7f, 0x037f, 0x007c, 0xa186, 0x0013, 0x00c0, + 0x70bb, 0x6004, 0xa086, 0x0042, 0x10c0, 0x12cd, 0x1078, 0x4b79, + 0x1078, 0x4c72, 0x007c, 0xa186, 0x0027, 0x0040, 0x70c3, 0xa186, + 0x0014, 0x00c0, 0x70d3, 0x6004, 0xa086, 0x0042, 0x10c0, 0x12cd, + 0x2001, 0x0007, 0x1078, 0x37d7, 0x1078, 0x4b79, 0x1078, 0x6a96, + 0x1078, 0x4c72, 0x007c, 0xa182, 0x0040, 0x0079, 0x70d7, 0x70e7, + 0x70e7, 0x70e7, 0x70e7, 0x70e7, 0x70e7, 0x70e7, 0x70e9, 0x70f5, + 0x70e7, 0x70e7, 0x70e7, 0x70e7, 0x70e7, 0x70e7, 0x70e7, 0x1078, + 0x12cd, 0x037e, 0x047e, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, + 0x1078, 0x156a, 0x047f, 0x037f, 0x007c, 0x6010, 0x0d7e, 0x2068, + 0x684c, 0xd0fc, 0x0040, 0x7101, 0x2009, 0x0041, 0x0d7f, 0x0078, + 0x7107, 0x6003, 0x0007, 0x1078, 0x4685, 0x0d7f, 0x007c, 0xa182, + 0x0040, 0x0079, 0x710b, 0x711b, 0x711d, 0x7129, 0x7135, 0x711b, + 0x711b, 0x711b, 0x711b, 0x711b, 0x711b, 0x711b, 0x711b, 0x711b, + 0x711b, 0x711b, 0x711b, 0x1078, 0x12cd, 0x6003, 0x0001, 0x6106, + 0x1078, 0x481d, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c72, 0x127f, + 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, 0x481d, 0x127e, 0x2091, + 0x8000, 0x1078, 0x4c72, 0x127f, 0x007c, 0x6003, 0x0003, 0x6106, + 0x2c10, 0x1078, 0x19c7, 0x127e, 0x2091, 0x8000, 0x1078, 0x4889, + 0x1078, 0x4d32, 0x127f, 0x007c, 0x1078, 0x4b79, 0x0078, 0x714a, + 0x1078, 0x4c21, 0x6110, 0x81ff, 0x0040, 0x7157, 0x0d7e, 0x2168, + 0x037e, 0x2019, 0x0029, 0x1078, 0x74f2, 0x037f, 0x0d7f, 0x1078, + 0x6a96, 0x1078, 0x4c72, 0x007c, 0xa182, 0x0085, 0x0079, 0x7160, + 0x7167, 0x7167, 0x7167, 0x7169, 0x7167, 0x7167, 0x7167, 0x1078, + 0x12cd, 0x027e, 0x0e7e, 0x2071, 0x7b80, 0x7220, 0x1078, 0x740c, + 0x0040, 0x7176, 0x6007, 0x0086, 0x0078, 0x7178, 0x6007, 0x0087, + 0x6003, 0x0001, 0x1078, 0x481d, 0x1078, 0x4c72, 0x0e7f, 0x027f, + 0x007c, 0xa186, 0x0013, 0x00c0, 0x7192, 0x6004, 0xa08a, 0x0085, + 0x1048, 0x12cd, 0xa08a, 0x008c, 0x10c8, 0x12cd, 0xa082, 0x0085, + 0x0079, 0x71a5, 0xa186, 0x0027, 0x0040, 0x719a, 0xa186, 0x0014, + 0x10c0, 0x12cd, 0x2001, 0x0007, 0x1078, 0x37d7, 0x1078, 0x4b79, + 0x1078, 0x6a96, 0x1078, 0x4c72, 0x007c, 0x71ac, 0x71ae, 0x71ae, + 0x71ac, 0x71ac, 0x71ac, 0x71ac, 0x1078, 0x12cd, 0x1078, 0x4b79, + 0x1078, 0x5bfa, 0x1078, 0x4c72, 0x007c, 0xa182, 0x0085, 0x1048, + 0x12cd, 0xa182, 0x008c, 0x10c8, 0x12cd, 0xa182, 0x0085, 0x0079, + 0x71c1, 0x71c8, 0x71c8, 0x71c8, 0x71ca, 0x71c8, 0x71c8, 0x71c8, + 0x1078, 0x12cd, 0x007c, 0x1078, 0x4b79, 0x1078, 0x6a96, 0x1078, + 0x4c72, 0x007c, 0x037e, 0x2019, 0x000b, 0x1078, 0x71db, 0x601f, + 0x0006, 0x037f, 0x007c, 0x127e, 0x037e, 0x087e, 0x2091, 0x8000, + 0x2c40, 0x1078, 0x590d, 0x00c0, 0x7208, 0x1078, 0x59ae, 0x00c0, + 0x7208, 0x6000, 0xa086, 0x0000, 0x0040, 0x7208, 0x601c, 0xa086, + 0x0007, 0x0040, 0x7208, 0x0d7e, 0x6000, 0xa086, 0x0004, 0x00c0, + 0x71fb, 0x1078, 0x166e, 0x6010, 0x2068, 0x1078, 0x6938, 0x0040, + 0x7203, 0x1078, 0x74f2, 0x0d7f, 0x6013, 0x0000, 0x601f, 0x0007, + 0x087f, 0x037f, 0x127f, 0x007c, 0x0f7e, 0x0c7e, 0x037e, 0x157e, + 0x2079, 0x7b80, 0x7838, 0xa08c, 0x00ff, 0x783c, 0x1078, 0x207f, + 0x00c0, 0x7243, 0x017e, 0x0c7e, 0x1078, 0x381d, 0x00c0, 0x7243, + 0x2011, 0x7b90, 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x6160, + 0x00c0, 0x7243, 0x017f, 0x027f, 0x027e, 0x017e, 0x2019, 0x0029, + 0x1078, 0x5a82, 0x1078, 0x495a, 0x1078, 0x489d, 0x017f, 0x1078, + 0x7370, 0x1078, 0x399e, 0x017f, 0x1078, 0x3619, 0x6612, 0x6516, + 0xa006, 0x0078, 0x7245, 0x0c7f, 0x017f, 0x157f, 0x037f, 0x0c7f, + 0x0f7f, 0x007c, 0x0c7e, 0x0d7e, 0x017e, 0x2009, 0x761e, 0x2104, + 0xa086, 0x0074, 0x00c0, 0x72a1, 0x2069, 0x7b8e, 0x690c, 0xa182, + 0x0100, 0x0048, 0x7291, 0x6908, 0xa184, 0x8000, 0x0040, 0x729d, + 0xa184, 0x0800, 0x0040, 0x729d, 0x6910, 0xa18a, 0x0001, 0x0048, + 0x7295, 0x6914, 0x2069, 0x7bae, 0x6904, 0x81ff, 0x00c0, 0x7289, + 0x690c, 0xa182, 0x0100, 0x0048, 0x7291, 0x6908, 0x81ff, 0x00c0, + 0x728d, 0x6910, 0xa18a, 0x0001, 0x0048, 0x7295, 0x6918, 0xa18a, + 0x0001, 0x0048, 0x729d, 0x0078, 0x72a7, 0x6013, 0x0100, 0x0078, + 0x72a3, 0x6013, 0x0300, 0x0078, 0x72a3, 0x6013, 0x0500, 0x0078, + 0x72a3, 0x6013, 0x0700, 0x0078, 0x72a3, 0x6013, 0x0900, 0x0078, + 0x72a3, 0x6013, 0x0b00, 0x0078, 0x72a3, 0x6013, 0x0f00, 0x0078, + 0x72a3, 0x6013, 0x2d00, 0xa085, 0x0001, 0x0078, 0x72a8, 0xa006, + 0x017f, 0x0d7f, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x027e, 0x037e, + 0x157e, 0x6218, 0x2268, 0x6b04, 0xa394, 0x00ff, 0xa286, 0x0006, + 0x0040, 0x72d0, 0xa286, 0x0004, 0x0040, 0x72d0, 0xa394, 0xff00, + 0x8217, 0xa286, 0x0006, 0x0040, 0x72d0, 0xa286, 0x0004, 0x0040, + 0x72d0, 0x0c7e, 0x2d60, 0x1078, 0x382f, 0x0c7f, 0x0078, 0x7303, + 0x2011, 0x7b96, 0xad98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x6160, + 0x00c0, 0x7304, 0x2011, 0x7b9a, 0xad98, 0x0006, 0x20a9, 0x0004, + 0x1078, 0x6160, 0x00c0, 0x7304, 0x047e, 0x017e, 0x6aa0, 0xa294, + 0x00ff, 0x8227, 0xa006, 0x2009, 0x7652, 0x210c, 0xd1a4, 0x0040, + 0x72f8, 0x2009, 0x0029, 0x1078, 0x7536, 0x6800, 0xc0e5, 0x6802, + 0x2019, 0x0029, 0x1078, 0x495a, 0x1078, 0x489d, 0x2c08, 0x1078, + 0x7370, 0x017f, 0x047f, 0xa006, 0x157f, 0x037f, 0x027f, 0x0d7f, + 0x0c7f, 0x007c, 0x0d7e, 0x2069, 0x7b8e, 0x6800, 0xa086, 0x0800, + 0x0040, 0x7316, 0x6013, 0x0000, 0x0078, 0x7317, 0xa006, 0x0d7f, + 0x007c, 0x0c7e, 0x0f7e, 0x017e, 0x027e, 0x037e, 0x157e, 0x2079, + 0x7b8c, 0x7930, 0x7834, 0x1078, 0x207f, 0x00c0, 0x733d, 0x1078, + 0x381d, 0x00c0, 0x733d, 0x2011, 0x7b90, 0xac98, 0x000a, 0x20a9, + 0x0004, 0x1078, 0x6160, 0x00c0, 0x733d, 0x2011, 0x7b94, 0xac98, + 0x0006, 0x20a9, 0x0004, 0x1078, 0x6160, 0x157f, 0x037f, 0x027f, + 0x017f, 0x0f7f, 0x0c7f, 0x007c, 0x0c7e, 0x007e, 0x017e, 0x027e, + 0x037e, 0x157e, 0x2011, 0x7b83, 0x2204, 0x8211, 0x220c, 0x1078, + 0x207f, 0x00c0, 0x7369, 0x1078, 0x381d, 0x00c0, 0x7369, 0x2011, + 0x7b96, 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x6160, 0x00c0, + 0x7369, 0x2011, 0x7b9a, 0xac98, 0x0006, 0x20a9, 0x0004, 0x1078, + 0x6160, 0x157f, 0x037f, 0x027f, 0x017f, 0x007f, 0x0c7f, 0x007c, + 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x057e, 0x047e, 0x027e, 0x127e, + 0x2091, 0x8000, 0x2029, 0x783f, 0x252c, 0x2021, 0x7845, 0x2424, + 0x2061, 0x7d00, 0x2071, 0x7600, 0x7644, 0x7060, 0x8001, 0xa602, + 0x00c8, 0x73d5, 0x2100, 0xac06, 0x0040, 0x73cb, 0x1078, 0x754e, + 0x0040, 0x73cb, 0x671c, 0xa786, 0x0001, 0x0040, 0x73ea, 0xa786, + 0x0007, 0x0040, 0x73cb, 0x2500, 0xac06, 0x0040, 0x73cb, 0x2400, + 0xac06, 0x0040, 0x73cb, 0x1078, 0x7562, 0x00c0, 0x73cb, 0x0d7e, + 0x6000, 0xa086, 0x0004, 0x00c0, 0x73b1, 0x017e, 0x1078, 0x166e, + 0x017f, 0x6010, 0x2068, 0x1078, 0x6938, 0x0040, 0x73c8, 0xa786, + 0x0003, 0x00c0, 0x73de, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x017e, 0x1078, 0x6b34, 0x1078, 0x3a72, 0x017f, 0x1078, 0x6a89, + 0x0d7f, 0x1078, 0x6a96, 0xace0, 0x0008, 0x2001, 0x7615, 0x2004, + 0xac02, 0x00c8, 0x73d5, 0x0078, 0x7382, 0x127f, 0x027f, 0x047f, + 0x057f, 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x007c, 0xa786, 0x0006, + 0x00c0, 0x73bb, 0xa386, 0x0005, 0x0040, 0x73cb, 0x1078, 0x74f2, + 0x0078, 0x73c8, 0x1078, 0x7562, 0x00c0, 0x73cb, 0xa180, 0x0001, + 0x2004, 0xa086, 0x0018, 0x00c0, 0x73cb, 0x6000, 0xa086, 0x0002, + 0x00c0, 0x73cb, 0x1078, 0x6aaf, 0x0040, 0x7406, 0x1078, 0x6ac3, + 0x00c0, 0x73cb, 0x1078, 0x5e4d, 0x0078, 0x7408, 0x1078, 0x22d7, + 0x1078, 0x6a96, 0x0078, 0x73cb, 0x0c7e, 0x0e7e, 0x017e, 0x2c08, + 0x2170, 0x1078, 0x7509, 0x017f, 0x0040, 0x741b, 0x601c, 0xa084, + 0x000f, 0x1079, 0x741e, 0x0e7f, 0x0c7f, 0x007c, 0x7426, 0x7426, + 0x7426, 0x7426, 0x7426, 0x7426, 0x7428, 0x7426, 0xa006, 0x007c, + 0x047e, 0x017e, 0x7018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, + 0x8427, 0x2c00, 0x2009, 0x0020, 0x1078, 0x7536, 0x017f, 0x047f, + 0x037e, 0x2019, 0x0002, 0x1078, 0x71db, 0x037f, 0xa085, 0x0001, + 0x007c, 0x2001, 0x0001, 0x1078, 0x37b5, 0x157e, 0x017e, 0x027e, + 0x037e, 0x20a9, 0x0004, 0x2019, 0x7605, 0x2011, 0x7b96, 0x1078, + 0x6160, 0x037f, 0x027f, 0x017f, 0x157f, 0xa005, 0x007c, 0x0f7e, + 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x027e, 0x127e, 0x2091, 0x8000, + 0x2061, 0x7d00, 0x2079, 0x0001, 0x8fff, 0x0040, 0x74b2, 0x2071, + 0x7600, 0x7644, 0x7060, 0x8001, 0xa602, 0x00c8, 0x74b2, 0x88ff, + 0x0040, 0x7478, 0x2800, 0xac06, 0x00c0, 0x74a8, 0x2079, 0x0000, + 0x1078, 0x754e, 0x0040, 0x74a8, 0x2400, 0xac06, 0x0040, 0x74a8, + 0x671c, 0xa786, 0x0006, 0x00c0, 0x74a8, 0xa786, 0x0007, 0x0040, + 0x74a8, 0x88ff, 0x00c0, 0x7490, 0x6018, 0xa206, 0x00c0, 0x74a8, + 0x0d7e, 0x6000, 0xa086, 0x0004, 0x00c0, 0x7498, 0x1078, 0x166e, + 0x6010, 0x2068, 0x1078, 0x6938, 0x0040, 0x74a2, 0x047e, 0x1078, + 0x74f2, 0x047f, 0x0d7f, 0x1078, 0x6a96, 0x88ff, 0x00c0, 0x74bb, + 0xace0, 0x0008, 0x2001, 0x7615, 0x2004, 0xac02, 0x00c8, 0x74b2, + 0x0078, 0x7464, 0xa006, 0x127f, 0x027f, 0x067f, 0x077f, 0x0c7f, + 0x0e7f, 0x0f7f, 0x007c, 0xa8c5, 0x0001, 0x0078, 0x74b3, 0x087e, + 0x2041, 0x0000, 0x2c20, 0x2019, 0x0002, 0x6218, 0x1078, 0x590d, + 0x1078, 0x59ae, 0x1078, 0x7457, 0x087f, 0x007c, 0x027e, 0x047e, + 0x087e, 0x0c7e, 0x157e, 0x2c20, 0x20a9, 0x007f, 0x2009, 0x0000, + 0x017e, 0x037e, 0x1078, 0x381d, 0x00c0, 0x74e7, 0x2c10, 0x2041, + 0x0000, 0x1078, 0x590d, 0x1078, 0x59ae, 0x1078, 0x7457, 0x037f, + 0x017f, 0x8108, 0x00f0, 0x74d8, 0x157f, 0x0c7f, 0x087f, 0x047f, + 0x027f, 0x007c, 0x017e, 0x0f7e, 0x8dff, 0x0040, 0x7506, 0x6800, + 0xa07d, 0x0040, 0x7503, 0x6803, 0x0000, 0x6b52, 0x1078, 0x3a72, + 0x2f68, 0x0078, 0x74f7, 0x6b52, 0x1078, 0x3a72, 0x0f7f, 0x017f, + 0x007c, 0x0e7e, 0x047e, 0x037e, 0x2061, 0x7d00, 0x2071, 0x7600, + 0x7444, 0x7060, 0x8001, 0xa402, 0x00c8, 0x7531, 0x2100, 0xac06, + 0x0040, 0x7523, 0x6000, 0xa086, 0x0000, 0x0040, 0x7523, 0x6008, + 0xa206, 0x0040, 0x752d, 0xace0, 0x0008, 0x2001, 0x7615, 0x2004, + 0xac02, 0x00c8, 0x7531, 0x0078, 0x750e, 0xa085, 0x0001, 0x0078, + 0x7532, 0xa006, 0x037f, 0x047f, 0x0e7f, 0x007c, 0x0d7e, 0x007e, + 0x1078, 0x1327, 0x007f, 0x1040, 0x12cd, 0x6837, 0x010d, 0x6803, + 0x0000, 0x683b, 0x0000, 0x685b, 0x0000, 0x685e, 0x6956, 0x6c46, + 0x684f, 0x0000, 0x1078, 0x3a72, 0x0d7f, 0x007c, 0x6700, 0xa786, + 0x0000, 0x0040, 0x7561, 0xa786, 0x0001, 0x0040, 0x7561, 0xa786, + 0x000a, 0x0040, 0x7561, 0xa786, 0x0009, 0x0040, 0x7561, 0xa085, + 0x0001, 0x007c, 0x0e7e, 0x6018, 0x2070, 0x70a0, 0xa206, 0x0e7f, + 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x7640, + 0xd5a4, 0x0040, 0x7576, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, + 0x757c, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0040, 0x7583, 0x2071, + 0x764a, 0x1078, 0x75b2, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, + 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x7640, 0xd5a4, 0x0040, + 0x7594, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, 0x759a, 0x7030, + 0x8000, 0x7032, 0xd5ac, 0x0040, 0x75a1, 0x2071, 0x764a, 0x1078, + 0x75b2, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e, + 0x2091, 0x8000, 0x2071, 0x7642, 0x1078, 0x75b2, 0x0e7f, 0x007f, + 0x127f, 0x007c, 0x2e04, 0x8000, 0x2072, 0x00c8, 0x75bb, 0x8e70, + 0x2e04, 0x8000, 0x2072, 0x007c, 0x0e7e, 0x2071, 0x7640, 0x1078, + 0x75b2, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0x7644, 0x1078, 0x75b2, + 0x0e7f, 0x007c, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, + 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, + 0x4000, 0x8000, 0x2212 +}; + +/* + * Firmware Version 2.00.16 (09:36 Jun 29, 1999) + */ + +unsigned short risc_code2200[] = { + 0x0470, 0x0000, 0x0000, 0x81bd, 0x0000, 0x0002, 0x0000, 0x0010, + 0x0027, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939, + 0x3920, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241, + 0x5449, 0x4f4e, 0x2049, 0x5350, 0x3232, 0x3030, 0x2046, 0x6972, + 0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, + 0x322e, 0x3030, 0x2e31, 0x3620, 0x2020, 0x2020, 0x2400, 0x20c1, + 0x0005, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, 0x96ff, 0x2091, + 0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x2490, + 0x2051, 0x9200, 0x2a70, 0x2029, 0xb100, 0x2031, 0xffff, 0x2039, + 0xb0f5, 0x2021, 0x0200, 0x0804, 0x136b, 0x20a1, 0x91bd, 0xa00e, + 0x20a9, 0x0743, 0x41a4, 0x3400, 0x755e, 0x7662, 0x775a, 0x7466, + 0x746a, 0x20a1, 0x9900, 0x7160, 0x810d, 0x810d, 0x810d, 0x810d, + 0xa18c, 0x000f, 0x2001, 0x0009, 0xa112, 0xa00e, 0x21a8, 0x41a4, + 0x3400, 0x8211, 0x1dd8, 0x7160, 0x3400, 0xa102, 0x0120, 0x0218, + 0x20a8, 0xa00e, 0x41a4, 0x3800, 0xd08c, 0x01d8, 0x2009, 0x9200, + 0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0001, + 0xa112, 0x20a1, 0x1000, 0xa00e, 0x21a8, 0x41a4, 0x8211, 0x1de0, + 0x2009, 0x9200, 0x3400, 0xa102, 0x0120, 0x0218, 0x20a8, 0xa00e, + 0x41a4, 0x080c, 0x1322, 0x080c, 0x14b6, 0x080c, 0x1649, 0x080c, + 0x1c81, 0x080c, 0x41d4, 0x080c, 0x7494, 0x080c, 0x1439, 0x080c, + 0x2819, 0x080c, 0x4e42, 0x080c, 0x4757, 0x080c, 0x5874, 0x080c, + 0x56c0, 0x080c, 0x2138, 0x080c, 0x5ed0, 0x080c, 0x532f, 0x080c, + 0x206a, 0x080c, 0x210e, 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, + 0x36d4, 0x080c, 0x2840, 0x080c, 0x4e90, 0x080c, 0x493b, 0x080c, + 0x58b1, 0x080c, 0x56d8, 0x0c70, 0x000b, 0x0c88, 0x10e8, 0x10e9, + 0x11b8, 0x10e6, 0x123f, 0x131f, 0x1320, 0x1321, 0x080c, 0x13fe, + 0x0005, 0x0126, 0x00f6, 0x2091, 0x8000, 0x080c, 0x4dc5, 0x0150, + 0x080c, 0x4deb, 0x11f8, 0x2079, 0x0100, 0x7828, 0xa085, 0x1800, + 0x782a, 0x00c0, 0x080c, 0x4d10, 0x7088, 0xa086, 0x0026, 0x1904, + 0x119d, 0x2079, 0x0100, 0x7827, 0xffff, 0x782b, 0x1c2b, 0x2011, + 0x4ce2, 0x080c, 0x5731, 0x2011, 0x8030, 0x2019, 0x0000, 0x7087, + 0x0000, 0x00a8, 0x080c, 0x3a6a, 0x2079, 0x0100, 0x7844, 0xa005, + 0x1904, 0x119d, 0x2011, 0x40af, 0x080c, 0x5731, 0x780f, 0x03ff, + 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011, 0x8010, 0x73c4, 0x080c, + 0x3698, 0x080c, 0x706b, 0x2011, 0x0004, 0x080c, 0x82f3, 0x080c, + 0x46a8, 0x080c, 0x4dc5, 0x0158, 0x080c, 0x41bd, 0x0140, 0x7087, + 0x0001, 0x70bf, 0x0000, 0x080c, 0x3bfd, 0x0804, 0x119d, 0x70d3, + 0x0000, 0x70cf, 0x0000, 0x706f, 0x0000, 0x7073, 0x0000, 0x080c, + 0x11a0, 0x72c8, 0x080c, 0x4dc5, 0x1160, 0x2011, 0x0000, 0x2001, + 0x0204, 0x2004, 0x2019, 0x94c8, 0x201a, 0x704f, 0xffff, 0x7053, + 0x00ef, 0x2079, 0x9251, 0x7804, 0xd0ac, 0x0108, 0xc295, 0x72ca, + 0x080c, 0x4dc5, 0x0118, 0xa296, 0x0004, 0x0500, 0x2011, 0x0001, + 0x080c, 0x82f3, 0x080c, 0x854a, 0x7097, 0x0000, 0x709b, 0xffff, + 0x7003, 0x0002, 0x00fe, 0x080c, 0x251c, 0x2011, 0x0005, 0x080c, + 0x718f, 0x080c, 0x6462, 0x080c, 0x4dc5, 0x0130, 0x00c6, 0x2061, + 0x0100, 0x60e3, 0x0008, 0x00ce, 0x012e, 0x00c8, 0x080c, 0x854a, + 0x7097, 0x0000, 0x709b, 0xffff, 0x7003, 0x0002, 0x2011, 0x0005, + 0x080c, 0x718f, 0x080c, 0x6462, 0x080c, 0x4dc5, 0x0130, 0x00c6, + 0x2061, 0x0100, 0x60e3, 0x0008, 0x00ce, 0x00fe, 0x012e, 0x0005, + 0x00c6, 0x080c, 0x4dc5, 0x1118, 0x20a9, 0x0100, 0x0010, 0x20a9, + 0x0082, 0x080c, 0x4dc5, 0x1118, 0x2009, 0x0000, 0x0010, 0x2009, + 0x007e, 0x080c, 0x441f, 0x8108, 0x1f04, 0x11b1, 0x00ce, 0x0005, + 0x0126, 0x2091, 0x8000, 0x7098, 0xa086, 0xffff, 0x0130, 0x080c, + 0x251c, 0x080c, 0x6462, 0x0804, 0x123d, 0x70c8, 0xd0ac, 0x1110, + 0xd09c, 0x0558, 0xd084, 0x0548, 0x0006, 0x70c8, 0xa084, 0x0030, + 0x000e, 0x1138, 0x00f6, 0x2079, 0x0100, 0x790c, 0xc1b5, 0x790e, + 0x00fe, 0xd08c, 0x01d0, 0x70cc, 0xa086, 0xffff, 0x0190, 0x080c, + 0x25fd, 0x080c, 0x6462, 0x70c8, 0xd094, 0x1904, 0x123d, 0x2011, + 0x0001, 0x2019, 0x0000, 0x080c, 0x2631, 0x080c, 0x6462, 0x0804, + 0x123d, 0x70d0, 0xa005, 0x1904, 0x123d, 0x7094, 0xa005, 0x1904, + 0x123d, 0x70c8, 0xd0a4, 0x0110, 0xd0b4, 0x05f8, 0x2001, 0x9252, + 0x2004, 0xd0ac, 0x01c0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x2009, + 0x0000, 0x0016, 0x080c, 0x4434, 0x1118, 0x6000, 0xd0ec, 0x1138, + 0x001e, 0x8108, 0x1f04, 0x1209, 0x00ce, 0x015e, 0x0020, 0x001e, + 0x00ce, 0x015e, 0x0410, 0x00f6, 0x2079, 0x0100, 0x780c, 0xc0b5, + 0x780e, 0x00fe, 0x7003, 0x0003, 0x709b, 0xffff, 0xa006, 0x080c, + 0x23ba, 0x080c, 0x370a, 0x2001, 0x94e6, 0x2004, 0xa086, 0x0005, + 0x1120, 0x2011, 0x0000, 0x080c, 0x718f, 0x2011, 0x0000, 0x080c, + 0x7199, 0x080c, 0x6462, 0x080c, 0x651c, 0x012e, 0x0005, 0x0016, + 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0x00f7, + 0x080c, 0x4186, 0x7940, 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4, + 0x0110, 0x7827, 0x0040, 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, + 0x0036, 0x0156, 0x7954, 0xd1ac, 0x1904, 0x12a5, 0x080c, 0x4dd7, + 0x0158, 0x080c, 0x4deb, 0x1128, 0x2001, 0x94d7, 0x2003, 0x0000, + 0x0070, 0x080c, 0x4dcd, 0x0dc0, 0x2001, 0x94d7, 0x2003, 0xaaaa, + 0x2001, 0x94d8, 0x2003, 0x0001, 0x080c, 0x4d10, 0x0058, 0x080c, + 0x4dc5, 0x0140, 0x2009, 0x00f8, 0x080c, 0x4186, 0x7843, 0x0090, + 0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c, + 0x4dc5, 0x0138, 0x7824, 0xd0ac, 0x1904, 0x130d, 0x1f04, 0x1284, + 0x0070, 0x7824, 0x080c, 0x4de1, 0x0118, 0xd0ac, 0x1904, 0x130d, + 0xa084, 0x1800, 0x0d98, 0x7003, 0x0001, 0x0804, 0x130d, 0x2001, + 0x0001, 0x080c, 0x23ba, 0x0804, 0x1318, 0x7850, 0xa084, 0x0180, + 0x7852, 0x782f, 0x0020, 0x20a9, 0x0050, 0x1d04, 0x12ad, 0x2091, + 0x6000, 0x1f04, 0x12ad, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, + 0x7852, 0x782f, 0x0000, 0x080c, 0x4dd7, 0x0158, 0x080c, 0x4deb, + 0x1128, 0x2001, 0x94d7, 0x2003, 0x0000, 0x0070, 0x080c, 0x4dcd, + 0x0dc0, 0x2001, 0x94d7, 0x2003, 0xaaaa, 0x2001, 0x94d8, 0x2003, + 0x0001, 0x080c, 0x4d10, 0x0020, 0x2009, 0x00f8, 0x080c, 0x4186, + 0x20a9, 0x000e, 0xe000, 0x1f04, 0x12da, 0x7850, 0xa084, 0x0180, + 0xa085, 0x1400, 0x7852, 0x080c, 0x4dc5, 0x0120, 0x7843, 0x0090, + 0x7843, 0x0010, 0x2019, 0x61a8, 0x7820, 0xd09c, 0x1130, 0x080c, + 0x4dc5, 0x0130, 0x7824, 0xd0ac, 0x11c0, 0x8319, 0x1da8, 0x0080, + 0x7827, 0x1800, 0xe000, 0xe000, 0x7824, 0x080c, 0x4de1, 0x0110, + 0xd0ac, 0x1158, 0xa084, 0x1800, 0x0d80, 0x7003, 0x0001, 0x0028, + 0x2001, 0x0001, 0x080c, 0x23ba, 0x0028, 0x7827, 0x0048, 0x7828, + 0xc09d, 0x782a, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852, + 0x015e, 0x003e, 0x000e, 0x012e, 0x00fe, 0x001e, 0x0005, 0x0005, + 0x0005, 0x0005, 0x2a70, 0x2001, 0x94d7, 0x2003, 0x0000, 0x7087, + 0x0000, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0218, 0x704f, + 0xffff, 0x0010, 0x704f, 0x0000, 0x7057, 0xffff, 0x706f, 0x0000, + 0x7073, 0x0000, 0x080c, 0x854a, 0x2061, 0x94c7, 0x6003, 0x0909, + 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, + 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, 0x07d0, 0x2061, 0x94cf, + 0x6003, 0x8800, 0x6007, 0x0000, 0x600b, 0x0000, 0x600f, 0x0200, + 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001, 0x601f, 0x0000, + 0x2061, 0x94df, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, + 0x600f, 0x2020, 0x0005, 0x04a0, 0x2011, 0x0000, 0x81ff, 0x0570, + 0xa186, 0x0001, 0x1148, 0x2031, 0x8fff, 0x2039, 0xa501, 0x2021, + 0x0100, 0x2029, 0xa500, 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, 0x13a7, 0x0804, 0x13f8, 0x2019, + 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04, + 0xa306, 0x2262, 0x1110, 0xc1b5, 0xc1a5, 0x2011, 0x0000, 0x2019, + 0x13ba, 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, 0x13d5, 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, 0x13f6, 0x0010, 0x0804, 0x136c, + 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0837, 0x2091, 0x8000, + 0x0e04, 0x1400, 0x0006, 0x0016, 0x2079, 0x0000, 0x7818, 0xd084, + 0x1de8, 0x001e, 0x792e, 0x000e, 0x782a, 0x000e, 0x7826, 0x3900, + 0x783a, 0x7823, 0x8002, 0x781b, 0x0001, 0x2091, 0x5000, 0x0156, + 0x0146, 0x20a9, 0x0010, 0x20a1, 0x95e6, 0x2091, 0x2000, 0x40a1, + 0x20a9, 0x0010, 0x2091, 0x2200, 0x40a1, 0x20a9, 0x0010, 0x2091, + 0x2400, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2600, 0x40a1, 0x014e, + 0x015e, 0x2079, 0x9200, 0x7803, 0x0005, 0x2091, 0x4080, 0x0cf8, + 0x0005, 0x2071, 0x9200, 0x715c, 0x712e, 0x2021, 0x0001, 0xa190, + 0x0030, 0xa298, 0x0030, 0x0240, 0x7060, 0xa302, 0x1228, 0x220a, + 0x2208, 0x2310, 0x8420, 0x0ca8, 0x3800, 0xd08c, 0x0148, 0x7060, + 0xa086, 0x9200, 0x0128, 0x7063, 0x9200, 0x2011, 0x1000, 0x0c48, + 0x200b, 0x0000, 0x74aa, 0x74ae, 0x70df, 0x0010, 0x0005, 0x00e6, + 0x0126, 0x2091, 0x8000, 0x2071, 0x9200, 0x70ac, 0x0016, 0x2008, + 0x70dc, 0xa16a, 0x2100, 0x001e, 0x0268, 0x8001, 0x70ae, 0x702c, + 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, + 0x00ee, 0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x2071, 0x9200, 0x0126, + 0x2091, 0x8000, 0x70ac, 0x8001, 0x0260, 0x70ae, 0x702c, 0x2068, + 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, + 0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, + 0x9200, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70ac, 0x8000, 0x70ae, + 0x012e, 0x00ee, 0x0005, 0x8dff, 0x0138, 0x6804, 0x6807, 0x0000, + 0x0006, 0x0c49, 0x00de, 0x0cb8, 0x0005, 0x00e6, 0x2071, 0x9200, + 0x70ac, 0xa08a, 0x0010, 0xa00d, 0x00ee, 0x0005, 0x00e6, 0x2071, + 0x9508, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x2071, + 0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x00ee, 0x0005, 0x00e6, + 0x2270, 0x700b, 0x0000, 0x2071, 0x9508, 0x7018, 0xa088, 0x9511, + 0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, 0x1128, + 0x00f6, 0x2079, 0x0010, 0x0081, 0x00fe, 0x00ee, 0x0005, 0x00e6, + 0x2071, 0x9508, 0x7004, 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, + 0x0019, 0x00fe, 0x00ee, 0x0005, 0x7000, 0x0002, 0x14f3, 0x1557, + 0x1574, 0x1574, 0x1f79, 0x7018, 0x711c, 0xa106, 0x1118, 0x7007, + 0x0000, 0x0005, 0x00d6, 0xa180, 0x9511, 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, 0x930e, 0x20a1, 0x0018, 0x20a9, 0x0008, + 0x53a3, 0x7803, 0x0020, 0x0126, 0x2091, 0x8000, 0x7803, 0x0041, + 0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x700b, 0x9309, 0x012e, + 0x015e, 0x014e, 0x013e, 0x0005, 0x0136, 0x0146, 0x0156, 0x2001, + 0x933d, 0x209c, 0x20a1, 0x0014, 0x7803, 0x0026, 0x2001, 0x933e, + 0x20ac, 0x53a6, 0x2099, 0x933f, 0x20a1, 0x0018, 0x20a9, 0x0008, + 0x53a3, 0x7803, 0x0020, 0x0126, 0x2091, 0x8000, 0x7803, 0x0001, + 0x7007, 0x0004, 0x7000, 0xc08c, 0x7002, 0x700b, 0x933a, 0x012e, + 0x015e, 0x014e, 0x013e, 0x0005, 0x0016, 0x00e6, 0x2071, 0x9508, + 0x00f6, 0x2079, 0x0010, 0x7904, 0x7803, 0x0002, 0xd1fc, 0x0120, + 0xa18c, 0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, + 0x14ec, 0x15b8, 0x15e2, 0x1608, 0x1638, 0x1f96, 0x15b7, 0x0cf8, + 0xa18c, 0x0700, 0x1508, 0x0136, 0x0146, 0x0156, 0x7014, 0x20a0, + 0x2099, 0x0014, 0x7803, 0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400, + 0x7016, 0x015e, 0x014e, 0x013e, 0x700c, 0xa005, 0x0530, 0x080c, + 0x151e, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007, + 0x0000, 0x080c, 0x14ec, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, + 0x0200, 0x0ca8, 0xa18c, 0x0700, 0x1130, 0x700c, 0xa005, 0x0168, + 0x080c, 0x1533, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200, + 0x7007, 0x0000, 0x080c, 0x14ec, 0x0005, 0x00d6, 0x7008, 0x2068, + 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, 0x682e, 0x783c, 0x6832, + 0x680b, 0x0100, 0x00de, 0x7007, 0x0000, 0x080c, 0x14ec, 0x0005, + 0xa18c, 0x0700, 0x1540, 0x0136, 0x0146, 0x0156, 0x2001, 0x930c, + 0x2004, 0xa080, 0x000d, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, + 0x20a9, 0x0020, 0x53a5, 0x2001, 0x930e, 0x2004, 0xd0bc, 0x0148, + 0x2001, 0x9317, 0x2004, 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020, + 0x53a5, 0x015e, 0x014e, 0x013e, 0x7007, 0x0000, 0x080c, 0x4f27, + 0x080c, 0x14ec, 0x0005, 0x2011, 0x8003, 0x080c, 0x3698, 0x0cf8, + 0xa18c, 0x0700, 0x1148, 0x2001, 0x933c, 0x2003, 0x0100, 0x7007, + 0x0000, 0x080c, 0x14ec, 0x0005, 0x2011, 0x8004, 0x080c, 0x3698, + 0x0cf8, 0x0126, 0x2091, 0x2200, 0x2079, 0x0030, 0x2071, 0x9519, + 0x7003, 0x0000, 0x700f, 0x9520, 0x7013, 0x9520, 0x780f, 0x00f0, + 0x012e, 0x0005, 0x6934, 0xa184, 0x0007, 0x0002, 0x1666, 0x16ab, + 0x1666, 0x1666, 0x166a, 0x1693, 0x167a, 0x1671, 0xa085, 0x0001, + 0x0804, 0x16c5, 0xa186, 0x0024, 0x05f0, 0xa186, 0x002c, 0x05d8, + 0x0ca8, 0x684c, 0xd0bc, 0x0d90, 0x6860, 0x682e, 0x685c, 0x682a, + 0x6858, 0x04c8, 0xa18c, 0x00ff, 0xa186, 0x001e, 0x1d38, 0x684c, + 0xd0bc, 0x0d20, 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a, + 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x1f59, 0x2005, + 0x6832, 0x6858, 0x0440, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x1970, + 0x684c, 0xd0ac, 0x0958, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, + 0xa084, 0x000f, 0xa080, 0x1f59, 0x2005, 0x6832, 0xa006, 0x682e, + 0x682a, 0x6858, 0x0080, 0x684c, 0xd0ac, 0x0904, 0x1666, 0xa006, + 0x682e, 0x682a, 0x6858, 0xa18c, 0x000f, 0xa188, 0x1f59, 0x210d, + 0x6932, 0x2d08, 0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, + 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x0005, 0x20e1, 0x0007, + 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x82ff, 0x0178, 0xa280, + 0x0004, 0x00d6, 0x206c, 0x684c, 0xd0dc, 0x1120, 0x080c, 0x165a, + 0x190c, 0x13fe, 0x6808, 0x8000, 0x680a, 0x00de, 0x0126, 0x0046, + 0x0036, 0x0026, 0x2091, 0x2200, 0x002e, 0x003e, 0x004e, 0x7000, + 0xa005, 0x0178, 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, + 0x8108, 0xa182, 0x953b, 0x0210, 0x2009, 0x9520, 0x710e, 0x012e, + 0x0005, 0x7206, 0x2001, 0x16f7, 0x0006, 0x2260, 0x0804, 0x17e8, + 0x0126, 0x0026, 0x0036, 0x00c6, 0x0006, 0x2091, 0x2200, 0x000e, + 0x004e, 0x003e, 0x002e, 0x00d6, 0x00c6, 0x2460, 0x6110, 0x2168, + 0x6a62, 0x6b5e, 0xa005, 0x05b8, 0x6808, 0xa005, 0x0904, 0x177c, + 0x7000, 0xa005, 0x1108, 0x0430, 0x700c, 0x7110, 0xa106, 0x1904, + 0x1784, 0x7004, 0xa406, 0x11f0, 0x2001, 0x0005, 0x2004, 0xd08c, + 0x0130, 0x0046, 0x080c, 0x1942, 0x004e, 0x2460, 0x0c28, 0x2001, + 0x0207, 0x2004, 0xd09c, 0x1d80, 0x7804, 0xa084, 0x6000, 0x0120, + 0xa086, 0x6000, 0x0108, 0x0c40, 0x7803, 0x0004, 0x7003, 0x0000, + 0x7004, 0x2060, 0x6100, 0xa18e, 0x0004, 0x15f0, 0x2009, 0x0048, + 0x080c, 0x7518, 0x04c8, 0x6808, 0xa005, 0x0570, 0x7000, 0xa005, + 0x0558, 0x700c, 0x7110, 0xa106, 0x1118, 0x7004, 0xa406, 0x1520, + 0x2001, 0x0005, 0x2004, 0xd08c, 0x0130, 0x0046, 0x080c, 0x1942, + 0x004e, 0x2460, 0x0c40, 0x2001, 0x0207, 0x2004, 0xd09c, 0x1d80, + 0x2001, 0x0005, 0x2004, 0xd08c, 0x1d80, 0x7804, 0xa084, 0x6000, + 0x0118, 0xa086, 0x6000, 0x1d20, 0x7818, 0x6812, 0x781c, 0x6816, + 0x7803, 0x0004, 0x7003, 0x0000, 0x6100, 0xa18e, 0x0004, 0x1120, + 0x2009, 0x0048, 0x080c, 0x7518, 0x00ce, 0x00de, 0x012e, 0x0005, + 0x00f6, 0x00e6, 0x0026, 0x0036, 0x0046, 0x080c, 0x1c26, 0x0026, + 0x2071, 0x9519, 0x7000, 0xa086, 0x0000, 0x0580, 0x7004, 0xac06, + 0x11f8, 0x2079, 0x0030, 0x7000, 0xa086, 0x0003, 0x01c8, 0x7804, + 0xd0fc, 0x1198, 0x2001, 0x0207, 0x2004, 0xd09c, 0x1dc0, 0x7803, + 0x0004, 0x7804, 0xd0ac, 0x1de8, 0x7803, 0x0002, 0x7803, 0x0009, + 0x7003, 0x0003, 0x7007, 0x0000, 0x0018, 0x080c, 0x1942, 0x08d0, + 0x0156, 0x20a9, 0x0009, 0x2009, 0x9520, 0x2104, 0xac06, 0x1108, + 0x200a, 0xa188, 0x0003, 0x1f04, 0x17bd, 0x015e, 0x002e, 0x2001, + 0x015d, 0x201c, 0x831a, 0x2302, 0x2001, 0x0138, 0x2202, 0x004e, + 0x003e, 0x002e, 0x00ee, 0x00fe, 0x0005, 0x700c, 0x7110, 0xa106, + 0x0904, 0x182c, 0x2104, 0x7006, 0x2060, 0x8108, 0x211c, 0x8108, + 0x2124, 0x8108, 0xa182, 0x953b, 0x0210, 0x2009, 0x9520, 0x7112, + 0x8cff, 0x05a0, 0x6010, 0x2068, 0x2d58, 0x6828, 0xa406, 0x1598, + 0x682c, 0xa306, 0x1580, 0x684c, 0xd0f4, 0x1540, 0x6850, 0xd0f4, + 0x1130, 0x7803, 0x0004, 0x6810, 0x781a, 0x6814, 0x781e, 0x6824, + 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, + 0x6834, 0xa08c, 0x00ff, 0xa186, 0x0024, 0x0118, 0xa186, 0x002c, + 0x1120, 0x2009, 0x0011, 0x00d9, 0x0038, 0x2009, 0x0011, 0x00b9, + 0x0118, 0x2009, 0x0001, 0x0099, 0x2d58, 0x0005, 0x7803, 0x0004, + 0x080c, 0x1be2, 0x0cd0, 0x601c, 0xa086, 0x0008, 0x1108, 0x0858, + 0x080c, 0x1fa7, 0x1d98, 0x0838, 0x7003, 0x0000, 0x0005, 0x8aff, + 0x0904, 0x191c, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x11b8, 0xd0f4, + 0x1538, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, 0x18b6, 0x1867, + 0x1867, 0x18b6, 0x18b9, 0x18ae, 0x18b6, 0x1867, 0x18b6, 0x1878, + 0x1878, 0x18b6, 0x18b9, 0x18b6, 0x18a6, 0x1878, 0x7803, 0x0004, + 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x00d6, 0xd99c, + 0x0904, 0x1909, 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x0804, 0x1909, + 0xc0f4, 0x6852, 0x6b6c, 0x6a70, 0x00d6, 0x0804, 0x1910, 0x2d10, + 0x00de, 0x00d6, 0x6834, 0x2268, 0xa084, 0x00ff, 0xa096, 0x0024, + 0x0904, 0x18e9, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0804, 0x1909, + 0x2d10, 0x00de, 0x00d6, 0x6834, 0x2268, 0xa084, 0x00ff, 0xa096, + 0x002c, 0x0904, 0x18c6, 0x7b0c, 0xd3bc, 0x01c0, 0x7004, 0x00e6, + 0x2070, 0x701c, 0x00ee, 0xa086, 0x0008, 0x1180, 0x7b08, 0xa39c, + 0x0fff, 0x2d20, 0x7a1c, 0x82ff, 0x1120, 0x7818, 0xa302, 0x0208, + 0x7b18, 0xa016, 0x7a1e, 0x7b1a, 0x2468, 0x0010, 0x6b10, 0x6a14, + 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0804, 0x1909, 0x00de, 0x00d6, + 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x1140, 0x00de, 0x080c, + 0x1f1b, 0x1904, 0x182f, 0xa00e, 0x0804, 0x191c, 0x00de, 0x080c, + 0x13fe, 0x2d10, 0x00de, 0x00d6, 0x6834, 0x2268, 0xa084, 0x00ff, + 0xa096, 0x0024, 0x0530, 0xa096, 0x002c, 0x1d80, 0x6b10, 0xa3a6, + 0xffff, 0x1130, 0x2d10, 0x00de, 0x00d6, 0x080c, 0x59f4, 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, 0x59f4, 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, 0x7902, + 0x7000, 0x8000, 0x7002, 0x00de, 0x6828, 0xa300, 0x682a, 0x682c, + 0xa201, 0x682e, 0x080c, 0x1f1b, 0x0005, 0x080c, 0x13fe, 0x7803, + 0x0004, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068, 0x7003, 0x0000, + 0x080c, 0x1c02, 0x080c, 0x82ee, 0x0170, 0x6808, 0x8001, 0x680a, + 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, 0x682f, 0xffff, + 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0x80f6, 0x0804, 0x1b4b, + 0x080c, 0x13fe, 0x0126, 0x2091, 0x2200, 0x0006, 0x0016, 0x2b68, + 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x1978, + 0xa184, 0x0003, 0xa086, 0x0003, 0x0d58, 0x7000, 0x0002, 0x195f, + 0x1961, 0x1aa6, 0x1b20, 0x1b3a, 0x195f, 0x195f, 0x195f, 0x080c, + 0x13fe, 0x8001, 0x7002, 0xa184, 0x0880, 0x1904, 0x19a8, 0x6834, + 0xa084, 0x00ff, 0xa086, 0x0024, 0x0130, 0x6834, 0xa084, 0x00ff, + 0xa086, 0x002c, 0x1518, 0x6864, 0x8000, 0x6866, 0xd19c, 0x0140, + 0x7004, 0x2060, 0x2009, 0x0102, 0x080c, 0x7518, 0x0804, 0x1a64, + 0x8aff, 0x0130, 0x2009, 0x0001, 0x080c, 0x182f, 0x0804, 0x1b4b, + 0x7004, 0x2060, 0x2009, 0x0106, 0x080c, 0x7518, 0x7007, 0x0000, + 0x7803, 0x0009, 0x7003, 0x0003, 0x0804, 0x1b4b, 0xd19c, 0x1904, + 0x1a49, 0x8aff, 0x0904, 0x1a49, 0x2009, 0x0001, 0x080c, 0x182f, + 0x0904, 0x1b4b, 0x2009, 0x0001, 0x080c, 0x182f, 0x0804, 0x1b4b, + 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x1904, 0x1a18, 0x6834, + 0xa084, 0x00ff, 0xa086, 0x0024, 0x0130, 0x6834, 0xa084, 0x00ff, + 0xa086, 0x002c, 0x1138, 0xd19c, 0x0128, 0x6864, 0x8000, 0x6866, + 0x0804, 0x1978, 0x0026, 0x0036, 0x7c20, 0x7d24, 0x7e30, 0x7f34, + 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201, 0x2004, 0xa005, + 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009, 0x7003, 0x0004, + 0x0070, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0024, 0x0140, 0x6834, + 0xa084, 0x00ff, 0xa086, 0x002c, 0x0110, 0x080c, 0x1b4f, 0x6b28, + 0x6a2c, 0x2400, 0x686e, 0xa31a, 0x2500, 0x6872, 0xa213, 0x6b2a, + 0x6a2e, 0x003e, 0x002e, 0x6e1e, 0x6f22, 0x080c, 0x1f31, 0x2a00, + 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6850, 0xc0fd, 0x6852, + 0x6808, 0x8001, 0x680a, 0x1148, 0x684c, 0xd0e4, 0x0130, 0x7004, + 0x2060, 0x2009, 0x0048, 0x080c, 0x7518, 0x7000, 0xa086, 0x0004, + 0x0904, 0x1b4b, 0x7003, 0x0000, 0x080c, 0x17d5, 0x0804, 0x1b4b, + 0x0056, 0x7d0c, 0xd5bc, 0x1110, 0x080c, 0x9171, 0x005e, 0x080c, + 0x1c02, 0x7004, 0x7007, 0x0000, 0x2060, 0x601c, 0xa086, 0x0009, + 0x1198, 0x790c, 0x0016, 0x2009, 0x0106, 0x080c, 0x7518, 0x001e, + 0xd0ec, 0x1118, 0x2009, 0x0009, 0x0010, 0x2009, 0x0019, 0x7902, + 0x7003, 0x0003, 0x0804, 0x1b4b, 0x682b, 0xffff, 0x682f, 0xffff, + 0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, 0x0804, + 0x1b4b, 0x7818, 0x6812, 0x7a1c, 0x6a16, 0xd19c, 0x0118, 0xa205, + 0x1904, 0x19a8, 0x684c, 0xc0f5, 0x684e, 0x7814, 0xa005, 0x1180, + 0x7003, 0x0000, 0x6808, 0x8001, 0x680a, 0x1130, 0x7004, 0x2060, + 0x2009, 0x0048, 0x080c, 0x7518, 0x080c, 0x17d5, 0x0804, 0x1b4b, + 0x7818, 0x6812, 0x781c, 0x6816, 0x7814, 0x7908, 0xa18c, 0x0fff, + 0xa188, 0x0007, 0x8114, 0x8214, 0x8214, 0xa10a, 0x8104, 0x8004, + 0x8004, 0xa20a, 0x810b, 0x810b, 0x810b, 0x080c, 0x1c40, 0x7803, + 0x0004, 0x780f, 0xffff, 0x7803, 0x0001, 0x7804, 0xd0fc, 0x0de8, + 0x7803, 0x0002, 0x7803, 0x0004, 0x780f, 0x00f0, 0x7004, 0x7007, + 0x0000, 0x2060, 0x2009, 0x0048, 0x080c, 0x7518, 0x080c, 0x1c62, + 0x0958, 0x7908, 0xd1ec, 0x1118, 0x2009, 0x0009, 0x0010, 0x2009, + 0x0019, 0x7902, 0x7003, 0x0003, 0x0804, 0x1b4b, 0x8001, 0x7002, + 0xd194, 0x0178, 0x7804, 0xd0fc, 0x1904, 0x194a, 0xd09c, 0x11a8, + 0x8aff, 0x0904, 0x1b4b, 0x2009, 0x0001, 0x080c, 0x182f, 0x0804, + 0x1b4b, 0xa184, 0x0888, 0x1148, 0x8aff, 0x0904, 0x1b4b, 0x2009, + 0x0001, 0x080c, 0x182f, 0x0804, 0x1b4b, 0x7803, 0x0004, 0x7003, + 0x0000, 0xd1bc, 0x1904, 0x1b0d, 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, 0x1b4f, 0x001e, 0x6b28, + 0x6a2c, 0x080c, 0x1f31, 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c, + 0x1128, 0x6808, 0xa31a, 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a, + 0x6814, 0xa213, 0x00de, 0xd194, 0x0904, 0x19e9, 0x2a00, 0x6826, + 0x2c00, 0x681a, 0x2800, 0x6832, 0x6808, 0x8001, 0x680a, 0x6b2a, + 0x6a2e, 0x003e, 0x002e, 0x0804, 0x1a64, 0x0056, 0x7d0c, 0x080c, + 0x9171, 0x005e, 0x080c, 0x1c02, 0x682b, 0xffff, 0x682f, 0xffff, + 0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, 0x0458, + 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, 0x0180, 0x6808, + 0x8001, 0x680a, 0x1160, 0x7004, 0x2060, 0x2009, 0x0048, 0x601c, + 0xa086, 0x0009, 0x1110, 0x080c, 0x13fe, 0x080c, 0x7518, 0x080c, + 0x17d5, 0x0088, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, + 0x6010, 0xa005, 0x0da0, 0x2068, 0x6808, 0x8000, 0x680a, 0x6c28, + 0x6b2c, 0x080c, 0x17e8, 0x001e, 0x000e, 0x012e, 0x0005, 0x700c, + 0x7110, 0xa106, 0x0904, 0x1bd6, 0x7004, 0x0016, 0x210c, 0xa106, + 0x001e, 0x0904, 0x1bd6, 0x00d6, 0x00c6, 0x216c, 0x2d00, 0xa005, + 0x0904, 0x1bd4, 0x6810, 0x2068, 0x6834, 0xa084, 0x00ff, 0xa086, + 0x0024, 0x0904, 0x1bd4, 0x6834, 0xa084, 0x00ff, 0xa086, 0x002c, + 0x0904, 0x1bd4, 0x6850, 0xd0fc, 0x0558, 0x8108, 0x2104, 0x6b2c, + 0xa306, 0x1904, 0x1bd4, 0x8108, 0x2104, 0x6a28, 0xa206, 0x1904, + 0x1bd4, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822, 0x6870, + 0x7826, 0x681c, 0x7832, 0x6820, 0x7836, 0x6818, 0x2060, 0x6034, + 0xd09c, 0x0150, 0x6830, 0x2005, 0x00d6, 0xac68, 0x6808, 0x783a, + 0x680c, 0x783e, 0x00de, 0x0490, 0xa006, 0x783a, 0x783e, 0x0470, + 0x8108, 0x2104, 0xa005, 0x1580, 0x8108, 0x2104, 0xa005, 0x1560, + 0x6850, 0xc0f5, 0x6852, 0x6830, 0x2005, 0x6918, 0xa160, 0x6834, + 0xd09c, 0x1170, 0x6008, 0x7822, 0x686e, 0x600c, 0x7826, 0x6872, + 0x6000, 0x7832, 0x6004, 0x7836, 0xa006, 0x783a, 0x783e, 0x0070, + 0x6010, 0x7822, 0x686e, 0x6014, 0x7826, 0x6872, 0x6000, 0x7832, + 0x6004, 0x7836, 0x6008, 0x783a, 0x600c, 0x783e, 0x6810, 0x781a, + 0x6814, 0x781e, 0x7803, 0x0011, 0x00ce, 0x00de, 0x0005, 0x2011, + 0x0201, 0x2009, 0x003c, 0x2204, 0xa005, 0x1118, 0x8109, 0x1dd8, + 0x0005, 0x0005, 0x0ca1, 0x01e0, 0x7908, 0xd1ec, 0x1160, 0x080c, + 0x1c62, 0x0148, 0x7803, 0x0009, 0x7904, 0xd1fc, 0x0de8, 0x7803, + 0x0006, 0x0c29, 0x0168, 0x780c, 0xd0a4, 0x1150, 0x7007, 0x0000, + 0x080c, 0x1c62, 0x0130, 0x7803, 0x0019, 0x7003, 0x0003, 0x0008, + 0x0009, 0x0005, 0x00c6, 0x0411, 0x20e1, 0x9028, 0x700c, 0x7110, + 0xa106, 0x0190, 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060, + 0x6008, 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0x953b, 0x0210, + 0x2009, 0x9520, 0x7112, 0x0c50, 0x2001, 0x015d, 0x200c, 0x810a, + 0x2102, 0x2001, 0x0138, 0x2202, 0x00ce, 0x0005, 0x2001, 0x0138, + 0x2014, 0x2003, 0x0000, 0x2021, 0xb015, 0x2001, 0x0141, 0x201c, + 0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0xa39c, 0x0048, 0x1138, + 0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, 0x0005, + 0x3c00, 0x0006, 0x00e6, 0x2071, 0x0200, 0x7808, 0xa084, 0xf000, + 0xa10d, 0x08e1, 0x20e1, 0x7000, 0x7324, 0x7420, 0x7028, 0x7028, + 0x7426, 0x7037, 0x0001, 0x810f, 0x712e, 0x702f, 0x0100, 0x7037, + 0x0008, 0x7326, 0x7422, 0x2001, 0x0138, 0x2202, 0x00ee, 0x000e, + 0x20e0, 0x0005, 0x3c00, 0x0006, 0x7908, 0xa18c, 0x0fff, 0xa182, + 0x0009, 0x0218, 0xa085, 0x0001, 0x0088, 0x2001, 0x020a, 0x81ff, + 0x0130, 0x20e1, 0x6000, 0x200c, 0x200c, 0x200c, 0x200c, 0x20e1, + 0x7000, 0x200c, 0x200c, 0x7003, 0x0000, 0xa006, 0x000e, 0x20e0, + 0x0005, 0x00e6, 0x2071, 0x953b, 0x7003, 0x0000, 0x00ee, 0x0005, + 0x00d6, 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x1904, 0x1d0d, + 0x6934, 0xa184, 0x0007, 0x0002, 0x1c9c, 0x1cf8, 0x1c9c, 0x1c9e, + 0x1c9c, 0x1cdf, 0x1cbe, 0x1cad, 0x080c, 0x13fe, 0x2100, 0xa084, + 0x00ff, 0xa086, 0x0013, 0x0904, 0x1cf8, 0x2100, 0xa084, 0x00ff, + 0xa086, 0x001b, 0x0904, 0x1cf8, 0x0c78, 0x684c, 0xd0b4, 0x0904, + 0x1e15, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, + 0x680a, 0x6880, 0x680e, 0x6958, 0x0804, 0x1d00, 0x6834, 0xa084, + 0x00ff, 0xa086, 0x001e, 0x19c0, 0x684c, 0xd0b4, 0x0904, 0x1e15, + 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, + 0x6880, 0x680e, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, + 0x000f, 0xa080, 0x1f59, 0x2005, 0x6832, 0x6958, 0x0450, 0xa18c, + 0x00ff, 0xa186, 0x0015, 0x1548, 0x684c, 0xd0b4, 0x0904, 0x1e15, + 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, + 0x1f59, 0x2005, 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, 0x0088, + 0x684c, 0xd0b4, 0x0904, 0x191d, 0x6958, 0xa006, 0x682e, 0x682a, + 0x2d00, 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, 0x1f59, 0x2005, + 0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, 0x00de, 0x0005, 0x00f6, + 0x2079, 0x0020, 0x7804, 0xd0fc, 0x190c, 0x1e3b, 0x00e6, 0x00d6, + 0x2071, 0x953b, 0x7000, 0xa005, 0x1904, 0x1d81, 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, 0xa184, 0x0007, 0x0128, 0x0016, + 0x2009, 0x0008, 0xa102, 0x001e, 0xa108, 0x791a, 0x7116, 0x701e, + 0x680c, 0xa081, 0x0000, 0x781e, 0x701a, 0xa006, 0x700e, 0x7012, + 0x7004, 0x692c, 0x6814, 0xa106, 0x1120, 0x6928, 0x6810, 0xa106, + 0x0158, 0x0036, 0x0046, 0x6b14, 0x6c10, 0x080c, 0x1fa7, 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, 0x1e0e, 0x700c, 0x7214, + 0xa23a, 0x7010, 0x7218, 0xa203, 0x0a04, 0x1e0d, 0xa705, 0x0904, + 0x1e0d, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x11a8, 0x00d6, 0x2805, + 0xac68, 0x2900, 0x0002, 0x1ddc, 0x1dc1, 0x1dc1, 0x1ddc, 0x1ddc, + 0x1dd5, 0x1ddc, 0x1dc1, 0x1ddc, 0x1dc6, 0x1dc6, 0x1ddc, 0x1ddc, + 0x1ddc, 0x1dcd, 0x1dc6, 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, 0x1f1b, + 0x1904, 0x1d8b, 0xa00e, 0x0490, 0x2d10, 0x00de, 0x00d6, 0x6834, + 0xa084, 0x00ff, 0xa086, 0x0013, 0x2268, 0x09d8, 0x2d10, 0x00de, + 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001b, 0x2268, 0x09b0, + 0x00de, 0x080c, 0x13fe, 0x00de, 0x7b22, 0x7a26, 0x7d32, 0x7c36, + 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x6828, 0xa300, + 0x682a, 0x682c, 0xa201, 0x682e, 0x700c, 0xa300, 0x700e, 0x7010, + 0xa201, 0x7012, 0x080c, 0x1f1b, 0x0008, 0xa006, 0x002e, 0x003e, + 0x004e, 0x005e, 0x006e, 0x007e, 0x0005, 0x080c, 0x13fe, 0x2001, + 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, + 0x0000, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068, 0x080c, 0x82ee, + 0x0118, 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0x80f6, 0x20e1, + 0x9040, 0x080c, 0x7366, 0x2011, 0x0000, 0x080c, 0x7199, 0x080c, + 0x651c, 0x0804, 0x1ef0, 0x0126, 0x2091, 0x2400, 0x0006, 0x0016, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0020, 0x2071, 0x953b, + 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, + 0x1930, 0x7000, 0x0002, 0x1ef0, 0x1e57, 0x1ec3, 0x1eee, 0x8001, + 0x7002, 0xd19c, 0x1170, 0x8aff, 0x0540, 0x2009, 0x0001, 0x080c, + 0x1d85, 0x0904, 0x1ef0, 0x2009, 0x0001, 0x080c, 0x1d85, 0x0804, + 0x1ef0, 0x7803, 0x0004, 0xd194, 0x0148, 0x6850, 0xc0fc, 0x6852, + 0x8aff, 0x1148, 0x684c, 0xc0f5, 0x684e, 0x0028, 0x080c, 0x1f31, + 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, + 0x6832, 0x7003, 0x0000, 0x0804, 0x1ef0, 0x711c, 0x81ff, 0x0190, + 0x7918, 0x7922, 0x7827, 0x0000, 0x7803, 0x0001, 0x7000, 0x8000, + 0x7002, 0x700c, 0xa100, 0x700e, 0x7010, 0xa081, 0x0000, 0x7012, + 0x0804, 0x1ef0, 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, + 0x2079, 0x0100, 0x7a14, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, + 0x7820, 0xd0bc, 0x1de8, 0x79c8, 0x000e, 0xa102, 0x001e, 0x0006, + 0x0016, 0x79c4, 0x000e, 0xa102, 0x78c6, 0x000e, 0x78ca, 0xa284, + 0x0004, 0xa085, 0x0012, 0x7816, 0x002e, 0x00fe, 0x7803, 0x0008, + 0x7003, 0x0000, 0x0468, 0x8001, 0x7002, 0xd194, 0x0168, 0x7804, + 0xd0fc, 0x1904, 0x1e4b, 0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009, + 0x0001, 0x080c, 0x1d85, 0x00e0, 0x0026, 0x0036, 0x6b28, 0x6a2c, + 0x080c, 0x1f31, 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, + 0x6808, 0xa31a, 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, + 0xa213, 0x00de, 0x0804, 0x1e76, 0x0804, 0x1e76, 0x080c, 0x13fe, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x001e, 0x000e, 0x012e, 0x0005, + 0x00f6, 0x00e6, 0x2071, 0x953b, 0x7000, 0xa086, 0x0000, 0x01c0, + 0x2079, 0x0020, 0x20e1, 0x9040, 0x7804, 0xd0fc, 0x0dd8, 0x080c, + 0x1e3b, 0x7000, 0xa086, 0x0000, 0x1da8, 0x7803, 0x0004, 0x7804, + 0xd0ac, 0x1de8, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, + 0x00ee, 0x00fe, 0x0005, 0x8840, 0x2805, 0xa005, 0x1170, 0x6004, + 0xa005, 0x0168, 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, + 0x1f59, 0x2045, 0x88ff, 0x090c, 0x13fe, 0x8a51, 0x0005, 0x2050, + 0x0005, 0x8a50, 0x8841, 0x2805, 0xa005, 0x1190, 0x2c00, 0xad06, + 0x0120, 0x6000, 0xa005, 0x1108, 0x2d00, 0x2060, 0x681a, 0x6034, + 0xa084, 0x000f, 0xa080, 0x1f69, 0x2045, 0x88ff, 0x090c, 0x13fe, + 0x0005, 0x0000, 0x0011, 0x0015, 0x0019, 0x001d, 0x0021, 0x0025, + 0x0029, 0x0000, 0x000f, 0x0015, 0x001b, 0x0021, 0x0027, 0x0000, + 0x0000, 0x0000, 0x1f4e, 0x1f4a, 0x1f4e, 0x1f4e, 0x1f58, 0x0000, + 0x1f4e, 0x0000, 0x1f55, 0x1f52, 0x1f55, 0x1f55, 0x0000, 0x1f58, + 0x1f55, 0x0000, 0x1f50, 0x1f50, 0x0000, 0x1f50, 0x1f58, 0x0000, + 0x1f50, 0x0000, 0x1f56, 0x1f56, 0x0000, 0x1f56, 0x0000, 0x1f58, + 0x1f56, 0x0136, 0x0146, 0x0156, 0x2099, 0x9359, 0x20a1, 0x0018, + 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126, 0x2091, 0x8000, + 0x7803, 0x0041, 0x7007, 0x0005, 0x7000, 0xc094, 0x7002, 0x700b, + 0x9354, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005, 0x2099, 0x0014, + 0x7803, 0x0040, 0x2001, 0x9359, 0x2004, 0x2010, 0x080c, 0x59a7, + 0x080c, 0x5949, 0x7007, 0x0000, 0x080c, 0x14ec, 0x0005, 0x00a6, + 0x0096, 0x0086, 0x6858, 0xa055, 0x0904, 0x2036, 0x2d60, 0x6034, + 0xa0cc, 0x000f, 0xa9c0, 0x1f59, 0xa986, 0x0007, 0x0130, 0xa986, + 0x000e, 0x0118, 0xa986, 0x000f, 0x1120, 0x605c, 0xa422, 0x6060, + 0xa31a, 0x2805, 0xa045, 0x1140, 0x0310, 0x0804, 0x2036, 0x6004, + 0xa065, 0x0904, 0x2036, 0x0c18, 0x2805, 0xa005, 0x01a8, 0xac68, + 0xd99c, 0x1128, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0020, 0x6810, + 0xa422, 0x6814, 0xa31b, 0x0620, 0x2300, 0xa405, 0x0150, 0x8a51, + 0x0904, 0x2036, 0x8840, 0x0c40, 0x6004, 0xa065, 0x0904, 0x2036, + 0x0830, 0x8a51, 0x0904, 0x2036, 0x8840, 0x2805, 0xa005, 0x1158, + 0x6004, 0xa065, 0x0904, 0x2036, 0x6034, 0xa0cc, 0x000f, 0xa9c0, + 0x1f59, 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, 0x13fe, 0x6800, 0xa420, 0x6804, 0xa319, + 0x0060, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x0a0c, + 0x13fe, 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, 0x204a, 0x204b, 0x204e, 0x2051, 0x2056, 0x2059, + 0x205e, 0x2063, 0x0005, 0x080c, 0x1e3b, 0x0005, 0x080c, 0x1942, + 0x0005, 0x080c, 0x1942, 0x080c, 0x1e3b, 0x0005, 0x080c, 0x159c, + 0x0005, 0x080c, 0x1e3b, 0x080c, 0x159c, 0x0005, 0x080c, 0x1942, + 0x080c, 0x159c, 0x0005, 0x080c, 0x1942, 0x080c, 0x1e3b, 0x080c, + 0x159c, 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, + 0x9780, 0x2069, 0x9200, 0x2009, 0x0004, 0x7912, 0x7817, 0x0004, + 0x080c, 0x23e6, 0x781b, 0x0002, 0x783b, 0x001f, 0x20e1, 0x8700, + 0x012e, 0x0005, 0x0126, 0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c, + 0x210b, 0xa084, 0x0007, 0x0002, 0x20a6, 0x2094, 0x2097, 0x209a, + 0x209f, 0x20a1, 0x20a3, 0x20a5, 0x080c, 0x5338, 0x0078, 0x080c, + 0x536c, 0x0060, 0x080c, 0x5338, 0x080c, 0x536c, 0x0038, 0x0041, + 0x0028, 0x0031, 0x0018, 0x0021, 0x0008, 0x0011, 0x012e, 0x0005, + 0x0006, 0x0016, 0x0026, 0x7930, 0xa184, 0x0003, 0x0118, 0x20e1, + 0x9040, 0x00b8, 0xa184, 0x0030, 0x0150, 0x6a00, 0xa286, 0x0003, + 0x1108, 0x0010, 0x080c, 0x4105, 0x20e1, 0x9010, 0x0050, 0xa184, + 0x00c0, 0x0110, 0x080c, 0x13fe, 0xa184, 0x0300, 0x0110, 0x20e1, + 0x9020, 0x7932, 0x002e, 0x001e, 0x000e, 0x0005, 0x0016, 0x00e6, + 0x00f6, 0x2071, 0x9200, 0x7128, 0x2001, 0x94ca, 0x2102, 0x2001, + 0x94d2, 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, 0x23e6, 0x00fe, + 0x00ee, 0x001e, 0x0005, 0x7938, 0x080c, 0x13fe, 0x0126, 0x2091, + 0x2400, 0x2061, 0x0100, 0x2071, 0x9200, 0x6024, 0x6026, 0x080c, + 0x2425, 0x6050, 0xa084, 0xfe7f, 0x6052, 0x2009, 0x00ef, 0x6132, + 0x6136, 0x080c, 0x2435, 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0008, + 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, + 0x6007, 0x0c9f, 0x600f, 0x03ff, 0x602b, 0x002f, 0x012e, 0x0005, + 0x2001, 0x9230, 0x2003, 0x0000, 0x2001, 0x922f, 0x2003, 0x0001, + 0x0005, 0x0126, 0x2091, 0x2400, 0x0006, 0x0016, 0x0026, 0x6124, + 0x0066, 0x2031, 0x9232, 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, 0x1c2c, 0x1118, 0xa184, 0x0007, 0x002a, 0xa195, 0x0004, + 0xa284, 0x0007, 0x0002, 0x2195, 0x217b, 0x217e, 0x2181, 0x2186, + 0x2188, 0x218c, 0x2190, 0x080c, 0x5ee3, 0x00b8, 0x080c, 0x5fbe, + 0x00a0, 0x080c, 0x5fbe, 0x080c, 0x5ee3, 0x0078, 0x0099, 0x0068, + 0x080c, 0x5ee3, 0x0079, 0x0048, 0x080c, 0x5fbe, 0x0059, 0x0028, + 0x080c, 0x5fbe, 0x080c, 0x5ee3, 0x0029, 0x002e, 0x001e, 0x000e, + 0x012e, 0x0005, 0xd19c, 0x1904, 0x238f, 0x080c, 0x4dc5, 0x01a0, + 0x080c, 0x4deb, 0x15c0, 0x6024, 0xa084, 0x1800, 0x1108, 0x0498, + 0x2001, 0x94d7, 0x2003, 0xaaaa, 0x2001, 0x94d8, 0x2003, 0x0001, + 0x080c, 0x4d10, 0x0804, 0x238f, 0xd1ac, 0x1528, 0x6024, 0xd0dc, + 0x1130, 0xd0e4, 0x1148, 0xd0d4, 0x1180, 0x0804, 0x238f, 0x2001, + 0x94d8, 0x2003, 0x0000, 0x0068, 0xa085, 0x0001, 0x080c, 0x4e05, + 0x2001, 0x94d8, 0x2003, 0x0002, 0x0020, 0x2001, 0x94d8, 0x2003, + 0x0003, 0x0016, 0x2001, 0x9200, 0x2003, 0x0001, 0x080c, 0x4d10, + 0x001e, 0x0804, 0x238f, 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, 0x9295, 0x200c, 0xc184, 0x2102, + 0x001e, 0x0804, 0x23b6, 0xd1ac, 0x0904, 0x22d7, 0x080c, 0x4dc5, + 0x1550, 0x6027, 0x0020, 0x0006, 0x0026, 0x0036, 0x2001, 0x94d8, + 0x080c, 0x4de1, 0x11d8, 0x2011, 0x9225, 0x2204, 0xa005, 0x1140, + 0x8000, 0x2012, 0x2011, 0x8036, 0x2019, 0x0001, 0x080c, 0x3698, + 0x2001, 0x94d8, 0x2003, 0x0001, 0x2001, 0x9200, 0x2003, 0x0001, + 0x080c, 0x4d10, 0x003e, 0x002e, 0x000e, 0x0005, 0x003e, 0x002e, + 0x000e, 0x080c, 0x4ca5, 0x0016, 0x0046, 0x00c6, 0x644c, 0xa486, + 0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, 0x6043, + 0x0010, 0x74c6, 0xa48c, 0xff00, 0xa196, 0xff00, 0x01e8, 0x7050, + 0xa084, 0x00ff, 0x810f, 0xa116, 0x01b8, 0x7130, 0xd18c, 0x11a0, + 0x2011, 0x9252, 0x2214, 0xd2ec, 0x0118, 0xc18d, 0x7132, 0x0060, + 0x6240, 0xa294, 0x0010, 0x0904, 0x22ad, 0x6248, 0xa294, 0xff00, + 0xa296, 0xff00, 0x1904, 0x22ad, 0x70bc, 0xa005, 0x1138, 0x0036, + 0x73c4, 0x2011, 0x8013, 0x080c, 0x3698, 0x003e, 0x7130, 0xc185, + 0x7132, 0x2011, 0x9252, 0x220c, 0xd1a4, 0x01d0, 0x0016, 0x2009, + 0x0001, 0x2011, 0x0100, 0x080c, 0x585b, 0x2019, 0x000e, 0x080c, + 0x9071, 0xa484, 0x00ff, 0xa080, 0x2719, 0x200d, 0xa18c, 0xff00, + 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x080c, 0x90d7, 0x001e, + 0xd1ac, 0x1128, 0x2019, 0x0004, 0x080c, 0x264b, 0x0070, 0x0156, + 0x20a9, 0x007f, 0x2009, 0x0000, 0x080c, 0x4434, 0x1110, 0x080c, + 0x41e0, 0x8108, 0x1f04, 0x22a4, 0x015e, 0x00ce, 0x004e, 0x2011, + 0x0003, 0x080c, 0x718f, 0x2011, 0x0002, 0x080c, 0x7199, 0x080c, + 0x708d, 0x080c, 0x57a1, 0x0036, 0x2019, 0x0000, 0x080c, 0x7110, + 0x003e, 0x60e3, 0x0000, 0x001e, 0x2001, 0x9200, 0x2014, 0xa296, + 0x0004, 0x1128, 0xd19c, 0x1118, 0x6228, 0xc29d, 0x622a, 0x2003, + 0x0001, 0x2001, 0x9222, 0x2003, 0x0000, 0x6027, 0x0020, 0xd194, + 0x0904, 0x238f, 0x0016, 0x6220, 0xd2b4, 0x0904, 0x2340, 0x080c, + 0x57a1, 0x080c, 0x6f1e, 0x6027, 0x0004, 0x00f6, 0x2019, 0x94ee, + 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, 0x6389, 0x080c, 0x6462, 0x7810, 0x2070, 0x7037, 0x0103, + 0x2f60, 0x080c, 0x74f2, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, + 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, + 0x0120, 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, + 0x94e5, 0x6028, 0xa09a, 0x0002, 0x1238, 0x8000, 0x602a, 0x00ce, + 0x080c, 0x6f11, 0x0804, 0x238e, 0x2019, 0x94ee, 0x2304, 0xa065, + 0x0120, 0x2009, 0x0027, 0x080c, 0x7518, 0x00ce, 0x0804, 0x238e, + 0xd2bc, 0x0904, 0x238e, 0x080c, 0x57ae, 0x6017, 0x0010, 0x6027, + 0x0004, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0120, + 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, 0x94e5, + 0x6044, 0xa09a, 0x0002, 0x12e0, 0x8000, 0x6046, 0x603c, 0x00ce, + 0xa005, 0x0560, 0x2009, 0x07d0, 0x080c, 0x57a6, 0xa080, 0x0007, + 0x2004, 0xa086, 0x0006, 0x1118, 0x6017, 0x0012, 0x00f8, 0xa080, + 0x0007, 0x2004, 0xa086, 0x0009, 0x0db8, 0x6017, 0x0016, 0x00b0, + 0x0036, 0x2019, 0x0001, 0x080c, 0x7110, 0x003e, 0x2019, 0x94f4, + 0x2304, 0xa065, 0x0150, 0x2009, 0x004f, 0x601c, 0xa086, 0x0009, + 0x1110, 0x2009, 0x0105, 0x080c, 0x7518, 0x00ce, 0x001e, 0xd19c, + 0x0528, 0x0016, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c, + 0x718f, 0x2011, 0x0002, 0x080c, 0x7199, 0x080c, 0x708d, 0x080c, + 0x57a1, 0x0036, 0x2019, 0x0000, 0x080c, 0x7110, 0x003e, 0x60e3, + 0x0000, 0x080c, 0x918b, 0x080c, 0x91a6, 0x2001, 0x9200, 0x2003, + 0x0004, 0x6027, 0x0008, 0x080c, 0x123f, 0x001e, 0xa18c, 0xffd0, + 0x6126, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, 0x0126, + 0x2091, 0x8000, 0x2071, 0x9200, 0x71bc, 0x70be, 0xa116, 0x01b8, + 0x81ff, 0x0128, 0x2011, 0x8011, 0x080c, 0x3698, 0x0080, 0x2011, + 0x8012, 0x080c, 0x3698, 0x0036, 0x00c6, 0x080c, 0x2480, 0x2061, + 0x0100, 0x2019, 0x0028, 0x080c, 0x264b, 0x00ce, 0x003e, 0x012e, + 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x00c6, 0x00f6, + 0x0006, 0x0026, 0x2061, 0x0100, 0xa190, 0x23f9, 0x2205, 0x60f2, + 0x2011, 0x2406, 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, 0x550c, 0x0038, 0xa080, + 0x2719, 0x200d, 0xa18c, 0xff00, 0x810f, 0xa006, 0x0005, 0xa080, + 0x2719, 0x200d, 0xa18c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, + 0x2001, 0x9214, 0x2003, 0x00ef, 0x20a9, 0x0010, 0xa006, 0x6852, + 0x6856, 0x1f04, 0x2430, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, + 0x2069, 0x0140, 0x2001, 0x9214, 0x2102, 0x8114, 0x8214, 0x8214, + 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, 0xa006, 0x82ff, 0x1128, + 0xa184, 0x000f, 0xa080, 0x91ac, 0x2005, 0x6856, 0x8211, 0x1f04, + 0x2445, 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0x9200, + 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, 0x2475, + 0x680f, 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, + 0x2001, 0x9252, 0x2004, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0xa006, + 0x0046, 0x2020, 0x2009, 0x002e, 0x080c, 0x90d7, 0x004e, 0x0005, + 0x24b0, 0x24b4, 0x24b8, 0x24be, 0x24c4, 0x24ca, 0x24d0, 0x24d8, + 0x24df, 0x24e4, 0x24e9, 0x24f0, 0x24f7, 0x24fe, 0x2505, 0x250e, + 0x2517, 0x2517, 0x2517, 0x2517, 0x2517, 0x2517, 0x2517, 0x2517, + 0x2517, 0x2517, 0x2517, 0x2517, 0x2517, 0x2517, 0x2517, 0x2517, + 0x0106, 0x0006, 0x0804, 0x2519, 0x0106, 0x0006, 0x0804, 0x2519, + 0x0106, 0x0006, 0x080c, 0x2141, 0x0804, 0x2519, 0x0106, 0x0006, + 0x080c, 0x2141, 0x0804, 0x2519, 0x0106, 0x0006, 0x080c, 0x203c, + 0x0804, 0x2519, 0x0106, 0x0006, 0x080c, 0x203c, 0x0804, 0x2519, + 0x0106, 0x0006, 0x080c, 0x2141, 0x080c, 0x203c, 0x0804, 0x2519, + 0x0106, 0x0006, 0x080c, 0x2141, 0x080c, 0x203c, 0x04d0, 0x0106, + 0x0006, 0x080c, 0x2082, 0x04a8, 0x0106, 0x0006, 0x080c, 0x2082, + 0x0480, 0x0106, 0x0006, 0x080c, 0x2141, 0x080c, 0x2082, 0x0448, + 0x0106, 0x0006, 0x080c, 0x2141, 0x080c, 0x2082, 0x0410, 0x0106, + 0x0006, 0x080c, 0x203c, 0x080c, 0x2082, 0x00d8, 0x0106, 0x0006, + 0x080c, 0x203c, 0x080c, 0x2082, 0x00a0, 0x0106, 0x0006, 0x080c, + 0x2141, 0x080c, 0x203c, 0x080c, 0x2082, 0x0058, 0x0106, 0x0006, + 0x080c, 0x2141, 0x080c, 0x203c, 0x080c, 0x2082, 0x0010, 0xe000, + 0x0cf0, 0x000e, 0x010e, 0x000d, 0x00c6, 0x0026, 0x2041, 0x007e, + 0x70c8, 0xd09c, 0x0110, 0x2041, 0x007f, 0xd094, 0x2001, 0x9214, + 0x203c, 0x15d8, 0x7284, 0x82ff, 0x05c0, 0x0036, 0x7398, 0xa38e, + 0xffff, 0x1110, 0x2019, 0x0001, 0x8314, 0xa2e0, 0x98c0, 0x2c04, + 0xa38c, 0x0001, 0x0120, 0xa084, 0xff00, 0x8007, 0x0010, 0xa084, + 0x00ff, 0xa70e, 0x01c8, 0xa08e, 0x00ff, 0x01d0, 0x2009, 0x0000, + 0x080c, 0x240b, 0x080c, 0x4400, 0x1188, 0x6004, 0xa084, 0x00ff, + 0xa086, 0x0006, 0x1120, 0x080c, 0x25b1, 0x0140, 0x0028, 0x080c, + 0x26ad, 0x080c, 0x25d7, 0x0110, 0x8318, 0x08b0, 0x739a, 0x0010, + 0x709b, 0xffff, 0x003e, 0x0804, 0x25ae, 0xa780, 0x2719, 0x203d, + 0xa7bc, 0xff00, 0x873f, 0x7098, 0xa096, 0xffff, 0x0128, 0xa812, + 0x12c8, 0x709b, 0xffff, 0x04b8, 0x2009, 0x0000, 0x70c8, 0xd09c, + 0x0120, 0xd094, 0x0110, 0x2009, 0x007e, 0x2001, 0x94d7, 0x2004, + 0xa005, 0x0120, 0x2009, 0x007e, 0x2041, 0x007f, 0x2100, 0xa802, + 0x20a8, 0x0020, 0x2008, 0x2810, 0xa202, 0x20a8, 0x2700, 0x0156, + 0x0016, 0xa106, 0x0180, 0x080c, 0x4400, 0x11a8, 0x6004, 0xa084, + 0x00ff, 0xa086, 0x0006, 0x1118, 0x00a1, 0x0168, 0x0020, 0x080c, + 0x26ad, 0x04a9, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x258e, + 0x709b, 0xffff, 0x0018, 0x001e, 0x015e, 0x719a, 0x002e, 0x00ce, + 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x080c, 0x749c, + 0x01c8, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, + 0x43d1, 0x2001, 0x0000, 0x080c, 0x43e3, 0x0126, 0x2091, 0x8000, + 0x7094, 0x8000, 0x7096, 0x012e, 0x2009, 0x0004, 0x080c, 0x7518, + 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x0016, + 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x080c, 0x749c, 0x01c8, 0x2d00, + 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x43d1, 0x2001, + 0x0002, 0x080c, 0x43e3, 0x0126, 0x2091, 0x8000, 0x7094, 0x8000, + 0x7096, 0x012e, 0x2009, 0x0002, 0x080c, 0x7518, 0xa085, 0x0001, + 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x0026, 0x2009, + 0x0080, 0x080c, 0x4400, 0x1120, 0x0031, 0x0110, 0x70cf, 0xffff, + 0x002e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, + 0x080c, 0x749c, 0x01c8, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, + 0x0000, 0x080c, 0x43d1, 0x2001, 0x0002, 0x080c, 0x43e3, 0x0126, + 0x2091, 0x8000, 0x70d0, 0x8000, 0x70d2, 0x012e, 0x2009, 0x0002, + 0x080c, 0x7518, 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, + 0x0005, 0x00c6, 0x00d6, 0x2009, 0x007f, 0x080c, 0x4400, 0x1180, + 0x2c68, 0x080c, 0x749c, 0x0160, 0x2d00, 0x601a, 0x6312, 0x601f, + 0x0001, 0x620a, 0x2009, 0x0022, 0x080c, 0x7518, 0xa085, 0x0001, + 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, + 0x080c, 0x6133, 0x080c, 0x60dc, 0x080c, 0x7a8c, 0x20a9, 0x007f, + 0x2009, 0x0000, 0x0016, 0x080c, 0x4434, 0x1120, 0x080c, 0x460d, + 0x080c, 0x41e0, 0x001e, 0x8108, 0x1f04, 0x265a, 0x002e, 0x003e, + 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0026, + 0x0016, 0x6218, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, + 0x6127, 0x0086, 0x2041, 0x0000, 0x080c, 0x606d, 0x2c08, 0x080c, + 0x8ee4, 0x008e, 0x001e, 0x2e60, 0x080c, 0x460d, 0x6210, 0x6314, + 0x080c, 0x41e0, 0x6212, 0x6316, 0x001e, 0x002e, 0x003e, 0x00ce, + 0x00ee, 0x0005, 0x00e6, 0x0006, 0x6018, 0xa080, 0x0028, 0x2004, + 0xa086, 0x0080, 0x0150, 0x2071, 0x9200, 0x7094, 0xa005, 0x0110, + 0x8001, 0x7096, 0x000e, 0x00ee, 0x0005, 0x2071, 0x9200, 0x70d0, + 0xa005, 0x0dc0, 0x8001, 0x70d2, 0x0ca8, 0x6000, 0xc08c, 0x6002, + 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x0156, + 0x2178, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0098, 0x2001, 0x9252, + 0x2004, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, + 0x2009, 0x002d, 0x080c, 0x90d7, 0x004e, 0x20a9, 0x00ff, 0x2011, + 0x0000, 0x0026, 0xa288, 0x936e, 0x210c, 0x81ff, 0x0508, 0x8fff, + 0x0559, 0x2019, 0x0029, 0x080c, 0x6127, 0x0086, 0x2041, 0x0000, + 0x080c, 0x606d, 0x00c6, 0x0026, 0x2160, 0x6204, 0xa294, 0x00ff, + 0x2001, 0x0004, 0x8007, 0xa215, 0x6206, 0x002e, 0x00ce, 0x0016, + 0x2c08, 0x080c, 0x8ee4, 0x001e, 0x008e, 0x2160, 0x080c, 0x460d, + 0x002e, 0x8210, 0x1f04, 0x26d1, 0x015e, 0x001e, 0x002e, 0x003e, + 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, 0x2001, + 0x9252, 0x2004, 0xd0c4, 0x0148, 0xd0a4, 0x0138, 0xa006, 0x2220, + 0x8427, 0x2009, 0x0029, 0x080c, 0x90d7, 0x001e, 0x002e, 0x004e, + 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, 0x9296, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, + 0x703a, 0x703e, 0x7033, 0x92a6, 0x7037, 0x92a6, 0x7007, 0x0001, + 0x2061, 0x92e6, 0x6003, 0x0002, 0x0005, 0x1004, 0x283f, 0x0e04, + 0x283f, 0x2071, 0x9296, 0x2b78, 0x7818, 0xd084, 0x1140, 0x2a60, + 0x7820, 0xa08e, 0x0069, 0x1904, 0x2924, 0x0804, 0x28bd, 0x0005, + 0x2071, 0x9296, 0x7004, 0x0002, 0x2848, 0x2849, 0x2852, 0x2863, + 0x0005, 0x1004, 0x2851, 0x0e04, 0x2851, 0x2b78, 0x7818, 0xd084, + 0x01e8, 0x0005, 0x2b78, 0x2061, 0x92e6, 0x6008, 0xa08e, 0x0100, + 0x0128, 0xa086, 0x0200, 0x0904, 0x291e, 0x0005, 0x7014, 0x2068, + 0x2a60, 0x7018, 0x0807, 0x7010, 0x2068, 0x6834, 0xa086, 0x0103, + 0x0108, 0x0005, 0x2a60, 0x2b78, 0x7018, 0x0807, 0x2a60, 0x7820, + 0xa08a, 0x0040, 0x1210, 0x61bc, 0x0042, 0x2100, 0xa08a, 0x003f, + 0x1a04, 0x291b, 0x61bc, 0x0804, 0x28bd, 0x28ff, 0x292a, 0x2932, + 0x2936, 0x293e, 0x2944, 0x2948, 0x2951, 0x2954, 0x295e, 0x2961, + 0x291b, 0x291b, 0x291b, 0x2964, 0x291b, 0x2973, 0x298a, 0x29a1, + 0x2a18, 0x2a1d, 0x2a46, 0x2a97, 0x2aa8, 0x2ac6, 0x2af2, 0x2afc, + 0x2b09, 0x2b1c, 0x2b3c, 0x2b45, 0x2b7b, 0x2b81, 0x291b, 0x2ba4, + 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x2ba8, 0x2bae, 0x291b, + 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x2bb6, + 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x2bc3, 0x2bc9, 0x291b, + 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x0002, 0x2bdb, 0x2c2e, + 0x2c88, 0x2c98, 0x291b, 0x2cb2, 0x309c, 0x291b, 0x291b, 0x291b, + 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x295e, 0x2961, + 0x291b, 0x291b, 0x309e, 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, + 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x30a2, 0x31e7, + 0x31fb, 0x3215, 0x3276, 0x32c7, 0x32d2, 0x3309, 0x3318, 0x3327, + 0x3336, 0x335e, 0x33a8, 0x340a, 0x3417, 0x3501, 0x35f6, 0x361f, + 0x3716, 0x3732, 0x373e, 0x3777, 0x381e, 0x3878, 0x38ff, 0x3908, + 0x390b, 0x3920, 0x393b, 0x39ab, 0x3a5b, 0x713c, 0x0000, 0x2021, + 0x4000, 0x080c, 0x3675, 0x0126, 0x2091, 0x8000, 0x0e04, 0x290b, + 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, 0x3682, 0x7823, 0x0004, 0x7824, 0x0807, 0xa02e, 0x2520, + 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, 0x3685, 0x7924, 0x7828, + 0x2114, 0x200a, 0x0804, 0x28ff, 0x7924, 0x2114, 0x0804, 0x28ff, + 0x2099, 0x0009, 0x20a1, 0x0009, 0x20a9, 0x0007, 0x53a3, 0x0804, + 0x28ff, 0x7824, 0x2060, 0x0090, 0x2009, 0x0002, 0x2011, 0x0000, + 0x2019, 0x0010, 0x783b, 0x0027, 0x0804, 0x28ff, 0x7d38, 0x7c3c, + 0x0858, 0x7d38, 0x7c3c, 0x08a0, 0x2061, 0x1000, 0xe10c, 0xa006, + 0x2c15, 0xa200, 0x8c60, 0x8109, 0x1dd8, 0x2010, 0xa005, 0x0904, + 0x28ff, 0x0804, 0x2921, 0x2069, 0x9251, 0x7824, 0x7930, 0xa11a, + 0x1a04, 0x2927, 0x8019, 0x0904, 0x2927, 0x684a, 0x6942, 0x782c, + 0x6852, 0x7828, 0x6856, 0xa006, 0x685a, 0x685e, 0x080c, 0x4e5d, + 0x0804, 0x28ff, 0x2069, 0x9251, 0x7824, 0x7934, 0xa11a, 0x1a04, + 0x2927, 0x8019, 0x0904, 0x2927, 0x684e, 0x6946, 0x782c, 0x6862, + 0x7828, 0x6866, 0xa006, 0x686a, 0x686e, 0x080c, 0x47d8, 0x0804, + 0x28ff, 0xa02e, 0x2520, 0x81ff, 0x1904, 0x2924, 0x7924, 0x7b28, + 0x7a2c, 0x20a9, 0x0005, 0x20a1, 0x929d, 0x41a1, 0x080c, 0x3641, + 0x0904, 0x2924, 0x2009, 0x0023, 0x080c, 0x3682, 0x701b, 0x29b9, + 0x0005, 0x6834, 0x2008, 0xa084, 0x00ff, 0xa096, 0x0011, 0x0120, + 0xa096, 0x0019, 0x1904, 0x2924, 0x810f, 0xa18c, 0x00ff, 0x0904, + 0x2924, 0x710e, 0x700c, 0x8001, 0x0528, 0x700e, 0x080c, 0x3641, + 0x0904, 0x2924, 0x2009, 0x0023, 0x2061, 0x92e6, 0x6224, 0x6328, + 0x642c, 0x6530, 0xa290, 0x0046, 0xa399, 0x0000, 0xa4a1, 0x0000, + 0xa5a9, 0x0000, 0x080c, 0x3682, 0x701b, 0x29e7, 0x0005, 0x6834, + 0xa084, 0x00ff, 0xa096, 0x0002, 0x0120, 0xa096, 0x000a, 0x1904, + 0x2924, 0x08c0, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, 0x080c, + 0x4337, 0x1128, 0x7007, 0x0003, 0x701b, 0x2a01, 0x0005, 0x080c, + 0x492c, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, 0x929d, + 0x530a, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, + 0x0000, 0xad80, 0x000d, 0x2009, 0x0023, 0x012e, 0x0804, 0x3685, + 0x61a4, 0x7824, 0x60a6, 0x0804, 0x28ff, 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, + 0x2924, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4434, 0x1904, + 0x2927, 0x7e38, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0210, 0x0804, + 0x2927, 0x7c28, 0x7d2c, 0x080c, 0x45d4, 0xd28c, 0x1118, 0x080c, + 0x457f, 0x0010, 0x080c, 0x45ad, 0x1518, 0x2061, 0x9900, 0x0126, + 0x2091, 0x8000, 0x6000, 0xa086, 0x0000, 0x0148, 0x6010, 0xa06d, + 0x0130, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0150, 0x012e, + 0xace0, 0x000c, 0x2001, 0x9216, 0x2004, 0xac02, 0x1a04, 0x2924, + 0x0c30, 0x080c, 0x80f6, 0x012e, 0x0904, 0x2924, 0x0804, 0x28ff, + 0xa00e, 0x2001, 0x0005, 0x080c, 0x492c, 0x0126, 0x2091, 0x8000, + 0x080c, 0x852d, 0x080c, 0x4809, 0x012e, 0x0804, 0x28ff, 0x81ff, + 0x1904, 0x2924, 0x080c, 0x3656, 0x0904, 0x2927, 0x080c, 0x44d4, + 0x0904, 0x2924, 0x080c, 0x45e0, 0x0904, 0x2924, 0x0804, 0x28ff, + 0x81ff, 0x1904, 0x2924, 0x080c, 0x3666, 0x0904, 0x2927, 0x080c, + 0x4644, 0x0904, 0x2924, 0x2019, 0x0005, 0x080c, 0x45fb, 0x0904, + 0x2924, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2927, 0x8003, 0x800b, + 0x810b, 0xa108, 0x080c, 0x573d, 0x0804, 0x28ff, 0x0126, 0x2091, + 0x8000, 0x81ff, 0x1508, 0x2029, 0x00ff, 0x644c, 0x2400, 0xa506, + 0x01b0, 0x2508, 0x080c, 0x4434, 0x1190, 0x080c, 0x4644, 0x01a0, + 0x2019, 0x0004, 0x080c, 0x45fb, 0x0178, 0x7824, 0xa08a, 0x1000, + 0x1270, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, 0x573d, 0x8529, + 0x1e28, 0x012e, 0x0804, 0x28ff, 0x012e, 0x0804, 0x2924, 0x012e, + 0x0804, 0x2927, 0x080c, 0x3656, 0x0904, 0x2927, 0x080c, 0x453a, + 0x080c, 0x45d4, 0x0804, 0x28ff, 0x81ff, 0x1904, 0x2924, 0x080c, + 0x3656, 0x0904, 0x2927, 0x080c, 0x452b, 0x080c, 0x45d4, 0x0804, + 0x28ff, 0x81ff, 0x1904, 0x2924, 0x080c, 0x3656, 0x0904, 0x2927, + 0x080c, 0x45af, 0x0904, 0x2924, 0x080c, 0x4373, 0x080c, 0x4578, + 0x080c, 0x45d4, 0x0804, 0x28ff, 0x080c, 0x3656, 0x0904, 0x2927, + 0x080c, 0x44d4, 0x0904, 0x2924, 0x62a0, 0x2019, 0x0005, 0x00c6, + 0x080c, 0x460d, 0x2061, 0x0000, 0x080c, 0x6127, 0x0086, 0x2041, + 0x0000, 0x080c, 0x606d, 0x2c08, 0x080c, 0x8ee4, 0x008e, 0x00ce, + 0x080c, 0x45d4, 0x0804, 0x28ff, 0x080c, 0x3656, 0x0904, 0x2927, + 0x080c, 0x45d4, 0x2208, 0x0804, 0x28ff, 0x0156, 0x00d6, 0x00e6, + 0x2069, 0x9328, 0x6810, 0x6914, 0xa10a, 0x1210, 0x2009, 0x0000, + 0x6816, 0x2011, 0x0000, 0x2019, 0x0000, 0x20a9, 0x007e, 0x2069, + 0x936e, 0x2d04, 0xa075, 0x0130, 0x704c, 0x0071, 0xa210, 0x7080, + 0x0059, 0xa318, 0x8d68, 0x1f04, 0x2b59, 0x2300, 0xa218, 0x00ee, + 0x00de, 0x015e, 0x0804, 0x28ff, 0x00f6, 0x0016, 0xa07d, 0x0140, + 0x2001, 0x0000, 0x8000, 0x2f0c, 0x81ff, 0x0110, 0x2178, 0x0cd0, + 0x001e, 0x00fe, 0x0005, 0x2069, 0x9328, 0x6910, 0x62a8, 0x0804, + 0x28ff, 0x81ff, 0x1904, 0x2924, 0x614c, 0xa190, 0x2719, 0x2215, + 0xa294, 0x00ff, 0x636c, 0x83ff, 0x0108, 0x6270, 0x67c8, 0xd79c, + 0x0118, 0x2031, 0x0001, 0x0060, 0xd7ac, 0x0118, 0x2031, 0x0003, + 0x0038, 0xd7a4, 0x0118, 0x2031, 0x0002, 0x0010, 0x2031, 0x0000, + 0x7e3a, 0x7f3e, 0x0804, 0x28ff, 0x613c, 0x6240, 0x0804, 0x28ff, + 0x080c, 0x3666, 0x0904, 0x2927, 0x0804, 0x28ff, 0x080c, 0x3666, + 0x0904, 0x2927, 0x6244, 0x6338, 0x0804, 0x28ff, 0x613c, 0x6240, + 0x7824, 0x603e, 0x7b28, 0x6342, 0x2069, 0x9251, 0x831f, 0xa305, + 0x6816, 0x0804, 0x28ff, 0x080c, 0x3666, 0x0904, 0x2927, 0x0804, + 0x28ff, 0x080c, 0x3666, 0x0904, 0x2927, 0x7828, 0xa00d, 0x0904, + 0x2927, 0x782c, 0xa005, 0x0904, 0x2927, 0x6244, 0x6146, 0x6338, + 0x603a, 0x0804, 0x28ff, 0x2001, 0x9200, 0x2004, 0xa086, 0x0003, + 0x1904, 0x2924, 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, + 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, 0x9214, 0x2004, 0xa085, + 0xff00, 0x0078, 0xa182, 0x007f, 0x1698, 0xa188, 0x2719, 0x210d, + 0xa18c, 0x00ff, 0x2001, 0x9214, 0x2004, 0xa116, 0x0548, 0x810f, + 0xa105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x749c, 0x000e, + 0x01e0, 0x601a, 0x600b, 0xbc09, 0x601f, 0x0001, 0x080c, 0x3641, + 0x01d0, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x701b, 0x2c81, 0x2d00, 0x6012, 0x2009, 0x0032, + 0x080c, 0x7518, 0x012e, 0x00ce, 0x0005, 0x00ce, 0x0804, 0x2924, + 0x00ce, 0x0804, 0x2927, 0x080c, 0x74f2, 0x0cb8, 0x2001, 0x9200, + 0x2004, 0xa086, 0x0003, 0x1904, 0x2924, 0x00c6, 0x2061, 0x0100, + 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, + 0x9214, 0x2004, 0xa085, 0xff00, 0x0078, 0xa182, 0x007f, 0x1698, + 0xa188, 0x2719, 0x210d, 0xa18c, 0x00ff, 0x2001, 0x9214, 0x2004, + 0xa116, 0x0548, 0x810f, 0xa105, 0x0126, 0x2091, 0x8000, 0x0006, + 0x080c, 0x749c, 0x000e, 0x01e0, 0x601a, 0x600b, 0xbc05, 0x601f, + 0x0001, 0x080c, 0x3641, 0x01d0, 0x6837, 0x0000, 0x7007, 0x0003, + 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x701b, 0x2c81, 0x2d00, + 0x6012, 0x2009, 0x0032, 0x080c, 0x7518, 0x012e, 0x00ce, 0x0005, + 0x00ce, 0x0804, 0x2924, 0x00ce, 0x0804, 0x2927, 0x080c, 0x74f2, + 0x0cb8, 0x6830, 0xa086, 0x0100, 0x0904, 0x2924, 0x0804, 0x28ff, + 0x2061, 0x9566, 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, 0x0128, + 0x6104, 0x6208, 0x012e, 0x0804, 0x28ff, 0x012e, 0x0804, 0x2927, + 0x81ff, 0x1904, 0x2924, 0x080c, 0x4dc5, 0x0904, 0x2924, 0x0126, + 0x2091, 0x8000, 0x6244, 0x6064, 0xa202, 0x0248, 0xa085, 0x0001, + 0x080c, 0x2455, 0x080c, 0x3bfd, 0x012e, 0x0804, 0x28ff, 0x012e, + 0x0804, 0x2927, 0x0126, 0x2091, 0x8000, 0x7824, 0xa084, 0x0007, + 0x0002, 0x2cc4, 0x2ccd, 0x2cd4, 0x2cc1, 0x2cc1, 0x2cc1, 0x2cc1, + 0x2cc1, 0x012e, 0x0804, 0x2927, 0x2009, 0x0114, 0x2104, 0xa085, + 0x0800, 0x200a, 0x080c, 0x2e1e, 0x0070, 0x2009, 0x010b, 0x200b, + 0x0010, 0x080c, 0x2e1e, 0x0038, 0x81ff, 0x0128, 0x012e, 0x2021, + 0x400b, 0x0804, 0x2901, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, + 0x00d6, 0x00e6, 0x00f6, 0x2009, 0x0101, 0x210c, 0x0016, 0x2001, + 0x0138, 0x200c, 0x2003, 0x0001, 0x0016, 0x2001, 0x007a, 0x2034, + 0x2001, 0x007b, 0x202c, 0xa006, 0x2048, 0x2050, 0x2058, 0x080c, + 0x302f, 0x080c, 0x2f99, 0xa03e, 0x2720, 0x00f6, 0x00e6, 0x00c6, + 0x2d60, 0x2071, 0x953b, 0x2079, 0x0020, 0x2011, 0x0001, 0x080c, + 0x2f45, 0x080c, 0x2f45, 0x00ce, 0x00ee, 0x00fe, 0x080c, 0x2ea6, + 0x080c, 0x2f6d, 0x080c, 0x2eea, 0x080c, 0x2e65, 0x080c, 0x2e96, + 0x00f6, 0x2079, 0x0100, 0x7824, 0xd094, 0x01d8, 0x7817, 0x0010, + 0x2079, 0x0140, 0x2001, 0x0109, 0x2004, 0xd0ac, 0x11a8, 0x7804, + 0xd0dc, 0x0dc0, 0x2079, 0x0100, 0x7827, 0x0086, 0x7817, 0x0032, + 0x7824, 0xd0ac, 0x1148, 0xd0bc, 0x0dd8, 0x7827, 0x0080, 0xa026, + 0x7c16, 0x7824, 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x2e06, 0x00fe, + 0x0804, 0x2dd0, 0x00fe, 0x1d04, 0x2d55, 0x2091, 0x6000, 0x8420, + 0xa486, 0x0064, 0x1150, 0x8948, 0x2001, 0x007a, 0x2602, 0x2001, + 0x007b, 0x2502, 0x080c, 0x2e06, 0x0088, 0x87ff, 0x0140, 0x2001, + 0x0201, 0x2004, 0xa005, 0x1904, 0x2d10, 0x8739, 0x0038, 0x2001, + 0x9519, 0x2004, 0xa086, 0x0000, 0x1904, 0x2d10, 0x2001, 0x0033, + 0x2003, 0x00f0, 0x8631, 0x1208, 0x8529, 0x2500, 0xa605, 0x0904, + 0x2dd0, 0x7824, 0xd0bc, 0x0128, 0x2900, 0xaa05, 0xab05, 0x1904, + 0x2dd0, 0x6033, 0x000d, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824, + 0xd0ac, 0x1148, 0x2001, 0x9519, 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, 0x0008, 0x2061, 0x0020, 0x6003, 0x0008, 0x2001, + 0x0203, 0x2004, 0x1f04, 0x2da5, 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, 0x2cfd, + 0x2061, 0x0100, 0x6027, 0x0002, 0x20e1, 0x9028, 0x6050, 0xa084, + 0xf7ef, 0x6052, 0x602f, 0x0000, 0x001e, 0x61e2, 0x001e, 0x6106, + 0x7824, 0xa084, 0x0003, 0xa086, 0x0002, 0x0148, 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, + 0x28ff, 0x012e, 0x2021, 0x400c, 0x0804, 0x2901, 0x2001, 0x0105, + 0x2003, 0x0010, 0x2001, 0x0030, 0x2003, 0x0004, 0x2001, 0x0020, + 0x2003, 0x0004, 0x2001, 0x9519, 0x2003, 0x0000, 0x2001, 0x953b, + 0x2003, 0x0000, 0x20e1, 0xf000, 0xa026, 0x0005, 0x00f6, 0x2079, + 0x0100, 0x7850, 0xa084, 0x0990, 0x7852, 0x782c, 0xa085, 0x0020, + 0x782e, 0x20a9, 0x0008, 0x1d04, 0x2e2b, 0x2091, 0x6000, 0x1f04, + 0x2e2b, 0x7850, 0xa085, 0x0400, 0x7852, 0x784b, 0xf7f7, 0x7843, + 0x0090, 0x7843, 0x0010, 0x20a9, 0x000e, 0xe000, 0x1f04, 0x2e3d, + 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, 0x7843, + 0x0000, 0x2003, 0x0000, 0x00fe, 0x0005, 0x7824, 0xd0ac, 0x11c8, + 0x00f6, 0x00e6, 0x2071, 0x9519, 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, 0x2009, 0x9214, 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, 0x7017, 0x0032, 0x080c, 0x2f6d, 0x7024, + 0xd0ac, 0x1120, 0xd0bc, 0x0dc8, 0x7027, 0x0080, 0x00f6, 0x00e6, + 0x2071, 0x9519, 0x2079, 0x0030, 0x2011, 0x0011, 0x080c, 0x2f45, + 0x2011, 0x0001, 0x080c, 0x2f45, 0x00ee, 0x00fe, 0x7017, 0x0000, + 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x9519, 0x2079, 0x0030, + 0x7904, 0xd1fc, 0x0904, 0x2f42, 0x7803, 0x0002, 0xa026, 0xd19c, + 0x1904, 0x2f3e, 0x7000, 0x0002, 0x2f42, 0x2f00, 0x2f24, 0x2f3e, + 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, 0x2e82, 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, 0x953b, 0x2079, 0x0020, 0x7904, 0xd1fc, 0x01f0, 0x7803, + 0x0002, 0x2d60, 0xa026, 0x7000, 0x0002, 0x2f95, 0x2f80, 0x2f8c, + 0x8001, 0x7002, 0xd19c, 0x1188, 0x2011, 0x0001, 0x080c, 0x2f45, + 0x0160, 0x080c, 0x2f45, 0x0048, 0x8001, 0x7002, 0x7804, 0xd0fc, + 0x1d30, 0x2011, 0x0001, 0x080c, 0x2f45, 0x00ce, 0x00ee, 0x00fe, + 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x601b, 0x0004, + 0x2061, 0x0100, 0x60cf, 0x0400, 0x6004, 0xc0ac, 0xa085, 0x0200, + 0x6006, 0x2001, 0x0074, 0x2004, 0xa005, 0x01f8, 0x2038, 0x2001, + 0x0076, 0x2024, 0x2001, 0x0077, 0x201c, 0x080c, 0x3089, 0x6833, + 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138, + 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d, + 0x04a1, 0x1d90, 0x2d00, 0x681a, 0x0088, 0x080c, 0x3089, 0x6833, + 0x000d, 0x2070, 0x6827, 0x0001, 0x2d00, 0x681a, 0x2001, 0x0076, + 0x2004, 0x2072, 0x2001, 0x0077, 0x2004, 0x7006, 0x2061, 0x0020, + 0x2079, 0x0100, 0x6013, 0x0400, 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, 0x3641, 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, 0x3089, 0x2d60, 0x6833, + 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138, + 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d, + 0x080c, 0x2ffd, 0x1d88, 0x2d00, 0x681a, 0x00d8, 0x0491, 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, + 0x9519, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003, 0x0009, 0x00ee, + 0x0005, 0x080c, 0x147c, 0x0178, 0xa006, 0x6802, 0x7010, 0xa005, + 0x1120, 0x2d00, 0x7012, 0x7016, 0x0020, 0x7014, 0x6802, 0x2d00, + 0x7016, 0xad80, 0x000d, 0x0005, 0x0804, 0x28ff, 0x7d38, 0x7c3c, + 0x0804, 0x29a3, 0x080c, 0x3641, 0x0904, 0x2924, 0x080c, 0x4dc5, + 0x0110, 0x080c, 0x41c5, 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x080c, 0x3682, 0x701b, 0x30b6, 0x0005, 0xade8, 0x000d, + 0x6800, 0xa005, 0x0904, 0x2927, 0x6804, 0xd0ac, 0x0118, 0xd0a4, + 0x0904, 0x2927, 0xd094, 0x00c6, 0x2061, 0x0100, 0x6104, 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, 0x2927, 0xa288, 0x2719, 0x210d, + 0xa18c, 0x00ff, 0x6156, 0xd0dc, 0x0130, 0x6828, 0xa08a, 0x007f, + 0x1a04, 0x2927, 0x604e, 0x6808, 0xa08a, 0x0100, 0x0a04, 0x2927, + 0xa08a, 0x0841, 0x1a04, 0x2927, 0xa084, 0x0007, 0x1904, 0x2927, + 0x680c, 0xa005, 0x0904, 0x2927, 0x6810, 0xa005, 0x0904, 0x2927, + 0x6848, 0x6940, 0xa10a, 0x1a04, 0x2927, 0x8001, 0x0904, 0x2927, + 0x684c, 0x6944, 0xa10a, 0x1a04, 0x2927, 0x8001, 0x0904, 0x2927, + 0x6804, 0xd0fc, 0x01f8, 0x080c, 0x3641, 0x0904, 0x2924, 0x2009, + 0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0xa290, 0x0038, 0xa399, + 0x0000, 0x080c, 0x3682, 0x701b, 0x312e, 0x0005, 0xade8, 0x000d, + 0x20a9, 0x0014, 0x2d98, 0x2069, 0x926d, 0x2da0, 0x53a3, 0x7010, + 0xa0e8, 0x000d, 0x20a9, 0x001c, 0x2d98, 0x2069, 0x9251, 0x2da0, + 0x53a3, 0x6814, 0xa08c, 0x00ff, 0x613e, 0x8007, 0xa084, 0x00ff, + 0x6042, 0x080c, 0x4e5d, 0x080c, 0x4780, 0x080c, 0x47d8, 0x6000, + 0xa086, 0x0000, 0x1904, 0x31e5, 0x6808, 0x602a, 0x080c, 0x20ce, + 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, 0x080c, 0x57bc, + 0x6904, 0xd1fc, 0x0520, 0x00c6, 0x2009, 0x0000, 0x20a9, 0x0001, + 0x6b70, 0xd384, 0x01c8, 0x0020, 0x839d, 0x12b0, 0x3508, 0x8109, + 0x080c, 0x532a, 0x6878, 0x6016, 0x6874, 0x2008, 0xa084, 0xff00, + 0x8007, 0x600a, 0xa184, 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003, + 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, 0x3184, 0x00ce, 0x2069, + 0x9251, 0x2001, 0x94d7, 0x6a80, 0xa294, 0x0030, 0xa28e, 0x0000, + 0x0178, 0xa28e, 0x0010, 0x0118, 0xa28e, 0x0020, 0x0148, 0x2003, + 0xaaaa, 0x2001, 0x0204, 0x2004, 0x2009, 0x94c8, 0x200a, 0x0008, + 0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, + 0x00ce, 0x080c, 0x4dc5, 0x0128, 0x080c, 0x3912, 0x0110, 0x080c, + 0x2455, 0x60c0, 0xa005, 0x01a8, 0x6003, 0x0001, 0x2091, 0x301d, + 0x080c, 0x4dc5, 0x1158, 0x2011, 0x4ce2, 0x080c, 0x5731, 0x2001, + 0x94d8, 0x2003, 0x0000, 0x080c, 0x4d10, 0x0038, 0x080c, 0x4105, + 0x0020, 0x6003, 0x0004, 0x2091, 0x301d, 0x0804, 0x28ff, 0x6000, + 0xa086, 0x0000, 0x0904, 0x2924, 0x2069, 0x9251, 0x7830, 0x6842, + 0x7834, 0x6846, 0x2d00, 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x0804, 0x3685, 0x81ff, 0x1904, 0x2924, 0x080c, 0x4dc5, + 0x1158, 0x2001, 0x94d8, 0x2003, 0x0001, 0x2001, 0x9200, 0x2003, + 0x0001, 0x080c, 0x4d10, 0x0038, 0xa006, 0x080c, 0x2455, 0x080c, + 0x41c5, 0x080c, 0x4105, 0x0804, 0x28ff, 0x81ff, 0x1904, 0x2924, + 0x080c, 0x4dc5, 0x1110, 0x0804, 0x2924, 0x6184, 0x81ff, 0x0198, + 0x703f, 0x0000, 0x2001, 0x98c0, 0x2009, 0x0040, 0x7a2c, 0x7b28, + 0x7c3c, 0x7d38, 0x0126, 0x2091, 0x8000, 0x080c, 0x3685, 0x701b, + 0x28fd, 0x012e, 0x0005, 0x703f, 0x0001, 0x00d6, 0x2069, 0x98c0, + 0x20a9, 0x0040, 0x20a1, 0x98c0, 0x2019, 0xffff, 0x43a4, 0x654c, + 0xa588, 0x2719, 0x210d, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, + 0x0002, 0x2100, 0xa506, 0x01a8, 0x080c, 0x4434, 0x1190, 0x6014, + 0x821c, 0x0238, 0xa398, 0x98c0, 0xa085, 0xff00, 0x8007, 0x201a, + 0x0038, 0xa398, 0x98c0, 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a, + 0x8210, 0x8108, 0xa182, 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, + 0x2d0c, 0xa105, 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, 0x98c0, + 0x2099, 0x98c0, 0x080c, 0x4166, 0x0804, 0x3222, 0x080c, 0x3666, + 0x0904, 0x2927, 0x00c6, 0x080c, 0x3641, 0x00ce, 0x0904, 0x2924, + 0x080c, 0x4dc5, 0x0500, 0x2001, 0x9252, 0x2004, 0xd0b4, 0x01d8, + 0x6000, 0xd08c, 0x11c0, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x1190, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x8476, + 0x0904, 0x2924, 0x7007, 0x0003, 0x701b, 0x329f, 0x0005, 0x080c, + 0x3666, 0x0904, 0x2927, 0x20a9, 0x002d, 0x2c98, 0xade8, 0x0002, + 0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, 0xad80, + 0x0006, 0x20a0, 0x080c, 0x4166, 0x20a9, 0x0004, 0xac80, 0x000a, + 0x2098, 0xad80, 0x000a, 0x20a0, 0x080c, 0x4166, 0x2d00, 0x2009, + 0x002f, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3685, 0x81ff, + 0x1904, 0x2924, 0x080c, 0x3656, 0x0904, 0x2927, 0x080c, 0x45e9, + 0x0804, 0x28ff, 0x81ff, 0x1904, 0x2924, 0x7828, 0xa08a, 0x1000, + 0x1a04, 0x2927, 0x080c, 0x3666, 0x0904, 0x2927, 0x080c, 0x4644, + 0x0904, 0x2924, 0x2019, 0x0004, 0x080c, 0x45fb, 0x7924, 0x810f, + 0x7a28, 0x0011, 0x0804, 0x28ff, 0xa186, 0x00ff, 0x0110, 0x0071, + 0x0060, 0x2029, 0x007e, 0x2061, 0x9200, 0x644c, 0x2400, 0xa506, + 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, 0x4434, + 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, 0x573d, + 0x0005, 0x81ff, 0x1904, 0x2924, 0x080c, 0x3656, 0x0904, 0x2927, + 0x080c, 0x44d4, 0x0904, 0x2924, 0x080c, 0x45f2, 0x0804, 0x28ff, + 0x81ff, 0x1904, 0x2924, 0x080c, 0x3656, 0x0904, 0x2927, 0x080c, + 0x44d4, 0x0904, 0x2924, 0x080c, 0x45e0, 0x0804, 0x28ff, 0x6100, + 0x2001, 0x94d8, 0x2014, 0xa282, 0x0003, 0x1210, 0x0804, 0x28ff, + 0x2011, 0x0000, 0x0804, 0x28ff, 0x0804, 0x28ff, 0x080c, 0x3666, + 0x0904, 0x2927, 0x6004, 0xa086, 0x0707, 0x0904, 0x2927, 0x2001, + 0x9200, 0x2004, 0xa086, 0x0003, 0x1904, 0x2924, 0x00d6, 0xace8, + 0x000a, 0x7924, 0xd184, 0x0110, 0xace8, 0x0006, 0x680c, 0x8007, + 0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f, 0x6a00, 0x8217, + 0x00de, 0x6100, 0xa18c, 0x0200, 0x0804, 0x28ff, 0x7824, 0xa09c, + 0x00ff, 0xa39a, 0x0003, 0x1a04, 0x2924, 0x624c, 0xa294, 0x00ff, + 0xa084, 0xff00, 0x8007, 0xa206, 0x1150, 0x2001, 0x9240, 0x2009, + 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3685, 0x81ff, + 0x1904, 0x2924, 0x080c, 0x3666, 0x0904, 0x2927, 0x6004, 0xa084, + 0x00ff, 0xa086, 0x0006, 0x1904, 0x2924, 0x00c6, 0x080c, 0x3641, + 0x00ce, 0x0904, 0x2924, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, + 0x080c, 0x8428, 0x0904, 0x2924, 0x7007, 0x0003, 0x701b, 0x3399, + 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x2924, 0xad80, 0x000e, + 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3685, + 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff, 0x0118, 0x81ff, 0x1904, + 0x2924, 0x080c, 0x4dc5, 0x0128, 0xa006, 0x080c, 0x2455, 0x080c, + 0x41c5, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2927, 0x7924, 0xa18c, + 0xff00, 0x810f, 0xa186, 0x00ff, 0x0138, 0xa182, 0x007f, 0x1a04, + 0x2927, 0x2100, 0x080c, 0x241f, 0x0026, 0x00c6, 0x0126, 0x2091, + 0x8000, 0x2061, 0x94f8, 0x601b, 0x0000, 0x601f, 0x0000, 0x080c, + 0x4dc5, 0x1158, 0x2001, 0x94d8, 0x2003, 0x0001, 0x2001, 0x9200, + 0x2003, 0x0001, 0x080c, 0x4d10, 0x00a0, 0x2061, 0x0100, 0x2001, + 0x9214, 0x2004, 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, 0x6043, + 0x0090, 0x6043, 0x0010, 0x2009, 0x001e, 0x2011, 0x412a, 0x080c, + 0x57b3, 0x7924, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4dc5, 0x1110, + 0x2009, 0x00ff, 0x7a28, 0x080c, 0x32ec, 0x012e, 0x00ce, 0x002e, + 0x0804, 0x28ff, 0x7924, 0xa18c, 0xff00, 0x810f, 0x00c6, 0x080c, + 0x4400, 0x2c08, 0x00ce, 0x1904, 0x2927, 0x0804, 0x28ff, 0x81ff, + 0x1904, 0x2924, 0x60c8, 0xd0ac, 0x1118, 0xd09c, 0x0904, 0x2924, + 0x080c, 0x3641, 0x0904, 0x2924, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x080c, 0x3682, 0x701b, 0x342e, 0x0005, 0x2009, 0x0080, + 0x080c, 0x4434, 0x1130, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x0120, 0x2021, 0x400a, 0x0804, 0x2901, 0x00d6, 0xade8, 0x000d, + 0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be, + 0x0100, 0x0904, 0x34a1, 0xa0be, 0x0112, 0x0904, 0x34a1, 0xa0be, + 0x0113, 0x0904, 0x34a1, 0xa0be, 0x0114, 0x0904, 0x34a1, 0xa0be, + 0x0117, 0x0904, 0x34a1, 0xa0be, 0x011a, 0x0904, 0x34a1, 0xa0be, + 0x0121, 0x05b0, 0xa0be, 0x0131, 0x0598, 0xa0be, 0x0171, 0x05c8, + 0xa0be, 0x0173, 0x05b0, 0xa0be, 0x01a1, 0x1120, 0x6830, 0x8007, + 0x6832, 0x04a0, 0xa0be, 0x0212, 0x0540, 0xa0be, 0x0213, 0x0528, + 0xa0be, 0x0214, 0x01b0, 0xa0be, 0x0217, 0x0168, 0xa0be, 0x021a, + 0x1120, 0x6838, 0x8007, 0x683a, 0x00e0, 0xa0be, 0x0300, 0x01c8, + 0x00de, 0x0804, 0x2927, 0xad80, 0x0010, 0x20a9, 0x0007, 0x080c, + 0x34dd, 0xad80, 0x000e, 0x20a9, 0x0001, 0x080c, 0x34dd, 0x0048, + 0xad80, 0x000c, 0x080c, 0x34eb, 0x0048, 0xad80, 0x000e, 0x080c, + 0x34eb, 0xad80, 0x000c, 0x20a9, 0x0001, 0x04b9, 0x00c6, 0x080c, + 0x3641, 0x0540, 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, 0x080c, 0x8442, 0x0904, 0x2924, 0x7007, 0x0003, 0x701b, + 0x34d6, 0x0005, 0x00ce, 0x00de, 0x0804, 0x2924, 0x6820, 0xa086, + 0x8001, 0x0904, 0x2924, 0x0804, 0x28ff, 0x0016, 0x2008, 0x2044, + 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, 0x1f04, + 0x34df, 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, 0x1904, 0x2924, 0x7924, 0x2140, 0xa18c, 0xff00, + 0x810f, 0x60c8, 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x2927, + 0xa182, 0x00ff, 0x1a04, 0x2927, 0x7a2c, 0x7b28, 0x606c, 0xa306, + 0x1140, 0x6070, 0xa24e, 0x0904, 0x2927, 0xa9cc, 0xff00, 0x0904, + 0x2927, 0x00c6, 0x080c, 0x359b, 0x2c68, 0x00ce, 0x01c0, 0xa0c6, + 0x4000, 0x1108, 0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, + 0xa0c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, + 0x1108, 0x0010, 0x2001, 0x4006, 0x2020, 0x0804, 0x2901, 0x2d00, + 0x7022, 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x749c, + 0x05b8, 0x2d00, 0x601a, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, + 0x3641, 0x00ce, 0x2b70, 0x1140, 0x080c, 0x74f2, 0x00ee, 0x00ce, + 0x00be, 0x001e, 0x0804, 0x2924, 0x6837, 0x0000, 0x683b, 0x0000, + 0x2d00, 0x6012, 0x6833, 0x0000, 0x6838, 0xc0fd, 0xd88c, 0x0108, + 0xc0f5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x266c, 0x012e, + 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x43d1, 0x2001, 0x0002, + 0x080c, 0x43e3, 0x2009, 0x0002, 0x080c, 0x7518, 0xa085, 0x0001, + 0x00ee, 0x00ce, 0x00be, 0x001e, 0x0904, 0x2924, 0x7007, 0x0003, + 0x701b, 0x358b, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x2924, + 0x7020, 0x2060, 0x2009, 0x0000, 0x080c, 0x46a5, 0x1110, 0x2009, + 0x0001, 0x0804, 0x28ff, 0x00e6, 0x00d6, 0x2029, 0x0000, 0x2001, + 0x9232, 0x2004, 0xd0ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, + 0x2071, 0x936e, 0x0030, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, + 0x93ee, 0x2e04, 0xa005, 0x1130, 0x2100, 0xa406, 0x1548, 0x2428, + 0xc5fd, 0x0430, 0x2068, 0x6f10, 0x2700, 0xa306, 0x11b0, 0x6e14, + 0x2600, 0xa206, 0x1190, 0x2400, 0xa106, 0x1160, 0x2d60, 0xd884, + 0x0540, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1510, 0x2001, + 0x4000, 0x0400, 0x2001, 0x4007, 0x00e8, 0x2400, 0xa106, 0x1140, + 0x6e14, 0x87ff, 0x1110, 0x86ff, 0x09d0, 0x2001, 0x4008, 0x0090, + 0x8420, 0x8e70, 0x1f04, 0x35b1, 0x85ff, 0x1130, 0x2001, 0x4009, + 0x0048, 0x2001, 0x0001, 0x0030, 0x080c, 0x4400, 0x1dd0, 0x6312, + 0x6216, 0xa006, 0xa005, 0x00de, 0x00ee, 0x0005, 0x81ff, 0x1904, + 0x2924, 0x080c, 0x3641, 0x0904, 0x2924, 0x6837, 0x0000, 0x6838, + 0xc0fd, 0x683a, 0x7824, 0xa005, 0x0904, 0x2927, 0xa096, 0x00ff, + 0x0120, 0xa092, 0x0004, 0x1a04, 0x2927, 0x2010, 0x2d18, 0x080c, + 0x2631, 0x0904, 0x2924, 0x7007, 0x0003, 0x701b, 0x3618, 0x0005, + 0x6830, 0xa086, 0x0100, 0x0904, 0x2924, 0x0804, 0x28ff, 0x7924, + 0xa18c, 0xff00, 0x810f, 0x60c8, 0xd0ac, 0x1120, 0xa182, 0x0080, + 0x0a04, 0x2927, 0xa182, 0x00ff, 0x1a04, 0x2927, 0x0126, 0x2091, + 0x8000, 0x080c, 0x831a, 0x1150, 0xa190, 0x936e, 0x2204, 0xa065, + 0x0128, 0x080c, 0x41e0, 0x012e, 0x0804, 0x28ff, 0x012e, 0x0804, + 0x2924, 0x080c, 0x147c, 0x0188, 0xa006, 0x6802, 0x7010, 0xa005, + 0x1120, 0x2d00, 0x7012, 0x7016, 0x0030, 0x7014, 0x6802, 0x2060, + 0x2d00, 0x6006, 0x7016, 0xad80, 0x000d, 0x0005, 0x7924, 0x810f, + 0xa18c, 0x00ff, 0x080c, 0x4434, 0x1130, 0x7e28, 0xa684, 0x3fff, + 0xa082, 0x4000, 0x0208, 0xa066, 0x8cff, 0x0005, 0x7e24, 0x860f, + 0xa18c, 0x00ff, 0x080c, 0x4434, 0x1128, 0xa6b4, 0x00ff, 0xa682, + 0x4000, 0x0208, 0xa066, 0x8cff, 0x0005, 0x0016, 0x7110, 0x81ff, + 0x0128, 0x2168, 0x6904, 0x080c, 0x1493, 0x0cc8, 0x7112, 0x7116, + 0x001e, 0x0005, 0x2031, 0x0001, 0x0010, 0x2031, 0x0000, 0x2061, + 0x92e6, 0x6606, 0x6112, 0x600e, 0x6226, 0x632a, 0x642e, 0x6532, + 0x2c10, 0x080c, 0x14c7, 0x7007, 0x0002, 0x701b, 0x28ff, 0x0005, + 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001, 0x92a4, + 0x2004, 0xa005, 0x1168, 0x0e04, 0x36b0, 0x7818, 0xd084, 0x1140, + 0x7a22, 0x7b26, 0x7c2a, 0x781b, 0x0001, 0x2091, 0x4080, 0x0408, + 0x0016, 0x00c6, 0x00e6, 0x2071, 0x9296, 0x7138, 0xa182, 0x0010, + 0x0218, 0x7030, 0x2060, 0x0078, 0x7030, 0xa0e0, 0x0004, 0xac82, + 0x92e6, 0x0210, 0x2061, 0x92a6, 0x2c00, 0x7032, 0x81ff, 0x1108, + 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, 0x00ee, 0x00ce, + 0x001e, 0x012e, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x9296, 0x7038, + 0xa005, 0x0570, 0x0126, 0x2091, 0x8000, 0x0e04, 0x3707, 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, + 0x92a6, 0x7037, 0x92a6, 0x00ce, 0x0048, 0xac80, 0x0004, 0xa0fa, + 0x92e6, 0x0210, 0x2001, 0x92a6, 0x7036, 0x00ce, 0x00fe, 0x012e, + 0x00ee, 0x0005, 0x0026, 0x2001, 0x9252, 0x2004, 0xd0c4, 0x0120, + 0x2011, 0x8014, 0x080c, 0x3698, 0x002e, 0x0005, 0x81ff, 0x1904, + 0x2924, 0x0126, 0x2091, 0x8000, 0x6030, 0xc08d, 0x6032, 0x080c, + 0x4dc5, 0x1158, 0x2001, 0x94d8, 0x2003, 0x0001, 0x2001, 0x9200, + 0x2003, 0x0001, 0x080c, 0x4d10, 0x0010, 0x080c, 0x4105, 0x012e, + 0x0804, 0x28ff, 0x7824, 0x2008, 0xa18c, 0xfffd, 0x1128, 0x61d4, + 0xa10d, 0x61d6, 0x0804, 0x28ff, 0x0804, 0x2927, 0x81ff, 0x1904, + 0x2924, 0x6000, 0xa086, 0x0003, 0x1904, 0x2924, 0x2001, 0x9252, + 0x2004, 0xd0a4, 0x1904, 0x2924, 0x080c, 0x3666, 0x0904, 0x2927, + 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1120, 0x7828, 0xa005, + 0x0904, 0x28ff, 0x00c6, 0x080c, 0x3641, 0x00ce, 0x0904, 0x2924, + 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, + 0x84d7, 0x0904, 0x2924, 0x7007, 0x0003, 0x701b, 0x3770, 0x0005, + 0x6830, 0xa086, 0x0100, 0x0904, 0x2924, 0x0804, 0x28ff, 0x2001, + 0x9200, 0x2004, 0xa086, 0x0003, 0x1904, 0x2924, 0x7f24, 0x7a2c, + 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3641, 0x0904, 0x2924, 0x2009, + 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80, + 0x0005, 0x7026, 0x20a0, 0x080c, 0x4434, 0x15e0, 0x6004, 0xa0c4, + 0x00ff, 0xa8c6, 0x0006, 0x0150, 0xa0c4, 0xff00, 0xa8c6, 0x0600, + 0x0128, 0xa084, 0x00ff, 0xa082, 0x0006, 0x1660, 0xd784, 0x0150, + 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x080c, + 0x34eb, 0x0048, 0xac80, 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004, + 0x53a3, 0x080c, 0x34eb, 0xa186, 0x007e, 0x0178, 0xa186, 0x0080, + 0x0160, 0x6004, 0xa084, 0x00ff, 0xa0c2, 0x0006, 0x1210, 0xc1fd, + 0x0020, 0x080c, 0x46a5, 0x1108, 0xc1fd, 0x21a2, 0xc1fc, 0x94a0, + 0xa6b0, 0x0005, 0x8108, 0x2001, 0x9232, 0x2004, 0xd0ac, 0x0118, + 0xa186, 0x0100, 0x0040, 0xd78c, 0x0120, 0xa186, 0x0100, 0x0148, + 0x0018, 0xa186, 0x007e, 0x0128, 0xa686, 0x0028, 0x0150, 0x0804, + 0x3793, 0x86ff, 0x1120, 0x7120, 0x810b, 0x0804, 0x28ff, 0x702f, + 0x0001, 0x711e, 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, 0x92e6, + 0x6007, 0x0000, 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, 0x642e, + 0x6532, 0x2c10, 0x080c, 0x14c7, 0x7007, 0x0002, 0x701b, 0x3809, + 0x0005, 0x702c, 0xa005, 0x1170, 0x711c, 0x7024, 0x20a0, 0x7728, + 0x2031, 0x0000, 0x2061, 0x92e6, 0x6224, 0x6328, 0x642c, 0x6530, + 0x0804, 0x3793, 0x7120, 0x810b, 0x0804, 0x28ff, 0x2029, 0x007e, + 0x7924, 0x7a28, 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, 0xa0e2, + 0x0020, 0x0a04, 0x2927, 0xa502, 0x0a04, 0x2927, 0xa184, 0x00ff, + 0xa0e2, 0x0020, 0x0a04, 0x2927, 0xa502, 0x0a04, 0x2927, 0xa284, + 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x2927, 0xa502, 0x0a04, + 0x2927, 0xa284, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x2927, 0xa502, + 0x0a04, 0x2927, 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, + 0x2927, 0xa502, 0x0a04, 0x2927, 0xa384, 0x00ff, 0xa0e2, 0x0020, + 0x0a04, 0x2927, 0xa502, 0x0a04, 0x2927, 0xa484, 0xff00, 0x8007, + 0xa0e2, 0x0020, 0x0a04, 0x2927, 0xa502, 0x0a04, 0x2927, 0xa484, + 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x2927, 0xa502, 0x0a04, 0x2927, + 0x2061, 0x94df, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x28ff, + 0x080c, 0x3641, 0x0904, 0x2924, 0x2009, 0x0015, 0x7a2c, 0x7b28, + 0x7c3c, 0x7d38, 0x080c, 0x3682, 0x701b, 0x3887, 0x0005, 0xade8, + 0x000d, 0x6800, 0xa005, 0x0904, 0x2927, 0x6804, 0x2008, 0xa18c, + 0xfff8, 0x1904, 0x2927, 0x680c, 0xa005, 0x0904, 0x2927, 0xa082, + 0xff01, 0x1a04, 0x2927, 0x6810, 0xa082, 0x005c, 0x0a04, 0x2927, + 0x6824, 0x2008, 0xa082, 0x0008, 0x0a04, 0x2927, 0xa182, 0x0400, + 0x1a04, 0x2927, 0x080c, 0x5a84, 0x6944, 0x6820, 0xa102, 0x0a04, + 0x2927, 0x6828, 0x6944, 0x810c, 0xa102, 0x0a04, 0x2927, 0x6840, + 0xa082, 0x000f, 0x1a04, 0x2927, 0x00d6, 0x080c, 0x145f, 0x0904, + 0x2924, 0x2d00, 0x00de, 0x684e, 0x00d6, 0x6848, 0xa005, 0x0148, + 0x2008, 0x2069, 0x9200, 0x68dc, 0xa108, 0x68a8, 0xa102, 0x1208, + 0x69de, 0x00de, 0x20a9, 0x0015, 0x2d98, 0x2069, 0x9281, 0x2da0, + 0x53a3, 0x080c, 0x5957, 0x0904, 0x2924, 0x080c, 0x5885, 0x1904, + 0x2924, 0x00c6, 0x2061, 0x0100, 0x6104, 0xa18d, 0x8000, 0x6106, + 0x610c, 0xa18d, 0x0100, 0x610e, 0x2061, 0x0140, 0x610c, 0xa18d, + 0x0100, 0x6902, 0x6b10, 0x2061, 0x9519, 0x6316, 0x080c, 0x4716, + 0x2001, 0x9295, 0x2003, 0x0000, 0x00ce, 0x0804, 0x28ff, 0xe000, + 0xe000, 0xe000, 0xe000, 0xe000, 0xe000, 0xe000, 0x0804, 0x28ff, + 0x7824, 0x0804, 0x28ff, 0x7824, 0x00e6, 0x2071, 0x9281, 0x00ee, + 0x0804, 0x28ff, 0x0006, 0x2001, 0x9252, 0x2004, 0xd0cc, 0x000e, + 0x0005, 0x0006, 0x2001, 0x9271, 0x2004, 0xd0bc, 0x000e, 0x0005, + 0x6164, 0x7a24, 0x6300, 0x82ff, 0x1118, 0x7926, 0x0804, 0x28ff, + 0x83ff, 0x1904, 0x2927, 0x2001, 0xfff0, 0xa200, 0x1a04, 0x2927, + 0x2019, 0xffff, 0x6068, 0xa302, 0xa200, 0x0a04, 0x2927, 0x7926, + 0x6266, 0x0804, 0x28ff, 0x2001, 0x9200, 0x2004, 0xa086, 0x0003, + 0x1904, 0x2924, 0x7c28, 0x7d24, 0x7e38, 0x7f2c, 0x080c, 0x3641, + 0x0904, 0x2924, 0x2009, 0x0000, 0x2019, 0x0000, 0x7023, 0x0000, + 0x702f, 0x0000, 0xad80, 0x0003, 0x7026, 0x20a0, 0xa1e0, 0x936e, + 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, 0x28ff, + 0x702f, 0x0001, 0x711e, 0x7020, 0xa300, 0x7022, 0x2061, 0x92e6, + 0x6007, 0x0000, 0x6312, 0x7024, 0x600e, 0x6426, 0x652a, 0x662e, + 0x6732, 0x2c10, 0x080c, 0x14c7, 0x7007, 0x0002, 0x701b, 0x3999, + 0x0005, 0x702c, 0xa005, 0x1158, 0x711c, 0x7024, 0x20a0, 0x2019, + 0x0000, 0x6424, 0x6528, 0x662c, 0x6730, 0x0804, 0x3956, 0x7120, + 0x810c, 0x0804, 0x28ff, 0x81ff, 0x1904, 0x2924, 0x60c8, 0xd0ac, + 0x1118, 0xd09c, 0x0904, 0x2924, 0x080c, 0x3641, 0x0904, 0x2924, + 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3682, 0x701b, + 0x39c2, 0x0005, 0x00d6, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, + 0x0148, 0xa0be, 0x7100, 0x0130, 0xa0be, 0x7200, 0x0118, 0x00de, + 0x0804, 0x2927, 0x6820, 0x6924, 0x080c, 0x240b, 0x1500, 0x080c, + 0x4400, 0x11e8, 0x7122, 0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c, + 0x3641, 0x01a8, 0x080c, 0x3641, 0x0190, 0x00ce, 0x00de, 0x6837, + 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x080c, 0x845c, + 0x0904, 0x2924, 0x7007, 0x0003, 0x701b, 0x39fa, 0x0005, 0x00de, + 0x0804, 0x2924, 0x7120, 0x080c, 0x441f, 0x6820, 0xa086, 0x8001, + 0x0904, 0x2924, 0x2d00, 0x701e, 0x6804, 0xa080, 0x0002, 0x0006, + 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x4166, 0x000e, 0xade8, + 0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0x92e6, 0x6007, + 0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x1108, 0x0018, 0xa7c6, + 0x7100, 0x1140, 0xa6c2, 0x0004, 0x0a04, 0x2927, 0x2009, 0x0004, + 0x0804, 0x3685, 0xa7c6, 0x7200, 0x1904, 0x2927, 0xa6c2, 0x0054, + 0x0a04, 0x2927, 0x600e, 0x6013, 0x002a, 0x6226, 0x632a, 0x642e, + 0x6532, 0x2c10, 0x080c, 0x14c7, 0x7007, 0x0002, 0x701b, 0x3a41, + 0x0005, 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, 0x2004, 0xa080, + 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x4166, + 0x000e, 0x2009, 0x002a, 0x2061, 0x92e6, 0x6224, 0x6328, 0x642c, + 0x6530, 0x0804, 0x3685, 0x81ff, 0x1904, 0x2924, 0x080c, 0x3656, + 0x0904, 0x2927, 0x080c, 0x44d4, 0x0904, 0x2924, 0x080c, 0x4604, + 0x0804, 0x28ff, 0x0126, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, + 0x9200, 0x6044, 0xd0a4, 0x11b0, 0xd084, 0x0118, 0x080c, 0x3bd7, + 0x0068, 0xd08c, 0x0118, 0x080c, 0x3af8, 0x0040, 0xd094, 0x0118, + 0x080c, 0x3ad0, 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, 0x0478, + 0xa294, 0xff00, 0xa296, 0xf700, 0x0160, 0x6240, 0xa295, 0x0100, + 0x6242, 0xa294, 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, 0x4186, + 0x00f0, 0x6040, 0xa084, 0x0010, 0xa085, 0x0040, 0x6042, 0x6043, + 0x0000, 0x7077, 0x0000, 0x7093, 0x0001, 0x70b3, 0x0000, 0x70cb, + 0x0000, 0x2009, 0x98c0, 0x200b, 0x0000, 0x7087, 0x0000, 0x707b, + 0x000f, 0x2009, 0x000f, 0x2011, 0x40a8, 0x080c, 0x57b3, 0x0005, + 0x0156, 0x7078, 0xa005, 0x1510, 0x2011, 0x40a8, 0x080c, 0x5731, + 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, 0x00c8, + 0x6044, 0xd08c, 0x1168, 0x1f04, 0x3ae0, 0x6242, 0x708b, 0x0000, + 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, 0x6242, 0x0030, + 0x6242, 0x708b, 0x0000, 0x707f, 0x0000, 0x0000, 0x015e, 0x0005, + 0x707c, 0xa08a, 0x0003, 0x1210, 0x0023, 0x0010, 0x080c, 0x13fe, + 0x0005, 0x3b04, 0x3b54, 0x3bd6, 0x00f6, 0x707f, 0x0001, 0x20e1, + 0xa000, 0xe000, 0x20e1, 0x8700, 0x080c, 0x20ce, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x2079, 0x9700, 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, 0x970c, 0x207b, 0x1101, + 0x7807, 0x0000, 0x2099, 0x9205, 0x20a1, 0x970e, 0x20a9, 0x0004, + 0x53a3, 0x2079, 0x9712, 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, + 0x9700, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, + 0x600f, 0x0000, 0x080c, 0x40ec, 0x00fe, 0x7083, 0x0000, 0x6043, + 0x0008, 0x6043, 0x0000, 0x0005, 0x00d6, 0x7080, 0x7083, 0x0000, + 0xa025, 0x0904, 0x3bbe, 0x6020, 0xd0b4, 0x1904, 0x3bbc, 0x7190, + 0x81ff, 0x0904, 0x3ba6, 0xa486, 0x000c, 0x1904, 0x3bb1, 0xa480, + 0x0018, 0x8004, 0x20a8, 0x2011, 0x9780, 0x2019, 0x9700, 0x220c, + 0x2304, 0xa106, 0x1188, 0x8210, 0x8318, 0x1f04, 0x3b6f, 0x6043, + 0x0004, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x707f, + 0x0002, 0x708b, 0x0002, 0x04c0, 0x2069, 0x9780, 0x6930, 0xa18e, + 0x1101, 0x1538, 0x6834, 0xa005, 0x1520, 0x6900, 0xa18c, 0x00ff, + 0x1118, 0x6804, 0xa005, 0x0190, 0x2011, 0x978e, 0x2019, 0x9205, + 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102, 0x0230, 0x1190, 0x8210, + 0x8318, 0x1f04, 0x3b9a, 0x0068, 0x7093, 0x0000, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x2099, 0x9780, 0x20a1, 0x020b, 0x20a9, 0x0014, + 0x53a6, 0x6043, 0x0008, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x1120, + 0x60c3, 0x000c, 0x080c, 0x40ec, 0x00de, 0x0005, 0x6040, 0xa085, + 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x60c3, 0x000c, 0x2011, + 0x94ef, 0x2013, 0x0000, 0x7083, 0x0000, 0x20e1, 0x9080, 0x60a3, + 0x0056, 0x60a7, 0x9575, 0x080c, 0x6f15, 0x0c30, 0x0005, 0x7088, + 0xa08a, 0x001d, 0x1210, 0x0023, 0x0010, 0x080c, 0x13fe, 0x0005, + 0x3c0a, 0x3c19, 0x3c43, 0x3c58, 0x3c7e, 0x3ca6, 0x3ccc, 0x3cfd, + 0x3d23, 0x3d4b, 0x3d86, 0x3dae, 0x3dca, 0x3de0, 0x3e00, 0x3e13, + 0x3e1b, 0x3e45, 0x3e6b, 0x3e93, 0x3eb9, 0x3eea, 0x3f25, 0x3f54, + 0x3f70, 0x3faf, 0x3fcf, 0x3fe8, 0x3fe9, 0x00c6, 0x2061, 0x9200, + 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, 0x6006, + 0x00ce, 0x0005, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0002, + 0x708b, 0x0001, 0x2009, 0x07d0, 0x2011, 0x40af, 0x080c, 0x5725, + 0x0005, 0x00f6, 0x7080, 0xa086, 0x0014, 0x1518, 0x6043, 0x0000, + 0x6020, 0xd0b4, 0x11f0, 0x2079, 0x9780, 0x7a30, 0xa296, 0x1102, + 0x11b0, 0x7834, 0xa005, 0x1198, 0x7a38, 0xd2fc, 0x0138, 0x70b0, + 0xa005, 0x1120, 0x080c, 0x419d, 0x70b3, 0x0001, 0x2011, 0x40af, + 0x080c, 0x5731, 0x708b, 0x0010, 0x080c, 0x3e1b, 0x0010, 0x7083, + 0x0000, 0x00fe, 0x0005, 0x708b, 0x0003, 0x6043, 0x0004, 0x080c, + 0x416e, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, 0x000a, 0x20a3, + 0x0000, 0x1f04, 0x3c4f, 0x60c3, 0x0014, 0x080c, 0x40ec, 0x0005, + 0x00f6, 0x7080, 0xa005, 0x0500, 0x2011, 0x40af, 0x080c, 0x5731, + 0xa086, 0x0014, 0x11b8, 0x2079, 0x9780, 0x7a30, 0xa296, 0x1102, + 0x1188, 0x7834, 0xa005, 0x1170, 0x7a38, 0xd2fc, 0x0138, 0x70b0, + 0xa005, 0x1120, 0x080c, 0x419d, 0x70b3, 0x0001, 0x708b, 0x0004, + 0x0029, 0x0010, 0x080c, 0x41b6, 0x00fe, 0x0005, 0x708b, 0x0005, + 0x080c, 0x416e, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, + 0x978e, 0x080c, 0x41bd, 0x1160, 0x7074, 0xa005, 0x1148, 0x714c, + 0xa186, 0xffff, 0x0128, 0x080c, 0x4074, 0x0110, 0x080c, 0x419d, + 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0014, 0x080c, 0x40ec, 0x0005, 0x00f6, 0x7080, + 0xa005, 0x0500, 0x2011, 0x40af, 0x080c, 0x5731, 0xa086, 0x0014, + 0x11b8, 0x2079, 0x9780, 0x7a30, 0xa296, 0x1103, 0x1188, 0x7834, + 0xa005, 0x1170, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, + 0x080c, 0x419d, 0x70b3, 0x0001, 0x708b, 0x0006, 0x0029, 0x0010, + 0x080c, 0x41b6, 0x00fe, 0x0005, 0x708b, 0x0007, 0x080c, 0x416e, + 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0x978e, 0x080c, + 0x41bd, 0x11a8, 0x7074, 0xa005, 0x1190, 0x7154, 0xa186, 0xffff, + 0x0170, 0xa180, 0x2719, 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, + 0x4074, 0x0128, 0x080c, 0x3919, 0x0110, 0x080c, 0x2455, 0x20a9, + 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0014, 0x080c, 0x40ec, 0x0005, 0x00f6, 0x7080, 0xa005, + 0x0500, 0x2011, 0x40af, 0x080c, 0x5731, 0xa086, 0x0014, 0x11b8, + 0x2079, 0x9780, 0x7a30, 0xa296, 0x1104, 0x1188, 0x7834, 0xa005, + 0x1170, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c, + 0x419d, 0x70b3, 0x0001, 0x708b, 0x0008, 0x0029, 0x0010, 0x080c, + 0x41b6, 0x00fe, 0x0005, 0x708b, 0x0009, 0x080c, 0x416e, 0x20a3, + 0x1105, 0x20a3, 0x0100, 0x3430, 0x080c, 0x41bd, 0x1150, 0x7074, + 0xa005, 0x1138, 0x080c, 0x3fea, 0x1170, 0xa085, 0x0001, 0x080c, + 0x2455, 0x20a9, 0x0008, 0x2099, 0x978e, 0x26a0, 0x53a6, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x40ec, 0x0010, + 0x080c, 0x3bfd, 0x0005, 0x00f6, 0x7080, 0xa005, 0x05a8, 0x2011, + 0x40af, 0x080c, 0x5731, 0xa086, 0x0014, 0x1560, 0x2079, 0x9780, + 0x7a30, 0xa296, 0x1105, 0x1530, 0x7834, 0x2011, 0x0100, 0xa21e, + 0x1170, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c, + 0x419d, 0x70b3, 0x0001, 0x708b, 0x000a, 0x00c1, 0x00a8, 0xa005, + 0x1188, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c, + 0x419d, 0x70b3, 0x0001, 0x7087, 0x0000, 0x708b, 0x000e, 0x080c, + 0x3e00, 0x0010, 0x080c, 0x41b6, 0x00fe, 0x0005, 0x708b, 0x000b, + 0x2011, 0x970e, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, 0x43a4, + 0x20a9, 0x0002, 0x2009, 0x0000, 0x41a4, 0x080c, 0x416e, 0x20a3, + 0x1106, 0x20a3, 0x0000, 0x080c, 0x41bd, 0x0118, 0x2013, 0x0000, + 0x0020, 0x7050, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, + 0x53a6, 0x60c3, 0x0084, 0x080c, 0x40ec, 0x0005, 0x00f6, 0x7080, + 0xa005, 0x01b0, 0x2011, 0x40af, 0x080c, 0x5731, 0xa086, 0x0084, + 0x1168, 0x2079, 0x9780, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834, + 0xa005, 0x1120, 0x708b, 0x000c, 0x0029, 0x0010, 0x080c, 0x41b6, + 0x00fe, 0x0005, 0x708b, 0x000d, 0x080c, 0x416e, 0x20a3, 0x1107, + 0x20a3, 0x0000, 0x2099, 0x978e, 0x20a9, 0x0040, 0x53a6, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x40ec, 0x0005, + 0x00f6, 0x7080, 0xa005, 0x01d0, 0x2011, 0x40af, 0x080c, 0x5731, + 0xa086, 0x0084, 0x1188, 0x2079, 0x9780, 0x7a30, 0xa296, 0x1107, + 0x1158, 0x7834, 0xa005, 0x1140, 0x7087, 0x0001, 0x080c, 0x4160, + 0x708b, 0x000e, 0x0029, 0x0010, 0x080c, 0x41b6, 0x00fe, 0x0005, + 0x708b, 0x000f, 0x7083, 0x0000, 0x608b, 0xbc85, 0x608f, 0xb5b5, + 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x40af, + 0x080c, 0x5725, 0x0005, 0x7080, 0xa005, 0x0120, 0x2011, 0x40af, + 0x080c, 0x5731, 0x0005, 0x708b, 0x0011, 0x716c, 0x81ff, 0x0170, + 0x2009, 0x0000, 0x7070, 0xa084, 0x00ff, 0x080c, 0x240b, 0xa186, + 0x0080, 0x0120, 0x2011, 0x978e, 0x080c, 0x4074, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x2099, 0x9780, 0x20a1, 0x020b, 0x7480, 0xa480, + 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, + 0x60c3, 0x0014, 0x080c, 0x40ec, 0x0005, 0x00f6, 0x7080, 0xa005, + 0x0500, 0x2011, 0x40af, 0x080c, 0x5731, 0xa086, 0x0014, 0x11b8, + 0x2079, 0x9780, 0x7a30, 0xa296, 0x1103, 0x1188, 0x7834, 0xa005, + 0x1170, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c, + 0x419d, 0x70b3, 0x0001, 0x708b, 0x0012, 0x0029, 0x0010, 0x7083, + 0x0000, 0x00fe, 0x0005, 0x708b, 0x0013, 0x080c, 0x417a, 0x20a3, + 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0x978e, 0x080c, 0x41bd, + 0x1160, 0x7074, 0xa005, 0x1148, 0x714c, 0xa186, 0xffff, 0x0128, + 0x080c, 0x4074, 0x0110, 0x080c, 0x419d, 0x20a9, 0x0008, 0x2298, + 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, + 0x080c, 0x40ec, 0x0005, 0x00f6, 0x7080, 0xa005, 0x0500, 0x2011, + 0x40af, 0x080c, 0x5731, 0xa086, 0x0014, 0x11b8, 0x2079, 0x9780, + 0x7a30, 0xa296, 0x1104, 0x1188, 0x7834, 0xa005, 0x1170, 0x7a38, + 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c, 0x419d, 0x70b3, + 0x0001, 0x708b, 0x0014, 0x0029, 0x0010, 0x7083, 0x0000, 0x00fe, + 0x0005, 0x708b, 0x0015, 0x080c, 0x417a, 0x20a3, 0x1104, 0x20a3, + 0x0000, 0x3430, 0x2011, 0x978e, 0x080c, 0x41bd, 0x11a8, 0x7074, + 0xa005, 0x1190, 0x7154, 0xa186, 0xffff, 0x0170, 0xa180, 0x2719, + 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4074, 0x0128, 0x080c, + 0x3919, 0x0110, 0x080c, 0x2455, 0x20a9, 0x0008, 0x2298, 0x26a0, + 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, + 0x40ec, 0x0005, 0x00f6, 0x7080, 0xa005, 0x05a8, 0x2011, 0x40af, + 0x080c, 0x5731, 0xa086, 0x0014, 0x1560, 0x2079, 0x9780, 0x7a30, + 0xa296, 0x1105, 0x1530, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1178, + 0x7a38, 0xd2f4, 0x0110, 0x70cb, 0x0008, 0xd2fc, 0x0138, 0x70b0, + 0xa005, 0x1120, 0x080c, 0x419d, 0x70b3, 0x0001, 0x0070, 0xa005, + 0x1180, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c, + 0x419d, 0x70b3, 0x0001, 0x7087, 0x0000, 0x708b, 0x0016, 0x0029, + 0x0010, 0x7083, 0x0000, 0x00fe, 0x0005, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x2099, 0x9780, 0x20a1, 0x020b, 0x20a9, 0x000e, 0x53a6, + 0x3430, 0x2011, 0x978e, 0x708b, 0x0017, 0x080c, 0x41bd, 0x1150, + 0x7074, 0xa005, 0x1138, 0x080c, 0x3fea, 0x1170, 0xa085, 0x0001, + 0x080c, 0x2455, 0x20a9, 0x0008, 0x2099, 0x978e, 0x26a0, 0x53a6, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x40ec, + 0x0010, 0x080c, 0x3bfd, 0x0005, 0x00f6, 0x7080, 0xa005, 0x01b0, + 0x2011, 0x40af, 0x080c, 0x5731, 0xa086, 0x0084, 0x1168, 0x2079, + 0x9780, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834, 0xa005, 0x1120, + 0x708b, 0x0018, 0x0029, 0x0010, 0x7083, 0x0000, 0x00fe, 0x0005, + 0x708b, 0x0019, 0x080c, 0x417a, 0x20a3, 0x1106, 0x20a3, 0x0000, + 0x3430, 0x2099, 0x978e, 0x2039, 0x970e, 0x27a0, 0x20a9, 0x0040, + 0x53a3, 0x080c, 0x41bd, 0x11e8, 0x2728, 0x2514, 0x8207, 0xa084, + 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, 0xa205, 0x202a, + 0x7050, 0x2310, 0x8214, 0xa2a0, 0x970e, 0x2414, 0xa38c, 0x0001, + 0x0118, 0xa294, 0xff00, 0x0018, 0xa294, 0x00ff, 0x8007, 0xa215, + 0x2222, 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x40ec, 0x0005, 0x00f6, + 0x7080, 0xa005, 0x01d0, 0x2011, 0x40af, 0x080c, 0x5731, 0xa086, + 0x0084, 0x1188, 0x2079, 0x9780, 0x7a30, 0xa296, 0x1107, 0x1158, + 0x7834, 0xa005, 0x1140, 0x7087, 0x0001, 0x080c, 0x4160, 0x708b, + 0x001a, 0x0029, 0x0010, 0x7083, 0x0000, 0x00fe, 0x0005, 0x708b, + 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x9780, 0x20a1, + 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, + 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x080c, 0x40ec, 0x0005, + 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0x9252, 0x252c, 0x20a9, + 0x0008, 0x2041, 0x970e, 0x28a0, 0x2099, 0x978e, 0x53a3, 0x20a9, + 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0110, 0x2011, 0x0000, 0x2800, + 0xa200, 0x200c, 0xa1a6, 0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210, + 0x0008, 0x8211, 0x1f04, 0x3fff, 0x0804, 0x406c, 0x82ff, 0x1160, + 0xd5d4, 0x0120, 0xa1a6, 0x3fff, 0x0d90, 0x0020, 0xa1a6, 0x3fff, + 0x0904, 0x406c, 0xa18d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, + 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423, + 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318, + 0x1f04, 0x4025, 0x04c8, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, + 0x1f04, 0x4037, 0x2328, 0x8529, 0xa2be, 0x0007, 0x0158, 0x0006, + 0x2039, 0x0007, 0x2200, 0xa73a, 0x000e, 0x27a8, 0xa5a8, 0x0010, + 0x1f04, 0x4046, 0x754e, 0xa5c8, 0x2719, 0x292d, 0xa5ac, 0x00ff, + 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x2435, 0x001e, 0x60e7, + 0x0000, 0x65ea, 0x2018, 0x2304, 0xa405, 0x201a, 0x7077, 0x0001, + 0x26a0, 0x2898, 0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0xa085, 0x0001, 0x0028, 0xa006, 0x0018, 0xa006, 0x080c, + 0x13fe, 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, + 0x11b0, 0xa405, 0x203a, 0x714e, 0xa1a0, 0x2719, 0x242d, 0xa5ac, + 0x00ff, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x2435, 0x001e, + 0x60e7, 0x0000, 0x65ea, 0x7077, 0x0001, 0xa084, 0x0000, 0x0005, + 0x00e6, 0x2071, 0x9200, 0x707b, 0x0000, 0x00ee, 0x0005, 0x00e6, + 0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, 0x6f1e, 0x7004, + 0xa084, 0x4000, 0x0120, 0x7003, 0x1000, 0x7003, 0x0000, 0x080c, + 0x4dcd, 0x01b0, 0x080c, 0x4deb, 0x1198, 0x2001, 0x94d7, 0x2003, + 0xaaaa, 0x2001, 0x0204, 0x2004, 0x0016, 0x2009, 0x94c8, 0x200a, + 0x001e, 0x2001, 0x94d8, 0x2003, 0x0000, 0x080c, 0x4d10, 0x0080, + 0x0126, 0x2091, 0x8000, 0x2071, 0x9222, 0x2073, 0x0000, 0x7840, + 0x0026, 0xa094, 0x0010, 0xa285, 0x0080, 0x7842, 0x7a42, 0x002e, + 0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x2011, + 0x94ef, 0x2013, 0x0000, 0x7083, 0x0000, 0x012e, 0x20e1, 0x9080, + 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x6f15, 0x2009, 0x07d0, + 0x2011, 0x40af, 0x080c, 0x57b3, 0x0005, 0x0016, 0x0026, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x2009, 0x00f7, 0x080c, 0x4186, 0x2061, + 0x94f8, 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0x9200, 0x6003, + 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, + 0x001e, 0x2011, 0x412a, 0x080c, 0x5725, 0x012e, 0x00ce, 0x002e, + 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, + 0x0100, 0x080c, 0x6f1e, 0x2071, 0x0140, 0x7004, 0xa084, 0x4000, + 0x0120, 0x7003, 0x1000, 0x7003, 0x0000, 0x080c, 0x4dcd, 0x01b0, + 0x080c, 0x4deb, 0x1198, 0x2001, 0x94d7, 0x2003, 0xaaaa, 0x2001, + 0x0204, 0x2004, 0x0016, 0x2009, 0x94c8, 0x200a, 0x001e, 0x2001, + 0x94d8, 0x2003, 0x0000, 0x080c, 0x4d10, 0x0030, 0x2001, 0x0001, + 0x080c, 0x23ba, 0x080c, 0x4105, 0x012e, 0x000e, 0x00ee, 0x0005, + 0x20a9, 0x0040, 0x20a1, 0x98c0, 0x2099, 0x978e, 0x3304, 0x8007, + 0x20a2, 0x9398, 0x94a0, 0x1f04, 0x4166, 0x0005, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x2099, 0x9700, 0x20a1, 0x020b, 0x20a9, 0x000c, + 0x53a6, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x9780, + 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x0005, 0x00c6, 0x0006, + 0x2061, 0x0100, 0x810f, 0x2001, 0x922f, 0x2004, 0xa005, 0x1138, + 0x2001, 0x9214, 0x2004, 0xa084, 0x00ff, 0xa105, 0x0010, 0xa185, + 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, 0x0016, 0x0046, 0x2001, + 0x9252, 0x2004, 0xd0a4, 0x0158, 0xa006, 0x2020, 0x2009, 0x002a, + 0x080c, 0x90d7, 0x2001, 0x920c, 0x200c, 0xc195, 0x2102, 0x2019, + 0x002a, 0x080c, 0x264b, 0x004e, 0x001e, 0x0005, 0x080c, 0x4105, + 0x708b, 0x0000, 0x7083, 0x0000, 0x0005, 0x0006, 0x2001, 0x920c, + 0x2004, 0xd09c, 0x0100, 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, + 0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102, + 0x012e, 0x001e, 0x000e, 0x0005, 0x0156, 0x20a9, 0x00ff, 0x2009, + 0x936e, 0xa006, 0x200a, 0x8108, 0x1f04, 0x41da, 0x015e, 0x0005, + 0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0x9251, 0xa006, + 0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x2719, + 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, 0x61a2, + 0x00d6, 0x60a4, 0xa06d, 0x0110, 0x080c, 0x1493, 0x60a7, 0x0000, + 0x60a8, 0xa06d, 0x0110, 0x080c, 0x1493, 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, + 0x42cf, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x1a04, 0x42d4, + 0x2001, 0x920c, 0x2004, 0xa084, 0x0003, 0x1904, 0x42bd, 0xa188, + 0x936e, 0x2104, 0xa065, 0x0904, 0x42a9, 0x6004, 0xa084, 0x00ff, + 0xa08e, 0x0006, 0x1904, 0x42ae, 0x60a4, 0xa00d, 0x0118, 0x080c, + 0x4630, 0x05d0, 0x60a8, 0xa00d, 0x0188, 0x080c, 0x467a, 0x1170, + 0x694c, 0xd1fc, 0x1118, 0x080c, 0x43c4, 0x0448, 0x080c, 0x4386, + 0x694c, 0xd1ec, 0x1520, 0x080c, 0x452b, 0x0408, 0x694c, 0xa184, + 0xa000, 0x0178, 0xd1ec, 0x0140, 0xd1fc, 0x0118, 0x080c, 0x453a, + 0x0028, 0x080c, 0x453a, 0x0028, 0xd1fc, 0x0118, 0x080c, 0x4386, + 0x0070, 0x6050, 0xa00d, 0x0130, 0x2d00, 0x200a, 0x6803, 0x0000, + 0x6052, 0x0028, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x080c, + 0x6015, 0xa006, 0x012e, 0x0005, 0x2001, 0x0005, 0x2009, 0x0000, + 0x0478, 0x2001, 0x0028, 0x2009, 0x0000, 0x0450, 0xa082, 0x0006, + 0x1260, 0x2001, 0x9232, 0x2004, 0xd0ac, 0x1120, 0x60a0, 0xd0bc, + 0x0904, 0x4264, 0x2001, 0x0028, 0x0078, 0x2009, 0x920c, 0x210c, + 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, + 0x0004, 0x0010, 0x2001, 0x0029, 0x2009, 0x0000, 0x0048, 0x2001, + 0x0029, 0x2009, 0x0000, 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, + 0xa005, 0x012e, 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, 0x6844, + 0x0006, 0x000e, 0x0006, 0x000e, 0xa084, 0xff00, 0xa08e, 0xff00, + 0x1120, 0x2001, 0x94c6, 0x2064, 0x0098, 0x6844, 0x8007, 0xa084, + 0x00ff, 0x2008, 0xa182, 0x00ff, 0x16c8, 0xa188, 0x936e, 0x2104, + 0xa065, 0x01f0, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11d8, + 0x2c70, 0x080c, 0x749c, 0x0580, 0x2e00, 0x601a, 0x2d00, 0x6012, + 0x601f, 0x0009, 0x600b, 0x0000, 0x6844, 0xa08e, 0xff00, 0x1110, + 0x600b, 0x8000, 0x2009, 0x0100, 0x080c, 0x7518, 0xa006, 0x00c8, + 0x2001, 0x0028, 0x00a8, 0xa082, 0x0006, 0x0e10, 0x2009, 0x920c, + 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, + 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, + 0xa005, 0x012e, 0x00ee, 0x0005, 0x2001, 0x002c, 0x0cc8, 0x6944, + 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, 0x1678, 0xa18c, 0xff00, + 0x810f, 0xa182, 0x00ff, 0x12e0, 0xa188, 0x936e, 0x2104, 0xa065, + 0x01b8, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11b0, 0x684c, + 0xd0ec, 0x0120, 0x080c, 0x453a, 0x0489, 0x0030, 0x0479, 0x684c, + 0xd0fc, 0x0110, 0x080c, 0x452b, 0x080c, 0x4578, 0xa006, 0x0088, + 0x2001, 0x0028, 0x2009, 0x0000, 0x0060, 0xa082, 0x0006, 0x0e38, + 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, 0x94e5, 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, 0xa294, 0xff00, 0xa215, 0x6206, 0x00ce, 0x012e, + 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, + 0xa294, 0x00ff, 0x8007, 0xa215, 0x6206, 0x00ce, 0x012e, 0x0005, + 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x00b0, 0xa190, + 0x936e, 0x2204, 0xa065, 0x1180, 0x0016, 0x00d6, 0x080c, 0x145f, + 0x2d60, 0x00de, 0x001e, 0x0d80, 0x2c00, 0x2012, 0x60a7, 0x0000, + 0x60ab, 0x0000, 0x080c, 0x41e0, 0xa006, 0x002e, 0x0005, 0x0026, + 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x0060, 0x00d6, 0xa190, + 0x936e, 0x2204, 0xa06d, 0x0120, 0x2013, 0x0000, 0x080c, 0x1493, + 0x00de, 0xa006, 0x002e, 0x0005, 0x0016, 0xa182, 0x00ff, 0x0218, + 0xa085, 0x0001, 0x0030, 0xa188, 0x936e, 0x2104, 0xa065, 0x0dc0, + 0xa006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x600b, + 0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, 0x6002, 0x080c, 0x4dc5, + 0x1520, 0x60a0, 0xa086, 0x007e, 0x2069, 0x9790, 0x0130, 0x2001, + 0x9232, 0x2004, 0xd0ac, 0x11c8, 0x0098, 0x2d04, 0xd0e4, 0x01a8, + 0x00d6, 0x2069, 0x978e, 0x00c6, 0x2061, 0x94d9, 0x6810, 0x2062, + 0x6814, 0x6006, 0x6818, 0x600a, 0x681c, 0x600e, 0x00ce, 0x00de, + 0x8d69, 0x2d04, 0x2069, 0x0140, 0x6886, 0x2069, 0x978e, 0x6808, + 0x605e, 0x6810, 0x6062, 0x6138, 0xa10a, 0x0208, 0x603a, 0x6814, + 0x6066, 0x2099, 0x9796, 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, + 0x53a3, 0x2099, 0x979a, 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, + 0x53a3, 0x2069, 0x97ae, 0x6808, 0x606a, 0x690c, 0x616e, 0x6810, + 0x6072, 0x6818, 0x6076, 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, 0x00e6, + 0x2071, 0x978d, 0x2e04, 0x6896, 0x2071, 0x978e, 0x7004, 0x689a, + 0x701c, 0x689e, 0x00ee, 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, 0x44e6, 0x080c, 0x13fe, 0x260a, + 0x8210, 0x6a06, 0x0098, 0x080c, 0x145f, 0x01a8, 0x2d00, 0x60a6, + 0x6803, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, + 0x8108, 0x1f04, 0x44fe, 0x6807, 0x0001, 0x6e12, 0xa085, 0x0001, + 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000, + 0x00d6, 0x60a4, 0xa00d, 0x01a0, 0x2168, 0x6800, 0xa005, 0x1160, + 0x080c, 0x4630, 0x1168, 0x200b, 0xffff, 0x6804, 0xa08a, 0x0002, + 0x0218, 0x8001, 0x6806, 0x0020, 0x080c, 0x1493, 0x60a7, 0x0000, + 0x00de, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x468d, + 0x0010, 0x080c, 0x4373, 0x080c, 0x45af, 0x1dd8, 0x080c, 0x4578, + 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, 0x454c, 0x080c, 0x13fe, 0x260a, 0x8210, 0x6a56, + 0x0098, 0x080c, 0x145f, 0x01d0, 0x2d00, 0x60aa, 0x6853, 0x0000, + 0xad88, 0x0018, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, + 0x4564, 0x6857, 0x0001, 0x6e62, 0x0010, 0x080c, 0x43c4, 0x0089, + 0x1de0, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, + 0x0126, 0x2091, 0x8000, 0x080c, 0x6015, 0x012e, 0x0005, 0xa01e, + 0x0010, 0x2019, 0x0001, 0xa00e, 0x0126, 0x2091, 0x8000, 0x604c, + 0x2068, 0x6000, 0xd0dc, 0x1170, 0x8dff, 0x01e8, 0x83ff, 0x0120, + 0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, 0x1118, 0x6840, + 0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 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, 0x462a, 0x1110, + 0x2011, 0x0001, 0x080c, 0x4674, 0x1110, 0xa295, 0x0002, 0x0005, + 0x080c, 0x46a5, 0x0118, 0x080c, 0x83ab, 0x0010, 0xa085, 0x0001, + 0x0005, 0x080c, 0x46a5, 0x0118, 0x080c, 0x8338, 0x0010, 0xa085, + 0x0001, 0x0005, 0x080c, 0x46a5, 0x0118, 0x080c, 0x837e, 0x0010, + 0xa085, 0x0001, 0x0005, 0x080c, 0x46a5, 0x0118, 0x080c, 0x8352, + 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x46a5, 0x0118, 0x080c, + 0x83d8, 0x0010, 0xa085, 0x0001, 0x0005, 0x0126, 0x0006, 0x00d6, + 0x2091, 0x8000, 0x6080, 0xa06d, 0x0168, 0x6800, 0x0006, 0x6837, + 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x8527, 0x080c, 0x4809, + 0x000e, 0x0c88, 0x6083, 0x0000, 0x6087, 0x0000, 0x00de, 0x000e, + 0x012e, 0x0005, 0x60a4, 0xa00d, 0x1118, 0xa085, 0x0001, 0x0005, + 0x00e6, 0x2170, 0x7000, 0xa005, 0x1160, 0x20a9, 0x0010, 0xae88, + 0x0004, 0x2104, 0xa606, 0x0128, 0x8108, 0x1f04, 0x4639, 0xa085, + 0x0001, 0xa006, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, + 0x60a4, 0xa06d, 0x1128, 0x080c, 0x145f, 0x01a0, 0x2d00, 0x60a6, + 0x6803, 0x0001, 0x6807, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, + 0x200b, 0xffff, 0x8108, 0x1f04, 0x4658, 0xa085, 0x0001, 0x012e, + 0x00de, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x0126, 0x2091, 0x8000, + 0x60a4, 0xa06d, 0x0130, 0x60a7, 0x0000, 0x080c, 0x1493, 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, + 0x4683, 0xa085, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, + 0x0c19, 0x1188, 0x200b, 0xffff, 0x00d6, 0x60a8, 0x2068, 0x6854, + 0xa08a, 0x0002, 0x0218, 0x8001, 0x6856, 0x0020, 0x080c, 0x1493, + 0x60ab, 0x0000, 0x00de, 0x012e, 0x0005, 0x609c, 0xd0a4, 0x0005, + 0x00f6, 0x2079, 0x9251, 0x7804, 0xd0a4, 0x0518, 0x0156, 0x00c6, + 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4434, 0x1168, + 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, 0x0118, 0xa086, + 0x0006, 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e, 0x8108, 0x1f04, + 0x46b4, 0x00ce, 0x015e, 0x2009, 0x07d0, 0x2011, 0x46d3, 0x080c, + 0x57b3, 0x00fe, 0x0005, 0x2011, 0x46d3, 0x080c, 0x5731, 0x0156, + 0x00c6, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4434, + 0x1530, 0x6000, 0xd0ec, 0x0518, 0x0046, 0x62a0, 0xa294, 0x00ff, + 0x8227, 0xa006, 0x2009, 0x0029, 0x080c, 0x90d7, 0x6000, 0xc0e5, + 0xc0ec, 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700, 0x6006, + 0x2019, 0x0029, 0x080c, 0x6127, 0x0086, 0x2041, 0x0000, 0x080c, + 0x606d, 0x2009, 0x0000, 0x080c, 0x8ee4, 0x008e, 0x004e, 0x001e, + 0x8108, 0x1f04, 0x46dd, 0x00ce, 0x015e, 0x0005, 0x00c6, 0x6018, + 0x2060, 0x6000, 0xc0ec, 0x6002, 0x00ce, 0x0005, 0x00c6, 0x00d6, + 0x080c, 0x145f, 0x2d60, 0x090c, 0x13fe, 0x2009, 0x00ff, 0x080c, + 0x41e0, 0x6007, 0x0006, 0x6013, 0x00ff, 0x6017, 0xffff, 0x606f, + 0x0200, 0x606c, 0x6093, 0x0002, 0x60bb, 0x0520, 0x60a3, 0x00ff, + 0x60b7, 0x0000, 0x60af, 0x0000, 0x2c08, 0x2001, 0x94c6, 0x2102, + 0x00de, 0x00ce, 0x0005, 0x0156, 0x00e6, 0x00d6, 0x00c6, 0x20a9, + 0x00ff, 0x2009, 0x0000, 0x0016, 0x080c, 0x4434, 0x1138, 0x2c70, + 0x70ac, 0xa005, 0x0118, 0x2060, 0x080c, 0x5cf4, 0x001e, 0x8108, + 0x1f04, 0x4743, 0x00ce, 0x00de, 0x00ee, 0x015e, 0x0005, 0x2071, + 0x9328, 0x7003, 0x0001, 0x7007, 0x0000, 0x7013, 0x0000, 0x7017, + 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x704b, 0x0001, 0x704f, + 0x0000, 0x705b, 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, + 0x94b6, 0x7003, 0x9328, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, + 0x9496, 0x7013, 0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x0005, + 0x0016, 0x00e6, 0x2071, 0x946e, 0xa00e, 0x7186, 0x718a, 0x7097, + 0x0001, 0x2001, 0x9252, 0x2004, 0xd0fc, 0x1148, 0x2001, 0x9252, + 0x2004, 0xa00e, 0xd09c, 0x0108, 0x8108, 0x7102, 0x04f0, 0x2001, + 0x9271, 0x200c, 0xa184, 0x000f, 0x2009, 0x9272, 0x210c, 0x0002, + 0x478e, 0x47b0, 0x47b7, 0x47c1, 0x47c6, 0x478e, 0x478e, 0x478e, + 0x478e, 0x478e, 0x478e, 0x478e, 0x478e, 0x478e, 0x478e, 0x478e, + 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, 0x9328, 0x684c, 0xa005, 0x1130, 0x7028, 0xc085, + 0x702a, 0xa085, 0x0001, 0x0418, 0x6a60, 0x7236, 0x6b64, 0x733a, + 0x6868, 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e, + 0x6844, 0x7032, 0x2009, 0x000d, 0x200a, 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, 0x4861, + 0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071, 0x9200, 0xa016, 0x702c, + 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e, + 0x70ac, 0xa200, 0x70ae, 0x00de, 0x2071, 0x9328, 0x701c, 0xa005, + 0x1904, 0x4871, 0x20a9, 0x0032, 0x0f04, 0x486f, 0x0e04, 0x482c, + 0x2071, 0x946e, 0x7200, 0x82ff, 0x05d0, 0x6934, 0xa186, 0x0103, + 0x1904, 0x487f, 0x6948, 0x6844, 0xa105, 0x1538, 0x2009, 0x8020, + 0x2200, 0x0002, 0x486f, 0x4846, 0x48e6, 0x48f3, 0x2071, 0x0000, + 0x20a9, 0x0032, 0x0f04, 0x486f, 0x7018, 0xd084, 0x1dd8, 0x7122, + 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, + 0x2071, 0x9200, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70ac, 0x8000, + 0x70ae, 0x002e, 0x00ee, 0x015e, 0x0005, 0x6844, 0xa086, 0x0100, + 0x1130, 0x6868, 0xa005, 0x1118, 0x2009, 0x8020, 0x0888, 0x2071, + 0x9328, 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, 0x4840, + 0x6848, 0xa005, 0x1960, 0x2009, 0x8022, 0x0804, 0x4840, 0x2071, + 0x0000, 0x7018, 0xd084, 0x1918, 0x00e6, 0x2071, 0x9281, 0x7140, + 0x00ee, 0x6838, 0xa102, 0x0a04, 0x486f, 0x684c, 0xa005, 0x1158, + 0x00e6, 0x2071, 0x9281, 0x7004, 0x00ee, 0xd08c, 0x1904, 0x486f, + 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, 0x4854, 0x7084, 0x8008, + 0xa092, 0x001e, 0x1a04, 0x486f, 0x7186, 0xae90, 0x0003, 0xa210, + 0x683c, 0x2012, 0x0080, 0x7084, 0x8008, 0xa092, 0x000f, 0x1a04, + 0x486f, 0x7186, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, + 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a, 0x0a04, 0x4858, 0x718c, + 0x7084, 0xa10a, 0x0a04, 0x4858, 0x2071, 0x0000, 0x7018, 0xd084, + 0x1904, 0x4858, 0x2071, 0x946e, 0x7000, 0xa086, 0x0002, 0x1150, + 0x080c, 0x4b12, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, + 0x0804, 0x4858, 0x080c, 0x4b3c, 0x2071, 0x0000, 0x701b, 0x0001, + 0x2091, 0x4080, 0x0804, 0x4858, 0x0006, 0x6837, 0x0103, 0x20a9, + 0x001c, 0xad80, 0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x000e, + 0x684a, 0x6952, 0x0005, 0x2071, 0x9328, 0x7004, 0x0002, 0x4948, + 0x4958, 0x4afd, 0x4afe, 0x4b0b, 0x4b11, 0x4949, 0x4aee, 0x4a9a, + 0x0005, 0x0126, 0x2091, 0x8000, 0x0e04, 0x4956, 0x2009, 0x000d, + 0x7030, 0x200a, 0x2091, 0x4080, 0x7007, 0x0001, 0x012e, 0x0005, + 0x2069, 0x94f8, 0x683c, 0xa005, 0x03f8, 0x11f0, 0x0126, 0x2091, + 0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0x9334, 0x2004, 0xa10a, + 0x0170, 0x0e04, 0x497c, 0x2069, 0x0000, 0x6818, 0xd084, 0x1158, + 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x2069, + 0x94f8, 0x683f, 0xffff, 0x012e, 0x2069, 0x9200, 0x6844, 0x6964, + 0xa102, 0x2069, 0x946e, 0x688a, 0x6984, 0x701c, 0xa06d, 0x0120, + 0x81ff, 0x0904, 0x49d1, 0x00a0, 0x81ff, 0x0904, 0x4a6f, 0x2071, + 0x946e, 0x7184, 0x7088, 0xa10a, 0x1258, 0x7190, 0x2071, 0x94f8, + 0x7038, 0xa005, 0x0128, 0x1b04, 0x4a6f, 0x713a, 0x0804, 0x4a6f, + 0x2071, 0x946e, 0x718c, 0x0126, 0x2091, 0x8000, 0x7084, 0xa10a, + 0x0a04, 0x4a70, 0x0e04, 0x4a2d, 0x2071, 0x0000, 0x7018, 0xd084, + 0x1904, 0x4a2d, 0x2001, 0xffff, 0x2071, 0x94f8, 0x703a, 0x2071, + 0x946e, 0x7000, 0xa086, 0x0002, 0x1150, 0x080c, 0x4b12, 0x2071, + 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x4a2d, 0x080c, + 0x4b3c, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, + 0x4a2d, 0x2071, 0x946e, 0x7000, 0xa005, 0x0904, 0x4a51, 0x6934, + 0xa186, 0x0103, 0x1904, 0x4a30, 0x6948, 0x6844, 0xa105, 0x1904, + 0x4a47, 0x2071, 0x946e, 0x7000, 0x0002, 0x4a51, 0x4a11, 0x49e9, + 0x49fb, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a04, 0x4a6f, 0xae90, + 0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0x9328, 0x080c, + 0x4b95, 0x0804, 0x4a6f, 0x7084, 0x8008, 0xa092, 0x000f, 0x1a04, + 0x4a6f, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, + 0x6840, 0x2012, 0x7186, 0x2071, 0x9328, 0x080c, 0x4b95, 0x0804, + 0x4a6f, 0x2009, 0x8020, 0x0126, 0x2091, 0x8000, 0x0e04, 0x4a2d, + 0x2071, 0x0000, 0x7018, 0xd084, 0x1180, 0x7122, 0x683c, 0x7026, + 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x012e, 0x2071, + 0x9328, 0x080c, 0x4b95, 0x0804, 0x4a6f, 0x012e, 0x0804, 0x4a6f, + 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118, + 0xa18e, 0x001f, 0x11b0, 0x684c, 0xd0cc, 0x0198, 0x6850, 0xa084, + 0x00ff, 0xa086, 0x0001, 0x1168, 0x2009, 0x8021, 0x0860, 0x6844, + 0xa086, 0x0100, 0x1130, 0x6868, 0xa005, 0x1118, 0x2009, 0x8020, + 0x0810, 0x2071, 0x9328, 0x080c, 0x4ba7, 0x01c8, 0x2071, 0x9328, + 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, 0x1130, + 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x7007, 0x0003, + 0x080c, 0x4bc0, 0x7050, 0xa086, 0x0100, 0x0904, 0x4afe, 0x0005, + 0x2071, 0x9328, 0x080c, 0x4ba7, 0x0518, 0x2071, 0x946e, 0x7084, + 0x700a, 0x20a9, 0x0020, 0x2099, 0x946f, 0x20a1, 0x9496, 0x53a3, + 0x7087, 0x0000, 0x2071, 0x9328, 0x2069, 0x94b6, 0x706c, 0x6826, + 0x7070, 0x682a, 0x7074, 0x682e, 0x7078, 0x6832, 0x2d10, 0x080c, + 0x14c7, 0x7007, 0x0008, 0x2001, 0xffff, 0x2071, 0x94f8, 0x703a, + 0x012e, 0x08a8, 0x2069, 0x94b6, 0x6808, 0xa08e, 0x0000, 0x0904, + 0x4aed, 0xa08e, 0x0200, 0x0904, 0x4aeb, 0xa08e, 0x0100, 0x1904, + 0x4aed, 0x0126, 0x2091, 0x8000, 0x0e04, 0x4ae9, 0x2069, 0x0000, + 0x6818, 0xd084, 0x15b0, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, + 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0048, 0x706c, 0xa080, + 0x0040, 0x706e, 0x1220, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, + 0x6936, 0x2001, 0x9493, 0x2004, 0xa005, 0x1190, 0x6934, 0x2069, + 0x946e, 0x689c, 0x699e, 0x2069, 0x94f8, 0xa102, 0x1118, 0x683c, + 0xa005, 0x1368, 0x2001, 0x9494, 0x200c, 0x810d, 0x693e, 0x0038, + 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x7007, + 0x0001, 0x012e, 0x0010, 0x7007, 0x0005, 0x0005, 0x701c, 0xa06d, + 0x0158, 0x080c, 0x4ba7, 0x0140, 0x7007, 0x0003, 0x080c, 0x4bc0, + 0x7050, 0xa086, 0x0100, 0x0110, 0x0005, 0x0005, 0x7050, 0xa09e, + 0x0100, 0x1118, 0x7007, 0x0004, 0x0030, 0xa086, 0x0200, 0x1110, + 0x7007, 0x0005, 0x0005, 0x080c, 0x4b61, 0x7006, 0x080c, 0x4b95, + 0x0005, 0x0005, 0x00e6, 0x0156, 0x2071, 0x946e, 0x7184, 0x81ff, + 0x0500, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, 0x0000, 0x21a8, + 0x2014, 0x7226, 0x8000, 0x0f04, 0x4b36, 0x2014, 0x722a, 0x8000, + 0x0f04, 0x4b36, 0x2014, 0x722e, 0x8000, 0x0f04, 0x4b36, 0x2014, + 0x723a, 0x8000, 0x0f04, 0x4b36, 0x2014, 0x723e, 0xa180, 0x8030, + 0x7022, 0x015e, 0x00ee, 0x0005, 0x00e6, 0x0156, 0x2071, 0x946e, + 0x7184, 0x81ff, 0x01d8, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, + 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x2014, 0x722a, 0x8000, + 0x0f04, 0x4b58, 0x2014, 0x723a, 0x8000, 0x2014, 0x723e, 0x0018, + 0x2001, 0x8020, 0x0010, 0xa180, 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, 0x11a0, 0x0126, 0x2091, 0x8000, 0x0e04, 0x4b91, 0x2001, + 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x012e, 0x0005, + 0x2001, 0x000d, 0x2102, 0x2001, 0x0001, 0x0005, 0x2001, 0x0007, + 0x0005, 0x2001, 0x0006, 0x012e, 0x0005, 0x701c, 0xa06d, 0x0170, + 0x0126, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, + 0xa005, 0x1108, 0x701a, 0x012e, 0x080c, 0x1493, 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, 0x9508, 0x2104, 0xc08d, 0x200a, 0x012e, + 0x080c, 0x14df, 0x0005, 0x7088, 0xa08a, 0x0027, 0x1220, 0xa082, + 0x001d, 0x0033, 0x0010, 0x080c, 0x13fe, 0x6027, 0x1e00, 0x0005, + 0x4c57, 0x4be9, 0x4bff, 0x4c27, 0x4c4a, 0x4c7c, 0x4c8e, 0x4bff, + 0x4c68, 0x6803, 0x0010, 0x6124, 0xd1e4, 0x1180, 0x080c, 0x4cd7, + 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1cc, 0x0140, 0x708b, 0x0020, + 0x0028, 0x708b, 0x001d, 0x0010, 0x708b, 0x001f, 0x0005, 0x6803, + 0x0008, 0x6124, 0xd1cc, 0x11e8, 0xd1dc, 0x11c0, 0xd1e4, 0x1198, + 0xa184, 0x1e00, 0x11d8, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e, + 0x080c, 0x4df5, 0x6803, 0x0000, 0x708b, 0x0026, 0x2001, 0x9225, + 0x2003, 0x0000, 0x0058, 0x708b, 0x001e, 0x0040, 0x708b, 0x001d, + 0x0028, 0x708b, 0x0020, 0x0010, 0x708b, 0x001f, 0x0005, 0x60e3, + 0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x4df5, 0x6803, 0x0000, + 0x6124, 0xd1d4, 0x11a0, 0xd1dc, 0x1178, 0xd1e4, 0x1150, 0xa184, + 0x1e00, 0x1178, 0x708b, 0x0026, 0x2001, 0x9225, 0x2003, 0x0000, + 0x0040, 0x708b, 0x001e, 0x0028, 0x708b, 0x001d, 0x0010, 0x708b, + 0x001f, 0x0005, 0x6803, 0x0020, 0x6124, 0xd1dc, 0x1128, 0xd1e4, + 0x0128, 0x708b, 0x001e, 0x0010, 0x708b, 0x001d, 0x0005, 0x080c, + 0x4d03, 0x6124, 0xd1dc, 0x1158, 0x080c, 0x4cd7, 0xd1d4, 0x1128, + 0xd1e4, 0x0128, 0x708b, 0x001e, 0x0010, 0x708b, 0x001f, 0x0005, + 0x6803, 0x0020, 0x6124, 0xd1d4, 0x1160, 0xd1cc, 0x1150, 0xd1dc, + 0x1128, 0xd1e4, 0x0140, 0x708b, 0x001e, 0x0028, 0x708b, 0x001d, + 0x0010, 0x708b, 0x0021, 0x0005, 0x080c, 0x4d03, 0x6124, 0xd1d4, + 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708b, 0x001e, 0x0028, + 0x708b, 0x001d, 0x0010, 0x708b, 0x001f, 0x0005, 0x6803, 0x0010, + 0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, + 0x0158, 0x708b, 0x001e, 0x0040, 0x708b, 0x001d, 0x0028, 0x708b, + 0x0020, 0x0010, 0x708b, 0x001f, 0x0005, 0x00c6, 0x00d6, 0x00e6, + 0x0126, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x9200, 0x2091, + 0x8000, 0x080c, 0x4de1, 0x0150, 0x080c, 0x4dd7, 0x1138, 0x2001, + 0x0001, 0x080c, 0x23ba, 0x080c, 0x4d9a, 0x00a0, 0x080c, 0x4d00, + 0x0178, 0x2001, 0x0001, 0x080c, 0x23ba, 0x7088, 0xa086, 0x001e, + 0x0120, 0x7088, 0xa086, 0x0022, 0x1118, 0x708b, 0x0025, 0x0010, + 0x708b, 0x0021, 0x012e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0016, + 0x0026, 0x2009, 0x0064, 0x2011, 0x4ce2, 0x080c, 0x57b3, 0x002e, + 0x001e, 0x0005, 0x00e6, 0x00f6, 0x0016, 0x080c, 0x6f1e, 0x2071, + 0x9200, 0x080c, 0x4ca5, 0x001e, 0x00fe, 0x00ee, 0x0005, 0x0026, + 0x00e6, 0x2011, 0x4ce2, 0x2071, 0x94f8, 0x701c, 0xa206, 0x1118, + 0x7018, 0xa005, 0x0110, 0xa085, 0x0001, 0x00ee, 0x002e, 0x0005, + 0x6020, 0xd09c, 0x0005, 0x6803, 0x0040, 0x0156, 0x20a9, 0x002d, + 0x1d04, 0x4d08, 0x2091, 0x6000, 0x1f04, 0x4d08, 0x015e, 0x0005, + 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, + 0x9200, 0x2001, 0x94d8, 0x200c, 0xa186, 0x0000, 0x0158, 0xa186, + 0x0001, 0x0158, 0xa186, 0x0002, 0x0158, 0xa186, 0x0003, 0x0158, + 0x0804, 0x4d88, 0x708b, 0x0022, 0x0048, 0x708b, 0x0021, 0x0030, + 0x708b, 0x0023, 0x0038, 0x708b, 0x0024, 0x0020, 0xa085, 0x0001, + 0x080c, 0x4e05, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, + 0x080c, 0x2460, 0x0026, 0x2011, 0x0003, 0x080c, 0x718f, 0x002e, + 0x7000, 0xa08e, 0x0004, 0x0118, 0x602b, 0x0028, 0x0010, 0x602b, + 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x6024, + 0xd0ac, 0x0118, 0x012e, 0x015e, 0x04c8, 0x6803, 0x0080, 0x6803, + 0x0000, 0x6904, 0xd1d4, 0x1130, 0x6803, 0x0100, 0x1f04, 0x4d57, + 0x080c, 0x4e12, 0x012e, 0x015e, 0x080c, 0x4dd7, 0x01a8, 0x6044, + 0xa005, 0x0168, 0x6050, 0x0006, 0xa085, 0x0020, 0x6052, 0x080c, + 0x4e12, 0xa006, 0x8001, 0x1df0, 0x000e, 0x6052, 0x0028, 0x6804, + 0xd0d4, 0x1110, 0x080c, 0x4e12, 0x2001, 0x94d8, 0x2003, 0x0004, + 0x080c, 0x4bd3, 0x080c, 0x4dd7, 0x0148, 0x6804, 0xd0d4, 0x1130, + 0xd0dc, 0x1100, 0x2001, 0x94d8, 0x2003, 0x0000, 0x00ee, 0x00de, + 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, + 0x0140, 0x2071, 0x9200, 0x2001, 0x94d7, 0x2003, 0x0000, 0x2001, + 0x94c8, 0x2003, 0x0000, 0x708b, 0x0000, 0x60e3, 0x0000, 0x6887, + 0x0000, 0x2001, 0x0000, 0x080c, 0x2460, 0x6803, 0x0000, 0x6043, + 0x0090, 0x6027, 0xffff, 0x602b, 0x002f, 0x2001, 0x9225, 0x2003, + 0x0000, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, 0x2001, 0x94d7, + 0x2004, 0xa086, 0xaaaa, 0x000e, 0x0005, 0x0006, 0x2001, 0x9271, + 0x2004, 0xa084, 0x0030, 0xa086, 0x0000, 0x000e, 0x0005, 0x0006, + 0x2001, 0x9271, 0x2004, 0xa084, 0x0030, 0xa086, 0x0030, 0x000e, + 0x0005, 0x0006, 0x2001, 0x9271, 0x2004, 0xa084, 0x0030, 0xa086, + 0x0010, 0x000e, 0x0005, 0x0006, 0x2001, 0x9271, 0x2004, 0xa084, + 0x0030, 0xa086, 0x0020, 0x000e, 0x0005, 0x2001, 0x920c, 0x2004, + 0xd0a4, 0x0150, 0x080c, 0x2480, 0x0036, 0x2019, 0x0028, 0x080c, + 0x264b, 0x003e, 0xa006, 0x0009, 0x0005, 0x00e6, 0x2071, 0x920c, + 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, 0x0080, 0x602f, 0x0000, 0x000e, 0x602a, + 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2, + 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x2460, + 0x6803, 0x0080, 0x6803, 0x0000, 0x6803, 0x0020, 0x000e, 0x6052, + 0x6050, 0x0005, 0x2071, 0x92f6, 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, 0x92f6, + 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, 0x92f6, 0x7004, 0x0043, 0x700c, 0x0002, 0x4e9c, + 0x4e93, 0x4e93, 0x4e93, 0x4e93, 0x0005, 0x4ef2, 0x4ef3, 0x4f25, + 0x4f26, 0x4ef0, 0x4f5a, 0x4f5f, 0x4f90, 0x4f91, 0x4fac, 0x4fad, + 0x4fae, 0x4faf, 0x4fb0, 0x4fb1, 0x502d, 0x5054, 0x700c, 0x0002, + 0x4eb5, 0x4ef0, 0x4ef0, 0x4ef1, 0x4ef1, 0x7830, 0x7930, 0xa106, + 0x0120, 0x7830, 0x7930, 0xa106, 0x1510, 0x7030, 0xa10a, 0x01f8, + 0x1210, 0x712c, 0xa10a, 0xa18a, 0x0002, 0x12d0, 0x080c, 0x145f, + 0x01b0, 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001, 0x0003, 0x7057, + 0x0000, 0x0126, 0x0006, 0x2091, 0x8000, 0x2009, 0x9508, 0x2104, + 0xc085, 0x200a, 0x000e, 0x700e, 0x012e, 0x080c, 0x14df, 0x0005, + 0x080c, 0x145f, 0x0de0, 0x2d00, 0x705a, 0x080c, 0x145f, 0x1108, + 0x0c10, 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, 0x08f8, + 0x0005, 0x0005, 0x0005, 0x700c, 0x0002, 0x4efa, 0x4efd, 0x4f0b, + 0x4f24, 0x4f24, 0x080c, 0x4eae, 0x0005, 0x0126, 0x8001, 0x700e, + 0x7058, 0x0006, 0x080c, 0x5311, 0x0120, 0x2091, 0x8000, 0x080c, + 0x4eae, 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, 0x5311, + 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, + 0x6834, 0xa084, 0x00ff, 0xa08a, 0x0020, 0x1218, 0x00db, 0x012e, + 0x0005, 0x012e, 0x080c, 0x4fb2, 0x0005, 0x0005, 0x0005, 0x00e6, + 0x2071, 0x92f6, 0x700c, 0x0002, 0x4f31, 0x4f31, 0x4f31, 0x4f33, + 0x4f36, 0x00ee, 0x0005, 0x700f, 0x0001, 0x0010, 0x700f, 0x0002, + 0x00ee, 0x0005, 0x4fb2, 0x4fb2, 0x4fce, 0x4fb2, 0x50e0, 0x4fb2, + 0x4fb2, 0x4fb2, 0x4fb2, 0x4fb2, 0x4fce, 0x5119, 0x515c, 0x51a5, + 0x51b9, 0x4fb2, 0x4fb2, 0x4fea, 0x4fce, 0x4ffe, 0x4fb2, 0x5013, + 0x5243, 0x525e, 0x4fb2, 0x4fea, 0x4fb2, 0x4ffe, 0x4fb2, 0x4fb2, + 0x5013, 0x525e, 0x7020, 0x2068, 0x080c, 0x1493, 0x0005, 0x700c, + 0x0002, 0x4f66, 0x4f69, 0x4f77, 0x4f8f, 0x4f8f, 0x080c, 0x4eae, + 0x0005, 0x0126, 0x8001, 0x700e, 0x7058, 0x0006, 0x080c, 0x5311, + 0x0120, 0x2091, 0x8000, 0x080c, 0x4eae, 0x00de, 0x0048, 0x0126, + 0x8001, 0x700e, 0x080c, 0x5311, 0x7058, 0x2068, 0x7084, 0x705a, + 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, + 0x001a, 0x1218, 0x003b, 0x012e, 0x0005, 0x012e, 0x0419, 0x0005, + 0x0005, 0x0005, 0x4fb2, 0x4fce, 0x50cc, 0x4fb2, 0x4fce, 0x4fb2, + 0x4fce, 0x4fce, 0x4fb2, 0x4fce, 0x50cc, 0x4fce, 0x4fce, 0x4fce, + 0x4fce, 0x4fce, 0x4fb2, 0x4fce, 0x50cc, 0x4fb2, 0x4fb2, 0x4fce, + 0x4fb2, 0x4fb2, 0x4fb2, 0x4fce, 0x0005, 0x0005, 0x0005, 0x0005, + 0x0005, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0d5, + 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x4809, 0x012e, 0x0005, + 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0e5, 0x683a, 0x0126, + 0x2091, 0x8000, 0x080c, 0x4809, 0x012e, 0x0005, 0x7007, 0x0001, + 0x6838, 0xa084, 0x00ff, 0xc0ed, 0x683a, 0x0126, 0x2091, 0x8000, + 0x080c, 0x4809, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, + 0x00ff, 0xc0dd, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x4809, + 0x012e, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0988, 0x8001, + 0x1120, 0x7007, 0x0001, 0x0804, 0x508d, 0x7007, 0x0006, 0x7012, + 0x2d00, 0x7016, 0x701a, 0x704b, 0x508d, 0x0005, 0x6834, 0x8007, + 0xa084, 0x00ff, 0x0904, 0x4fc0, 0x8001, 0x1120, 0x7007, 0x0001, + 0x0804, 0x50ac, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, + 0x704b, 0x50ac, 0x0005, 0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004, + 0xa080, 0x0024, 0x2098, 0x20a1, 0x9321, 0x53a3, 0x6858, 0x7012, + 0xa082, 0x0401, 0x1a04, 0x4fdc, 0x6884, 0xa08a, 0x0003, 0x1a04, + 0x4fdc, 0xa080, 0x507e, 0x2005, 0x70c6, 0x7010, 0xa015, 0x0904, + 0x5072, 0x080c, 0x145f, 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, 0x14c7, 0x7090, 0xa08e, 0x0100, 0x0170, + 0xa086, 0x0200, 0x0118, 0x7007, 0x0010, 0x0005, 0x7020, 0x2068, + 0x080c, 0x1493, 0x7014, 0x2068, 0x0804, 0x4fdc, 0x7020, 0x2068, + 0x7018, 0x6802, 0x6807, 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, + 0x0804, 0x502d, 0x7014, 0x2068, 0x7007, 0x0001, 0x6834, 0xa084, + 0x00ff, 0xa086, 0x001e, 0x0904, 0x5276, 0x0078, 0x5081, 0x5085, + 0x5089, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a, 0x000f, 0x0005, + 0x0006, 0x0012, 0x000f, 0x0005, 0x0006, 0x2009, 0x922f, 0x210c, + 0x81ff, 0x11a8, 0x6838, 0xa084, 0x00ff, 0x683a, 0x6853, 0x0000, + 0x080c, 0x423e, 0x1108, 0x0005, 0x080c, 0x492c, 0x0126, 0x2091, + 0x8000, 0x080c, 0x8527, 0x080c, 0x4809, 0x012e, 0x0ca0, 0x2001, + 0x0028, 0x2009, 0x0000, 0x0c80, 0x2009, 0x922f, 0x210c, 0x81ff, + 0x11a8, 0x6858, 0xa005, 0x01a8, 0x6838, 0xa084, 0x00ff, 0x683a, + 0x6853, 0x0000, 0x080c, 0x42db, 0x1108, 0x0005, 0x684a, 0x0126, + 0x2091, 0x8000, 0x080c, 0x4809, 0x012e, 0x0cb8, 0x2001, 0x0028, + 0x0ca8, 0x2001, 0x0000, 0x0c90, 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, 0x007e, 0xa096, 0x0002, 0x0178, 0xa005, 0x11f8, 0x6944, + 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4434, 0x11c0, 0x0066, 0x6e50, + 0x080c, 0x450d, 0x006e, 0x0090, 0x0046, 0x2011, 0x920c, 0x2224, + 0xc484, 0xc48c, 0x2412, 0x004e, 0x00c6, 0x080c, 0x4434, 0x1110, + 0x080c, 0x4664, 0x8108, 0x1f04, 0x510d, 0x00ce, 0x080c, 0x1493, + 0x0005, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0x9252, + 0x2004, 0xd0a4, 0x0580, 0x2061, 0x9566, 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, 0x5300, 0x012e, 0x0804, 0x52fa, 0x012e, 0x0804, + 0x52f4, 0x012e, 0x0804, 0x52f7, 0x0126, 0x2091, 0x8000, 0x7007, + 0x0001, 0x2001, 0x9252, 0x2004, 0xd0a4, 0x05e0, 0x2061, 0x9566, + 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, 0x5300, 0x012e, + 0x0804, 0x52fd, 0x012e, 0x0804, 0x52fa, 0x0126, 0x2091, 0x8000, + 0x7007, 0x0001, 0x2061, 0x9566, 0x6300, 0xd38c, 0x1120, 0x6308, + 0x8318, 0x0220, 0x630a, 0x012e, 0x0804, 0x530e, 0x012e, 0x0804, + 0x52fd, 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, + 0xd0ac, 0x0148, 0x00c6, 0x2061, 0x9566, 0x6000, 0xa084, 0xfcff, + 0x6002, 0x00ce, 0x04d8, 0x6858, 0xa005, 0x0904, 0x521a, 0x685c, + 0xa065, 0x0904, 0x5216, 0x2001, 0x922f, 0x2004, 0xa005, 0x0118, + 0x080c, 0x849b, 0x0030, 0x6013, 0x0400, 0x2009, 0x0041, 0x080c, + 0x7518, 0x6958, 0xa18c, 0xf600, 0xa186, 0x2000, 0x01b8, 0xa186, + 0x0400, 0x01a0, 0xa186, 0x1000, 0x0140, 0xa186, 0x4000, 0x01b0, + 0x6118, 0x2104, 0xc0fc, 0x200a, 0x0088, 0x00c6, 0x2061, 0x9566, + 0x6000, 0xa084, 0xfdff, 0x6002, 0x00ce, 0x0040, 0x0026, 0x2009, + 0x0000, 0x2011, 0xfdff, 0x080c, 0x585b, 0x002e, 0x684c, 0xd0c4, + 0x0148, 0x2061, 0x9566, 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, + 0x0208, 0x600a, 0x00ce, 0x012e, 0x0804, 0x5300, 0x00ce, 0x012e, + 0x0804, 0x52fa, 0x6954, 0xa186, 0x002e, 0x0d40, 0xa186, 0x002d, + 0x0d28, 0xa186, 0x002a, 0x1130, 0x2001, 0x920c, 0x200c, 0xc194, + 0x2102, 0x08e0, 0xa186, 0x0020, 0x0170, 0xa186, 0x0029, 0x1d30, + 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4434, 0x1978, 0x6000, + 0xc0e4, 0x6002, 0x0858, 0x685c, 0xa065, 0x09c0, 0x2001, 0x94dd, + 0x2004, 0x6016, 0x0818, 0x2061, 0x9566, 0x6000, 0xd084, 0x0190, + 0xd08c, 0x1904, 0x530e, 0x0126, 0x2091, 0x8000, 0x6204, 0x8210, + 0x0220, 0x6206, 0x012e, 0x0804, 0x530e, 0x012e, 0x6853, 0x0016, + 0x0804, 0x5307, 0x6853, 0x0007, 0x0804, 0x5307, 0x6834, 0x8007, + 0xa084, 0x00ff, 0x1118, 0x080c, 0x4fc0, 0x0078, 0x2030, 0x8001, + 0x1120, 0x7007, 0x0001, 0x0051, 0x0040, 0x7007, 0x0006, 0x7012, + 0x2d00, 0x7016, 0x701a, 0x704b, 0x5276, 0x0005, 0x00e6, 0x0126, + 0x2091, 0x8000, 0x2009, 0x922f, 0x210c, 0x81ff, 0x1904, 0x52e9, + 0x2009, 0x920c, 0x210c, 0xd194, 0x1904, 0x52f1, 0x6848, 0x2070, + 0xae82, 0x9900, 0x0a04, 0x52dd, 0x2001, 0x9216, 0x2004, 0xae02, + 0x1a04, 0x52dd, 0x2061, 0x9566, 0x6100, 0xa184, 0x0001, 0x0578, + 0xa184, 0x0100, 0x1904, 0x52e0, 0xa184, 0x0200, 0x1904, 0x52e3, + 0x601c, 0xa005, 0x1904, 0x52e6, 0x711c, 0xa186, 0x0006, 0x1520, + 0x7018, 0xa005, 0x05f0, 0x2004, 0xd0e4, 0x15f0, 0xd0fc, 0x1598, + 0x6853, 0x0000, 0x6803, 0x0000, 0x2d08, 0x7010, 0xa005, 0x1138, + 0x7112, 0x2e60, 0x080c, 0x57ca, 0x012e, 0x00ee, 0x0005, 0x2068, + 0x6800, 0xa005, 0x1de0, 0x6902, 0x012e, 0x00ee, 0x0005, 0x012e, + 0x00ee, 0x6853, 0x0006, 0x04d8, 0x6944, 0xa18c, 0xff00, 0x810f, + 0x080c, 0x4434, 0x11c8, 0x6000, 0xd0e4, 0x11b0, 0x711c, 0xa186, + 0x0007, 0x1118, 0x6853, 0x0002, 0x0088, 0x6853, 0x0008, 0x0070, + 0x6853, 0x000e, 0x0058, 0x6853, 0x0017, 0x0040, 0x6853, 0x0035, + 0x0028, 0x6853, 0x0028, 0x0010, 0x6853, 0x0029, 0x012e, 0x00ee, + 0x00b0, 0x6853, 0x002a, 0x0cd0, 0x2009, 0x003e, 0x0058, 0x2009, + 0x0004, 0x0040, 0x2009, 0x0006, 0x0028, 0x2009, 0x0016, 0x0010, + 0x2009, 0x0001, 0x6854, 0xa084, 0xff00, 0xa105, 0x6856, 0x0126, + 0x2091, 0x8000, 0x080c, 0x4809, 0x012e, 0x0005, 0x080c, 0x1493, + 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, 0x57c1, 0x00de, 0x0005, 0x00d6, + 0x2011, 0x0004, 0x2204, 0xa085, 0x8002, 0x2012, 0x00de, 0x0005, + 0x20e1, 0x0002, 0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, + 0x0118, 0xa086, 0x1000, 0x1520, 0x20e1, 0x0004, 0x3d60, 0xd1bc, + 0x1170, 0x2100, 0xa084, 0xff00, 0xa086, 0x0500, 0x1140, 0x0026, + 0x2c10, 0x080c, 0x566e, 0x002e, 0x0198, 0x0070, 0x3e60, 0xac84, + 0x0003, 0x1170, 0xac82, 0x9900, 0x0258, 0x6858, 0xac02, 0x1240, + 0x2009, 0x0047, 0x080c, 0x7518, 0x7a1c, 0xd284, 0x1988, 0x0005, + 0xa016, 0x080c, 0x16c6, 0x0cc0, 0x0156, 0x0136, 0x0146, 0x20e1, + 0x3000, 0x3d20, 0x3e28, 0xa584, 0x0070, 0x1528, 0xa484, 0x7000, + 0xa086, 0x1000, 0x11a0, 0x04a1, 0x01f0, 0x20e1, 0x3000, 0x7828, + 0x7828, 0x080c, 0x53cc, 0x014e, 0x013e, 0x015e, 0x2009, 0x94ed, + 0x2104, 0xa005, 0x1108, 0x0005, 0x080c, 0x6462, 0x0ce0, 0xa484, + 0x7000, 0x1148, 0x00e9, 0x0190, 0x7000, 0xa084, 0xff00, 0xa086, + 0x8100, 0x0d18, 0x0058, 0xd5a4, 0x0140, 0x080c, 0x1c26, 0x20e1, + 0x9010, 0x2001, 0x0138, 0x2202, 0x0038, 0x0051, 0x080c, 0x9157, + 0x20e1, 0x3000, 0x7828, 0x7828, 0x014e, 0x013e, 0x015e, 0x08d8, + 0xa484, 0x01ff, 0x6882, 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, 0x5571, 0x0005, + 0xa196, 0x2000, 0x1148, 0x6900, 0xa18e, 0x0001, 0x1118, 0x080c, + 0x3a6a, 0x0ca8, 0x0039, 0x0c98, 0xa196, 0x8000, 0x1d80, 0x080c, + 0x55f9, 0x0c68, 0x00c6, 0x6a80, 0x82ff, 0x0904, 0x5506, 0x7110, + 0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0120, 0xa196, 0x0023, + 0x1904, 0x5506, 0xa08e, 0x0023, 0x1558, 0x080c, 0x565c, 0x0904, + 0x5506, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1150, 0x7034, + 0xa005, 0x1904, 0x5506, 0x2009, 0x0015, 0x080c, 0x7518, 0x0804, + 0x5506, 0xa08e, 0x0210, 0x1130, 0x2009, 0x0015, 0x080c, 0x7518, + 0x0804, 0x5506, 0xa08e, 0x0100, 0x1904, 0x5506, 0x7034, 0xa005, + 0x1904, 0x5506, 0x2009, 0x0016, 0x080c, 0x7518, 0x0804, 0x5506, + 0xa08e, 0x0022, 0x1904, 0x5506, 0x7030, 0xa08e, 0x0300, 0x1568, + 0x68c8, 0xd0a4, 0x0510, 0xc0b5, 0x68ca, 0x7100, 0xa18c, 0x00ff, + 0x696e, 0x7004, 0x6872, 0x00f6, 0x2079, 0x0100, 0x79e6, 0x78ea, + 0x0006, 0xa084, 0x00ff, 0x0016, 0x2008, 0x080c, 0x2435, 0x7932, + 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x240b, 0x694e, 0x703c, + 0x00e6, 0x2071, 0x0140, 0x7086, 0x00ee, 0x7034, 0xa005, 0x1904, + 0x5506, 0x2009, 0x0017, 0x0804, 0x54d9, 0xa08e, 0x0400, 0x1158, + 0x7034, 0xa005, 0x1904, 0x5506, 0x68c8, 0xc0a5, 0x68ca, 0x2009, + 0x0030, 0x0804, 0x54d9, 0xa08e, 0x0500, 0x1140, 0x7034, 0xa005, + 0x1904, 0x5506, 0x2009, 0x0018, 0x0804, 0x54d9, 0xa08e, 0x2010, + 0x1120, 0x2009, 0x0019, 0x0804, 0x54d9, 0xa08e, 0x2110, 0x1120, + 0x2009, 0x001a, 0x0804, 0x54d9, 0xa08e, 0x5200, 0x1140, 0x7034, + 0xa005, 0x1904, 0x5506, 0x2009, 0x001b, 0x0804, 0x54d9, 0xa08e, + 0x5000, 0x1140, 0x7034, 0xa005, 0x1904, 0x5506, 0x2009, 0x001c, + 0x0804, 0x54d9, 0xa08e, 0x1200, 0x1138, 0x7034, 0xa005, 0x1904, + 0x5506, 0x2009, 0x0024, 0x04a8, 0xa08c, 0xff00, 0xa18e, 0x2400, + 0x1118, 0x2009, 0x002d, 0x0468, 0xa08c, 0xff00, 0xa18e, 0x5300, + 0x1118, 0x2009, 0x002a, 0x0428, 0xa08e, 0x0f00, 0x1118, 0x2009, + 0x0020, 0x00f8, 0xa08e, 0x5300, 0x1108, 0x00c8, 0xa08e, 0x6104, + 0x11b0, 0x2011, 0x978d, 0x8208, 0x2204, 0xa082, 0x0004, 0x20a8, + 0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108, 0x2124, 0x080c, + 0x3698, 0x8108, 0x1f04, 0x54ca, 0x2009, 0x0023, 0x0010, 0x2009, + 0x001d, 0x0016, 0x2011, 0x9783, 0x2204, 0x8211, 0x220c, 0x080c, + 0x240b, 0x1530, 0x080c, 0x4400, 0x1518, 0x6612, 0x6516, 0x86ff, + 0x0180, 0x001e, 0x0016, 0xa186, 0x0017, 0x1158, 0x686c, 0xa606, + 0x1140, 0x6870, 0xa506, 0xa084, 0xff00, 0x1118, 0x6000, 0xc0f5, + 0x6002, 0x00c6, 0x080c, 0x749c, 0x0168, 0x001e, 0x611a, 0x601f, + 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x7518, 0x00ce, 0x0005, + 0x001e, 0x0ce0, 0x00ce, 0x0ce0, 0x00e6, 0x00d6, 0x2028, 0x2130, + 0xa696, 0x00ff, 0x1518, 0xa596, 0xfffd, 0x1120, 0x2009, 0x007f, + 0x0804, 0x556d, 0xa596, 0xfffe, 0x1120, 0x2009, 0x007e, 0x0804, + 0x556d, 0xa596, 0xfffc, 0x1120, 0x2009, 0x0080, 0x0804, 0x556d, + 0xa594, 0xff00, 0xa296, 0xfc00, 0x1148, 0x2011, 0x0000, 0x2021, + 0x0081, 0x20a9, 0x007e, 0x2071, 0x93ef, 0x00a0, 0x2011, 0x0000, + 0x2019, 0x9232, 0x231c, 0xd3ac, 0x0138, 0x2021, 0x0000, 0x20a9, + 0x00ff, 0x2071, 0x936e, 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e, + 0x2071, 0x93ef, 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, 0x554a, 0x82ff, 0x1118, + 0xa085, 0x0001, 0x0018, 0xc2fc, 0x2208, 0xa006, 0x00de, 0x00ee, + 0x0005, 0xa084, 0x0007, 0x000a, 0x0005, 0x557d, 0x557d, 0x557d, + 0x557d, 0x557d, 0x557e, 0x5593, 0x55e6, 0x0005, 0x7110, 0xd1bc, + 0x0188, 0x7120, 0x2160, 0xac8c, 0x0003, 0x1160, 0xac8a, 0x9900, + 0x0248, 0x6858, 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0046, + 0x080c, 0x7518, 0x0005, 0x00c6, 0x7110, 0xd1bc, 0x1904, 0x55e4, + 0x2011, 0x9783, 0x2204, 0x8211, 0x220c, 0x080c, 0x240b, 0x1904, + 0x55e4, 0x080c, 0x4434, 0x1904, 0x55e4, 0x6000, 0xd0ec, 0x15e0, + 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x0160, 0x080c, + 0x4dc5, 0x11d0, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x11a0, + 0xa295, 0x0600, 0x6206, 0x00c6, 0x080c, 0x749c, 0x001e, 0x0520, + 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, 0x6122, 0x2009, + 0x0044, 0x080c, 0x7518, 0x00c0, 0x00c6, 0x080c, 0x749c, 0x001e, + 0x0198, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004, + 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, 0x0001, + 0x080c, 0x603e, 0x080c, 0x6462, 0x00ce, 0x0005, 0x7110, 0xd1bc, + 0x0178, 0x7020, 0x2060, 0xac84, 0x0003, 0x1150, 0xac82, 0x9900, + 0x0238, 0x6858, 0xac02, 0x1220, 0x2009, 0x0045, 0x080c, 0x7518, + 0x0005, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, 0x1138, + 0xa084, 0x000f, 0xa08a, 0x0006, 0x1a0c, 0x13fe, 0x000b, 0x0005, + 0x560e, 0x560f, 0x560e, 0x560e, 0x5644, 0x5650, 0x0005, 0x7110, + 0xd1bc, 0x1588, 0x700c, 0x7108, 0x080c, 0x240b, 0x1560, 0x080c, + 0x4400, 0x1548, 0x6612, 0x6516, 0x6204, 0xa294, 0xff00, 0x8217, + 0xa286, 0x0004, 0x0118, 0xa286, 0x0006, 0x1178, 0x00c6, 0x080c, + 0x749c, 0x001e, 0x01c0, 0x611a, 0x601f, 0x0005, 0x7120, 0x610a, + 0x2009, 0x0088, 0x080c, 0x7518, 0x0070, 0x00c6, 0x080c, 0x749c, + 0x001e, 0x0148, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x2009, + 0x0001, 0x080c, 0x7518, 0x0005, 0x7110, 0xd1bc, 0x0140, 0x00a1, + 0x0130, 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0x7518, 0x0005, + 0x7110, 0xd1bc, 0x0140, 0x0041, 0x0130, 0x7124, 0x610a, 0x2009, + 0x008a, 0x080c, 0x7518, 0x0005, 0x7020, 0x2060, 0xac84, 0x0003, + 0x1158, 0xac82, 0x9900, 0x0240, 0x2001, 0x9216, 0x2004, 0xac02, + 0x1218, 0xa085, 0x0001, 0x0005, 0xa006, 0x0ce8, 0x00c6, 0x00d6, + 0x00e6, 0x20e1, 0x0000, 0x3d08, 0xa18c, 0x00ff, 0xa18e, 0x00ff, + 0x1150, 0x3e00, 0xa086, 0xffff, 0x1130, 0x2001, 0x94c6, 0x2064, + 0x2009, 0x00ff, 0x0060, 0x20e1, 0x0001, 0x3d08, 0x3e00, 0x0156, + 0x080c, 0x240b, 0x015e, 0x1578, 0x080c, 0x4434, 0x1560, 0x2138, + 0x873f, 0x2c00, 0x2070, 0x20e1, 0x0003, 0x3d18, 0x831f, 0xa39c, + 0x00ff, 0x0036, 0x0036, 0x003e, 0x003e, 0x20e1, 0x2000, 0x3d00, + 0xa084, 0x7000, 0xa086, 0x1000, 0x0120, 0x080c, 0x5cc0, 0x1198, + 0x0040, 0x080c, 0x749c, 0x0178, 0x2e00, 0x601a, 0x620a, 0x601f, + 0x0009, 0x2009, 0x0101, 0x080c, 0x7518, 0xa085, 0x0001, 0x00ee, + 0x00de, 0x00ce, 0x0005, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x0005, + 0x2071, 0x94f8, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a, + 0x7012, 0x7017, 0x9900, 0x7007, 0x0000, 0x7026, 0x702b, 0x6f2b, + 0x7032, 0x7037, 0x6f69, 0x703b, 0xffff, 0x703f, 0xffff, 0x0005, + 0x2071, 0x94f8, 0x1d04, 0x5720, 0x2091, 0x6000, 0x700c, 0x8001, + 0x700e, 0x1120, 0x700f, 0x0361, 0x7007, 0x0001, 0x0126, 0x2091, + 0x8000, 0x7024, 0xa00d, 0x0158, 0x7020, 0x8001, 0x7022, 0x1138, + 0x7023, 0x0009, 0x8109, 0x7126, 0x1110, 0x7028, 0x080f, 0x7030, + 0xa00d, 0x0158, 0x702c, 0x8001, 0x702e, 0x1138, 0x702f, 0x0009, + 0x8109, 0x7132, 0x1110, 0x7034, 0x080f, 0x7038, 0xa005, 0x0118, + 0x0310, 0x8001, 0x703a, 0x703c, 0xa005, 0x0118, 0x0310, 0x8001, + 0x703e, 0x7018, 0xa00d, 0x0158, 0x7008, 0x8001, 0x700a, 0x1138, + 0x700b, 0x0009, 0x8109, 0x711a, 0x1110, 0x701c, 0x080f, 0x012e, + 0x7004, 0x0002, 0x5746, 0x5747, 0x575f, 0x00e6, 0x2071, 0x94f8, + 0x7018, 0xa005, 0x1120, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, + 0x0005, 0x00e6, 0x0006, 0x2071, 0x94f8, 0x701c, 0xa206, 0x1110, + 0x701a, 0x701e, 0x000e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x94f8, + 0x6088, 0xa102, 0x0208, 0x618a, 0x00ee, 0x0005, 0x0005, 0x7110, + 0x080c, 0x4434, 0x1158, 0x6088, 0x8001, 0x0240, 0x608a, 0x1130, + 0x0126, 0x2091, 0x8000, 0x080c, 0x6462, 0x012e, 0x8108, 0xa182, + 0x00ff, 0x0218, 0xa00e, 0x7007, 0x0002, 0x7112, 0x0005, 0x7014, + 0x2060, 0x0126, 0x2091, 0x8000, 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, 0x8185, 0x012e, 0xac88, 0x000c, 0x7116, 0x2001, 0x9217, + 0x2004, 0xa102, 0x0220, 0x7017, 0x9900, 0x7007, 0x0000, 0x0005, + 0x00e6, 0x2071, 0x94f8, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee, + 0x0005, 0x2001, 0x9501, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071, + 0x94f8, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0x9504, + 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x94f8, 0x711a, 0x721e, + 0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, 0x2061, 0x9566, 0x00ce, + 0x0005, 0xa184, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x9566, + 0x2060, 0x0005, 0x6854, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, + 0xa005, 0x1150, 0x00c6, 0x2061, 0x9566, 0x6014, 0x00ce, 0xa005, + 0x1138, 0x2001, 0x001e, 0x0020, 0xa08e, 0xffff, 0x1108, 0xa006, + 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c, 0x00c0, + 0xa18e, 0x00c0, 0x0588, 0xd0b4, 0x1138, 0xd0bc, 0x11f0, 0x2009, + 0x0006, 0x080c, 0x5838, 0x0005, 0xd0fc, 0x0140, 0xa084, 0x0003, + 0xa08e, 0x0003, 0x05b8, 0xa08e, 0x0000, 0x15a0, 0x2009, 0x9273, + 0x2104, 0xd084, 0x0128, 0x2009, 0x0042, 0x080c, 0x7518, 0x0005, + 0x2009, 0x0043, 0x080c, 0x7518, 0x0005, 0xd0fc, 0x0140, 0xa084, + 0x0003, 0xa08e, 0x0003, 0x01f0, 0xa08e, 0x0000, 0x11d8, 0x2009, + 0x0042, 0x080c, 0x7518, 0x0005, 0xd0fc, 0x0168, 0xa084, 0x0003, + 0xa08e, 0x0003, 0x0178, 0xa08e, 0x0002, 0x0138, 0x2009, 0x0041, + 0x080c, 0x7518, 0x0005, 0x0051, 0x0ce8, 0x2009, 0x0043, 0x080c, + 0x7518, 0x0cc0, 0x2009, 0x0004, 0x0019, 0x0005, 0x2009, 0x0001, + 0x6010, 0xa0ec, 0xf000, 0x01f0, 0x2068, 0x6952, 0x6800, 0x6012, + 0xa186, 0x0001, 0x1188, 0x694c, 0xa18c, 0x8100, 0xa18e, 0x8100, + 0x1158, 0x00c6, 0x2061, 0x9566, 0x6200, 0xd28c, 0x1120, 0x6204, + 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, 0x4809, 0x6010, 0xa06d, + 0x190c, 0x57ca, 0x0005, 0x0156, 0x00c6, 0x2061, 0x9566, 0x6000, + 0x81ff, 0x0110, 0xa205, 0x0008, 0xa204, 0x6002, 0x00ce, 0x015e, + 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, 0xa005, 0x0120, 0x8001, + 0x680a, 0xa085, 0x0001, 0x0005, 0x2071, 0x9349, 0x7003, 0x0006, + 0x7007, 0x0000, 0x700f, 0x0000, 0x7013, 0x0001, 0x702f, 0x0006, + 0x7033, 0x0001, 0x7063, 0x0000, 0x0005, 0x00e6, 0x2071, 0x9349, + 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, 0x9349, 0x7004, 0x004b, 0x700c, 0x0002, + 0x58bb, 0x58b4, 0x58b4, 0x0005, 0x58c5, 0x5913, 0x5914, 0x5915, + 0x5916, 0x5929, 0x592a, 0x700c, 0x0cba, 0x2f00, 0xa080, 0x0070, + 0x2004, 0x2f08, 0xa188, 0x0070, 0x210c, 0xa106, 0x0150, 0x2f00, + 0xa080, 0x0070, 0x2004, 0x2f08, 0xa188, 0x0070, 0x210c, 0xa106, + 0x15c8, 0x7018, 0xa10a, 0x05b0, 0x1210, 0x7114, 0xa10a, 0xa192, + 0x000a, 0x0210, 0x2009, 0x000a, 0x00d6, 0x0016, 0x2001, 0x9281, + 0xa080, 0x0011, 0x2014, 0x2001, 0x9363, 0xa080, 0x0005, 0x2004, + 0xa100, 0xa202, 0x001e, 0x00de, 0x02e8, 0x080c, 0x5976, 0x2200, + 0xa102, 0x0208, 0x2208, 0x713a, 0x080c, 0x5a67, 0x2100, 0x7042, + 0x2001, 0x0002, 0x7037, 0x0000, 0x0126, 0x0006, 0x2091, 0x8000, + 0x2009, 0x9508, 0x2104, 0xc095, 0x200a, 0x000e, 0x700e, 0x012e, + 0x080c, 0x14df, 0x0005, 0x0005, 0x0005, 0x0005, 0x700c, 0x0002, + 0x591b, 0x591e, 0x5928, 0x080c, 0x58c3, 0x0005, 0x0126, 0x8001, + 0x700e, 0x7138, 0x0041, 0x2091, 0x8000, 0x080c, 0x58c3, 0x012e, + 0x0005, 0x0005, 0x0005, 0x7018, 0xa100, 0x7214, 0xa21a, 0x1130, + 0x701c, 0x7052, 0x7020, 0x7056, 0xa006, 0x0068, 0x0006, 0x080c, + 0x5a67, 0x2100, 0x7250, 0xa210, 0x7252, 0x1220, 0x7054, 0xa081, + 0x0000, 0x7056, 0x000e, 0x2f08, 0xa188, 0x0070, 0x200a, 0x701a, + 0x0005, 0x00e6, 0x2071, 0x9349, 0x700c, 0x0002, 0x5951, 0x5951, + 0x5953, 0x00ee, 0x0005, 0x700f, 0x0001, 0x00ee, 0x0005, 0x00d6, + 0x00e6, 0x2071, 0x9363, 0xa006, 0x7006, 0x700e, 0x701a, 0x701e, + 0x7022, 0x702a, 0x7026, 0x080c, 0x5b1b, 0x0170, 0x080c, 0x5b4d, + 0x0158, 0x2d00, 0x7002, 0x700a, 0x701a, 0x7013, 0x0001, 0x701f, + 0x0007, 0x00ee, 0x00de, 0x0005, 0xa00e, 0x0cd8, 0x00e6, 0x00d6, + 0x00c6, 0x2071, 0x9363, 0x721c, 0x2100, 0xa202, 0x1618, 0x080c, + 0x5b4d, 0x090c, 0x13fe, 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, 0x9363, + 0x7300, 0xa398, 0x0003, 0x7104, 0x080c, 0x5a67, 0x810c, 0x2100, + 0xa318, 0x8003, 0x2228, 0x2021, 0x0054, 0xa402, 0xa532, 0x0208, + 0x2028, 0x2500, 0x8004, 0x20a8, 0x23a0, 0xe000, 0xe000, 0xe000, + 0x53a5, 0x2508, 0x080c, 0x5a70, 0x2130, 0x7014, 0xa600, 0x7016, + 0x2600, 0x711c, 0xa102, 0x701e, 0x7004, 0xa600, 0x2008, 0xa082, + 0x0007, 0x1180, 0x7000, 0x2004, 0xa005, 0x1140, 0x2009, 0x0001, + 0x0026, 0x080c, 0x5976, 0x002e, 0x7000, 0x2004, 0x7002, 0x7007, + 0x0000, 0x0008, 0x7106, 0x2500, 0xa212, 0x1910, 0x012e, 0x00ee, + 0x014e, 0x013e, 0x015e, 0x0005, 0x0016, 0x0026, 0x00e6, 0x00d6, + 0x04e9, 0x15c8, 0x2170, 0x2805, 0xac68, 0x2900, 0x0002, 0x5a0f, + 0x5a0f, 0x5a13, 0x5a0f, 0x5a13, 0x5a0f, 0x5a0f, 0x5a0f, 0x5a0f, + 0x5a0f, 0x5a1c, 0x5a0f, 0x5a1c, 0x5a0f, 0x5a0f, 0x5a0f, 0x080c, + 0x13fe, 0xa005, 0x00d8, 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, 0x00d6, 0xa006, 0x00de, 0x00ee, + 0x002e, 0x001e, 0x0005, 0xa085, 0x0001, 0x0cc0, 0x00e6, 0x0036, + 0x2071, 0x9363, 0x7014, 0xa005, 0x0538, 0x8001, 0x7016, 0x7008, + 0xa080, 0x0003, 0x710c, 0x2110, 0x0411, 0x810c, 0xa118, 0x8210, + 0xa282, 0x0007, 0x11b0, 0x7008, 0x2004, 0xa005, 0x0178, 0x00d6, + 0x0006, 0x7008, 0x2068, 0x080c, 0x5b5c, 0x000e, 0x2068, 0x6807, + 0x0000, 0x700a, 0x00de, 0x7010, 0x8001, 0x7012, 0x700f, 0x0000, + 0x0008, 0x720e, 0x2308, 0xa006, 0x003e, 0x00ee, 0x0005, 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, 0x5ab2, 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, + 0x9200, 0x7128, 0x6810, 0x2019, 0x0001, 0xa10a, 0x0118, 0x0210, + 0x8318, 0x0cd8, 0x2031, 0x5ac5, 0x0870, 0x6c16, 0x00ee, 0x0005, + 0x00e6, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2e00, 0x2060, 0x2071, + 0x9363, 0x2009, 0x0001, 0x0026, 0x080c, 0x5976, 0x002e, 0x7300, + 0xa398, 0x0003, 0x7104, 0x080c, 0x5a67, 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, 0x5976, 0x002e, + 0x7000, 0x2004, 0x7002, 0x7007, 0x0000, 0x0008, 0x7106, 0x012e, + 0x00ce, 0x00ee, 0x0005, 0x00d6, 0x0046, 0x0126, 0x2091, 0x8000, + 0x2001, 0x9281, 0xa080, 0x0011, 0x2004, 0x8003, 0x2020, 0x080c, + 0x145f, 0x01d0, 0x2d00, 0x7026, 0x6803, 0x0000, 0x6807, 0x0000, + 0x080c, 0x145f, 0x0188, 0x7024, 0x6802, 0x6807, 0x0000, 0x2d00, + 0x7026, 0xa4a2, 0x0007, 0x0110, 0x0208, 0x0c90, 0xa085, 0x0001, + 0x012e, 0x004e, 0x00de, 0x0005, 0x7024, 0xa005, 0x0dc8, 0x2068, + 0x2024, 0x080c, 0x1493, 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, 0x00f6, 0x00e6, 0x00d6, + 0x00c6, 0x0086, 0x0046, 0x0056, 0x0026, 0x2031, 0x0000, 0x2001, + 0x934a, 0x2004, 0xa005, 0x0904, 0x5bee, 0x2071, 0x9281, 0x20e1, + 0x0002, 0x3d08, 0xd19c, 0x0140, 0x2069, 0x9200, 0x6a28, 0x761c, + 0x7114, 0x2041, 0x0000, 0x0028, 0x7118, 0x720c, 0x7620, 0x7008, + 0x2040, 0x080c, 0x5d03, 0x0904, 0x5bee, 0x7004, 0xd084, 0x1128, + 0x2021, 0x0024, 0x2029, 0x0002, 0x0020, 0x2021, 0x002c, 0x2029, + 0x000a, 0x080c, 0x147c, 0x0904, 0x5bee, 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, 0x6056, 0x605e, 0x6066, 0x604e, + 0x2800, 0x606a, 0x604c, 0xc0ad, 0x604e, 0x665a, 0x2c00, 0x2078, + 0x0479, 0x607f, 0xffff, 0x6083, 0x0000, 0x8109, 0x0180, 0x080c, + 0x147c, 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, 0x14a3, 0x2600, 0x2071, + 0x9363, 0x7120, 0xa102, 0x0a0c, 0x13fe, 0x7022, 0xa006, 0x0c48, + 0x00d6, 0x00c6, 0x0136, 0x0146, 0x0156, 0x0016, 0x2068, 0x2400, + 0xa084, 0x000f, 0xa080, 0x1f59, 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, 0x9363, 0x7120, + 0xa102, 0x0a0c, 0x13fe, 0x7022, 0x6960, 0x694e, 0x697c, 0x2009, + 0xffff, 0x7818, 0xa102, 0xe000, 0x0006, 0x0006, 0x0006, 0x0006, + 0x0006, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x6852, 0x684b, + 0x0000, 0x6868, 0xa005, 0x0118, 0x6848, 0xc085, 0x684a, 0x2d00, + 0xa080, 0x0015, 0x2038, 0x2031, 0x0018, 0x6864, 0x2020, 0x683a, + 0x685c, 0xa08a, 0x00ff, 0x1a0c, 0x13fe, 0x2028, 0x2d00, 0x2060, + 0x2078, 0x6934, 0xa18c, 0x000f, 0xa188, 0x1f59, 0x2145, 0x685c, + 0x2050, 0xa005, 0x0530, 0x2805, 0xac70, 0x6834, 0xa084, 0x00ff, + 0xa086, 0x0024, 0x1110, 0x7008, 0x0040, 0x6834, 0xa084, 0x00ff, + 0xa086, 0x002c, 0x190c, 0x13fe, 0x7010, 0x0006, 0x2400, 0xa005, + 0x000e, 0x0168, 0x203a, 0x8738, 0x8631, 0x090c, 0x13fe, 0x8421, + 0x8529, 0x0138, 0x080c, 0x1f1b, 0x090c, 0x13fe, 0x08e0, 0x080c, + 0x5ac8, 0x6837, 0x0023, 0x00fe, 0x00ee, 0x00ce, 0x0005, 0x00e6, + 0x00c6, 0x00a6, 0x0086, 0x0056, 0x6858, 0x2071, 0x9363, 0x7120, + 0xa102, 0x0a0c, 0x13fe, 0x7022, 0x2d00, 0x2060, 0x6934, 0xa18c, + 0x000f, 0xa188, 0x1f59, 0x2145, 0x685c, 0x2050, 0xa005, 0x01d0, + 0x2028, 0x2805, 0xac70, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0024, + 0x1110, 0x7008, 0x0008, 0x7010, 0x0006, 0xa086, 0xffff, 0x000e, + 0x0110, 0x080c, 0x5ac8, 0x8529, 0x0128, 0x080c, 0x1f1b, 0x090c, + 0x13fe, 0x0c38, 0x005e, 0x008e, 0x00ae, 0x00ce, 0x00ee, 0x0005, + 0x70ac, 0xa005, 0x0138, 0x2060, 0x6008, 0xa306, 0x0110, 0x600c, + 0x0cc0, 0x0005, 0xa085, 0x0001, 0x0ce0, 0x70ac, 0x600e, 0x2c00, + 0x70ae, 0x0005, 0x00f6, 0x00d6, 0x0036, 0x70ac, 0xa005, 0x090c, + 0x13fe, 0x2068, 0x2079, 0x0000, 0x2c08, 0xa11e, 0x1118, 0x680c, + 0x70ae, 0x0060, 0xa106, 0x0140, 0x2d00, 0x2078, 0x680c, 0xa005, + 0x090c, 0x13fe, 0x2068, 0x0cb0, 0x6b0c, 0x7b0e, 0x600f, 0x0000, + 0x003e, 0x00de, 0x00fe, 0x0005, 0x00e6, 0x080c, 0x5c87, 0x6018, + 0x2070, 0xa006, 0x70b2, 0x70b6, 0x080c, 0x14a3, 0x0899, 0x080c, + 0x74f2, 0x00ee, 0x0005, 0x00d6, 0x0026, 0x0016, 0x2061, 0x9363, + 0x6020, 0x6414, 0xa600, 0xa42a, 0x02c8, 0x6022, 0x2069, 0x9281, + 0x6828, 0x6114, 0xa102, 0x1260, 0x2011, 0x8025, 0x080c, 0x3698, + 0xa080, 0x0013, 0x2004, 0xa080, 0x0000, 0x200c, 0x8108, 0x2102, + 0xa085, 0x0001, 0x001e, 0x002e, 0x00de, 0x0005, 0x2069, 0x9281, + 0x6804, 0xd09c, 0x0120, 0x2011, 0x8026, 0x080c, 0x3698, 0x2001, + 0x9281, 0xa080, 0x0013, 0x2004, 0xa080, 0x0001, 0x200c, 0x8108, + 0x2102, 0xa006, 0x2031, 0x0000, 0x0c28, 0x0066, 0x6000, 0xa0b2, + 0x0010, 0x1a0c, 0x13fe, 0x0013, 0x006e, 0x0005, 0x5d56, 0x5d56, + 0x5d56, 0x5d58, 0x5db1, 0x5d56, 0x5d56, 0x5d56, 0x5de6, 0x5d56, + 0x5e34, 0x5d56, 0x5d56, 0x5d56, 0x5d56, 0x5d56, 0x080c, 0x13fe, + 0xa182, 0x0100, 0x0002, 0x5d6a, 0x5d6a, 0x5d6a, 0x5d6c, 0x5d85, + 0x5d9d, 0x5d6a, 0x5d6a, 0x5d6a, 0x5d6a, 0x5d6a, 0x5d6a, 0x5d6a, + 0x5d6a, 0x5d6a, 0x080c, 0x13fe, 0x00d6, 0x080c, 0x641b, 0x080c, + 0x651c, 0x6110, 0x2168, 0x684b, 0x0000, 0x00d6, 0x6018, 0x2068, + 0x6008, 0x68b6, 0x68bb, 0x0500, 0xa006, 0x68b2, 0x00de, 0x080c, + 0x4809, 0x080c, 0x74f2, 0x00de, 0x0005, 0x080c, 0x641b, 0x00f6, + 0x00d6, 0x6110, 0x2178, 0x080c, 0x82ee, 0x0140, 0x784b, 0x0006, + 0xa006, 0x70b2, 0x70b6, 0x2f68, 0x080c, 0x4809, 0x00de, 0x00fe, + 0x080c, 0x74f2, 0x080c, 0x651c, 0x0005, 0x080c, 0x641b, 0x080c, + 0x266c, 0x00d6, 0x6110, 0x2168, 0x080c, 0x82ee, 0x0120, 0x684b, + 0x0029, 0x080c, 0x4809, 0x00de, 0x080c, 0x74f2, 0x080c, 0x651c, + 0x0005, 0xa182, 0x0100, 0x0002, 0x5dc3, 0x5dc5, 0x5dcd, 0x5dc3, + 0x5dc3, 0x5dc3, 0x5de1, 0x5dc3, 0x5dc3, 0x5dc3, 0x5dc3, 0x5dc3, + 0x5dc3, 0x5dc3, 0x5dc3, 0x080c, 0x13fe, 0x20e1, 0x0005, 0x3d18, + 0x3e20, 0x2c10, 0x080c, 0x16c6, 0x0005, 0x00d6, 0x00e6, 0x6110, + 0x2168, 0x080c, 0x5c19, 0x080c, 0x4809, 0x6018, 0x2070, 0xa006, + 0x70b2, 0x70b6, 0x080c, 0x5cd2, 0x00ee, 0x00de, 0x080c, 0x74f2, + 0x0005, 0x080c, 0x5cf4, 0x080c, 0x473b, 0x0005, 0xa182, 0x0100, + 0x0002, 0x5dfb, 0x5e16, 0x5df9, 0x5df9, 0x5df9, 0x5df9, 0x5df9, + 0x5df9, 0x5df9, 0x5df9, 0x5df9, 0x5df9, 0x5df9, 0x5df9, 0x5df9, + 0x5df9, 0x080c, 0x13fe, 0x00d6, 0x6003, 0x0003, 0x6106, 0x6010, + 0x2068, 0x687c, 0x680a, 0x6880, 0x680e, 0x6813, 0x0000, 0x6817, + 0x0000, 0x00de, 0x2c10, 0x080c, 0x1c88, 0x080c, 0x605b, 0x0126, + 0x2091, 0x8000, 0x080c, 0x651c, 0x012e, 0x0005, 0x6003, 0x0004, + 0x630a, 0x080c, 0x5b65, 0x0168, 0x6012, 0x600f, 0x0000, 0x080c, + 0x5ccd, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x16c6, + 0x0005, 0x2011, 0x0000, 0x080c, 0x16c6, 0x70b3, 0x0000, 0x70b7, + 0x0000, 0x080c, 0x74f2, 0x0005, 0x00d6, 0x080c, 0x641b, 0x080c, + 0x651c, 0x6110, 0x2168, 0x684b, 0x0000, 0x00d6, 0x6018, 0x2068, + 0x6008, 0x68b6, 0x68bb, 0x0500, 0xa006, 0x68b2, 0x00de, 0x080c, + 0x4809, 0x080c, 0x74f2, 0x00de, 0x0005, 0x6000, 0xa08a, 0x0010, + 0x1a0c, 0x13fe, 0x000b, 0x0005, 0x5e64, 0x5e64, 0x5e64, 0x5e66, + 0x5e7f, 0x5e64, 0x5e64, 0x5e64, 0x5e64, 0x5e64, 0x5e64, 0x5e64, + 0x5e64, 0x5e64, 0x5e64, 0x5e64, 0x080c, 0x13fe, 0x080c, 0x7366, + 0x190c, 0x13fe, 0x6110, 0x2168, 0x684b, 0x0006, 0x00d6, 0x6018, + 0x2068, 0x6008, 0x68b6, 0x68bb, 0x0500, 0xa006, 0x68b2, 0x00de, + 0x080c, 0x4809, 0x080c, 0x74f2, 0x00de, 0x0005, 0x0005, 0x0005, + 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x13fe, 0x000b, 0x0005, 0x5e97, + 0x5e97, 0x5e97, 0x5e99, 0x5e9b, 0x5e97, 0x5e97, 0x5e97, 0x5e97, + 0x5e97, 0x5e97, 0x5e97, 0x5e97, 0x5e97, 0x5e97, 0x5e97, 0x080c, + 0x13fe, 0x080c, 0x13fe, 0x00d6, 0x6010, 0x2068, 0x080c, 0x5cf4, + 0x00de, 0x0005, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, + 0x1208, 0xa200, 0x1f04, 0x5ea6, 0x8086, 0x818e, 0x0005, 0x0156, + 0x20a9, 0x0010, 0xa005, 0x01b8, 0xa11a, 0x12a8, 0x8213, 0x818d, + 0x0228, 0xa11a, 0x1220, 0x1f04, 0x5eb6, 0x0028, 0xa11a, 0x2308, + 0x8210, 0x1f04, 0x5eb6, 0x0006, 0x3200, 0xa084, 0xefff, 0x2080, + 0x000e, 0x015e, 0x0005, 0x0006, 0x3200, 0xa085, 0x1000, 0x0cb8, + 0x0126, 0x2091, 0x2400, 0x2079, 0x94e5, 0x012e, 0x00d6, 0x2069, + 0x94e5, 0x6803, 0x0005, 0x2069, 0x0004, 0x2d04, 0xa085, 0x8001, + 0x206a, 0x00de, 0x0005, 0x00c6, 0x6027, 0x0001, 0x7804, 0xa084, + 0x0007, 0x0002, 0x5ef4, 0x5f15, 0x5f68, 0x5efa, 0x5f15, 0x5ef4, + 0x5ef2, 0x5ef2, 0x080c, 0x13fe, 0x080c, 0x57a1, 0x080c, 0x6462, + 0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, 0x2011, + 0x40af, 0x080c, 0x5731, 0x7828, 0xa092, 0x0002, 0x1228, 0x8000, + 0x782a, 0x080c, 0x40fc, 0x0c88, 0x080c, 0x40af, 0x7807, 0x0003, + 0x7827, 0x0000, 0x782b, 0x0000, 0x0c40, 0x080c, 0x57a1, 0x3c00, + 0x0006, 0x2011, 0x0209, 0x20e1, 0x4000, 0x2214, 0x000e, 0x20e0, + 0x82ff, 0x0178, 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, + 0xa065, 0x090c, 0x13fe, 0x2009, 0x0013, 0x080c, 0x7518, 0x00ce, + 0x0005, 0x3900, 0xa082, 0x9606, 0x1210, 0x080c, 0x7432, 0x00c6, + 0x7824, 0xa065, 0x090c, 0x13fe, 0x7804, 0xa086, 0x0004, 0x0904, + 0x5fa8, 0x7828, 0xa092, 0x2710, 0x1230, 0x8000, 0x782a, 0x00ce, + 0x080c, 0x6f11, 0x0c20, 0x6104, 0xa186, 0x0003, 0x1188, 0x00e6, + 0x2071, 0x9200, 0x70d4, 0x00ee, 0xd08c, 0x0150, 0x00c6, 0x00e6, + 0x2061, 0x0100, 0x2071, 0x9200, 0x080c, 0x4105, 0x00ee, 0x00ce, + 0x080c, 0x91a0, 0x2009, 0x0014, 0x080c, 0x7518, 0x00ce, 0x0838, + 0x2001, 0x9501, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b, + 0x0000, 0x7824, 0xa065, 0x090c, 0x13fe, 0x2009, 0x0013, 0x080c, + 0x7563, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x3900, 0xa082, 0x9606, + 0x1210, 0x080c, 0x7432, 0x7824, 0xa005, 0x090c, 0x13fe, 0x781c, + 0xa06d, 0x090c, 0x13fe, 0x6800, 0xc0dc, 0x6802, 0x7924, 0x2160, + 0x080c, 0x74f2, 0x693c, 0x81ff, 0x090c, 0x13fe, 0x8109, 0x693e, + 0x6854, 0xa015, 0x0110, 0x7a1e, 0x0010, 0x7918, 0x791e, 0x7807, + 0x0000, 0x7827, 0x0000, 0x00de, 0x00ce, 0x080c, 0x6462, 0x0888, + 0x6104, 0xa186, 0x0002, 0x0128, 0xa186, 0x0004, 0x0110, 0x0804, + 0x5f41, 0x7808, 0xac06, 0x0904, 0x5f41, 0x080c, 0x6389, 0x080c, + 0x603e, 0x00ce, 0x080c, 0x6462, 0x0804, 0x5f2f, 0x00c6, 0x6027, + 0x0002, 0x62c8, 0x60c4, 0xa205, 0x11a0, 0x793c, 0xa1e5, 0x0000, + 0x0150, 0x2009, 0x0049, 0x601c, 0xa086, 0x0009, 0x1110, 0x2009, + 0x0103, 0x080c, 0x7518, 0x2011, 0x9504, 0x2013, 0x0000, 0x00ce, + 0x0005, 0x3908, 0xa192, 0x9606, 0x1210, 0x080c, 0x7432, 0x6017, + 0x0010, 0x793c, 0x81ff, 0x0d78, 0x793c, 0xa188, 0x0007, 0x210c, + 0xa18e, 0x0006, 0x1118, 0x6017, 0x0012, 0x0c48, 0x793c, 0xa188, + 0x0007, 0x210c, 0xa18e, 0x0009, 0x0db0, 0x6017, 0x0016, 0x08f8, + 0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, + 0x2c08, 0x2061, 0x94e5, 0x6020, 0x8000, 0x6022, 0x6010, 0xa005, + 0x0148, 0xa080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, + 0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0x94e5, + 0x6000, 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0xa086, 0x0001, + 0x1110, 0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, 0x0804, 0x646f, + 0xc0d5, 0x6002, 0x6818, 0xa005, 0x0158, 0x6056, 0x605b, 0x0000, + 0x0006, 0x2c00, 0x681a, 0x00de, 0x685a, 0x2069, 0x94e5, 0x0c18, + 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x08e8, 0x0006, 0x0016, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, + 0x94e5, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0148, 0xa080, + 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, + 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, 0x2061, + 0x94e5, 0x6034, 0xa005, 0x0130, 0xa080, 0x0003, 0x2102, 0x6136, + 0x00ce, 0x0005, 0x613a, 0x6136, 0x0cd8, 0x00f6, 0x00e6, 0x00d6, + 0x00c6, 0x0066, 0x0026, 0x0016, 0x0006, 0x0126, 0x2071, 0x94e5, + 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, 0x60cb, + 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, 0x60c6, 0x88ff, + 0x0118, 0x6020, 0xa106, 0x15d0, 0x703c, 0xac06, 0x1120, 0x6003, + 0x000a, 0x630a, 0x0498, 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, 0x82ee, 0x0188, + 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x11f8, 0x6837, 0x0103, + 0x6b4a, 0x6847, 0x0000, 0x080c, 0x8527, 0x080c, 0x4809, 0x080c, + 0x848f, 0x080c, 0x849b, 0x00ce, 0x0804, 0x607d, 0x2c78, 0x600c, + 0x2060, 0x0804, 0x607d, 0x012e, 0x000e, 0x001e, 0x002e, 0x006e, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, + 0x19e8, 0x080c, 0x9097, 0x0c28, 0x0006, 0x0066, 0x00c6, 0x00d6, + 0x00f6, 0x2031, 0x0000, 0x0126, 0x2091, 0x8000, 0x2079, 0x94e5, + 0x7838, 0xa065, 0x0510, 0x600c, 0x0006, 0x600f, 0x0000, 0x783c, + 0xac06, 0x1128, 0x6003, 0x000a, 0x630a, 0x2c30, 0x00a0, 0x080c, + 0x82ee, 0x0178, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x11b0, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x4809, 0x080c, + 0x848f, 0x080c, 0x849b, 0x000e, 0x08e0, 0x7e3a, 0x7e36, 0x012e, + 0x00fe, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c, 0xa086, + 0x0006, 0x0150, 0x601c, 0xa086, 0x0009, 0x1d10, 0x6b4a, 0x080c, + 0x4809, 0x080c, 0x74f2, 0x0c38, 0x080c, 0x9097, 0x0c10, 0x0016, + 0x0026, 0x0086, 0x2041, 0x0000, 0x0099, 0x080c, 0x61d3, 0x008e, + 0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0x94e5, 0x2091, + 0x8000, 0x080c, 0x625e, 0x080c, 0x62be, 0x012e, 0x00fe, 0x0005, + 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2071, 0x94e5, 0x7614, 0x2660, 0x2678, 0x8cff, + 0x0904, 0x61c3, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, + 0x61be, 0x88ff, 0x0120, 0x6020, 0xa106, 0x1904, 0x61be, 0x7024, + 0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, + 0x57a1, 0x080c, 0x6f1e, 0x68c3, 0x0000, 0x080c, 0x7356, 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, + 0x04a8, 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, 0x82ee, 0x0178, + 0x601c, 0xa086, 0x0003, 0x1500, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x080c, 0x8527, 0x080c, 0x4809, 0x080c, 0x848f, 0x080c, + 0x849b, 0x080c, 0x7238, 0x00ce, 0x0804, 0x614f, 0x2c78, 0x600c, + 0x2060, 0x0804, 0x614f, 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x19e0, + 0x080c, 0x9097, 0x0c20, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, + 0xa280, 0x936e, 0x2004, 0xa065, 0x0904, 0x625a, 0x00f6, 0x00e6, + 0x00d6, 0x0066, 0x2071, 0x94e5, 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, 0x43ba, 0x0904, 0x6256, 0x7624, + 0x86ff, 0x05e8, 0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, + 0x2069, 0x0100, 0x68c0, 0xa005, 0x0548, 0x080c, 0x57a1, 0x080c, + 0x6f1e, 0x68c3, 0x0000, 0x080c, 0x7356, 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, 0x849b, 0x00ce, 0x0048, 0x00de, 0x00c6, + 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x6203, 0x8dff, + 0x0148, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x8527, + 0x080c, 0x4809, 0x080c, 0x7238, 0x0804, 0x6203, 0x006e, 0x00de, + 0x00ee, 0x00fe, 0x012e, 0x000e, 0x00ce, 0x0005, 0x0006, 0x0066, + 0x00c6, 0x00d6, 0x2031, 0x0000, 0x7814, 0xa065, 0x0904, 0x62b0, + 0x600c, 0x0006, 0x600f, 0x0000, 0x7824, 0xac06, 0x1540, 0x2069, + 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, 0x57a1, 0x080c, 0x6f1e, + 0x68c3, 0x0000, 0x080c, 0x7356, 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, 0x82ee, 0x0168, 0x601c, 0xa086, 0x0003, 0x11b8, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x4809, 0x080c, + 0x848f, 0x080c, 0x849b, 0x080c, 0x7238, 0x000e, 0x0804, 0x6265, + 0x7e16, 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c, + 0xa086, 0x0006, 0x1d28, 0x080c, 0x9097, 0x0c58, 0x0006, 0x0066, + 0x00c6, 0x00d6, 0x7818, 0xa065, 0x0904, 0x6324, 0x6054, 0x0006, + 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, + 0x080c, 0x43ba, 0x0904, 0x6321, 0x7e24, 0x86ff, 0x05e8, 0xa680, + 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100, 0x68c0, + 0xa005, 0x0548, 0x080c, 0x57a1, 0x080c, 0x6f1e, 0x68c3, 0x0000, + 0x080c, 0x7356, 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, + 0x849b, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, + 0x630a, 0x00ce, 0x0804, 0x62d0, 0x8dff, 0x0138, 0x6837, 0x0103, + 0x6b4a, 0x6847, 0x0000, 0x080c, 0x4809, 0x080c, 0x7238, 0x0804, + 0x62d0, 0x000e, 0x0804, 0x62c3, 0x781e, 0x781a, 0x00de, 0x00ce, + 0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0066, 0x6000, 0xd0dc, + 0x0188, 0x604c, 0xa06d, 0x0170, 0x6848, 0xa606, 0x1158, 0x2071, + 0x94e5, 0x7024, 0xa035, 0x0130, 0xa080, 0x0004, 0x2004, 0xad06, + 0x1108, 0x0021, 0x006e, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x2079, + 0x0100, 0x78c0, 0xa005, 0x1138, 0x00c6, 0x2660, 0x6003, 0x0009, + 0x630a, 0x00ce, 0x04a0, 0x080c, 0x6f1e, 0x78c3, 0x0000, 0x080c, + 0x7356, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, 0xa384, + 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x2079, 0x0100, + 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, 0x7356, 0x003e, + 0x080c, 0x43ba, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, + 0x2660, 0x080c, 0x74f2, 0x00ce, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x080c, 0x8527, 0x080c, 0x4809, 0x080c, 0x7238, 0x00fe, + 0x0005, 0x00e6, 0x00c6, 0x2071, 0x94e5, 0x7004, 0xa084, 0x0007, + 0x0002, 0x639b, 0x639e, 0x63b4, 0x63cd, 0x6406, 0x639b, 0x6399, + 0x6399, 0x080c, 0x13fe, 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, 0x43ba, + 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, 0x7238, 0x600c, 0xa015, 0x0120, + 0x720e, 0x600f, 0x0000, 0x0428, 0x720e, 0x720a, 0x0410, 0x7014, + 0xac06, 0x1160, 0x080c, 0x7238, 0x600c, 0xa015, 0x0120, 0x7216, + 0x600f, 0x0000, 0x00b0, 0x7216, 0x7212, 0x0098, 0x6018, 0x2060, + 0x080c, 0x43ba, 0x6000, 0xc0dc, 0x6002, 0x080c, 0x7238, 0x701c, + 0xa065, 0x0138, 0x6054, 0xa015, 0x0110, 0x721e, 0x0010, 0x7218, + 0x721e, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7024, 0xa065, + 0x0140, 0x080c, 0x7238, 0x600c, 0xa015, 0x0150, 0x720e, 0x600f, + 0x0000, 0x080c, 0x7356, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, + 0x720e, 0x720a, 0x0cb0, 0x00d6, 0x2069, 0x94e5, 0x6830, 0xa084, + 0x0003, 0x0002, 0x6428, 0x642a, 0x644a, 0x6426, 0x080c, 0x13fe, + 0x00de, 0x0005, 0x00c6, 0x6840, 0xa086, 0x0001, 0x0198, 0x683c, + 0xa065, 0x0130, 0x600c, 0xa015, 0x0150, 0x6a3a, 0x600f, 0x0000, + 0x6833, 0x0000, 0x683f, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, + 0x6836, 0x0cb0, 0x6843, 0x0000, 0x6838, 0xa065, 0x0d88, 0x6003, + 0x0003, 0x0c70, 0x00c6, 0x6843, 0x0000, 0x6847, 0x0000, 0x683c, + 0xa065, 0x0168, 0x600c, 0xa015, 0x0130, 0x6a3a, 0x600f, 0x0000, + 0x683f, 0x0000, 0x0020, 0x683f, 0x0000, 0x683a, 0x6836, 0x00ce, + 0x00de, 0x0005, 0x00d6, 0x2001, 0x9295, 0x2004, 0xd084, 0x0110, + 0x00de, 0x0005, 0x2069, 0x94e5, 0x6804, 0xa084, 0x0007, 0x0002, + 0x647a, 0x650c, 0x650c, 0x650c, 0x650c, 0x650e, 0x6478, 0x6478, + 0x080c, 0x13fe, 0x6820, 0xa005, 0x1110, 0x00de, 0x0005, 0x00c6, + 0x680c, 0xa065, 0x0150, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, + 0x080c, 0x656d, 0x00ce, 0x00de, 0x0005, 0x6814, 0xa065, 0x0150, + 0x6807, 0x0001, 0x6826, 0x682b, 0x0000, 0x080c, 0x656d, 0x00ce, + 0x00de, 0x0005, 0x00e6, 0x0036, 0x6a1c, 0xa2f5, 0x0000, 0x0904, + 0x6508, 0x704c, 0xa00d, 0x0118, 0x7088, 0xa005, 0x01a0, 0x7054, + 0xa075, 0x0120, 0xa20e, 0x0904, 0x6508, 0x0028, 0x6818, 0xa20e, + 0x0904, 0x6508, 0x2070, 0x704c, 0xa00d, 0x0d88, 0x7088, 0xa005, + 0x1d70, 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302, 0x1e40, 0x080c, + 0x74c9, 0x0904, 0x6508, 0x8318, 0x733e, 0x6112, 0x2e10, 0x621a, + 0xa180, 0x0015, 0x2004, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, + 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, 0x00f6, 0x2c78, + 0x71a0, 0x2001, 0x9232, 0x2004, 0xd0ac, 0x1110, 0xd1bc, 0x0150, + 0x7100, 0xd1f4, 0x0120, 0x7114, 0xa18c, 0x00ff, 0x0040, 0x2009, + 0x0000, 0x0028, 0xa1e0, 0x2719, 0x2c0d, 0xa18c, 0x00ff, 0x2061, + 0x0100, 0x619a, 0x080c, 0x6a46, 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, + 0x656d, 0x00ce, 0x00de, 0x0005, 0x00f6, 0x00d6, 0x2069, 0x94e5, + 0x6830, 0xa086, 0x0000, 0x1590, 0x6838, 0xa07d, 0x0578, 0x781c, + 0xa086, 0x0009, 0x1140, 0x7808, 0xd0fc, 0x0128, 0x2001, 0x94e6, + 0x2004, 0xa005, 0x1518, 0x2f00, 0x6833, 0x0001, 0x683e, 0x6847, + 0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x1d0f, + 0x11c0, 0x012e, 0xe000, 0xe000, 0xe000, 0x6a3c, 0x2278, 0x781c, + 0xa086, 0x0009, 0x1148, 0x7808, 0xd0fc, 0x0118, 0x080c, 0x6cf9, + 0x0028, 0x080c, 0x6d75, 0x0010, 0x080c, 0x6dec, 0x00de, 0x00fe, + 0x0005, 0x012e, 0xe000, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, + 0xa015, 0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, + 0x0000, 0x0c60, 0x683a, 0x6836, 0x0cc0, 0x601c, 0xa084, 0x000f, + 0x000b, 0x0005, 0x657b, 0x6580, 0x68f8, 0x6a03, 0x6580, 0x68f8, + 0x6a03, 0x657b, 0x6580, 0x080c, 0x6389, 0x080c, 0x6462, 0x0005, + 0x0156, 0x0136, 0x0146, 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x003e, + 0x1a0c, 0x13fe, 0x6118, 0x2178, 0x79a0, 0x2011, 0x9232, 0x2214, + 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914, + 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, 0x2719, + 0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0x0033, + 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x65f5, 0x662d, + 0x6647, 0x66fa, 0x6725, 0x672d, 0x674e, 0x675f, 0x6770, 0x6778, + 0x6789, 0x6778, 0x67ce, 0x675f, 0x67ef, 0x67f7, 0x6770, 0x67f7, + 0x6808, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec, + 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x6fda, 0x6fef, 0x7012, + 0x7036, 0x674e, 0x65ec, 0x674e, 0x6778, 0x65ec, 0x6647, 0x66fa, + 0x65ec, 0x744f, 0x6778, 0x65ec, 0x746f, 0x6778, 0x65ec, 0x6770, + 0x65ee, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec, + 0x65ec, 0x65ec, 0x65ec, 0x704b, 0x080c, 0x13fe, 0x2001, 0x9214, + 0x2004, 0x609a, 0x080c, 0x6f0b, 0x0005, 0x20a1, 0x020b, 0x080c, + 0x681d, 0x20a3, 0x5200, 0x20a3, 0x0000, 0x00d6, 0x2069, 0x9251, + 0x6804, 0xd084, 0x0150, 0x6828, 0x20a3, 0x0000, 0x0016, 0x080c, + 0x241f, 0x21a2, 0x001e, 0x00de, 0x0028, 0x00de, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0x9205, 0x53a6, 0x20a9, + 0x0004, 0x2099, 0x9201, 0x53a6, 0x20a3, 0x0000, 0x2001, 0x9214, + 0x2004, 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x001c, 0x080c, 0x6f0b, 0x0005, 0x20a1, 0x020b, 0x080c, + 0x681d, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x2001, 0x921b, 0x2004, + 0x20a2, 0x2001, 0x921c, 0x2004, 0x20a2, 0x20a9, 0x0004, 0x2099, + 0x9205, 0x53a6, 0x60c3, 0x0010, 0x080c, 0x6f0b, 0x0005, 0x20a1, + 0x020b, 0x080c, 0x681d, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, + 0x007e, 0x1130, 0x20a3, 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0010, + 0x20a3, 0x0300, 0x20a3, 0x0000, 0x7818, 0xa080, 0x0028, 0x2004, + 0xa086, 0x007e, 0x1904, 0x66bc, 0x2001, 0x9232, 0x2004, 0xd0a4, + 0x01c8, 0x2099, 0x94c7, 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398, + 0x3304, 0xa084, 0x2000, 0x20a2, 0x9398, 0x33a6, 0x9398, 0x20a3, + 0x0000, 0x9398, 0x2001, 0x2710, 0x20a2, 0x9398, 0x33a6, 0x9398, + 0x33a6, 0x00d0, 0x2099, 0x94c7, 0x33a6, 0x9398, 0x33a6, 0x9398, + 0x3304, 0x080c, 0x4dc5, 0x1118, 0xa084, 0x37ff, 0x0010, 0xa084, + 0x3fff, 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0x9205, + 0x53a6, 0x20a9, 0x0004, 0x2099, 0x9201, 0x53a6, 0x20a9, 0x0008, + 0x20a3, 0x0000, 0x1f04, 0x66a8, 0x20a9, 0x0008, 0x20a3, 0x0000, + 0x1f04, 0x66ae, 0x2099, 0x94cf, 0x33a6, 0x20a9, 0x0007, 0x20a3, + 0x0000, 0x1f04, 0x66b7, 0x0468, 0x2001, 0x9232, 0x2004, 0xd0a4, + 0x0140, 0x2001, 0x94c8, 0x2004, 0x60e3, 0x0000, 0x080c, 0x2460, + 0x60e2, 0x2099, 0x94c7, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0004, + 0x2099, 0x9205, 0x53a6, 0x20a9, 0x0004, 0x2099, 0x9201, 0x53a6, + 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x66da, 0x20a9, 0x0008, + 0x20a3, 0x0000, 0x1f04, 0x66e0, 0x2099, 0x94cf, 0x20a9, 0x0008, + 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x66eb, 0x20a9, + 0x000a, 0x20a3, 0x0000, 0x1f04, 0x66f1, 0x60c3, 0x0074, 0x080c, + 0x6f0b, 0x0005, 0x20a1, 0x020b, 0x080c, 0x681d, 0x20a3, 0x2010, + 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, 0xa006, 0x20a2, + 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x00f6, 0x2079, 0x9251, 0x7904, + 0x00fe, 0xd1ac, 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, + 0x0010, 0xa085, 0x0002, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0014, 0x080c, 0x6f0b, 0x0005, 0x20a1, 0x020b, 0x080c, + 0x681d, 0x20a3, 0x5000, 0x0804, 0x665a, 0x20a1, 0x020b, 0x080c, + 0x681d, 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, 0x6f0b, 0x0005, 0x20a1, 0x020b, + 0x080c, 0x68a0, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0004, 0x080c, 0x6f0b, 0x0005, 0x20a1, + 0x020b, 0x080c, 0x68a0, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, + 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x6f0b, 0x0005, + 0x20a1, 0x020b, 0x080c, 0x68a0, 0x20a3, 0x0200, 0x0804, 0x665a, + 0x20a1, 0x020b, 0x080c, 0x68a0, 0x20a3, 0x0100, 0x20a3, 0x0000, + 0x20a3, 0x0003, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x6f0b, + 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x68a0, 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, 0x9251, 0x7904, 0x00fe, 0xd1ac, 0x1110, + 0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010, 0x2009, 0x9273, + 0x210c, 0xd184, 0x1110, 0xa085, 0x0002, 0x20a2, 0x20a2, 0x20a2, + 0x60c3, 0x0014, 0x080c, 0x6f0b, 0x00de, 0x0005, 0x20a1, 0x020b, + 0x080c, 0x68a0, 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, 0x6f0b, 0x0005, 0x20a1, + 0x020b, 0x080c, 0x68a0, 0x20a3, 0x0200, 0x0804, 0x65fb, 0x20a1, + 0x020b, 0x080c, 0x68a0, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, + 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x6f0b, 0x0005, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, 0x080c, 0x68a0, + 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3, 0x0000, + 0x60c3, 0x0008, 0x080c, 0x6f0b, 0x0005, 0x0026, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, + 0x1198, 0x20a3, 0x22ff, 0x20a3, 0xfffe, 0x20a3, 0x0000, 0x2011, + 0x9214, 0x2214, 0x2001, 0x94d7, 0x2004, 0xa005, 0x0118, 0x2011, + 0x921c, 0x2214, 0x22a2, 0x0498, 0xa286, 0x007f, 0x1130, 0x00d6, + 0x20a3, 0x22ff, 0x20a3, 0xfffd, 0x00c8, 0x2001, 0x9232, 0x2004, + 0xd0ac, 0x1110, 0xd2bc, 0x01c8, 0xa286, 0x0080, 0x00d6, 0x1128, + 0x20a3, 0x22ff, 0x20a3, 0xfffc, 0x0048, 0xa2e8, 0x936e, 0x2d6c, + 0x6810, 0xa085, 0x2200, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x921b, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0050, 0x20a3, 0x2200, 0x6298, + 0x22a2, 0x20a3, 0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, 0x20a3, + 0x0129, 0x20a3, 0x0000, 0x080c, 0x6efa, 0x22a2, 0x20a3, 0x0000, + 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, + 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, + 0x2011, 0xfffc, 0x22a2, 0x00d6, 0x2069, 0x921b, 0x2da6, 0x8d68, + 0x2da6, 0x00de, 0x20a3, 0x2029, 0x20a3, 0x0000, 0x08e0, 0x20a3, + 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, 0x0005, + 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0x2011, 0x9232, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, + 0x02e0, 0x00d6, 0xa0e8, 0x936e, 0x2d6c, 0x6810, 0xa085, 0x2300, + 0x20a2, 0x6814, 0x20a2, 0x6810, 0xa005, 0x1140, 0x6814, 0xa005, + 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0028, 0x2069, 0x921b, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0050, 0x20a3, 0x2300, 0x6298, + 0x22a2, 0x20a3, 0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, 0x20a3, + 0x0198, 0x20a3, 0x0000, 0x080c, 0x6efa, 0x22a2, 0x20a3, 0x0000, + 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, + 0x0005, 0x080c, 0x6efa, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, + 0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, + 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x13fe, 0xa08a, + 0x008c, 0x1a0c, 0x13fe, 0x6118, 0x2178, 0x79a0, 0x2011, 0x9232, + 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, + 0x7914, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, + 0x2719, 0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, + 0xa082, 0x0085, 0x001b, 0x00fe, 0x00ce, 0x0005, 0x692f, 0x6939, + 0x6954, 0x692d, 0x692d, 0x692d, 0x692f, 0x080c, 0x13fe, 0x0146, + 0x20a1, 0x020b, 0x04a1, 0x60c3, 0x0000, 0x080c, 0x6f0b, 0x014e, + 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6999, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, 0x20a3, 0x0000, + 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c, + 0x080c, 0x6f0b, 0x014e, 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, + 0x69d1, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0004, 0x080c, 0x6f0b, 0x014e, 0x0005, 0x0026, + 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, + 0x2011, 0x9232, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, + 0x00d6, 0xa0e8, 0x936e, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0x921b, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0050, 0x20a3, 0x8100, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x2011, + 0x9214, 0x2214, 0x22a2, 0x20a3, 0x0009, 0x20a3, 0x0000, 0x0804, + 0x6873, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, + 0x0028, 0x2004, 0x2011, 0x9232, 0x2214, 0xd2ac, 0x1118, 0xa092, + 0x007e, 0x0288, 0x00d6, 0xa0e8, 0x936e, 0x2d6c, 0x6810, 0xa085, + 0x8400, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x921b, 0x2da6, 0x8d68, + 0x2da6, 0x00de, 0x0050, 0x20a3, 0x8400, 0x6298, 0x22a2, 0x20a3, + 0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, 0x080c, 0x4dc5, 0x1118, + 0x20a3, 0x0099, 0x0010, 0x20a3, 0x00d1, 0x20a3, 0x0000, 0x0804, + 0x68e9, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, + 0x0028, 0x2004, 0x2011, 0x9232, 0x2214, 0xd2ac, 0x1118, 0xa092, + 0x007e, 0x0288, 0x00d6, 0xa0e8, 0x936e, 0x2d6c, 0x6810, 0xa085, + 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x921b, 0x2da6, 0x8d68, + 0x2da6, 0x00de, 0x0050, 0x20a3, 0x8500, 0x6298, 0x22a2, 0x20a3, + 0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, 0x20a3, 0x0099, 0x20a3, + 0x0000, 0x0804, 0x68e9, 0x00c6, 0x00f6, 0x2c78, 0x7804, 0xa08a, + 0x0040, 0x0a0c, 0x13fe, 0xa08a, 0x0053, 0x1a0c, 0x13fe, 0x7918, + 0x2160, 0x61a0, 0x2011, 0x9232, 0x2214, 0xd2ac, 0x1110, 0xd1bc, + 0x0150, 0x6100, 0xd1f4, 0x0120, 0x6114, 0xa18c, 0x00ff, 0x0040, + 0x2009, 0x0000, 0x0028, 0xa1e0, 0x2719, 0x2c0d, 0xa18c, 0x00ff, + 0x2061, 0x0100, 0x619a, 0xa082, 0x0040, 0x001b, 0x00fe, 0x00ce, + 0x0005, 0x6a46, 0x6b3a, 0x6ade, 0x6c75, 0x6a44, 0x6a44, 0x6a44, + 0x6a44, 0x6a44, 0x6a44, 0x6a44, 0x71f1, 0x7201, 0x7211, 0x7221, + 0x6a44, 0x6a44, 0x6a44, 0x71e0, 0x080c, 0x13fe, 0x00d6, 0x0156, + 0x0146, 0x20a1, 0x020b, 0x080c, 0x6a9c, 0x7910, 0x2168, 0x6948, + 0x7922, 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, + 0x000f, 0x1118, 0x2001, 0x0005, 0x0040, 0xd184, 0x0118, 0x2001, + 0x0004, 0x0018, 0xa084, 0x0006, 0x8004, 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, 0x9501, + 0x2003, 0x07d0, 0x2001, 0x9500, 0x2003, 0x0009, 0x080c, 0x165a, + 0x014e, 0x015e, 0x00de, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, + 0x8217, 0x7818, 0xa080, 0x0028, 0x2004, 0x2019, 0x9232, 0x231c, + 0xd3ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0x936e, 0x2d6c, + 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x921b, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0050, 0x20a3, 0x0600, 0x6198, + 0x21a2, 0x20a3, 0x0000, 0x2009, 0x9214, 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, 0x6f0b, + 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0026, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0x9232, + 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0x936e, + 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x2069, + 0x921b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0050, 0x20a3, 0x0500, + 0x6298, 0x22a2, 0x20a3, 0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, + 0x20a3, 0x0889, 0x20a3, 0x0000, 0x080c, 0x6efa, 0x22a2, 0x20a3, + 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x20a1, 0x020b, + 0x080c, 0x6c38, 0x7810, 0x2068, 0xa016, 0x22a2, 0x22a2, 0x22a2, + 0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, 0x1130, 0x7810, 0xa084, + 0x0700, 0x8007, 0x0043, 0x0010, 0xa006, 0x002b, 0x014e, 0x013e, + 0x015e, 0x00de, 0x0005, 0x6b65, 0x6bde, 0x6be1, 0x6c04, 0x6c11, + 0x6c23, 0x6c26, 0x6b63, 0x080c, 0x13fe, 0x0016, 0x0036, 0x694c, + 0xa18c, 0x0003, 0xa186, 0x0000, 0x1150, 0x6b78, 0x23a2, 0x6868, + 0x20a2, 0x6864, 0x20a2, 0x003e, 0x001e, 0x0804, 0x6c08, 0xa186, + 0x0001, 0x1904, 0x6bd9, 0x6b78, 0x23a2, 0x6868, 0x20a2, 0x6864, + 0x20a2, 0x22a2, 0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, + 0x0018, 0xa384, 0x0300, 0x0904, 0x6bd8, 0xd3c4, 0x0110, 0x687c, + 0xa108, 0xd3cc, 0x0110, 0x6874, 0xa108, 0x0156, 0x20a9, 0x000d, + 0xad80, 0x0020, 0x201c, 0x831f, 0x23a2, 0x8000, 0x1f04, 0x6b9a, + 0x015e, 0x22a2, 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0588, 0x20a1, + 0x020b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x0006, 0x7818, 0xa080, + 0x0028, 0x2004, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0x936e, 0x2d6c, + 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x921b, + 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0050, 0x20a3, 0x0700, 0x6298, + 0x22a2, 0x20a3, 0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, 0x000e, + 0x20a3, 0x0898, 0x20a2, 0x080c, 0x6efa, 0x22a2, 0x20a3, 0x0000, + 0x61c2, 0x003e, 0x001e, 0x080c, 0x6f0b, 0x0005, 0x20a3, 0x0008, + 0x0428, 0x20a3, 0x0302, 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, 0x6f0b, 0x0005, 0x20a3, 0x0028, 0x22a2, 0x22a2, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0018, 0x080c, 0x6f0b, + 0x0005, 0x20a3, 0x0100, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, + 0x20a3, 0x0008, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0020, + 0x080c, 0x6f0b, 0x0005, 0x20a3, 0x0008, 0x0c00, 0x0036, 0x7b10, + 0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, 0x1118, 0x22a2, + 0x003e, 0x08a0, 0x20a3, 0x0800, 0x22a2, 0x20a2, 0x003e, 0x0880, + 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0x2011, 0x9232, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, + 0x00d6, 0xa0e8, 0x936e, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0x921b, 0x2da6, 0x8d68, 0x2da6, 0x00de, + 0x0050, 0x20a3, 0x0700, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x2011, + 0x9214, 0x2214, 0x22a2, 0x20a3, 0x0898, 0x20a3, 0x0000, 0x080c, + 0x6efa, 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, 0x6c8f, + 0x6c8f, 0x6c91, 0x6c8f, 0x6c8f, 0x6c8f, 0x6cb3, 0x6c8f, 0x080c, + 0x13fe, 0x7910, 0xa18c, 0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1, + 0x020b, 0x2009, 0x0003, 0x00f9, 0x00d6, 0x2069, 0x9251, 0x6804, + 0xd0bc, 0x0130, 0x682c, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0010, + 0x20a3, 0x3f00, 0x00de, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, + 0x080c, 0x6f0b, 0x0005, 0x20a1, 0x020b, 0x2009, 0x0003, 0x0019, + 0x20a3, 0x7f00, 0x0c80, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0x9232, 0x2214, 0xd2ac, + 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0x936e, 0x2d6c, 0x6810, + 0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x921b, 0x2da6, + 0x8d68, 0x2da6, 0x00de, 0x0050, 0x20a3, 0x0100, 0x6298, 0x22a2, + 0x20a3, 0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, 0x20a3, 0x0888, + 0xa18d, 0x0008, 0x21a2, 0x080c, 0x6efa, 0x22a2, 0x20a3, 0x0000, + 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, + 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0036, + 0x2061, 0x0100, 0x2071, 0x9200, 0x2009, 0x9214, 0x210c, 0x7818, + 0x2068, 0x2031, 0x9232, 0x2634, 0xa6b4, 0x0028, 0x0110, 0x736c, + 0x7470, 0x2500, 0x2031, 0x9232, 0x2634, 0xa6b4, 0x0028, 0x0140, + 0x2001, 0x04ff, 0x6062, 0x6067, 0xffff, 0x636a, 0x646e, 0x0050, + 0x2001, 0x00ff, 0xa085, 0x0400, 0x6062, 0x6067, 0xffff, 0x606b, + 0x0000, 0x616e, 0x68b8, 0x6072, 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, 0x9232, 0x2004, 0xd09c, 0x0128, 0x609f, 0x0000, 0x2001, + 0x0012, 0x0048, 0x6028, 0xc0bd, 0x602a, 0x609f, 0x00ff, 0x6027, + 0xffff, 0x2001, 0x0032, 0x6016, 0x2009, 0x07d0, 0x080c, 0x57a6, + 0x2001, 0x9295, 0x200c, 0xc185, 0x2102, 0x003e, 0x004e, 0x005e, + 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, + 0x0066, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x9200, + 0x2009, 0x9214, 0x210c, 0x7818, 0x2068, 0x68a0, 0x2028, 0x2031, + 0x9232, 0x2634, 0xd6ac, 0x1140, 0xd0bc, 0x1130, 0xa080, 0x2719, + 0x2015, 0xa294, 0x00ff, 0x0020, 0x6910, 0x6a14, 0x736c, 0x7470, + 0x2001, 0x9232, 0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, + 0x0400, 0x6062, 0x6266, 0x636a, 0x646e, 0x0030, 0x6063, 0x0400, + 0x6266, 0x606b, 0x0000, 0x616e, 0x68b8, 0x6072, 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, 0x0080, 0x0210, 0x2011, 0x0000, 0x629e, + 0x00f6, 0x2079, 0x0140, 0x7803, 0x0000, 0x00fe, 0x6017, 0x0012, + 0x2009, 0x07d0, 0x080c, 0x57a6, 0x003e, 0x004e, 0x005e, 0x006e, + 0x00ce, 0x00de, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0056, + 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x9200, 0x7150, 0x7818, + 0x2068, 0x68a0, 0x2028, 0x76c8, 0xd6ac, 0x1140, 0xd0bc, 0x1130, + 0xa080, 0x2719, 0x2015, 0xa294, 0x00ff, 0x0020, 0x6910, 0x6a14, + 0x736c, 0x7470, 0x781c, 0xa086, 0x0006, 0x0904, 0x6e65, 0x70c8, + 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, + 0x636a, 0x646e, 0x0030, 0x6063, 0x0100, 0x6266, 0x606b, 0x0000, + 0x616e, 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, 0x0248, 0x6a00, + 0xd2f4, 0x0120, 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, + 0x629e, 0x6017, 0x0016, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, + 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x57a6, 0x003e, 0x004e, + 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7810, 0x2070, 0x704c, + 0xa084, 0x0003, 0xa086, 0x0002, 0x0904, 0x6eb4, 0x2001, 0x9232, + 0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, + 0x6266, 0x636a, 0x646e, 0x0030, 0x6063, 0x0100, 0x6266, 0x606b, + 0x0000, 0x616e, 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, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, + 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, + 0x0120, 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, + 0x6017, 0x0012, 0x0804, 0x6e53, 0x2001, 0x9232, 0x2004, 0xd0ac, + 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, + 0x646e, 0x0030, 0x6063, 0x0700, 0x6266, 0x606b, 0x0000, 0x616e, + 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, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, + 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x6017, 0x0016, + 0x0804, 0x6e53, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, + 0x00ff, 0x2202, 0x8217, 0x0005, 0x00d6, 0x2069, 0x94e5, 0x6843, + 0x0001, 0x00de, 0x0005, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, + 0x9575, 0x0019, 0x080c, 0x5798, 0x0005, 0x0006, 0x6014, 0xa084, + 0x0004, 0xa085, 0x0009, 0x6016, 0x000e, 0x0005, 0x0006, 0x00c6, + 0x2061, 0x0100, 0x6014, 0xa084, 0x0004, 0xa085, 0x0008, 0x6016, + 0x00ce, 0x000e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x080c, + 0x57a1, 0x2061, 0x0100, 0x2069, 0x0140, 0x6904, 0xa194, 0x4000, + 0x0538, 0x0c21, 0x6803, 0x1000, 0x6803, 0x0000, 0x00c6, 0x2061, + 0x94e5, 0x6128, 0xa192, 0x0002, 0x1250, 0x8108, 0x612a, 0x6124, + 0x00ce, 0x81ff, 0x0180, 0x080c, 0x5798, 0x0839, 0x0060, 0x6124, + 0xa1e5, 0x0000, 0x0130, 0x080c, 0x91a0, 0x2009, 0x0014, 0x080c, + 0x7518, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, + 0x080c, 0x4dc5, 0x1118, 0x080c, 0x6f1e, 0x08c0, 0x080c, 0x4105, + 0x0c90, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, 0x080c, 0x57ae, + 0x2071, 0x94e5, 0x713c, 0x81ff, 0x0578, 0x2061, 0x0100, 0x2069, + 0x0140, 0x6904, 0xa194, 0x4000, 0x0568, 0x6803, 0x1000, 0x6803, + 0x0000, 0x0036, 0x2019, 0x0001, 0x080c, 0x7110, 0x003e, 0x713c, + 0x2160, 0x080c, 0x91a0, 0x2009, 0x004a, 0x621c, 0xa296, 0x0009, + 0x1110, 0x2009, 0x0104, 0x080c, 0x7518, 0x080c, 0x4dc5, 0x1160, + 0x0006, 0x2001, 0x94d8, 0x2003, 0x0002, 0x2001, 0x9200, 0x2003, + 0x0001, 0x080c, 0x4d10, 0x000e, 0x002e, 0x001e, 0x00ee, 0x00de, + 0x00ce, 0x0005, 0x08b0, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, + 0x0046, 0x0006, 0x0126, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0, + 0x2071, 0x94e5, 0x7018, 0x2068, 0x8dff, 0x0198, 0x68a0, 0xa406, + 0x0118, 0x6854, 0x2068, 0x0cc0, 0x6010, 0x2060, 0x643c, 0x6540, + 0x6e48, 0x2d60, 0x080c, 0x457f, 0x0120, 0x080c, 0x7238, 0xa085, + 0x0001, 0x012e, 0x000e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, + 0x00ee, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x681d, + 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, + 0x60c3, 0x0008, 0x080c, 0x6f0b, 0x014e, 0x015e, 0x0005, 0x0156, + 0x0146, 0x20a1, 0x020b, 0x080c, 0x68a0, 0x20a3, 0x0200, 0x20a3, + 0x0000, 0x20a9, 0x0006, 0x2011, 0x9240, 0x2019, 0x9241, 0x23a6, + 0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x1f04, 0x6fff, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x6f0b, 0x014e, + 0x015e, 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, + 0x080c, 0x6881, 0x080c, 0x6897, 0x7810, 0x0006, 0xa080, 0x0015, + 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0xa080, 0x0004, + 0x8003, 0x60c2, 0x000e, 0xa080, 0x0001, 0x2004, 0x7812, 0x080c, + 0x6f0b, 0x002e, 0x001e, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, + 0x20a1, 0x020b, 0x080c, 0x681d, 0x20a3, 0x6200, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x6f0b, + 0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, + 0x020b, 0x080c, 0x681d, 0x7810, 0x0006, 0xa080, 0x0017, 0x2098, + 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, 0x000e, + 0xa080, 0x0001, 0x2004, 0x7812, 0x080c, 0x6f0b, 0x002e, 0x001e, + 0x014e, 0x015e, 0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, + 0x8000, 0x2071, 0x94e5, 0x700c, 0x2060, 0x8cff, 0x0168, 0x080c, + 0x84c8, 0x1110, 0x080c, 0x7776, 0x600c, 0x0006, 0x080c, 0x74f2, + 0x080c, 0x7238, 0x00ce, 0x0c88, 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, 0x94e5, 0x7024, 0x2060, + 0x8cff, 0x05a0, 0x080c, 0x6f1e, 0x68c3, 0x0000, 0x080c, 0x57a1, + 0x2009, 0x0013, 0x080c, 0x7518, 0x20a9, 0x01f4, 0x6824, 0xd094, + 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, + 0x1000, 0x7803, 0x0000, 0x0078, 0xd084, 0x0118, 0x6827, 0x0001, + 0x0010, 0x1f04, 0x70ae, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, + 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e, 0x00ce, + 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, 0x9200, + 0x2004, 0xa096, 0x0001, 0x0550, 0xa096, 0x0004, 0x0538, 0x6817, + 0x0008, 0x68c3, 0x0000, 0x2011, 0x40af, 0x080c, 0x5731, 0x20a9, + 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, + 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd084, + 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x70e9, 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, + 0x94e5, 0x703c, 0x2060, 0x8cff, 0x0904, 0x7185, 0x6817, 0x0010, + 0x68c7, 0x0000, 0x68cb, 0x0000, 0x080c, 0x57ae, 0x080c, 0x1ef8, + 0x0046, 0x0056, 0x2009, 0x017f, 0x212c, 0x200b, 0x00a5, 0x2021, + 0x0169, 0x2404, 0xa084, 0x000f, 0xa086, 0x0004, 0x11b0, 0x68c7, + 0x0000, 0x68cb, 0x0008, 0x00e6, 0x00f6, 0x2079, 0x0020, 0x2071, + 0x953b, 0x6814, 0xa084, 0x0004, 0xa085, 0x0012, 0x6816, 0x7803, + 0x0008, 0x7003, 0x0000, 0x00fe, 0x00ee, 0x250a, 0x005e, 0x004e, + 0xa39d, 0x0000, 0x1150, 0x2009, 0x0049, 0x601c, 0xa086, 0x0009, + 0x1110, 0x2009, 0x0103, 0x080c, 0x7518, 0x20a9, 0x03e8, 0x6824, + 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, + 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd094, 0x0118, 0x6827, + 0x0002, 0x0010, 0x1f04, 0x7167, 0x7804, 0xa084, 0x1000, 0x0120, + 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e, + 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, + 0x0126, 0x2091, 0x8000, 0x2069, 0x94e5, 0x6a06, 0x012e, 0x00de, + 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0x94e5, 0x6a32, + 0x012e, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006, + 0x0126, 0x2071, 0x94e5, 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, + 0x849b, 0x080c, 0x7238, 0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060, + 0x08b8, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, + 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6a9c, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804, + 0x7230, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6a9c, 0x7810, + 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000, + 0x0478, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6a9c, 0x7810, + 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, + 0x00f8, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6a9c, 0x7810, + 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, + 0x0078, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6a9c, 0x7810, + 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, + 0x0089, 0x60c3, 0x0020, 0x080c, 0x6f0b, 0x014e, 0x015e, 0x0005, + 0x00e6, 0x2071, 0x94e5, 0x7020, 0xa005, 0x0110, 0x8001, 0x7022, + 0x00ee, 0x0005, 0x20a9, 0x0008, 0x20a2, 0x1f04, 0x7244, 0x20a2, + 0x20a2, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, + 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x94e5, 0x7614, 0x2660, + 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0x72d2, 0x8cff, 0x0904, + 0x72d2, 0x601c, 0xa086, 0x0006, 0x1904, 0x72cd, 0x88ff, 0x0138, + 0x2800, 0xac06, 0x1904, 0x72cd, 0x2039, 0x0000, 0x0050, 0x6018, + 0xa206, 0x1904, 0x72cd, 0x85ff, 0x0120, 0x6020, 0xa106, 0x1904, + 0x72cd, 0x7024, 0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005, + 0x01f0, 0x080c, 0x57a1, 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, + 0x7356, 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, 0x0450, 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, + 0x82ee, 0x0110, 0x080c, 0x9097, 0x080c, 0x849b, 0x080c, 0x7238, + 0x88ff, 0x1190, 0x00ce, 0x0804, 0x725b, 0x2c78, 0x600c, 0x2060, + 0x0804, 0x725b, 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, 0x94e5, 0x7638, 0x2660, + 0x2678, 0x8cff, 0x0904, 0x7346, 0x601c, 0xa086, 0x0006, 0x1904, + 0x7341, 0x88ff, 0x0128, 0x2800, 0xac06, 0x1904, 0x7341, 0x0040, + 0x6018, 0xa206, 0x15f0, 0x85ff, 0x0118, 0x6020, 0xa106, 0x15c8, + 0x703c, 0xac06, 0x1170, 0x0036, 0x2019, 0x0001, 0x080c, 0x7110, + 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 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, 0x82ee, 0x0110, + 0x080c, 0x9097, 0x080c, 0x849b, 0x88ff, 0x1190, 0x00ce, 0x0804, + 0x72f1, 0x2c78, 0x600c, 0x2060, 0x0804, 0x72f1, 0xa006, 0x012e, + 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, + 0x6017, 0x0000, 0x00ce, 0xa8c5, 0x0001, 0x0c88, 0x00e6, 0x2071, + 0x94e5, 0x2001, 0x9200, 0x2004, 0xa086, 0x0002, 0x1118, 0x7007, + 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, + 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, + 0x94e5, 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, 0x94e5, 0x760c, 0x2660, 0x2678, + 0x8cff, 0x0904, 0x7423, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, + 0x1904, 0x741e, 0x7024, 0xac06, 0x1500, 0x2069, 0x0100, 0x68c0, + 0xa005, 0x01d8, 0x080c, 0x6f1e, 0x68c3, 0x0000, 0x080c, 0x7356, + 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, + 0x84b7, 0x1118, 0x080c, 0x2692, 0x00c0, 0x080c, 0x84c8, 0x1118, + 0x080c, 0x7776, 0x0090, 0x6010, 0x2068, 0x080c, 0x82ee, 0x0168, + 0x601c, 0xa086, 0x0003, 0x11f8, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x080c, 0x4809, 0x080c, 0x848f, 0x6003, 0x0000, 0x080c, + 0x849b, 0x080c, 0x7238, 0x00ce, 0x0804, 0x73b0, 0x2c78, 0x600c, + 0x2060, 0x0804, 0x73b0, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00de, + 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x19e8, 0x080c, + 0x9097, 0x0c18, 0x0036, 0x0156, 0x0136, 0x0146, 0x3908, 0xa006, + 0xa190, 0x0020, 0x221c, 0xa39e, 0x251b, 0x1118, 0x8210, 0x8000, + 0x0cc8, 0xa005, 0x0138, 0x20a9, 0x0020, 0x2198, 0xa110, 0x22a0, + 0x22c8, 0x53a3, 0x014e, 0x013e, 0x015e, 0x003e, 0x0005, 0x00d6, + 0x20a1, 0x020b, 0x080c, 0x68a0, 0x20a3, 0x0200, 0x20a3, 0x0014, + 0x60c3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2099, 0x94df, + 0x20a9, 0x0004, 0x53a6, 0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x080c, 0x6f0b, 0x00de, 0x0005, 0x20a1, + 0x020b, 0x080c, 0x68a0, 0x20a3, 0x0210, 0x20a3, 0x0018, 0x20a3, + 0x0800, 0x7810, 0xa084, 0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7810, + 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x0018, 0x080c, 0x6f0b, 0x0005, 0x2061, 0x9900, 0x2a70, 0x7064, + 0x7046, 0x704b, 0x9900, 0x0005, 0x00e6, 0x0126, 0x2071, 0x9200, + 0x2091, 0x8000, 0x7544, 0xa582, 0x0001, 0x0608, 0x7048, 0x2060, + 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x000c, 0x7058, 0xac02, + 0x1208, 0x0cb0, 0x2061, 0x9900, 0x0c98, 0x6003, 0x0008, 0x8529, + 0x7546, 0xaca8, 0x000c, 0x7058, 0xa502, 0x1230, 0x754a, 0xa085, + 0x0001, 0x012e, 0x00ee, 0x0005, 0x704b, 0x9900, 0x0cc0, 0xa006, + 0x0cc0, 0x00e6, 0x2071, 0x9200, 0x7544, 0xa582, 0x0001, 0x0600, + 0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x000c, + 0x7058, 0xac02, 0x1208, 0x0cb0, 0x2061, 0x9900, 0x0c98, 0x6003, + 0x0008, 0x8529, 0x7546, 0xaca8, 0x000c, 0x7058, 0xa502, 0x1228, + 0x754a, 0xa085, 0x0001, 0x00ee, 0x0005, 0x704b, 0x9900, 0x0cc8, + 0xa006, 0x0cc8, 0xac82, 0x9900, 0x0a0c, 0x13fe, 0x2001, 0x9216, + 0x2004, 0xac02, 0x1a0c, 0x13fe, 0xa006, 0x6006, 0x600a, 0x600e, + 0x6012, 0x6016, 0x601a, 0x601f, 0x0000, 0x6003, 0x0000, 0x6022, + 0x2061, 0x9200, 0x6044, 0x8000, 0x6046, 0xa086, 0x0001, 0x0108, + 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x6462, 0x012e, 0x0cc0, + 0x601c, 0xa084, 0x000f, 0x0002, 0x7526, 0x752d, 0x7548, 0x7563, + 0x8555, 0x8570, 0x858b, 0x7526, 0x752d, 0x5d3d, 0xa18e, 0x0047, + 0x1118, 0xa016, 0x080c, 0x16c6, 0x0005, 0x0066, 0x6000, 0xa0b2, + 0x0010, 0x1a0c, 0x13fe, 0x0013, 0x006e, 0x0005, 0x7546, 0x7654, + 0x779c, 0x7546, 0x77eb, 0x7546, 0x7546, 0x7546, 0x75f6, 0x7b03, + 0x7546, 0x7546, 0x7546, 0x7546, 0x7546, 0x7546, 0x080c, 0x13fe, + 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x13fe, 0x0013, 0x006e, + 0x0005, 0x7561, 0x7fa1, 0x7561, 0x7561, 0x7561, 0x7561, 0x7561, + 0x7561, 0x7f89, 0x8078, 0x7561, 0x7fce, 0x8023, 0x7fce, 0x8023, + 0x7561, 0x080c, 0x13fe, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, + 0x13fe, 0x0013, 0x006e, 0x0005, 0x757c, 0x7b3f, 0x7bf0, 0x7cb4, + 0x7df4, 0x757c, 0x757c, 0x757c, 0x7b1b, 0x7f40, 0x7f43, 0x757c, + 0x757c, 0x757c, 0x757c, 0x7f66, 0x080c, 0x13fe, 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, 0x758c, + 0x00e6, 0x080c, 0x82ee, 0x0130, 0x6010, 0x2070, 0x7007, 0x0000, + 0x7037, 0x0103, 0x00ee, 0x080c, 0x74f2, 0x0005, 0x00d6, 0x0036, + 0x7330, 0xa386, 0x0200, 0x1130, 0x6018, 0x2068, 0x6813, 0x00ff, + 0x6817, 0xfffd, 0x6010, 0xa005, 0x0130, 0x2068, 0x6807, 0x0000, + 0x6837, 0x0103, 0x6b32, 0x080c, 0x74f2, 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, 0x74f2, 0x001e, 0x0005, + 0x00d6, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0xa1b6, + 0x0015, 0x1148, 0x6018, 0x2068, 0x7038, 0x680a, 0x703c, 0x680e, + 0x6800, 0xc08d, 0x6802, 0x00de, 0x0804, 0x7598, 0x2100, 0xa1b2, + 0x003e, 0x1a0c, 0x13fe, 0x0002, 0x763c, 0x7648, 0x763c, 0x763c, + 0x763c, 0x763c, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, + 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, + 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, + 0x763a, 0x763a, 0x763a, 0x763c, 0x763a, 0x763c, 0x763c, 0x763a, + 0x763a, 0x763a, 0x763a, 0x763a, 0x763c, 0x763a, 0x763a, 0x763a, + 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763c, 0x763a, + 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, + 0x763a, 0x763c, 0x080c, 0x13fe, 0x6003, 0x0001, 0x6106, 0x080c, + 0x603e, 0x0126, 0x2091, 0x8000, 0x080c, 0x6462, 0x012e, 0x0005, + 0x6003, 0x0001, 0x6106, 0x080c, 0x603e, 0x0126, 0x2091, 0x8000, + 0x080c, 0x6462, 0x012e, 0x0005, 0x6004, 0xa0b2, 0x003e, 0x1a0c, + 0x13fe, 0xa1b6, 0x0013, 0x0904, 0x76f0, 0xa1b6, 0x0027, 0x1904, + 0x76b6, 0x080c, 0x6389, 0x6004, 0x080c, 0x84b7, 0x0178, 0x080c, + 0x84c8, 0x0904, 0x76b0, 0xa08e, 0x0021, 0x0904, 0x76b3, 0xa08e, + 0x0022, 0x05f0, 0xa08e, 0x003d, 0x05f0, 0x04a8, 0x080c, 0x2692, + 0x2001, 0x0007, 0x080c, 0x43e3, 0x6018, 0xa080, 0x0028, 0x200c, + 0x080c, 0x7776, 0xa186, 0x007e, 0x1148, 0x2001, 0x9232, 0x2014, + 0xc285, 0x080c, 0x4dc5, 0x1108, 0xc2ad, 0x2202, 0x0016, 0x0026, + 0x0036, 0x2110, 0x2019, 0x0028, 0x080c, 0x6127, 0x0086, 0x2041, + 0x0000, 0x080c, 0x606d, 0x00c6, 0x6018, 0xa065, 0x0110, 0x080c, + 0x460d, 0x00ce, 0x2c08, 0x080c, 0x8ee4, 0x008e, 0x003e, 0x002e, + 0x001e, 0x080c, 0x441f, 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005, + 0x080c, 0x7776, 0x0cc0, 0x080c, 0x7790, 0x0ca8, 0xa186, 0x0014, + 0x1db0, 0x080c, 0x6389, 0x080c, 0x266c, 0x080c, 0x84b7, 0x1188, + 0x080c, 0x2692, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x7776, + 0xa186, 0x007e, 0x1128, 0x2001, 0x9232, 0x200c, 0xc185, 0x2102, + 0x08d0, 0x080c, 0x84c8, 0x1118, 0x080c, 0x7776, 0x08a0, 0x6004, + 0xa08e, 0x0032, 0x1158, 0x00e6, 0x00f6, 0x2071, 0x9296, 0x2079, + 0x0000, 0x080c, 0x2924, 0x00fe, 0x00ee, 0x0828, 0x6004, 0xa08e, + 0x0021, 0x0d50, 0xa08e, 0x0022, 0x090c, 0x7790, 0x0804, 0x76ab, + 0x2008, 0x0002, 0x7732, 0x7733, 0x7736, 0x7739, 0x773c, 0x773f, + 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, + 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, + 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, + 0x7742, 0x7747, 0x7730, 0x7750, 0x7747, 0x7730, 0x7730, 0x7730, + 0x7730, 0x7730, 0x7747, 0x7747, 0x7730, 0x7730, 0x7730, 0x7730, + 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, + 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7747, + 0x080c, 0x13fe, 0x00a0, 0x2001, 0x000b, 0x0418, 0x2001, 0x0003, + 0x0400, 0x2001, 0x0005, 0x00e8, 0x2001, 0x0001, 0x00d0, 0x2001, + 0x0009, 0x00b8, 0x080c, 0x13fe, 0x0098, 0x080c, 0x43e3, 0x080c, + 0x6389, 0x6003, 0x0002, 0x6017, 0x0028, 0x080c, 0x6462, 0x0040, + 0x080c, 0x6389, 0x6003, 0x0004, 0x6017, 0x0028, 0x080c, 0x6462, + 0x0005, 0x080c, 0x43e3, 0x080c, 0x6389, 0x6003, 0x0002, 0x0036, + 0x2019, 0x925c, 0x2304, 0xa084, 0xff00, 0x1118, 0x2019, 0x0028, + 0x0040, 0x8007, 0xa09a, 0x0004, 0x0ec8, 0x8003, 0x801b, 0x831b, + 0xa318, 0x6316, 0x003e, 0x080c, 0x6462, 0x0c10, 0x00e6, 0x080c, + 0x82ee, 0x0188, 0x6010, 0x2070, 0x7007, 0x0000, 0x0016, 0x6004, + 0xa08e, 0x0021, 0x0150, 0xa08e, 0x003d, 0x0138, 0x001e, 0x7037, + 0x0103, 0x7033, 0x0100, 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cd8, + 0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, + 0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6, 0x6618, 0x2668, 0x6804, + 0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c, 0x1a0c, 0x13fe, 0x6604, + 0xa6b6, 0x0028, 0x1118, 0x080c, 0x84f2, 0x0468, 0x6604, 0xa6b6, + 0x0029, 0x1118, 0x080c, 0x8509, 0x0430, 0x6604, 0xa6b6, 0x001f, + 0x1118, 0x080c, 0x757e, 0x00f8, 0x6604, 0xa6b6, 0x0000, 0x1118, + 0x080c, 0x75e0, 0x00c0, 0x6604, 0xa6b6, 0x0022, 0x1118, 0x080c, + 0x75a6, 0x0088, 0x6604, 0xa6b6, 0x003d, 0x1118, 0x080c, 0x75c0, + 0x0050, 0xa1b6, 0x0015, 0x1110, 0x0053, 0x0028, 0xa1b6, 0x0016, + 0x1118, 0x0804, 0x7983, 0x0005, 0x080c, 0x7526, 0x0ce0, 0x7805, + 0x7808, 0x7805, 0x7844, 0x7805, 0x7923, 0x7805, 0x7805, 0x7805, + 0x795b, 0x7805, 0x7971, 0xa1b6, 0x0048, 0x0140, 0x20e1, 0x0005, + 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x16c6, 0x0005, 0x00e6, 0xacf0, + 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, + 0x74f2, 0x0005, 0x080c, 0x74f2, 0x0005, 0xe000, 0xe000, 0x0005, + 0x00e6, 0x2071, 0x9200, 0x7080, 0xa086, 0x0074, 0x11f0, 0x080c, + 0x8ebb, 0x1170, 0x00d6, 0x6018, 0x2068, 0x00e9, 0x00de, 0x2001, + 0x0006, 0x080c, 0x43e3, 0x080c, 0x2692, 0x080c, 0x74f2, 0x0088, + 0x2001, 0x000a, 0x080c, 0x43e3, 0x080c, 0x2692, 0x6003, 0x0001, + 0x6007, 0x0001, 0x080c, 0x603e, 0x0020, 0x2001, 0x0001, 0x080c, + 0x7910, 0x00ee, 0x0005, 0x6800, 0xd084, 0x0168, 0x2001, 0x0000, + 0x080c, 0x43d1, 0x2069, 0x9251, 0x6804, 0xd0a4, 0x0120, 0x2001, + 0x0006, 0x080c, 0x43f1, 0x0005, 0x00d6, 0x2011, 0x9220, 0x2204, + 0xa086, 0x0074, 0x1904, 0x790b, 0x080c, 0x7a64, 0x6018, 0x2068, + 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x0198, 0xa286, 0x0080, + 0x1904, 0x789c, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005, + 0x0588, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833, 0x0200, + 0x0448, 0x00d6, 0x00e6, 0x00f6, 0x6813, 0x00ff, 0x6817, 0xfffe, + 0x2071, 0x9232, 0x2e04, 0xa085, 0x0003, 0x2072, 0x2071, 0x9780, + 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0x921b, 0x206a, + 0x78e6, 0x8e70, 0x2e04, 0x2069, 0x921c, 0x206a, 0x78ea, 0x7832, + 0x7836, 0xa084, 0x00ff, 0x2008, 0x080c, 0x2435, 0x00fe, 0x00ee, + 0x00de, 0x00f8, 0x2001, 0x0006, 0x080c, 0x43e3, 0x080c, 0x2692, + 0x080c, 0x74f2, 0x0804, 0x790e, 0x6010, 0xa005, 0x0130, 0x2068, + 0x6838, 0xd0f4, 0x0110, 0x0804, 0x7862, 0x2001, 0x0004, 0x080c, + 0x43e3, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x603e, 0x0804, + 0x790e, 0x685c, 0xd0e4, 0x01c8, 0x080c, 0x8531, 0x080c, 0x4dc5, + 0x0110, 0xd0dc, 0x19b8, 0x2011, 0x9232, 0x2204, 0xc0ad, 0x2012, + 0x2001, 0x94c8, 0x2004, 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, + 0x080c, 0x2460, 0x78e2, 0x00fe, 0x0828, 0x080c, 0x854a, 0x2011, + 0x9232, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0x8fa4, 0x000e, + 0x1904, 0x7892, 0xc0b5, 0x2012, 0x2001, 0x0000, 0x080c, 0x43d1, + 0x00c6, 0x2009, 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932, + 0x7936, 0x00fe, 0x080c, 0x2435, 0x2001, 0x9214, 0x2004, 0x2009, + 0x0000, 0x080c, 0x240b, 0x2001, 0x9213, 0x2102, 0x8108, 0x080c, + 0x4400, 0x2c00, 0x00ce, 0x1904, 0x7892, 0x601a, 0x2001, 0x0002, + 0x080c, 0x43e3, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, + 0x080c, 0x603e, 0x0018, 0x2001, 0x0001, 0x0011, 0x00de, 0x0005, + 0x0006, 0x2001, 0x9200, 0x2004, 0xa086, 0x0003, 0x000e, 0x0130, + 0xa005, 0x0120, 0x2001, 0x0007, 0x080c, 0x43e3, 0x080c, 0x2692, + 0x080c, 0x74f2, 0x0005, 0x00e6, 0x2071, 0x9200, 0x7080, 0xa086, + 0x0014, 0x1548, 0x7000, 0xa086, 0x0003, 0x1128, 0x6010, 0xa005, + 0x1110, 0x080c, 0x370a, 0x00d6, 0x6018, 0x2068, 0x080c, 0x44c7, + 0x080c, 0x7833, 0x00de, 0x080c, 0x7a6e, 0x11a8, 0x2001, 0x0006, + 0x080c, 0x43e3, 0x00e6, 0x6010, 0xa005, 0x0138, 0x2070, 0x7007, + 0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, 0x2692, + 0x080c, 0x74f2, 0x0030, 0x080c, 0x7776, 0x2001, 0x0000, 0x080c, + 0x7910, 0x00ee, 0x0005, 0x2011, 0x9220, 0x2204, 0xa086, 0x0014, + 0x1158, 0x2001, 0x0002, 0x080c, 0x43e3, 0x6003, 0x0001, 0x6007, + 0x0001, 0x080c, 0x603e, 0x0020, 0x2001, 0x0001, 0x080c, 0x7910, + 0x0005, 0x2011, 0x9220, 0x2204, 0xa086, 0x0004, 0x1138, 0x2001, + 0x0007, 0x080c, 0x43e3, 0x080c, 0x74f2, 0x0020, 0x2001, 0x0001, + 0x080c, 0x7910, 0x0005, 0x000b, 0x0005, 0x7805, 0x7991, 0x7805, + 0x79b5, 0x7805, 0x7a1a, 0x7805, 0x7802, 0x7805, 0x7a2f, 0x7805, + 0x7a41, 0x00c6, 0x080c, 0x7a53, 0x1178, 0x2001, 0x0000, 0x080c, + 0x43d1, 0x2001, 0x0002, 0x080c, 0x43e3, 0x6003, 0x0001, 0x6007, + 0x0002, 0x080c, 0x603e, 0x0078, 0x2009, 0x978f, 0x2104, 0xa084, + 0xff00, 0xa086, 0x1900, 0x1118, 0x080c, 0x74f2, 0x0020, 0x2001, + 0x0001, 0x080c, 0x7910, 0x00ce, 0x0005, 0x080c, 0x7a61, 0x00d6, + 0x2069, 0x94d7, 0x2d04, 0xa005, 0x0168, 0x6018, 0x2068, 0x68a0, + 0xa086, 0x007e, 0x1138, 0x2069, 0x921c, 0x2d04, 0x8000, 0x206a, + 0x00de, 0x0010, 0x00de, 0x0078, 0x2001, 0x0000, 0x080c, 0x43d1, + 0x2001, 0x0002, 0x080c, 0x43e3, 0x6003, 0x0001, 0x6007, 0x0002, + 0x080c, 0x603e, 0x0400, 0x080c, 0x7776, 0x2009, 0x978e, 0x2134, + 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x01b8, 0x2009, 0x978f, 0x2104, + 0xa084, 0xff00, 0xa086, 0x1900, 0x1150, 0xa686, 0x0009, 0x0160, + 0x2001, 0x0004, 0x080c, 0x43e3, 0x080c, 0x74f2, 0x0020, 0x2001, + 0x0001, 0x080c, 0x7910, 0x0005, 0x00d6, 0x6010, 0x2068, 0x080c, + 0x82ee, 0x0128, 0x6838, 0xd0fc, 0x0110, 0x00de, 0x0c80, 0x6018, + 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0140, 0x8001, 0x6842, + 0x6017, 0x000a, 0x6007, 0x0016, 0x00de, 0x0c28, 0x080c, 0x266c, + 0x00de, 0x08e8, 0x080c, 0x7a61, 0x1158, 0x2001, 0x0004, 0x080c, + 0x43e3, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x603e, 0x0030, + 0x080c, 0x7776, 0x2001, 0x0000, 0x080c, 0x7910, 0x0005, 0x0489, + 0x1158, 0x2001, 0x0008, 0x080c, 0x43e3, 0x6003, 0x0001, 0x6007, + 0x0005, 0x080c, 0x603e, 0x0020, 0x2001, 0x0001, 0x080c, 0x7910, + 0x0005, 0x00f9, 0x1158, 0x2001, 0x000a, 0x080c, 0x43e3, 0x6003, + 0x0001, 0x6007, 0x0001, 0x080c, 0x603e, 0x0020, 0x2001, 0x0001, + 0x080c, 0x7910, 0x0005, 0x2009, 0x978e, 0x2104, 0xa086, 0x0003, + 0x1138, 0x2009, 0x978f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, + 0x0005, 0xa085, 0x0001, 0x0005, 0x00c6, 0x0016, 0xac88, 0x0006, + 0x2164, 0x080c, 0x4443, 0x001e, 0x00ce, 0x0005, 0x00e6, 0x2071, + 0x978c, 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, + 0x94ee, 0x252c, 0x2021, 0x94f4, 0x2424, 0x2061, 0x9900, 0x2071, + 0x9200, 0x7244, 0x7064, 0xa202, 0x1688, 0x080c, 0x90ee, 0x0540, + 0x671c, 0xa786, 0x0001, 0x0520, 0xa786, 0x0007, 0x0508, 0x2500, + 0xac06, 0x01f0, 0x2400, 0xac06, 0x01d8, 0x00c6, 0x6000, 0xa086, + 0x0004, 0x1110, 0x080c, 0x1788, 0x6010, 0x2068, 0x080c, 0x82ee, + 0x0160, 0xa786, 0x0003, 0x11e0, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x080c, 0x4809, 0x080c, 0x848f, 0x080c, 0x849b, 0x00ce, + 0xace0, 0x000c, 0x7058, 0xac02, 0x1208, 0x0858, 0x012e, 0x000e, + 0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x0005, + 0xa786, 0x0006, 0x1118, 0x080c, 0x9097, 0x0c38, 0xa786, 0x0009, + 0x19d8, 0x2009, 0x0106, 0x080c, 0x7518, 0x0c08, 0x220c, 0x2304, + 0xa106, 0x1130, 0x8210, 0x8318, 0x1f04, 0x7aee, 0xa006, 0x0005, + 0x2304, 0xa102, 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, + 0xa18d, 0x0001, 0x0005, 0x6004, 0xa08a, 0x003e, 0x1a0c, 0x13fe, + 0x080c, 0x84b7, 0x0120, 0x080c, 0x84c8, 0x0150, 0x0010, 0x080c, + 0x2692, 0x080c, 0x6389, 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005, + 0x080c, 0x7776, 0x0cb0, 0xa182, 0x0040, 0x0002, 0x7b31, 0x7b31, + 0x7b31, 0x7b31, 0x7b31, 0x7b31, 0x7b31, 0x7b31, 0x7b31, 0x7b31, + 0x7b31, 0x7b33, 0x7b33, 0x7b33, 0x7b33, 0x7b31, 0x7b31, 0x7b31, + 0x7b33, 0x080c, 0x13fe, 0x6003, 0x0001, 0x6106, 0x080c, 0x5ff8, + 0x0126, 0x2091, 0x8000, 0x080c, 0x6462, 0x012e, 0x0005, 0xa186, + 0x0013, 0x1128, 0x6004, 0xa082, 0x0040, 0x0804, 0x7bc5, 0xa186, + 0x0027, 0x11d0, 0x080c, 0x6389, 0x080c, 0x266c, 0x00d6, 0x6110, + 0x2168, 0x080c, 0x82ee, 0x0150, 0x6837, 0x0103, 0x684b, 0x0029, + 0x6847, 0x0000, 0x080c, 0x4809, 0x080c, 0x848f, 0x00de, 0x080c, + 0x74f2, 0x080c, 0x6462, 0x0005, 0xa186, 0x0014, 0x1120, 0x6004, + 0xa082, 0x0040, 0x0428, 0xa186, 0x0046, 0x0138, 0xa186, 0x0045, + 0x0120, 0xa186, 0x0047, 0x190c, 0x13fe, 0x2001, 0x0109, 0x2004, + 0xd084, 0x0198, 0x0126, 0x2091, 0x2400, 0x0006, 0x0016, 0x0026, + 0x080c, 0x5ee3, 0x002e, 0x001e, 0x000e, 0x012e, 0xe000, 0x6000, + 0xa086, 0x0002, 0x1110, 0x0804, 0x7bf0, 0x080c, 0x7526, 0x0005, + 0x0002, 0x7ba6, 0x7ba4, 0x7ba4, 0x7ba4, 0x7ba4, 0x7ba4, 0x7ba4, + 0x7ba4, 0x7ba4, 0x7ba4, 0x7ba4, 0x7bbe, 0x7bbe, 0x7bbe, 0x7bbe, + 0x7ba4, 0x7ba4, 0x7ba4, 0x7bbe, 0x080c, 0x13fe, 0x080c, 0x6389, + 0x00d6, 0x6110, 0x2168, 0x080c, 0x82ee, 0x0150, 0x6837, 0x0103, + 0x684b, 0x0006, 0x6847, 0x0000, 0x080c, 0x4809, 0x080c, 0x848f, + 0x00de, 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005, 0x080c, 0x6389, + 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005, 0x0002, 0x7bdb, 0x7bd9, + 0x7bd9, 0x7bd9, 0x7bd9, 0x7bd9, 0x7bd9, 0x7bd9, 0x7bd9, 0x7bd9, + 0x7bd9, 0x7be9, 0x7be9, 0x7be9, 0x7be9, 0x7bd9, 0x7bd9, 0x7bd9, + 0x7be9, 0x080c, 0x13fe, 0x080c, 0x6389, 0x6003, 0x0002, 0x080c, + 0x6462, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, + 0x0005, 0x080c, 0x6389, 0x6003, 0x000f, 0x080c, 0x6462, 0x0005, + 0xa182, 0x0040, 0x0002, 0x7c06, 0x7c06, 0x7c06, 0x7c06, 0x7c06, + 0x7c08, 0x7c8a, 0x7ca9, 0x7c06, 0x7c06, 0x7c06, 0x7c06, 0x7c06, + 0x7c06, 0x7c06, 0x7c06, 0x7c06, 0x7c06, 0x7c06, 0x080c, 0x13fe, + 0x00e6, 0x00d6, 0x2071, 0x978c, 0x6110, 0x2168, 0x7614, 0xa6b4, + 0x0fff, 0x86ff, 0x0904, 0x7c70, 0xa68c, 0x0c00, 0x0120, 0x7318, + 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0190, + 0xa186, 0x0028, 0x1128, 0x080c, 0x84a6, 0x684b, 0x001c, 0x0060, + 0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, + 0x0007, 0x0010, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0xa01e, + 0xd6c4, 0x01b0, 0xa686, 0x0100, 0x1138, 0x2001, 0x9799, 0x2004, + 0xa005, 0x1110, 0xc6c4, 0x0868, 0x7328, 0x732c, 0x6b56, 0x0036, + 0x2308, 0x2019, 0x9798, 0xad90, 0x0019, 0x080c, 0x80e6, 0x003e, + 0xd6cc, 0x0560, 0x7124, 0x695a, 0xa192, 0x0021, 0x1250, 0x2071, + 0x9798, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x80e6, + 0x00e8, 0x6838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78, + 0x00f6, 0x2d78, 0x080c, 0x808b, 0x00fe, 0x080c, 0x80d6, 0x0080, + 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0130, + 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x7de6, 0x080c, 0x4809, + 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x00de, 0x00ee, 0x080c, + 0x74f2, 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0x978c, 0x7c04, + 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x784c, 0xd0ac, 0x0120, + 0x6003, 0x0002, 0x00fe, 0x0005, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, + 0x00fe, 0x2c10, 0x080c, 0x1c88, 0x080c, 0x605b, 0x080c, 0x651c, + 0x0005, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, + 0x2c10, 0x080c, 0x16c6, 0x0005, 0xa182, 0x0040, 0x0002, 0x7cca, + 0x7cca, 0x7cca, 0x7cca, 0x7cca, 0x7ccc, 0x7d54, 0x7cca, 0x7cca, + 0x7d6a, 0x7dc1, 0x7cca, 0x7cca, 0x7cca, 0x7cca, 0x7dcc, 0x7cca, + 0x7cca, 0x7cca, 0x080c, 0x13fe, 0x0076, 0x00f6, 0x00e6, 0x00d6, + 0x2071, 0x978c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46, + 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, + 0x86ff, 0x0904, 0x7d4f, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0120, + 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0904, 0x7d4f, + 0x080c, 0x147c, 0x090c, 0x13fe, 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, 0x0160, + 0x7328, 0x732c, 0x6b56, 0x0036, 0x2308, 0x2019, 0x9798, 0xad90, + 0x0019, 0x080c, 0x80e6, 0x003e, 0xd6cc, 0x01c8, 0x7124, 0x695a, + 0xa192, 0x0021, 0x1250, 0x2071, 0x9798, 0x831c, 0x2300, 0xae18, + 0xad90, 0x001d, 0x080c, 0x80e6, 0x0050, 0x7838, 0xd0fc, 0x0120, + 0x2009, 0x0020, 0x695a, 0x0c78, 0x2d78, 0x080c, 0x808b, 0x00de, + 0x00ee, 0x00fe, 0x007e, 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, + 0x978c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, + 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x2c10, 0x080c, 0x1c88, 0x080c, + 0x6f04, 0x0005, 0x00d6, 0x6003, 0x0002, 0x080c, 0x641b, 0x080c, + 0x651c, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904, 0x7dbf, 0xd1cc, + 0x0540, 0x6948, 0x6838, 0xd0fc, 0x01e8, 0x0016, 0x684c, 0x0006, + 0x6850, 0x0006, 0xad90, 0x000d, 0xa198, 0x000d, 0x2009, 0x0023, + 0x0156, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0x7d8a, + 0x015e, 0x000e, 0x6852, 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, + 0x14a3, 0x0418, 0x0016, 0x080c, 0x14a3, 0x00de, 0x080c, 0x80d6, + 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, 0x4809, 0x080c, 0x74f2, 0x00de, + 0x0005, 0x2019, 0x0001, 0x080c, 0x7110, 0x6003, 0x0002, 0x080c, + 0x641b, 0x080c, 0x651c, 0x0005, 0x080c, 0x641b, 0x080c, 0x266c, + 0x00d6, 0x6110, 0x2168, 0x080c, 0x82ee, 0x0150, 0x6837, 0x0103, + 0x684b, 0x0029, 0x6847, 0x0000, 0x080c, 0x4809, 0x080c, 0x848f, + 0x00de, 0x080c, 0x74f2, 0x080c, 0x651c, 0x0005, 0x684b, 0x0015, + 0xd1fc, 0x0138, 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, + 0x0000, 0x6962, 0x685e, 0x0005, 0xa182, 0x0040, 0x0002, 0x7e0a, + 0x7e0a, 0x7e0a, 0x7e0a, 0x7e0a, 0x7e0c, 0x7e0a, 0x7eac, 0x7eb4, + 0x7e0a, 0x7e0a, 0x7e0a, 0x7e0a, 0x7e0a, 0x7e0a, 0x7e0a, 0x7e0a, + 0x7e0a, 0x7e0a, 0x080c, 0x13fe, 0x0076, 0x00f6, 0x00e6, 0x00d6, + 0x2071, 0x978c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46, + 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, + 0x86ff, 0x0904, 0x7e9d, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0120, + 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0904, 0x7e9b, + 0xa686, 0x0100, 0x1140, 0x2001, 0x9799, 0x2004, 0xa005, 0x1118, + 0xc6c4, 0x7e46, 0x0c28, 0x080c, 0x147c, 0x090c, 0x13fe, 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, 0x0160, 0x7328, 0x732c, 0x6b56, 0x0036, + 0x2308, 0x2019, 0x9798, 0xad90, 0x0019, 0x080c, 0x80e6, 0x003e, + 0xd6cc, 0x01c8, 0x7124, 0x695a, 0xa192, 0x0021, 0x1250, 0x2071, + 0x9798, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x80e6, + 0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78, + 0x2d78, 0x080c, 0x808b, 0xd6dc, 0x1110, 0xa006, 0x0030, 0x2001, + 0x0001, 0x2071, 0x978c, 0x7218, 0x731c, 0x080c, 0x1700, 0x00de, + 0x00ee, 0x00fe, 0x007e, 0x0005, 0x20e1, 0x0005, 0x3d18, 0x3e20, + 0x2c10, 0x080c, 0x16c6, 0x0005, 0x00d6, 0x6003, 0x0002, 0x6110, + 0x2168, 0x694c, 0xd1e4, 0x0904, 0x7f3e, 0xd1cc, 0x0904, 0x7f17, + 0x6948, 0x6838, 0xd0fc, 0x0590, 0x0016, 0x684c, 0x0006, 0x6850, + 0x0006, 0x684c, 0xd0ac, 0x0180, 0x6810, 0x6914, 0xa115, 0x0160, + 0x080c, 0x7de6, 0x00f6, 0x6948, 0x2178, 0x6848, 0x784a, 0x6860, + 0x7862, 0x685c, 0x785e, 0x00fe, 0x6948, 0xad90, 0x000d, 0xa198, + 0x000d, 0x2009, 0x0023, 0x0156, 0x21a8, 0x2304, 0x2012, 0x8318, + 0x8210, 0x1f04, 0x7ee5, 0x015e, 0x000e, 0x6852, 0x000e, 0x684e, + 0x001e, 0x2168, 0x080c, 0x14a3, 0x0804, 0x7f3c, 0x0016, 0x684c, + 0xd0ac, 0x0190, 0x6810, 0x6914, 0xa115, 0x0170, 0x080c, 0x7de6, + 0x00f6, 0x6948, 0x2178, 0x6848, 0x784a, 0x6860, 0x7862, 0x685c, + 0x785e, 0x684c, 0x784e, 0x00fe, 0x6948, 0xa188, 0x0013, 0x684c, + 0x200a, 0x080c, 0x14a3, 0x00de, 0x080c, 0x80d6, 0x0428, 0x6837, + 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0180, 0xa086, + 0x0028, 0x1118, 0x684b, 0x001c, 0x00a8, 0xd1dc, 0x0118, 0x684b, + 0x0015, 0x0080, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0058, 0x684b, + 0x0000, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, + 0x080c, 0x7de6, 0x080c, 0x4809, 0x080c, 0x74f2, 0x00de, 0x0005, + 0x080c, 0x6389, 0x0010, 0x080c, 0x641b, 0x080c, 0x82ee, 0x0198, + 0x00d6, 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0x920c, 0x210c, + 0xd18c, 0x1188, 0xd184, 0x1160, 0x6108, 0x694a, 0x6847, 0x0000, + 0x080c, 0x4809, 0x00de, 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005, + 0x684b, 0x0004, 0x0c98, 0x684b, 0x0004, 0x0c80, 0xa182, 0x0040, + 0x0002, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7e, 0x7f7c, + 0x7f81, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, + 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, 0x080c, 0x13fe, 0x080c, 0x74f2, + 0x0005, 0x0006, 0x0026, 0xa016, 0x080c, 0x16c6, 0x002e, 0x000e, + 0x0005, 0xa182, 0x0085, 0x0002, 0x7f95, 0x7f93, 0x7f93, 0x7f93, + 0x7f93, 0x7f93, 0x7f93, 0x080c, 0x13fe, 0x6003, 0x000b, 0x6106, + 0x080c, 0x5ff8, 0x0126, 0x2091, 0x8000, 0x080c, 0x6462, 0x012e, + 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085, 0x0a0c, + 0x13fe, 0xa08a, 0x008c, 0x1a0c, 0x13fe, 0xa082, 0x0085, 0x0072, + 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, 0x13fe, 0x080c, + 0x6389, 0x080c, 0x849b, 0x080c, 0x6462, 0x0005, 0x7fc5, 0x7fc7, + 0x7fc7, 0x7fc5, 0x7fc5, 0x7fc5, 0x7fc5, 0x080c, 0x13fe, 0x080c, + 0x6389, 0x080c, 0x849b, 0x080c, 0x6462, 0x0005, 0xa186, 0x0013, + 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x0492, 0xa186, 0x0027, + 0x11e8, 0x080c, 0x6389, 0x080c, 0x266c, 0x00d6, 0x6010, 0x2068, + 0x080c, 0x82ee, 0x0150, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, + 0x0029, 0x080c, 0x4809, 0x080c, 0x848f, 0x00de, 0x080c, 0x74f2, + 0x080c, 0x6462, 0x0005, 0x080c, 0x7526, 0x0ce0, 0xa186, 0x0014, + 0x1dd0, 0x080c, 0x6389, 0x00d6, 0x6010, 0x2068, 0x080c, 0x82ee, + 0x0d60, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, 0x0006, 0x0c08, + 0x8011, 0x800f, 0x800f, 0x800f, 0x800f, 0x800f, 0x801a, 0x080c, + 0x13fe, 0x080c, 0x6389, 0x6017, 0x0014, 0x6003, 0x000c, 0x080c, + 0x6462, 0x0005, 0x080c, 0x6389, 0x6017, 0x0014, 0x6003, 0x000e, + 0x080c, 0x6462, 0x0005, 0xa182, 0x008c, 0x1220, 0xa182, 0x0085, + 0x0208, 0x001a, 0x080c, 0x7526, 0x0005, 0x8034, 0x8034, 0x8034, + 0x8034, 0x8036, 0x8057, 0x8034, 0x080c, 0x13fe, 0x00d6, 0x080c, + 0x848f, 0x080c, 0x82ee, 0x01b8, 0x6010, 0x2068, 0x6837, 0x0103, + 0x6850, 0xd0b4, 0x0118, 0x684b, 0x0006, 0x0048, 0xd0bc, 0x0118, + 0x684b, 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x852d, 0x6847, + 0x0000, 0x080c, 0x4809, 0x080c, 0x74f2, 0x00de, 0x0005, 0x00d6, + 0x6010, 0x2068, 0x080c, 0x82ee, 0x01b8, 0x6837, 0x0103, 0x6850, + 0xd0b4, 0x0118, 0x684b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0x684b, + 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x852d, 0x6847, 0x0000, + 0x080c, 0x4809, 0x080c, 0x848f, 0x00de, 0x080c, 0x74f2, 0x0005, + 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186, 0x0027, + 0x0118, 0x080c, 0x7526, 0x0030, 0x080c, 0x6389, 0x080c, 0x849b, + 0x080c, 0x6462, 0x0005, 0x0056, 0x0066, 0x00d6, 0x00f6, 0x2029, + 0x0001, 0xa182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, 0x2130, + 0x2069, 0x9798, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90, + 0x001d, 0x080c, 0x80e6, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0110, + 0x080c, 0x14a3, 0x080c, 0x147c, 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, 0x4809, + 0x2f68, 0x0cb8, 0x080c, 0x4809, 0x00fe, 0x0005, 0x0156, 0xa184, + 0x0001, 0x0108, 0x8108, 0x810c, 0x21a8, 0x2304, 0x8007, 0x2012, + 0x8318, 0x8210, 0x1f04, 0x80ed, 0x015e, 0x0005, 0x0126, 0x2091, + 0x8000, 0x601c, 0xa084, 0x000f, 0x0013, 0x012e, 0x0005, 0x8117, + 0x8109, 0x8112, 0x812e, 0x8109, 0x8112, 0x810b, 0x8112, 0x8109, + 0x5e80, 0x080c, 0x13fe, 0x0036, 0x2019, 0x0010, 0x080c, 0x8d4e, + 0x003e, 0x0005, 0xa006, 0x0005, 0xa085, 0x0001, 0x0005, 0x00d6, + 0x6010, 0x2068, 0x080c, 0x82ee, 0x0178, 0xa00e, 0x2001, 0x0005, + 0x080c, 0x492c, 0x080c, 0x852d, 0x080c, 0x4809, 0x080c, 0x74f2, + 0xa085, 0x0001, 0x00de, 0x0005, 0xa006, 0x0ce0, 0x6000, 0xa08a, + 0x0010, 0x1a0c, 0x13fe, 0x000b, 0x0005, 0x8145, 0x8160, 0x8147, + 0x816f, 0x815d, 0x8145, 0x8112, 0x8117, 0x8117, 0x8112, 0x8112, + 0x8112, 0x8112, 0x8112, 0x8112, 0x8112, 0x080c, 0x13fe, 0x00d6, + 0x6010, 0x2068, 0x080c, 0x82ee, 0x0110, 0x080c, 0x852d, 0x00de, + 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x5ff8, + 0x080c, 0x6462, 0xa085, 0x0001, 0x0005, 0x080c, 0x1788, 0x0c38, + 0x00e6, 0x2071, 0x94e5, 0x7024, 0xac06, 0x1110, 0x080c, 0x708d, + 0x080c, 0x6fab, 0x00ee, 0x19d8, 0x080c, 0x8112, 0x0005, 0x0036, + 0x00e6, 0x2071, 0x94e5, 0x703c, 0xac06, 0x1138, 0x2019, 0x0000, + 0x080c, 0x7110, 0x00ee, 0x003e, 0x0850, 0x080c, 0x7366, 0x00ee, + 0x003e, 0x1928, 0x080c, 0x8112, 0x0005, 0x00c6, 0x601c, 0xa084, + 0x000f, 0x0013, 0x00ce, 0x0005, 0x819a, 0x81f7, 0x829a, 0x819e, + 0x819a, 0x819a, 0x8d44, 0x74f2, 0x81f7, 0x080c, 0x84c8, 0x1110, + 0x080c, 0x7776, 0x0005, 0x6017, 0x0001, 0x0005, 0x6000, 0xa08a, + 0x0010, 0x1a0c, 0x13fe, 0x000b, 0x0005, 0x81b5, 0x81b7, 0x81d5, + 0x81e7, 0x81f4, 0x81b5, 0x819a, 0x819a, 0x819a, 0x81e7, 0x81e7, + 0x81b5, 0x81b5, 0x81b5, 0x81b5, 0x81f1, 0x080c, 0x13fe, 0x00e6, + 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071, 0x94e5, 0x7024, + 0xac06, 0x0180, 0x080c, 0x6fab, 0x6007, 0x0085, 0x6003, 0x000b, + 0x601f, 0x0002, 0x6017, 0x0014, 0x080c, 0x5ff8, 0x080c, 0x6462, + 0x00ee, 0x0005, 0x6017, 0x0001, 0x0cd8, 0x00d6, 0x6010, 0x2068, + 0x6850, 0xc0b5, 0x6852, 0x00de, 0x6007, 0x0085, 0x6003, 0x000b, + 0x601f, 0x0002, 0x080c, 0x5ff8, 0x080c, 0x6462, 0x0005, 0x00d6, + 0x6017, 0x0001, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de, + 0x0005, 0x080c, 0x74f2, 0x0005, 0x080c, 0x1788, 0x08f0, 0x6000, + 0xa08a, 0x0010, 0x1a0c, 0x13fe, 0x000b, 0x0005, 0x820e, 0x819b, + 0x8210, 0x820e, 0x8210, 0x820e, 0x820e, 0x820e, 0x8195, 0x8195, + 0x820e, 0x820e, 0x820e, 0x820e, 0x820e, 0x820e, 0x080c, 0x13fe, + 0x00d6, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa08a, + 0x000c, 0x1a0c, 0x13fe, 0x000b, 0x0005, 0x8229, 0x824a, 0x8229, + 0x824a, 0x8229, 0x824a, 0x822b, 0x8232, 0x8229, 0x824a, 0x8229, + 0x8243, 0x080c, 0x13fe, 0x6004, 0xa08e, 0x0004, 0x01b0, 0xa08e, + 0x0002, 0x0198, 0x6004, 0x080c, 0x84c8, 0x0904, 0x8292, 0xa08e, + 0x0021, 0x0904, 0x8296, 0xa08e, 0x0022, 0x0904, 0x8292, 0xa08e, + 0x003d, 0x0904, 0x8296, 0x080c, 0x266c, 0x080c, 0x7776, 0x080c, + 0x74f2, 0x0005, 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x0598, + 0xa186, 0x0002, 0x11f8, 0x6018, 0x2068, 0x2001, 0x9232, 0x2004, + 0xd0ac, 0x11c0, 0x68a0, 0xd0bc, 0x11a8, 0x6840, 0xa084, 0x00ff, + 0xa005, 0x0180, 0x8001, 0x6842, 0x6013, 0x0000, 0x601f, 0x0007, + 0x6017, 0x0398, 0x080c, 0x749c, 0x0128, 0x2d00, 0x601a, 0x601f, + 0x0001, 0x0088, 0x00de, 0x00ce, 0x080c, 0x7776, 0x080c, 0x266c, + 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2692, 0x012e, 0x00ee, + 0x080c, 0x74f2, 0x0005, 0x2001, 0x0002, 0x080c, 0x43e3, 0x6003, + 0x0001, 0x6007, 0x0002, 0x080c, 0x603e, 0x080c, 0x6462, 0x00de, + 0x00ce, 0x0c80, 0x080c, 0x7776, 0x0804, 0x8247, 0x080c, 0x7790, + 0x0804, 0x8247, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x13fe, 0x000b, + 0x0005, 0x82b1, 0x82b1, 0x82b1, 0x82b1, 0x82b1, 0x82b1, 0x82b1, + 0x82b1, 0x82b1, 0x819a, 0x82b1, 0x819b, 0x82b3, 0x819b, 0x82bc, + 0x82b1, 0x080c, 0x13fe, 0x6007, 0x008b, 0x6003, 0x000d, 0x080c, + 0x5ff8, 0x080c, 0x6462, 0x0005, 0x080c, 0x848f, 0x0479, 0x01d8, + 0x080c, 0x266c, 0x00d6, 0x0451, 0x0150, 0x6010, 0x2068, 0x6837, + 0x0103, 0x684b, 0x0006, 0x6847, 0x0000, 0x080c, 0x4809, 0x00de, + 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x603e, + 0x080c, 0x6462, 0x0010, 0x080c, 0x74f2, 0x0005, 0xa284, 0x0003, + 0x1158, 0xa282, 0x9900, 0x0240, 0x2001, 0x9216, 0x2004, 0xa202, + 0x1218, 0xa085, 0x0001, 0x0005, 0xa006, 0x0ce8, 0x0026, 0x6210, + 0x82ff, 0x002e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, + 0x2091, 0x8000, 0x2061, 0x9900, 0x2071, 0x9200, 0x7344, 0x7064, + 0xa302, 0x1290, 0x601c, 0xa206, 0x1148, 0x080c, 0x84c8, 0x1110, + 0x080c, 0x7776, 0x00c6, 0x080c, 0x74f2, 0x00ce, 0xace0, 0x000c, + 0x7058, 0xac02, 0x1208, 0x0c50, 0x012e, 0x000e, 0x003e, 0x00ce, + 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0016, 0xa188, 0x936e, 0x210c, + 0x81ff, 0x0170, 0x2061, 0x9900, 0x2071, 0x9200, 0x0016, 0x080c, + 0x749c, 0x001e, 0x0138, 0x611a, 0x080c, 0x266c, 0x080c, 0x74f2, + 0xa006, 0x0010, 0xa085, 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, + 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x749c, + 0x005e, 0x0170, 0x6612, 0x651a, 0x601f, 0x0003, 0x2009, 0x004b, + 0x080c, 0x7518, 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, + 0xa006, 0x0cd0, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x62a0, + 0x00c6, 0x080c, 0x749c, 0x005e, 0x01f8, 0x6013, 0x0000, 0x651a, + 0x601f, 0x0003, 0x00c6, 0x2560, 0x080c, 0x460d, 0x00ce, 0x080c, + 0x6127, 0x0086, 0x2041, 0x0000, 0x080c, 0x606d, 0x2c08, 0x080c, + 0x8ee4, 0x008e, 0x2009, 0x004c, 0x080c, 0x7518, 0xa085, 0x0001, + 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00c6, 0x0056, + 0x0126, 0x2091, 0x8000, 0x62a0, 0x00c6, 0x080c, 0x749c, 0x005e, + 0x0500, 0x6612, 0x651a, 0x601f, 0x0003, 0x2019, 0x0005, 0x00c6, + 0x2560, 0x080c, 0x460d, 0x00ce, 0x080c, 0x6127, 0x0086, 0x2041, + 0x0000, 0x080c, 0x606d, 0x2c08, 0x080c, 0x8ee4, 0x008e, 0x2009, + 0x004d, 0x080c, 0x7518, 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, + 0x0005, 0xa006, 0x0cd0, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, + 0x62a0, 0x00c6, 0x080c, 0x749c, 0x005e, 0x0500, 0x6612, 0x651a, + 0x601f, 0x0003, 0x2019, 0x0005, 0x00c6, 0x2560, 0x080c, 0x460d, + 0x00ce, 0x080c, 0x6127, 0x0086, 0x2041, 0x0000, 0x080c, 0x606d, + 0x2c08, 0x080c, 0x8ee4, 0x008e, 0x2009, 0x004e, 0x080c, 0x7518, + 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0, + 0x00c6, 0x0096, 0x0086, 0x0056, 0x0126, 0x2091, 0x8000, 0x62a0, + 0x00c6, 0x080c, 0x749c, 0x005e, 0x0904, 0x8426, 0x6612, 0x651a, + 0x601f, 0x0003, 0x00c6, 0x2560, 0x080c, 0x45af, 0x0118, 0x2001, + 0x83ec, 0x0028, 0x080c, 0x4581, 0x0160, 0x2001, 0x83f2, 0x0006, + 0xa00e, 0x2001, 0x0004, 0x080c, 0x492c, 0x080c, 0x4809, 0x000e, + 0x0807, 0x2019, 0x0004, 0x080c, 0x632b, 0x0036, 0x003e, 0x00ce, + 0x2041, 0x0001, 0x2608, 0x080c, 0x6140, 0x080c, 0x606d, 0x2c08, + 0x2648, 0x080c, 0x8ee4, 0x6018, 0xa080, 0x000f, 0x200c, 0x81ff, + 0x090c, 0x61d3, 0x2009, 0x0052, 0x080c, 0x7518, 0xa085, 0x0001, + 0x012e, 0x005e, 0x008e, 0x009e, 0x00ce, 0x0005, 0xa006, 0x0cc0, + 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x749c, 0x001e, + 0x0178, 0x660a, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, + 0x001f, 0x080c, 0x7518, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, + 0x749c, 0x001e, 0x0178, 0x660a, 0x611a, 0x601f, 0x0008, 0x2d00, + 0x6012, 0x2009, 0x0021, 0x080c, 0x7518, 0xa085, 0x0001, 0x012e, + 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, + 0x00c6, 0x080c, 0x749c, 0x001e, 0x0178, 0x660a, 0x611a, 0x601f, + 0x0001, 0x2d00, 0x6012, 0x2009, 0x003d, 0x080c, 0x7518, 0xa085, + 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, + 0x2091, 0x8000, 0x00c6, 0x080c, 0x749c, 0x001e, 0x0170, 0x611a, + 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x080c, 0x7518, + 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x0026, + 0x00d6, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, + 0x00de, 0x002e, 0x0005, 0x0006, 0x6013, 0x0000, 0x601f, 0x0007, + 0x2001, 0x94dd, 0x2004, 0x6016, 0x000e, 0x0005, 0x0066, 0x00c6, + 0x00d6, 0x2031, 0x9252, 0x2634, 0xd6e4, 0x0128, 0x6618, 0x2660, + 0x6e48, 0x080c, 0x453a, 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, 0x0128, 0x6838, 0xd0fc, 0x0110, + 0xa006, 0x0010, 0xa085, 0x0001, 0x00de, 0x000e, 0x0005, 0x00c6, + 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x749c, 0x001e, 0x0180, + 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x080c, 0x266c, 0x2009, + 0x0028, 0x080c, 0x7518, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, + 0xa006, 0x0cd8, 0xa186, 0x0015, 0x1178, 0x2011, 0x9220, 0x2204, + 0xa086, 0x0074, 0x1148, 0x080c, 0x7a64, 0x6003, 0x0001, 0x6007, + 0x0029, 0x080c, 0x603e, 0x0020, 0x080c, 0x7776, 0x080c, 0x74f2, + 0x0005, 0xa186, 0x0015, 0x11b0, 0x2011, 0x9220, 0x2204, 0xa086, + 0x0014, 0x1180, 0x00d6, 0x6018, 0x2068, 0x080c, 0x44c7, 0x00de, + 0x080c, 0x7a6e, 0x1138, 0x2001, 0x0006, 0x080c, 0x43e3, 0x080c, + 0x7598, 0x0020, 0x080c, 0x7776, 0x080c, 0x74f2, 0x0005, 0x6848, + 0xa086, 0x0005, 0x1108, 0x0009, 0x0005, 0x6850, 0xc0ad, 0x6852, + 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x2001, 0x94d9, 0x200c, + 0x8000, 0x2014, 0x2001, 0x0064, 0x080c, 0x5eaf, 0x2001, 0x94dd, + 0x82ff, 0x1110, 0x2011, 0x0002, 0x2202, 0x003e, 0x002e, 0x001e, + 0x000e, 0x0005, 0x0006, 0x2001, 0x94dd, 0x2003, 0x0028, 0x2001, + 0x94de, 0x2003, 0x07d0, 0x000e, 0x0005, 0x0066, 0x6000, 0xa0b2, + 0x0010, 0x1a0c, 0x13fe, 0x0013, 0x006e, 0x0005, 0x856e, 0x881c, + 0x8907, 0x856e, 0x856e, 0x856e, 0x856e, 0x856e, 0x85a6, 0x8973, + 0x856e, 0x856e, 0x856e, 0x856e, 0x856e, 0x856e, 0x080c, 0x13fe, + 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x13fe, 0x0013, 0x006e, + 0x0005, 0x8589, 0x8ce9, 0x8589, 0x8589, 0x8589, 0x8589, 0x8589, + 0x8589, 0x8cad, 0x8d31, 0x8589, 0x9105, 0x9135, 0x9105, 0x9135, + 0x8589, 0x080c, 0x13fe, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, + 0x13fe, 0x0013, 0x006e, 0x0005, 0x85a4, 0x8ab9, 0x8b64, 0x8b88, + 0x8bd3, 0x85a4, 0x85a4, 0x8c44, 0x897f, 0x8c87, 0x8c9a, 0x85a4, + 0x85a4, 0x85a4, 0x85a4, 0x85a4, 0x080c, 0x13fe, 0xa1b2, 0x003e, + 0x1a0c, 0x13fe, 0x2100, 0x0002, 0x85df, 0x86f0, 0x85df, 0x85df, + 0x85df, 0x86f7, 0x85df, 0x85df, 0x85df, 0x85df, 0x85df, 0x85df, + 0x85df, 0x85df, 0x85df, 0x85df, 0x85df, 0x85df, 0x85df, 0x85df, + 0x85df, 0x85df, 0x85df, 0x85e1, 0x860b, 0x8616, 0x865a, 0x8674, + 0x86aa, 0x86dd, 0x85df, 0x85df, 0x86fa, 0x85df, 0x85df, 0x8709, + 0x8710, 0x85df, 0x85df, 0x85df, 0x85df, 0x85df, 0x87ab, 0x85df, + 0x85df, 0x87b5, 0x85df, 0x85df, 0x875d, 0x85df, 0x85df, 0x080c, + 0x13fe, 0x080c, 0x470e, 0x6618, 0x00c6, 0x2660, 0x080c, 0x4443, + 0x00ce, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, + 0x0278, 0x080c, 0x8e28, 0x1904, 0x8654, 0x080c, 0x8dd3, 0x1120, + 0x6007, 0x0008, 0x0804, 0x86eb, 0x6007, 0x0009, 0x0804, 0x86eb, + 0x080c, 0x8fa4, 0x0128, 0x080c, 0x8e28, 0x0d78, 0x0804, 0x8654, + 0x6013, 0x1900, 0x0c88, 0x6106, 0x080c, 0x8d83, 0x6007, 0x0006, + 0x0804, 0x86eb, 0x6007, 0x0007, 0x0804, 0x86eb, 0x080c, 0x9150, + 0x1904, 0x87c6, 0x00d6, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0006, 0x01a0, 0xa686, 0x0004, 0x0188, 0x080c, + 0x4dc5, 0x1160, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0140, + 0xa686, 0x0004, 0x0128, 0xa686, 0x0005, 0x0110, 0x00de, 0x00e0, + 0x080c, 0x8e86, 0x11a0, 0xa686, 0x0006, 0x1150, 0x0026, 0x6218, + 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x26b1, 0x002e, + 0x080c, 0x44c7, 0x6007, 0x000a, 0x00de, 0x0804, 0x86eb, 0x6007, + 0x000b, 0x00de, 0x0804, 0x86eb, 0x080c, 0x266c, 0x6007, 0x0001, + 0x0804, 0x86eb, 0x080c, 0x9150, 0x1904, 0x87c6, 0x6618, 0x00d6, + 0x2668, 0x6e04, 0x00de, 0xa686, 0x0707, 0x0d70, 0x0026, 0x6218, + 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x26b1, 0x002e, + 0x6007, 0x000c, 0x0804, 0x86eb, 0x080c, 0x470e, 0x6618, 0xa6b0, + 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x02b0, 0xa6b4, + 0xff00, 0x8637, 0xa686, 0x0004, 0x0118, 0xa686, 0x0006, 0x1960, + 0x080c, 0x8e93, 0x1120, 0x6007, 0x000e, 0x0804, 0x86eb, 0x080c, + 0x266c, 0x6007, 0x000f, 0x0804, 0x86eb, 0x080c, 0x8fa4, 0x0160, + 0xa6b4, 0xff00, 0x8637, 0xa682, 0x0004, 0x0a04, 0x8654, 0xa682, + 0x0007, 0x0e30, 0x0804, 0x8654, 0x6013, 0x1900, 0x6007, 0x0009, + 0x0804, 0x86eb, 0x080c, 0x470e, 0x6618, 0xa6b0, 0x0001, 0x2634, + 0xa684, 0x00ff, 0xa082, 0x0006, 0x02c0, 0xa6b4, 0xff00, 0x8637, + 0xa686, 0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0x8654, 0x080c, + 0x8ebb, 0x1130, 0x080c, 0x8dd3, 0x1118, 0x6007, 0x0010, 0x0418, + 0x080c, 0x266c, 0x6007, 0x0011, 0x00f0, 0x080c, 0x8fa4, 0x0140, + 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0d48, 0x0804, 0x8654, + 0x6013, 0x1900, 0x6007, 0x0009, 0x0070, 0x7030, 0xa086, 0x6000, + 0x0140, 0x080c, 0x9150, 0x1904, 0x87c6, 0x080c, 0x87c9, 0x1904, + 0x8654, 0x6007, 0x0012, 0x6003, 0x0001, 0x080c, 0x603e, 0x0005, + 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x603e, 0x0cc0, 0x6007, + 0x0005, 0x0cc0, 0x080c, 0x9150, 0x1904, 0x87c6, 0x080c, 0x87c9, + 0x1904, 0x8654, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, 0x603e, + 0x0005, 0x6007, 0x0023, 0x6003, 0x0001, 0x080c, 0x603e, 0x0005, + 0x080c, 0x9150, 0x1904, 0x87c6, 0x080c, 0x87c9, 0x1904, 0x8654, + 0x0016, 0x0026, 0x2011, 0x9791, 0x2214, 0xa286, 0xffff, 0x0190, + 0x2c08, 0x080c, 0x82de, 0x01d8, 0x2260, 0x2011, 0x9790, 0x2214, + 0x6008, 0xa206, 0x11a0, 0x6018, 0xa190, 0x0006, 0x2214, 0xa206, + 0x01e0, 0x0068, 0x2011, 0x9790, 0x2214, 0x2c08, 0x080c, 0x90ab, + 0x11a0, 0x2011, 0x9791, 0x2214, 0xa286, 0xffff, 0x01a0, 0x2160, + 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0x9789, 0x2214, 0xa296, + 0xffff, 0x1160, 0x6007, 0x0025, 0x0048, 0x601c, 0xa086, 0x0007, + 0x1d70, 0x080c, 0x74f2, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, + 0x080c, 0x603e, 0x002e, 0x001e, 0x0005, 0x2001, 0x0001, 0x080c, + 0x43d1, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, + 0x9205, 0x2011, 0x9796, 0x080c, 0x7aee, 0x003e, 0x002e, 0x001e, + 0x015e, 0x0120, 0x6007, 0x0031, 0x0804, 0x86eb, 0x080c, 0x7910, + 0x080c, 0x4dc5, 0x1578, 0x0006, 0x0026, 0x0036, 0x2011, 0x9223, + 0x2204, 0x8000, 0x2012, 0xa084, 0x0007, 0x0190, 0x2001, 0x94d7, + 0x2003, 0xaaaa, 0x2001, 0x94d8, 0x2003, 0x0001, 0x2001, 0x9200, + 0x2003, 0x0001, 0x080c, 0x4d10, 0x003e, 0x002e, 0x000e, 0x0005, + 0x2001, 0x0001, 0x080c, 0x23ba, 0x080c, 0x4dd7, 0x1110, 0x080c, + 0x4d9a, 0x2011, 0x8036, 0x2019, 0x0005, 0x080c, 0x3698, 0x003e, + 0x002e, 0x000e, 0x0005, 0x6106, 0x0479, 0x6007, 0x002b, 0x0804, + 0x86eb, 0x6007, 0x002c, 0x0804, 0x86eb, 0x080c, 0x9150, 0x1170, + 0x0081, 0x1904, 0x8654, 0x6106, 0x0419, 0x1120, 0x6007, 0x002e, + 0x0804, 0x86eb, 0x6007, 0x002f, 0x0804, 0x86eb, 0x080c, 0x74f2, + 0x0005, 0x00d6, 0x0066, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0006, 0x0128, 0xa686, 0x0004, 0x0110, 0xa085, + 0x0001, 0x006e, 0x00de, 0x0005, 0x00d6, 0x0439, 0x00de, 0x0005, + 0x00d6, 0x0481, 0x11e0, 0x680c, 0xa08c, 0xff00, 0x6824, 0xa084, + 0x00ff, 0xa115, 0x6212, 0xd1e4, 0x0118, 0x2009, 0x0001, 0x0060, + 0xd1ec, 0x0168, 0x6920, 0xa18c, 0x00ff, 0x6824, 0x080c, 0x240b, + 0x1130, 0x2110, 0x2009, 0x0000, 0x080c, 0x26b1, 0x0018, 0xa085, + 0x0001, 0x0008, 0xa006, 0x00de, 0x0005, 0x2069, 0x978d, 0x6800, + 0xa082, 0x0010, 0x1228, 0x6013, 0x0000, 0xa085, 0x0001, 0x0008, + 0xa006, 0x0005, 0x6013, 0x0000, 0x2069, 0x978c, 0x6808, 0xa084, + 0xff00, 0xa086, 0x0800, 0x0005, 0x6004, 0xa0b2, 0x003e, 0x1a0c, + 0x13fe, 0xa1b6, 0x0013, 0x1110, 0x2008, 0x0092, 0xa1b6, 0x0027, + 0x0120, 0xa1b6, 0x0014, 0x190c, 0x13fe, 0x2001, 0x0007, 0x080c, + 0x43f1, 0x080c, 0x6389, 0x080c, 0x849b, 0x080c, 0x6462, 0x0005, + 0x8875, 0x8877, 0x8875, 0x8875, 0x8875, 0x8877, 0x8885, 0x88e7, + 0x88b2, 0x88e7, 0x88c3, 0x88e7, 0x8885, 0x88e7, 0x88df, 0x88e7, + 0x88df, 0x88e7, 0x88e7, 0x8875, 0x8875, 0x8875, 0x8875, 0x8875, + 0x8875, 0x8875, 0x8875, 0x8875, 0x8875, 0x8875, 0x8875, 0x8875, + 0x88e7, 0x8875, 0x8875, 0x88e7, 0x8875, 0x88e7, 0x88e7, 0x8875, + 0x8875, 0x8875, 0x8875, 0x88e7, 0x88e7, 0x8875, 0x88e7, 0x88e7, + 0x8875, 0x887f, 0x8875, 0x8875, 0x8875, 0x8875, 0x8875, 0x8875, + 0x8875, 0x8875, 0x8875, 0x8875, 0x8875, 0x080c, 0x13fe, 0x080c, + 0x6389, 0x6003, 0x0002, 0x080c, 0x6462, 0x0804, 0x88ed, 0x2001, + 0x0000, 0x080c, 0x43d1, 0x0804, 0x88e7, 0x00f6, 0x2079, 0x9251, + 0x7804, 0x00fe, 0xd0ac, 0x1904, 0x88e7, 0x2001, 0x0000, 0x080c, + 0x43d1, 0x6018, 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, 0x0904, + 0x88e7, 0x2001, 0x0002, 0x080c, 0x43e3, 0x080c, 0x6389, 0x601f, + 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x603e, 0x080c, + 0x6462, 0x00c6, 0x6118, 0x2160, 0x2009, 0x0001, 0x080c, 0x573d, + 0x00ce, 0x04d8, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4, + 0xff00, 0x8637, 0xa686, 0x0006, 0x0550, 0xa686, 0x0004, 0x0538, + 0x2001, 0x0004, 0x0410, 0x2001, 0x9200, 0x2004, 0xa086, 0x0003, + 0x1110, 0x080c, 0x370a, 0x2001, 0x0006, 0x0401, 0x6618, 0x00d6, + 0x2668, 0x6e04, 0x00de, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, + 0x0170, 0x2001, 0x0006, 0x0048, 0x2001, 0x0004, 0x0030, 0x2001, + 0x0006, 0x0061, 0x0020, 0x0018, 0x0010, 0x080c, 0x43f1, 0x080c, + 0x6389, 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005, 0x0016, 0x00d6, + 0x6118, 0x2168, 0x6900, 0xd184, 0x0178, 0x6104, 0xa18e, 0x000a, + 0x1128, 0x699c, 0xd1a4, 0x1110, 0x2001, 0x0007, 0x2001, 0x0000, + 0x080c, 0x43d1, 0x080c, 0x2692, 0x00de, 0x001e, 0x0005, 0x00d6, + 0x6618, 0x2668, 0x6804, 0xa084, 0xff00, 0x8007, 0x00de, 0xa0b2, + 0x000c, 0x1a0c, 0x13fe, 0xa1b6, 0x0015, 0x1110, 0x003b, 0x0028, + 0xa1b6, 0x0016, 0x190c, 0x13fe, 0x04eb, 0x0005, 0x7805, 0x7805, + 0x7805, 0x7805, 0x7805, 0x7805, 0x7805, 0x892a, 0x7805, 0x7805, + 0x7805, 0x7805, 0x00f6, 0x2079, 0x9251, 0x7804, 0x00fe, 0xd0ac, + 0x1198, 0x2001, 0x0000, 0x080c, 0x43d1, 0x2001, 0x0002, 0x080c, + 0x43e3, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, + 0x603e, 0x080c, 0x6462, 0x00a8, 0x2011, 0x9783, 0x2204, 0x8211, + 0x220c, 0x080c, 0x240b, 0x1168, 0x00c6, 0x080c, 0x4434, 0x0120, + 0x00ce, 0x080c, 0x74f2, 0x0028, 0x080c, 0x41e0, 0x00ce, 0x080c, + 0x74f2, 0x0005, 0x7805, 0x7805, 0x7805, 0x7805, 0x7805, 0x7805, + 0x7805, 0x8966, 0x7805, 0x7805, 0x7805, 0x7805, 0x080c, 0x7a61, + 0x1138, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x603e, 0x0010, + 0x080c, 0x74f2, 0x0005, 0x6004, 0xa08a, 0x003e, 0x1a0c, 0x13fe, + 0x080c, 0x6389, 0x080c, 0x849b, 0x080c, 0x6462, 0x0005, 0xa182, + 0x0040, 0x0002, 0x8995, 0x8995, 0x8995, 0x8995, 0x8997, 0x8995, + 0x8995, 0x8995, 0x8995, 0x8995, 0x8995, 0x8995, 0x8995, 0x8995, + 0x8995, 0x8995, 0x8995, 0x8995, 0x8995, 0x080c, 0x13fe, 0x00d6, + 0x00e6, 0x00f6, 0x0156, 0x0046, 0x0026, 0x6106, 0x2071, 0x9780, + 0x7444, 0xa4a4, 0xf600, 0x0904, 0x8a0d, 0xa486, 0x2000, 0x01f0, + 0xa486, 0x0400, 0x01d8, 0xa486, 0x1000, 0x0178, 0xa486, 0x4000, + 0x01d8, 0xa486, 0x0200, 0x0120, 0x080c, 0x74f2, 0x0804, 0x8a67, + 0x6118, 0x2104, 0xc0fd, 0x200a, 0x0078, 0x2069, 0x9566, 0x6a00, + 0xd284, 0x0904, 0x8a79, 0xc2cd, 0x6a02, 0x0030, 0x2009, 0x0001, + 0x2011, 0x0200, 0x080c, 0x585b, 0x080c, 0x147c, 0x090c, 0x13fe, + 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, 0x6857, 0x0036, 0x080c, 0x4809, 0x001e, 0xa486, + 0x2000, 0x1130, 0x2019, 0x0017, 0x080c, 0x9071, 0x0804, 0x8a67, + 0xa486, 0x0400, 0x1130, 0x2019, 0x0002, 0x080c, 0x9033, 0x0804, + 0x8a67, 0xa486, 0x0200, 0x1110, 0x080c, 0x9020, 0xa486, 0x1000, + 0x1110, 0x080c, 0x905e, 0x0804, 0x8a67, 0x2069, 0x9566, 0x6a00, + 0xd284, 0x0904, 0x8ab6, 0xa284, 0x0300, 0x1904, 0x8ab0, 0x6804, + 0xa005, 0x0904, 0x8aa1, 0x2d78, 0x6003, 0x0007, 0x6018, 0x2004, + 0xd0fc, 0x1904, 0x8ab0, 0x080c, 0x145f, 0x0904, 0x8a6e, 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, + 0x6853, 0x003d, 0x7244, 0xa294, 0x0003, 0xa286, 0x0002, 0x1118, + 0x684f, 0x0040, 0x0040, 0xa286, 0x0001, 0x1118, 0x684f, 0x0080, + 0x0010, 0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, 0x9790, 0xad90, + 0x0015, 0x200c, 0x810f, 0x2112, 0x8000, 0x8210, 0x1f04, 0x8a59, + 0x200c, 0x6982, 0x8000, 0x200c, 0x697e, 0x080c, 0x4809, 0x002e, + 0x004e, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x6013, 0x0100, + 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x5ff8, 0x080c, 0x6462, + 0x0c70, 0x2069, 0x9792, 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200, + 0x11a8, 0x2069, 0x9780, 0x686c, 0xa084, 0x00ff, 0x0016, 0x6110, + 0xa18c, 0x0700, 0xa10d, 0x6112, 0x001e, 0x6003, 0x0001, 0x6007, + 0x0043, 0x080c, 0x5ff8, 0x080c, 0x6462, 0x0888, 0x6013, 0x0200, + 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x5ff8, 0x080c, 0x6462, + 0x0830, 0x6013, 0x0300, 0x0010, 0x6013, 0x0100, 0x6003, 0x0001, + 0x6007, 0x0041, 0x080c, 0x5ff8, 0x080c, 0x6462, 0x0804, 0x8a67, + 0x6013, 0x0500, 0x0c98, 0x6013, 0x0600, 0x0818, 0x6013, 0x0200, + 0x0800, 0xa186, 0x0013, 0x1170, 0x6004, 0xa08a, 0x0040, 0x0a0c, + 0x13fe, 0xa08a, 0x0053, 0x1a0c, 0x13fe, 0xa082, 0x0040, 0x2008, + 0x0804, 0x8b24, 0xa186, 0x0047, 0x11b8, 0x2001, 0x0109, 0x2004, + 0xd084, 0x01f0, 0x0126, 0x2091, 0x2400, 0x0006, 0x0016, 0x0026, + 0x080c, 0x5ee3, 0x002e, 0x001e, 0x000e, 0x012e, 0x6000, 0xa086, + 0x0002, 0x1170, 0x0804, 0x8b64, 0xa186, 0x0027, 0x0120, 0xa186, + 0x0014, 0x190c, 0x13fe, 0x6004, 0xa082, 0x0040, 0x2008, 0x001a, + 0x080c, 0x7526, 0x0005, 0x8b06, 0x8b08, 0x8b08, 0x8b06, 0x8b06, + 0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x8b06, + 0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x080c, 0x13fe, + 0x080c, 0x6389, 0x080c, 0x6462, 0x0036, 0x00d6, 0x6010, 0xa06d, + 0x0180, 0xad84, 0xf000, 0x0168, 0x2019, 0x0004, 0x080c, 0x9097, + 0x6013, 0x0000, 0x6014, 0xa005, 0x1110, 0x6017, 0x0014, 0x6003, + 0x0007, 0x00de, 0x003e, 0x0005, 0x0002, 0x8b38, 0x8b55, 0x8b41, + 0x8b5e, 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38, + 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38, + 0x080c, 0x13fe, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, + 0x200a, 0x080c, 0x6389, 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4, + 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, 0x7518, 0x0010, + 0x6003, 0x0002, 0x080c, 0x6462, 0x0005, 0x080c, 0x6389, 0x080c, + 0x5836, 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005, 0x080c, 0x6389, + 0x2009, 0x0041, 0x0804, 0x8c44, 0xa182, 0x0040, 0x0002, 0x8b7a, + 0x8b7c, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7d, 0x8b7a, + 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, + 0x8b7a, 0x8b7a, 0x080c, 0x13fe, 0x0005, 0x6003, 0x0004, 0x6110, + 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x16c6, 0x0005, + 0xa182, 0x0040, 0x0002, 0x8b9e, 0x8b9e, 0x8b9e, 0x8b9e, 0x8b9e, + 0x8b9e, 0x8b9e, 0x8b9e, 0x8b9e, 0x8ba0, 0x8bc0, 0x8b9e, 0x8b9e, + 0x8b9e, 0x8b9e, 0x8bc0, 0x8b9e, 0x8b9e, 0x8b9e, 0x080c, 0x13fe, + 0x080c, 0x641b, 0x080c, 0x651c, 0x6010, 0x00d6, 0x2068, 0x684c, + 0xd0fc, 0x0150, 0xa08c, 0x0003, 0xa18e, 0x0002, 0x0158, 0x2009, + 0x0041, 0x00de, 0x0804, 0x8c44, 0x6003, 0x0007, 0x080c, 0x5836, + 0x00de, 0x0005, 0x080c, 0x5836, 0x080c, 0x74f2, 0x00de, 0x0cc8, + 0x0036, 0x080c, 0x641b, 0x080c, 0x651c, 0x6010, 0x00d6, 0x2068, + 0x2019, 0x0004, 0x080c, 0x9097, 0x080c, 0x849b, 0x6017, 0x0028, + 0x00de, 0x003e, 0x0005, 0xa186, 0x0013, 0x1150, 0x6004, 0xa086, + 0x0042, 0x190c, 0x13fe, 0x080c, 0x6389, 0x080c, 0x6462, 0x0005, + 0xa186, 0x0027, 0x0118, 0xa186, 0x0014, 0x1180, 0x6004, 0xa086, + 0x0042, 0x190c, 0x13fe, 0x2001, 0x0007, 0x080c, 0x43f1, 0x080c, + 0x6389, 0x080c, 0x849b, 0x080c, 0x6462, 0x0005, 0xa182, 0x0040, + 0x0002, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, + 0x8c0e, 0x8c1a, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, + 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, 0x080c, 0x13fe, 0x0036, 0x0046, + 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x16c6, 0x004e, + 0x003e, 0x0005, 0x6010, 0x00d6, 0x2068, 0x6810, 0x6a14, 0xa20d, + 0x1168, 0x684c, 0xd0fc, 0x0120, 0x2009, 0x0041, 0x00de, 0x00e0, + 0x6003, 0x0007, 0x080c, 0x5836, 0x00de, 0x0005, 0x6003, 0x0007, + 0x0021, 0x080c, 0x5838, 0x00de, 0x0005, 0xd2fc, 0x0140, 0x8002, + 0x8000, 0x8212, 0xa291, 0x0000, 0x2009, 0x0009, 0x0010, 0x2009, + 0x0015, 0x6a6a, 0x6866, 0x0005, 0xa182, 0x0040, 0x0002, 0x8c5a, + 0x8c5c, 0x8c68, 0x8c74, 0x8c5a, 0x8c5a, 0x8c5a, 0x8c83, 0x8c5a, + 0x8c5a, 0x8c5a, 0x8c5a, 0x8c5a, 0x8c5a, 0x8c5a, 0x8c5a, 0x8c5a, + 0x8c5a, 0x8c5a, 0x080c, 0x13fe, 0x6003, 0x0001, 0x6106, 0x080c, + 0x5ff8, 0x0126, 0x2091, 0x8000, 0x080c, 0x6462, 0x012e, 0x0005, + 0x6003, 0x0001, 0x6106, 0x080c, 0x5ff8, 0x0126, 0x2091, 0x8000, + 0x080c, 0x6462, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x2c10, + 0x080c, 0x1c88, 0x0126, 0x2091, 0x8000, 0x080c, 0x605b, 0x080c, + 0x651c, 0x012e, 0x0005, 0xa016, 0x080c, 0x16c6, 0x0005, 0x080c, + 0x6389, 0x6110, 0x81ff, 0x0148, 0x00d6, 0x2168, 0x0036, 0x2019, + 0x0029, 0x080c, 0x9097, 0x003e, 0x00de, 0x080c, 0x849b, 0x080c, + 0x6462, 0x0005, 0x080c, 0x641b, 0x6110, 0x81ff, 0x0148, 0x00d6, + 0x2168, 0x0036, 0x2019, 0x0029, 0x080c, 0x9097, 0x003e, 0x00de, + 0x080c, 0x849b, 0x080c, 0x651c, 0x0005, 0xa182, 0x0085, 0x0002, + 0x8cb9, 0x8cb7, 0x8cb7, 0x8cc5, 0x8cb7, 0x8cb7, 0x8cb7, 0x080c, + 0x13fe, 0x6003, 0x000b, 0x6106, 0x080c, 0x5ff8, 0x0126, 0x2091, + 0x8000, 0x080c, 0x6462, 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c, + 0x9150, 0x0118, 0x080c, 0x74f2, 0x00c8, 0x2071, 0x9780, 0x7224, + 0x6212, 0x7220, 0x080c, 0x8f71, 0x0118, 0x6007, 0x0086, 0x0040, + 0x6007, 0x0087, 0x7224, 0xa296, 0xffff, 0x1110, 0x6007, 0x0086, + 0x6003, 0x0001, 0x080c, 0x5ff8, 0x080c, 0x6462, 0x00ee, 0x002e, + 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085, 0x0a0c, + 0x13fe, 0xa08a, 0x008c, 0x1a0c, 0x13fe, 0xa082, 0x0085, 0x00a2, + 0xa186, 0x0027, 0x0130, 0xa186, 0x0014, 0x0118, 0x080c, 0x7526, + 0x0050, 0x2001, 0x0007, 0x080c, 0x43f1, 0x080c, 0x6389, 0x080c, + 0x849b, 0x080c, 0x6462, 0x0005, 0x8d13, 0x8d15, 0x8d15, 0x8d13, + 0x8d13, 0x8d13, 0x8d13, 0x080c, 0x13fe, 0x080c, 0x6389, 0x080c, + 0x74f2, 0x080c, 0x6462, 0x0005, 0xa182, 0x0085, 0x0a0c, 0x13fe, + 0xa182, 0x008c, 0x1a0c, 0x13fe, 0xa182, 0x0085, 0x0002, 0x8d2e, + 0x8d2e, 0x8d2e, 0x8d30, 0x8d2e, 0x8d2e, 0x8d2e, 0x080c, 0x13fe, + 0x0005, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186, + 0x0027, 0x0118, 0x080c, 0x7526, 0x0030, 0x080c, 0x6389, 0x080c, + 0x849b, 0x080c, 0x6462, 0x0005, 0x0036, 0x2019, 0x000b, 0x0031, + 0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, 0x0036, + 0x0086, 0x2091, 0x8000, 0x2c40, 0x080c, 0x724a, 0x1540, 0x080c, + 0x72e2, 0x1528, 0x6000, 0xa086, 0x0000, 0x0508, 0x601c, 0xa086, + 0x0007, 0x01e8, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1140, 0x601f, + 0x0007, 0x2001, 0x94dd, 0x2004, 0x6016, 0x080c, 0x1788, 0x6010, + 0x2068, 0x080c, 0x82ee, 0x0110, 0x080c, 0x9097, 0x00de, 0x6013, + 0x0000, 0x601f, 0x0007, 0x2001, 0x94dd, 0x2004, 0x6016, 0x008e, + 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6, 0x0036, 0x0156, 0x2079, + 0x9780, 0x7938, 0x783c, 0x080c, 0x240b, 0x1904, 0x8dce, 0x0016, + 0x00c6, 0x080c, 0x4434, 0x15c0, 0x2011, 0x9790, 0xac98, 0x000a, + 0x20a9, 0x0004, 0x080c, 0x7aee, 0x1578, 0x001e, 0x002e, 0x0026, + 0x0016, 0x2019, 0x0029, 0x080c, 0x73a2, 0x080c, 0x6127, 0x0086, + 0x2041, 0x0000, 0x080c, 0x606d, 0x008e, 0x001e, 0x0086, 0x2041, + 0x0000, 0x080c, 0x8ee4, 0x008e, 0x080c, 0x460d, 0x0026, 0x6204, + 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x0118, 0xa286, 0x0004, + 0x1118, 0x62a0, 0x080c, 0x2704, 0x002e, 0x001e, 0x080c, 0x41e0, + 0x6612, 0x6516, 0xa006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, + 0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x2009, 0x9220, + 0x2104, 0xa086, 0x0074, 0x1904, 0x8e1e, 0x2069, 0x978e, 0x690c, + 0xa182, 0x0100, 0x0678, 0x6908, 0xa184, 0x8000, 0x05a0, 0x2001, + 0x94d7, 0x2004, 0xa005, 0x1118, 0xa184, 0x0800, 0x0560, 0x6910, + 0xa18a, 0x0001, 0x0610, 0x6914, 0x2069, 0x97ae, 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, 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, 0x4443, 0x00ce, 0x04c0, 0x2011, + 0x9796, 0xad98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x7aee, 0x1580, + 0x2011, 0x979a, 0xad98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x7aee, + 0x1538, 0x0046, 0x0016, 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, + 0x2009, 0x9252, 0x210c, 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c, + 0x90d7, 0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, 0x080c, 0x6127, + 0x0086, 0x2041, 0x0000, 0x080c, 0x606d, 0x2c08, 0x080c, 0x8ee4, + 0x008e, 0x2001, 0x0007, 0x080c, 0x43f1, 0x001e, 0x004e, 0xa006, + 0x015e, 0x003e, 0x002e, 0x00de, 0x00ce, 0x0005, 0x00d6, 0x2069, + 0x978e, 0x6800, 0xa086, 0x0800, 0x0118, 0x6013, 0x0000, 0x0008, + 0xa006, 0x00de, 0x0005, 0x00c6, 0x00f6, 0x0016, 0x0026, 0x0036, + 0x0156, 0x2079, 0x978c, 0x7930, 0x7834, 0x080c, 0x240b, 0x11a0, + 0x080c, 0x4434, 0x1188, 0x2011, 0x9790, 0xac98, 0x000a, 0x20a9, + 0x0004, 0x080c, 0x7aee, 0x1140, 0x2011, 0x9794, 0xac98, 0x0006, + 0x20a9, 0x0004, 0x080c, 0x7aee, 0x015e, 0x003e, 0x002e, 0x001e, + 0x00fe, 0x00ce, 0x0005, 0x00c6, 0x0006, 0x0016, 0x0026, 0x0036, + 0x0156, 0x2011, 0x9783, 0x2204, 0x8211, 0x220c, 0x080c, 0x240b, + 0x11a0, 0x080c, 0x4434, 0x1188, 0x2011, 0x9796, 0xac98, 0x000a, + 0x20a9, 0x0004, 0x080c, 0x7aee, 0x1140, 0x2011, 0x979a, 0xac98, + 0x0006, 0x20a9, 0x0004, 0x080c, 0x7aee, 0x015e, 0x003e, 0x002e, + 0x001e, 0x000e, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0076, 0x0066, + 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, 0x2029, 0x94ee, + 0x252c, 0x2021, 0x94f4, 0x2424, 0x2061, 0x9900, 0x2071, 0x9200, + 0x7644, 0x7064, 0x8001, 0xa602, 0x1a04, 0x8f44, 0x2100, 0xac06, + 0x05d0, 0x080c, 0x90ee, 0x05b8, 0x671c, 0xa786, 0x0001, 0x0904, + 0x8f56, 0xa786, 0x0007, 0x0578, 0x2500, 0xac06, 0x0560, 0x2400, + 0xac06, 0x0548, 0x080c, 0x90fe, 0x1530, 0x88ff, 0x0118, 0x6020, + 0xa906, 0x1508, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1120, 0x0016, + 0x080c, 0x1788, 0x001e, 0x6010, 0x2068, 0x080c, 0x82ee, 0x0180, + 0xa786, 0x0003, 0x1510, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x0016, 0x080c, 0x8527, 0x080c, 0x4809, 0x001e, 0x080c, 0x848f, + 0x00de, 0x080c, 0x849b, 0xace0, 0x000c, 0x2001, 0x9216, 0x2004, + 0xac02, 0x1210, 0x0804, 0x8ef6, 0x012e, 0x002e, 0x004e, 0x005e, + 0x006e, 0x007e, 0x00ce, 0x00ee, 0x0005, 0xa786, 0x0006, 0x19d8, + 0xa386, 0x0005, 0x0d40, 0x080c, 0x9097, 0x0c10, 0x080c, 0x90fe, + 0x1d10, 0xa180, 0x0001, 0x2004, 0xa086, 0x0018, 0x19e0, 0x6000, + 0xa086, 0x0002, 0x19c0, 0x080c, 0x84b7, 0x0130, 0x080c, 0x84c8, + 0x1990, 0x080c, 0x7776, 0x0010, 0x080c, 0x2692, 0x080c, 0x849b, + 0x0850, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, 0x080c, 0x90ab, + 0x001e, 0x0120, 0x601c, 0xa084, 0x000f, 0x001b, 0x00ee, 0x00ce, + 0x0005, 0x8f89, 0x8f89, 0x8f89, 0x8f89, 0x8f89, 0x8f89, 0x8f8b, + 0x8f89, 0xa006, 0x0005, 0x0046, 0x0016, 0x7018, 0xa080, 0x0028, + 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009, 0x0020, 0x080c, + 0x90d7, 0x001e, 0x004e, 0x0036, 0x2019, 0x0002, 0x080c, 0x8d4e, + 0x003e, 0xa085, 0x0001, 0x0005, 0x2001, 0x0001, 0x080c, 0x43d1, + 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x9205, + 0x2011, 0x9796, 0x080c, 0x7aee, 0x003e, 0x002e, 0x001e, 0x015e, + 0xa005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x0026, + 0x0126, 0x2091, 0x8000, 0x2061, 0x9900, 0x2079, 0x0001, 0x8fff, + 0x0904, 0x9014, 0x2071, 0x9200, 0x7644, 0x7064, 0x8001, 0xa602, + 0x1a04, 0x9014, 0x88ff, 0x0128, 0x2800, 0xac06, 0x15a0, 0x2079, + 0x0000, 0x080c, 0x90ee, 0x0578, 0x2400, 0xac06, 0x0560, 0x671c, + 0xa786, 0x0006, 0x1540, 0xa786, 0x0007, 0x0528, 0x88ff, 0x1140, + 0x6018, 0xa206, 0x1500, 0x85ff, 0x0118, 0x6020, 0xa106, 0x11d8, + 0x00d6, 0x6000, 0xa086, 0x0004, 0x1140, 0x601f, 0x0007, 0x2001, + 0x94dd, 0x2004, 0x6016, 0x080c, 0x1788, 0x6010, 0x2068, 0x080c, + 0x82ee, 0x0120, 0x0046, 0x080c, 0x9097, 0x004e, 0x00de, 0x080c, + 0x849b, 0x88ff, 0x1190, 0xace0, 0x000c, 0x2001, 0x9216, 0x2004, + 0xac02, 0x1210, 0x0804, 0x8fc7, 0xa006, 0x012e, 0x002e, 0x006e, + 0x007e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0xa8c5, 0x0001, 0x0ca8, + 0x0086, 0x0056, 0x2041, 0x0000, 0x2029, 0x0001, 0x2c20, 0x2019, + 0x0002, 0x6218, 0x080c, 0x724a, 0x080c, 0x72e2, 0x080c, 0x8fba, + 0x005e, 0x008e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0086, 0x00c6, + 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, + 0x0036, 0x080c, 0x4434, 0x1170, 0x2c10, 0x2041, 0x0000, 0x2508, + 0x0056, 0x2029, 0x0001, 0x080c, 0x724a, 0x080c, 0x72e2, 0x080c, + 0x8fba, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, 0x903f, 0x015e, + 0x00ce, 0x008e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0086, 0x0056, + 0x6218, 0x2041, 0x0000, 0x2029, 0x0001, 0x2019, 0x0048, 0x080c, + 0x724a, 0x080c, 0x72e2, 0x2c20, 0x080c, 0x8fba, 0x005e, 0x008e, + 0x0005, 0x0026, 0x0046, 0x0056, 0x0086, 0x00c6, 0x0156, 0x2c20, + 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, 0x080c, 0x4434, + 0x1150, 0x2c10, 0x2041, 0x0000, 0x2828, 0x080c, 0x724a, 0x080c, + 0x72e2, 0x080c, 0x8fba, 0x003e, 0x001e, 0x8108, 0x1f04, 0x907c, + 0x015e, 0x00ce, 0x008e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0016, + 0x00f6, 0x8dff, 0x0168, 0x6800, 0xa07d, 0x0138, 0x6803, 0x0000, + 0x6b52, 0x080c, 0x4809, 0x2f68, 0x0cb0, 0x6b52, 0x080c, 0x4809, + 0x00fe, 0x001e, 0x0005, 0x00e6, 0x0046, 0x0036, 0x2061, 0x9900, + 0x2071, 0x9200, 0x7444, 0x7064, 0x8001, 0xa402, 0x12d8, 0x2100, + 0xac06, 0x0168, 0x6000, 0xa086, 0x0000, 0x0148, 0x6008, 0xa206, + 0x1130, 0x6018, 0xa1a0, 0x0006, 0x2424, 0xa406, 0x0140, 0xace0, + 0x000c, 0x2001, 0x9216, 0x2004, 0xac02, 0x1220, 0x0c08, 0xa085, + 0x0001, 0x0008, 0xa006, 0x003e, 0x004e, 0x00ee, 0x0005, 0x00d6, + 0x0006, 0x080c, 0x147c, 0x000e, 0x090c, 0x13fe, 0x6837, 0x010d, + 0x685e, 0x6956, 0x6c46, 0x684f, 0x0000, 0xa006, 0x68b2, 0x6802, + 0x683a, 0x685a, 0x080c, 0x4809, 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, 0xa186, 0x0013, 0x1128, + 0x6004, 0xa082, 0x0085, 0x2008, 0x00c2, 0xa186, 0x0027, 0x1178, + 0x080c, 0x6389, 0x0036, 0x00d6, 0x6010, 0x2068, 0x2019, 0x0004, + 0x080c, 0x9097, 0x00de, 0x003e, 0x080c, 0x6462, 0x0005, 0xa186, + 0x0014, 0x0d70, 0x080c, 0x7526, 0x0005, 0x912e, 0x912c, 0x912c, + 0x912c, 0x912c, 0x912c, 0x912e, 0x080c, 0x13fe, 0x080c, 0x6389, + 0x6003, 0x000c, 0x080c, 0x6462, 0x0005, 0xa182, 0x008c, 0x1220, + 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x7526, 0x0005, 0x9146, + 0x9146, 0x9146, 0x9146, 0x9148, 0x914d, 0x9146, 0x080c, 0x13fe, + 0x00d6, 0x080c, 0x74f2, 0x00de, 0x0005, 0x080c, 0x74f2, 0x0005, + 0x00e6, 0x6018, 0x2070, 0x7000, 0xd0ec, 0x00ee, 0x0005, 0x0126, + 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0x9240, 0xd5a4, 0x0118, + 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, 0x7030, 0x8000, 0x7032, + 0xd5ac, 0x0118, 0x2071, 0x924a, 0x0451, 0x00ee, 0x000e, 0x012e, + 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0x9240, + 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, 0x7030, + 0x8000, 0x7032, 0xd5ac, 0x0118, 0x2071, 0x924a, 0x0081, 0x00ee, + 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, + 0x2071, 0x9242, 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e04, + 0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005, + 0x00e6, 0x2071, 0x9240, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, + 0x9244, 0x0c69, 0x00ee, 0x0005, 0x0001, 0x0002, 0x0004, 0x0008, + 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, + 0x1000, 0x2000, 0x4000, 0x8000, 0x448c }; -unsigned short risc_code_length01 = 0x65e6; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/qlogicisp.c linux.pre11.3/drivers/scsi/qlogicisp.c --- linux.vanilla/drivers/scsi/qlogicisp.c Wed Apr 28 19:14:28 1999 +++ linux.pre11.3/drivers/scsi/qlogicisp.c Mon Jul 19 23:28:01 1999 @@ -1065,8 +1065,10 @@ ip[0] = 255; ip[1] = 63; ip[2] = size / (ip[0] * ip[1]); +#if 0 if (ip[2] > 1023) ip[2] = 1023; +#endif } LEAVE("isp1020_biosparam"); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/scsi.c linux.pre11.3/drivers/scsi/scsi.c --- linux.vanilla/drivers/scsi/scsi.c Tue Jun 15 16:49:51 1999 +++ linux.pre11.3/drivers/scsi/scsi.c Tue Jul 20 00:03:35 1999 @@ -32,6 +32,8 @@ * Converted cli() code to spinlocks, Ingo Molnar * * Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli + * + * out_of_space + add-single-device work, D. Gilbert (dpg) 990612 */ #include @@ -180,6 +182,7 @@ int * sparse_lun, Scsi_Device ** SDpnt, Scsi_Cmnd * SCpnt, struct Scsi_Host *shpnt, char * scsi_result); void scsi_build_commandblocks(Scsi_Device * SDpnt); +static int scsi_unregister_device(struct Scsi_Device_Template * tpnt); /* * These are the interface to the old error handling code. It should go away @@ -451,16 +454,18 @@ Scsi_Device * SDtail; int sparse_lun; - SCpnt = (Scsi_Cmnd *) scsi_init_malloc (sizeof (Scsi_Cmnd), GFP_ATOMIC | GFP_DMA); - memset (SCpnt, 0, sizeof (Scsi_Cmnd)); - - SDpnt = (Scsi_Device *) scsi_init_malloc (sizeof (Scsi_Device), GFP_ATOMIC); - memset (SDpnt, 0, sizeof (Scsi_Device)); - - - /* Make sure we have something that is valid for DMA purposes */ - scsi_result = ( ( !shpnt->unchecked_isa_dma ) - ? &scsi_result0[0] : scsi_init_malloc (512, GFP_DMA)); + scsi_result = NULL; + SCpnt = (Scsi_Cmnd *) scsi_init_malloc (sizeof (Scsi_Cmnd), + GFP_ATOMIC | GFP_DMA); + if (SCpnt) { + SDpnt = (Scsi_Device *) scsi_init_malloc(sizeof (Scsi_Device), + GFP_ATOMIC); + if (SDpnt) { + /* Make sure we have something that is valid for DMA purposes */ + scsi_result = ( ( !shpnt->unchecked_isa_dma ) + ? &scsi_result0[0] : scsi_init_malloc (512, GFP_DMA)); + } + } if (scsi_result == NULL) { @@ -512,18 +517,32 @@ if(lun >= shpnt->max_lun) goto leave; scan_scsis_single (channel, dev, lun, &max_dev_lun, &sparse_lun, &SDpnt, SCpnt, shpnt, scsi_result); + + /* See warning by (DB) in scsi_proc_info() towards end of + 'add-single-device' section. (dpg) */ + if (shpnt->select_queue_depths != NULL) + (shpnt->select_queue_depths)(shpnt, shpnt->host_queue); + if(SDpnt!=oldSDpnt) { /* it could happen the blockdevice hasn't yet been inited */ - for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) - if(sdtpnt->init && sdtpnt->dev_noticed) (*sdtpnt->init)(); + for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) + if(sdtpnt->init && sdtpnt->dev_noticed) (*sdtpnt->init)(); - oldSDpnt->scsi_request_fn = NULL; - for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) - if(sdtpnt->attach) { - (*sdtpnt->attach)(oldSDpnt); - if(oldSDpnt->attached) scsi_build_commandblocks(oldSDpnt);} - resize_dma_pool(); + oldSDpnt->scsi_request_fn = NULL; + for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) { + if(sdtpnt->attach) { + (*sdtpnt->attach)(oldSDpnt); + if(oldSDpnt->attached) { + scsi_build_commandblocks(oldSDpnt); + if (0 == oldSDpnt->has_cmdblocks) { + printk("scan_scsis: DANGER, no command blocks\n"); + /* What to do now ?? */ + } + } + } + } + resize_dma_pool(); for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) { if(sdtpnt->finish && sdtpnt->nr_dev) @@ -743,6 +762,17 @@ scsi_result[1] |= 0x80; /* removable */ } + /* + * It would seem the Panasonic DVD-RAM is backwards too + * If DVD-RAM or PD media used, it seems to function + * as Direct-Access + */ + if (!strncmp (scsi_result + 8, "MATSHITA", 7) && + !strncmp (scsi_result + 16, "PD-2 LF-D100", 12)) { + scsi_result[0] = TYPE_DISK; + scsi_result[1] |= 0x80; /* removable */ + } + memcpy (SDpnt->vendor, scsi_result + 8, 8); memcpy (SDpnt->model, scsi_result + 16, 16); memcpy (SDpnt->rev, scsi_result + 32, 4); @@ -884,8 +914,6 @@ return 0; } - memset (SDpnt, 0, sizeof (Scsi_Device)); - /* * And hook up our command block to the new device we will be testing * for. @@ -1429,6 +1457,7 @@ { struct Scsi_Host * host = SCpnt->host; Scsi_Device * device = SCpnt->device; + int mlqueue = 0; SCpnt->owner = SCSI_OWNER_MIDLEVEL; @@ -1463,6 +1492,10 @@ SCpnt->pid = scsi_pid++; while (SCSI_BLOCK((Scsi_Device *) NULL, host)) { + if (in_interrupt()){ + mlqueue = 1; + break; + } spin_unlock(&io_request_lock); /* FIXME!!! */ SCSI_SLEEP(&host->host_wait, SCSI_BLOCK((Scsi_Device *) NULL, host)); spin_lock_irq(&io_request_lock); /* FIXME!!! */ @@ -1509,7 +1542,15 @@ SCpnt->internal_timeout = NORMAL_TIMEOUT; SCpnt->abort_reason = 0; SCpnt->result = 0; - internal_cmnd (SCpnt); + + if (mlqueue == 1 && host->hostt->use_new_eh_code){ + /* Assign a unique nonzero serial_number. */ + if (++serial_number == 0) serial_number = 1; + SCpnt->serial_number = serial_number; + scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_HOST_BUSY); + } + else + internal_cmnd (SCpnt); SCSI_LOG_MLQUEUE(3,printk ("Leaving scsi_do_cmd()\n")); } @@ -1899,9 +1940,9 @@ for (order = 0, a_size = PAGE_SIZE; a_size < size; order++, a_size <<= 1) ; - retval = (void *) __get_free_pages(gfp_mask | GFP_DMA, order); + retval = (void *) __get_free_pages(gfp_mask | GFP_DMA, order); } else - retval = kmalloc(size, gfp_mask); + retval = kmalloc(size, gfp_mask); if (retval) memset(retval, 0, size); @@ -1970,9 +2011,10 @@ printk("scsi_build_commandblocks: want=%d, space for=%d blocks\n", SDpnt->queue_depth, j); SDpnt->queue_depth = j; - /* Still problem if 0==j , continue anyway ... */ + SDpnt->has_cmdblocks = (0 != j); } - SDpnt->has_cmdblocks = 1; + else + SDpnt->has_cmdblocks = 1; } #ifndef MODULE /* { */ @@ -2036,7 +2078,13 @@ /* SDpnt->scsi_request_fn = NULL; */ for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) if(sdtpnt->attach) (*sdtpnt->attach)(SDpnt); - if(SDpnt->attached) scsi_build_commandblocks(SDpnt); + if(SDpnt->attached) { + scsi_build_commandblocks(SDpnt); + if (0 == SDpnt->has_cmdblocks) { + printk("scsi_dev_init: DANGER, no command blocks\n"); + /* What to do now ?? */ + } + } } } @@ -2332,8 +2380,9 @@ /* FIXME (DB) This assumes that the queue_depth routines can be used in this context as well, while they were all designed to be called only once after the detect routine. (DB) */ - if (HBA_ptr->select_queue_depths != NULL) - (HBA_ptr->select_queue_depths)(HBA_ptr, HBA_ptr->host_queue); + /* ... but scan_scsis(,1,,,) needs the correct queue_length. So + select_queue_depths() has been moved inside scan_scsis() and + is only used in this context (ie scan_scsis(,1,,,) ). (dpg) */ return(length); @@ -2396,7 +2445,7 @@ * Nobody is using this device any more. * Free all of the command structures. */ - for(SCpnt=scd->device_queue; SCpnt; SCpnt = SCpnt->next) + for(SCpnt=scd->device_queue; SCpnt; SCpnt = scd->device_queue) { scd->device_queue = SCpnt->next; scsi_init_free((char *) SCpnt, sizeof(*SCpnt)); @@ -2429,7 +2478,7 @@ */ static void resize_dma_pool(void) { - int i; + int i, k; unsigned long size; struct Scsi_Host * shpnt; struct Scsi_Host * host = NULL; @@ -2438,6 +2487,7 @@ unsigned int new_dma_sectors = 0; unsigned int new_need_isa_buffer = 0; unsigned char ** new_dma_malloc_pages = NULL; + int out_of_space = 0; if( !scsi_hostlist ) { @@ -2529,27 +2579,67 @@ * race conditions that I would rather not even think * about right now. */ - if( new_dma_sectors < dma_sectors ) +#if 0 /* Why do this? No gain and risks out_of_space */ + if( new_dma_sectors < dma_sectors ) new_dma_sectors = dma_sectors; +#endif + if( new_dma_sectors <= dma_sectors ) + return; /* best to quit while we are in front */ - if (new_dma_sectors) - { - size = (new_dma_sectors / SECTORS_PER_PAGE)*sizeof(FreeSectorBitmap); - new_dma_malloc_freelist = (FreeSectorBitmap *) scsi_init_malloc(size, GFP_ATOMIC); - memset(new_dma_malloc_freelist, 0, size); - - size = (new_dma_sectors / SECTORS_PER_PAGE)*sizeof(*new_dma_malloc_pages); - new_dma_malloc_pages = (unsigned char **) scsi_init_malloc(size, GFP_ATOMIC); - memset(new_dma_malloc_pages, 0, size); - } + for (k = 0; k < 20; ++k) { /* just in case */ + out_of_space = 0; + size = (new_dma_sectors / SECTORS_PER_PAGE) * + sizeof(FreeSectorBitmap); + new_dma_malloc_freelist = (FreeSectorBitmap *) + scsi_init_malloc(size, GFP_ATOMIC); + if (new_dma_malloc_freelist) { + size = (new_dma_sectors / SECTORS_PER_PAGE) * + sizeof(*new_dma_malloc_pages); + new_dma_malloc_pages = (unsigned char **) + scsi_init_malloc(size, GFP_ATOMIC); + if (! new_dma_malloc_pages) { + size = (new_dma_sectors / SECTORS_PER_PAGE) * + sizeof(FreeSectorBitmap); + scsi_init_free((char *)new_dma_malloc_freelist, size); + out_of_space = 1; + } + } + else + out_of_space = 1; + + if ((! out_of_space) && (new_dma_sectors > dma_sectors)) { + for(i = dma_sectors / SECTORS_PER_PAGE; + i < new_dma_sectors / SECTORS_PER_PAGE; i++) { + new_dma_malloc_pages[i] = (unsigned char *) + scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA); + if (! new_dma_malloc_pages[i]) + break; + } + if (i != new_dma_sectors / SECTORS_PER_PAGE) { /* clean up */ + int k = i; - /* - * If we need more buffers, expand the list. - */ - if( new_dma_sectors > dma_sectors ) { - for(i=dma_sectors / SECTORS_PER_PAGE; i< new_dma_sectors / SECTORS_PER_PAGE; i++) - new_dma_malloc_pages[i] = (unsigned char *) - scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA); + out_of_space = 1; + for (i = 0; i < k; ++i) + scsi_init_free(new_dma_malloc_pages[i], PAGE_SIZE); + } + } + if (out_of_space) { /* try scaling down new_dma_sectors request (dpg) */ + printk("scsi::resize_dma_pool: WARNING, dma_sectors=%u, " + "wanted=%u, scaling\n", dma_sectors, new_dma_sectors); + if (new_dma_sectors < (8 * SECTORS_PER_PAGE)) + break; /* pretty well hopeless ... */ + new_dma_sectors = (new_dma_sectors * 3) / 4; + new_dma_sectors = (new_dma_sectors + 15) & 0xfff0; + if (new_dma_sectors <= dma_sectors) + break; /* stick with what we have got */ + } + else + break; /* found space ... */ + } /* end of for loop */ + if (out_of_space) { + scsi_need_isa_buffer = new_need_isa_buffer; /* some useful info */ + printk(" WARNING, not enough memory, pool not expanded\n"); + return; } /* When we dick with the actual DMA list, we need to @@ -2596,6 +2686,7 @@ struct Scsi_Device_Template * sdtpnt; const char * name; unsigned long flags; + int out_of_space = 0; if (tpnt->next || !tpnt->detect) return 1;/* Must be already loaded, or * no detect routine available @@ -2695,11 +2786,11 @@ { if(shpnt->hostt == tpnt) { - scan_scsis(shpnt,0,0,0,0); - if (shpnt->select_queue_depths != NULL) - { - (shpnt->select_queue_depths)(shpnt, shpnt->host_queue); - } + scan_scsis(shpnt,0,0,0,0); + if (shpnt->select_queue_depths != NULL) + { + (shpnt->select_queue_depths)(shpnt, shpnt->host_queue); + } } } @@ -2718,14 +2809,19 @@ { for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) if(sdtpnt->attach) (*sdtpnt->attach)(SDpnt); - if(SDpnt->attached) scsi_build_commandblocks(SDpnt); + if(SDpnt->attached) { + scsi_build_commandblocks(SDpnt); + if (0 == SDpnt->has_cmdblocks) + out_of_space = 1; + } } } /* * Now that we have all of the devices, resize the DMA pool, * as required. */ - resize_dma_pool(); + if (! out_of_space) + resize_dma_pool(); /* This does any final handling that is required. */ @@ -2746,7 +2842,13 @@ #endif MOD_INC_USE_COUNT; - return 0; + + if (out_of_space) { + scsi_unregister_host(tpnt); /* easiest way to clean up?? */ + return 1; + } + else + return 0; } /* @@ -3007,6 +3109,7 @@ { Scsi_Device * SDpnt; struct Scsi_Host * shpnt; + int out_of_space = 0; if (tpnt->next) return 1; @@ -3048,6 +3151,8 @@ { SDpnt->online = TRUE; scsi_build_commandblocks(SDpnt); + if (0 == SDpnt->has_cmdblocks) + out_of_space = 1; } } } @@ -3056,15 +3161,22 @@ * This does any final handling that is required. */ if(tpnt->finish && tpnt->nr_dev) (*tpnt->finish)(); - resize_dma_pool(); + if (! out_of_space) + resize_dma_pool(); MOD_INC_USE_COUNT; - return 0; + + if (out_of_space) { + scsi_unregister_device(tpnt); /* easiest way to clean up?? */ + return 1; + } + else + return 0; } static int scsi_unregister_device(struct Scsi_Device_Template * tpnt) { Scsi_Device * SDpnt; - Scsi_Cmnd * SCpnt; + Scsi_Cmnd * SCpnt, *SCnext; struct Scsi_Host * shpnt; struct Scsi_Device_Template * spnt; struct Scsi_Device_Template * prev_spnt; @@ -3092,11 +3204,14 @@ * Nobody is using this device any more. Free all of the * command structures. */ - for(SCpnt = SDpnt->device_queue; SCpnt; - SCpnt = SCpnt->next) + + SCpnt = SDpnt->device_queue; + if (SCpnt) SCnext = SCpnt->next; + for(; SCpnt; SCpnt = SCnext) { if(SCpnt == SDpnt->device_queue) SDpnt->device_queue = SCpnt->next; + SCnext = SCpnt->next; scsi_init_free((char *) SCpnt, sizeof(*SCpnt)); } SDpnt->has_cmdblocks = 0; @@ -3229,7 +3344,7 @@ printk("(%3d) %2d:%1d:%2d:%2d (%6s %4ld %4ld %4ld %4x %1d) (%1d %1d 0x%2x) (%4d %4d %4d) 0x%2.2x 0x%2.2x 0x%8.8x\n", i++, - SCpnt->host->host_no, + SCpnt->host ? SCpnt->host->host_no : -1, SCpnt->channel, SCpnt->target, SCpnt->lun, @@ -3294,6 +3409,7 @@ int init_module(void) { unsigned long size; + int has_space = 0; /* * This makes /proc/scsi visible. @@ -3309,7 +3425,6 @@ proc_scsi_register(0, &proc_scsi_scsi); #endif - dma_sectors = PAGE_SIZE / SECTOR_SIZE; scsi_dma_free_sectors= dma_sectors; /* @@ -3318,15 +3433,31 @@ */ /* One bit per sector to indicate free/busy */ - size = (dma_sectors / SECTORS_PER_PAGE)*sizeof(FreeSectorBitmap); - dma_malloc_freelist = (FreeSectorBitmap *) scsi_init_malloc(size, GFP_ATOMIC); - memset(dma_malloc_freelist, 0, size); - - /* One pointer per page for the page list */ - dma_malloc_pages = (unsigned char **) - scsi_init_malloc((dma_sectors / SECTORS_PER_PAGE)*sizeof(*dma_malloc_pages), GFP_ATOMIC); - dma_malloc_pages[0] = (unsigned char *) - scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA); + size = (dma_sectors / SECTORS_PER_PAGE) * sizeof(FreeSectorBitmap); + dma_malloc_freelist = (FreeSectorBitmap *) + scsi_init_malloc(size, GFP_ATOMIC); + if (dma_malloc_freelist) { + /* One pointer per page for the page list */ + dma_malloc_pages = (unsigned char **)scsi_init_malloc( + (dma_sectors / SECTORS_PER_PAGE) * sizeof(*dma_malloc_pages), + GFP_ATOMIC); + if (dma_malloc_pages) { + dma_malloc_pages[0] = (unsigned char *) + scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA); + if (dma_malloc_pages[0]) + has_space = 1; + } + } + if (! has_space) { + if (dma_malloc_freelist) { + scsi_init_free((char *)dma_malloc_freelist, size); + if (dma_malloc_pages) + scsi_init_free((char *)dma_malloc_pages, + (dma_sectors / SECTORS_PER_PAGE) * sizeof(*dma_malloc_pages)); + } + printk("scsi::init_module: failed, out of memory\n"); + return 1; + } /* * This is where the processing takes place for most everything diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/scsi.h linux.pre11.3/drivers/scsi/scsi.h --- linux.vanilla/drivers/scsi/scsi.h Tue Jun 15 16:49:51 1999 +++ linux.pre11.3/drivers/scsi/scsi.h Tue Jul 20 01:42:53 1999 @@ -377,6 +377,9 @@ extern int scsi_decide_disposition (Scsi_Cmnd * SCpnt); extern int scsi_block_when_processing_errors(Scsi_Device *); extern void scsi_sleep(int); +extern int scsi_partsize(struct buffer_head *bh, unsigned long capacity, + unsigned int *cyls, unsigned int *hds, + unsigned int *secs); /* * scsi_abort aborts the current command that is executing on host host. diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/scsi_error.c linux.pre11.3/drivers/scsi/scsi_error.c --- linux.vanilla/drivers/scsi/scsi_error.c Wed Mar 10 21:13:06 1999 +++ linux.pre11.3/drivers/scsi/scsi_error.c Mon Jul 19 23:28:02 1999 @@ -1926,6 +1926,7 @@ int rtn; struct semaphore sem = MUTEX_LOCKED; unsigned long flags; + struct fs_struct *fs; lock_kernel(); @@ -1936,16 +1937,18 @@ */ exit_mm(current); - current->session = 1; current->pgrp = 1; - /* - * FIXME(eric) this is still a child process of the one that did the insmod. - * This needs to be attached to task[0] instead. - */ + + /* Become as one with the init task */ + + exit_fs(current); /* current->fs->count--; */ + fs = init_task.fs; + current->fs = fs; + atomic_inc(&fs->count); siginitsetinv(¤t->blocked, SHUTDOWN_SIGS); - current->fs->umask = 0; + /* * Set the name of this process. diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/sd.c linux.pre11.3/drivers/scsi/sd.c --- linux.vanilla/drivers/scsi/sd.c Tue Jun 15 16:49:51 1999 +++ linux.pre11.3/drivers/scsi/sd.c Mon Jul 19 23:27:56 1999 @@ -1050,6 +1050,7 @@ SCpnt->transfersize = rscsi_disks[dev].sector_size; SCpnt->underflow = this_count << 9; + SCpnt->cmd_len = 0; scsi_do_cmd (SCpnt, (void *) cmd, buff, this_count * rscsi_disks[dev].sector_size, rw_intr, diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/sgiwd93.c linux.pre11.3/drivers/scsi/sgiwd93.c --- linux.vanilla/drivers/scsi/sgiwd93.c Sun Nov 8 15:07:57 1998 +++ linux.pre11.3/drivers/scsi/sgiwd93.c Mon Jul 19 23:28:03 1999 @@ -5,13 +5,14 @@ * * (In all truth, Jed Schimmel wrote all this code.) * - * $Id: sgiwd93.c,v 1.1 1998/05/01 01:35:42 ralf Exp $ + * $Id: sgiwd93.c,v 1.13 1999/03/28 23:06:06 tsbogend Exp $ */ #include #include #include #include #include +#include #include #include @@ -21,6 +22,7 @@ #include #include #include +#include #include #include "scsi.h" @@ -65,14 +67,40 @@ /* XXX woof! */ static void sgiwd93_intr(int irq, void *dev_id, struct pt_regs *regs) { + unsigned long flags; + + spin_lock_irqsave(&io_request_lock, flags); wd33c93_intr(sgiwd93_host); + spin_unlock_irqrestore(&io_request_lock, flags); } #undef DEBUG_DMA +static inline +void fill_hpc_entries (struct hpc_chunk **hcp, char *addr, unsigned long len) +{ + unsigned long physaddr; + unsigned long count; + + dma_cache_wback_inv((unsigned long)addr,len); + physaddr = PHYSADDR(addr); + while (len) { + /* + * even cntinfo could be up to 16383, without + * magic only 8192 works correctly + */ + count = len > 8192 ? 8192 : len; + (*hcp)->desc.pbuf = physaddr; + (*hcp)->desc.cntinfo = count; + (*hcp)++; + len -= count; + physaddr += count; + } +} + static int dma_setup(Scsi_Cmnd *cmd, int datainp) { - struct WD33C93_hostdata *hdata = CMDHOSTDATA(cmd); + struct WD33C93_hostdata *hdata = (struct WD33C93_hostdata *)cmd->host->hostdata; wd33c93_regs *regp = hdata->regp; struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) cmd->host->base; struct hpc_chunk *hcp = (struct hpc_chunk *) hdata->dma_bounce_buffer; @@ -84,21 +112,18 @@ hdata->dma_dir = datainp; - if(cmd->use_sg) { + if(cmd->SCp.buffers_residual) { struct scatterlist *slp = cmd->SCp.buffer; int i, totlen = 0; #ifdef DEBUG_DMA printk("SCLIST<"); #endif - for(i = 0; i <= (cmd->use_sg - 1); i++, hcp++) { + for(i = 0; i <= cmd->SCp.buffers_residual; i++) { #ifdef DEBUG_DMA printk("[%p,%d]", slp[i].address, slp[i].length); #endif - dma_cache_wback_inv((unsigned long)slp[i].address, - PAGE_SIZE); - hcp->desc.pbuf = PHYSADDR(slp[i].address); - hcp->desc.cntinfo = (slp[i].length & HPCDMA_BCNT); + fill_hpc_entries (&hcp, slp[i].address, slp[i].length); totlen += slp[i].length; } #ifdef DEBUG_DMA @@ -111,10 +136,16 @@ #ifdef DEBUG_DMA printk("ONEBUF<%p,%d>", cmd->SCp.ptr, cmd->SCp.this_residual); #endif - dma_cache_wback_inv((unsigned long)cmd->SCp.ptr, PAGE_SIZE); - hcp->desc.pbuf = PHYSADDR(cmd->SCp.ptr); - hcp->desc.cntinfo = (cmd->SCp.this_residual & HPCDMA_BCNT); - hcp++; + /* + * wd33c93 shouldn't pass us bogus dma_setups, but + * it does:-( The other wd33c93 drivers deal with + * it the same way (which isn't that obvious). + * IMHO a better fix would be, not to do these + * dma setups in the first place + */ + if (cmd->SCp.ptr == NULL) + return 1; + fill_hpc_entries (&hcp, cmd->SCp.ptr,cmd->SCp.this_residual); write_wd33c93_count(regp, cmd->SCp.this_residual); } @@ -141,9 +172,14 @@ static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *SCpnt, int status) { - struct WD33C93_hostdata *hdata = INSTHOSTDATA(instance); + struct WD33C93_hostdata *hdata = (struct WD33C93_hostdata *)instance->hostdata; wd33c93_regs *regp = hdata->regp; - struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) SCpnt->host->base; + struct hpc3_scsiregs *hregs; + + if (!SCpnt) + return; + + hregs = (struct hpc3_scsiregs *) SCpnt->host->base; #ifdef DEBUG_DMA printk("dma_stop: status<%d> ", status); @@ -158,7 +194,7 @@ hregs->ctrl = 0; /* See how far we got and update scatterlist state if necessary. */ - if(SCpnt->use_sg) { + if(SCpnt->SCp.buffers_residual) { struct scatterlist *slp = SCpnt->SCp.buffer; int totlen, wd93_residual, transferred, i; @@ -178,7 +214,7 @@ #ifdef DEBUG_DMA printk("Jed was here..."); #endif - for(i = 0; i <= (SCpnt->use_sg - 1); i++) { + for(i = 0; i <= SCpnt->SCp.buffers_residual; i++) { if(slp[i].length >= transferred) break; transferred -= slp[i].length; @@ -188,10 +224,10 @@ #ifdef DEBUG_DMA printk("did it all..."); #endif - i = (SCpnt->use_sg - 1); + i = SCpnt->SCp.buffers_residual; } SCpnt->SCp.buffer = &slp[i]; - SCpnt->SCp.buffers_residual = (SCpnt->use_sg - 1 - i); + SCpnt->SCp.buffers_residual = SCpnt->SCp.buffers_residual - i; SCpnt->SCp.ptr = (char *) slp[i].address; SCpnt->SCp.this_residual = slp[i].length; } @@ -200,6 +236,15 @@ #endif } +void sgiwd93_reset(void) +{ + struct hpc3_scsiregs *hregs = &hpc3c0->scsi_chan0; + + hregs->ctrl = HPC3_SCTRL_CRESET; + udelay (50); + hregs->ctrl = 0; +} + static inline void init_hpc_chain(uchar *buf) { struct hpc_chunk *hcp = (struct hpc_chunk *) buf; @@ -231,6 +276,7 @@ sgiwd93_host = scsi_register(HPsUX, sizeof(struct WD33C93_hostdata)); sgiwd93_host->base = (unsigned char *) hregs; + sgiwd93_host->irq = 1; buf = (uchar *) get_free_page(GFP_KERNEL); init_hpc_chain(buf); @@ -239,7 +285,7 @@ wd33c93_init(sgiwd93_host, (wd33c93_regs *) 0xbfbc0003, dma_setup, dma_stop, WD33C93_FS_16_20); - hdata = INSTHOSTDATA(sgiwd93_host); + hdata = (struct WD33C93_hostdata *)sgiwd93_host->hostdata; hdata->no_sync = 0; hdata->dma_bounce_buffer = (uchar *) (KSEG1ADDR(buf)); dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/sgiwd93.h linux.pre11.3/drivers/scsi/sgiwd93.h --- linux.vanilla/drivers/scsi/sgiwd93.h Sun Nov 8 15:07:57 1998 +++ linux.pre11.3/drivers/scsi/sgiwd93.h Mon Jul 19 23:28:03 1999 @@ -1,4 +1,4 @@ -/* $Id: sgiwd93.h,v 1.2 1998/05/04 09:18:49 ralf Exp $ +/* $Id: sgiwd93.h,v 1.5 1998/08/25 09:18:50 ralf Exp $ * sgiwd93.h: SGI WD93 scsi definitions. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/sym53c416.c linux.pre11.3/drivers/scsi/sym53c416.c --- linux.vanilla/drivers/scsi/sym53c416.c Wed Mar 10 21:13:06 1999 +++ linux.pre11.3/drivers/scsi/sym53c416.c Mon Jul 19 23:28:06 1999 @@ -3,6 +3,10 @@ * Low-level SCSI driver for sym53c416 chip. * Copyright (C) 1998 Lieven Willems (lw_linux@hotmail.com) * + * Changes : + * + * Marcelo Tosatti : Added io_request_lock locking + * * LILO command line usage: sym53c416=[,] * * This program is free software; you can redistribute it and/or modify it @@ -30,6 +34,7 @@ #include #include #include +#include #include #include #include "scsi.h" @@ -371,7 +376,9 @@ printk("sym53c416: Warning: Reset received\n"); current_command->SCp.phase = idle; current_command->result = DID_RESET << 16; + spin_lock_irqsave(&io_request_lock, flags); current_command->scsi_done(current_command); + spin_unlock_irqrestore(&io_request_lock, flags); return; } if(int_reg & ILCMD) /* Illegal Command */ @@ -379,7 +386,9 @@ printk("sym53c416: Warning: Illegal Command: 0x%02x\n", inb(base + COMMAND_REG)); current_command->SCp.phase = idle; current_command->result = DID_ERROR << 16; + spin_lock_irqsave(&io_request_lock, flags); current_command->scsi_done(current_command); + spin_unlock_irqrestore(&io_request_lock, flags); return; } if(status_reg & GE) /* Gross Error */ @@ -387,7 +396,9 @@ printk("sym53c416: Warning: Gross Error\n"); current_command->SCp.phase = idle; current_command->result = DID_ERROR << 16; + spin_lock_irqsave(&io_request_lock, flags); current_command->scsi_done(current_command); + spin_unlock_irqrestore(&io_request_lock, flags); return; } if(status_reg & PE) /* Parity Error */ @@ -395,7 +406,9 @@ printk("sym53c416: Warning: Parity Error\n"); current_command->SCp.phase = idle; current_command->result = DID_PARITY << 16; + spin_lock_irqsave(&io_request_lock, flags); current_command->scsi_done(current_command); + spin_unlock_irqrestore(&io_request_lock, flags); return; } if(pio_int_reg & (CE | OUE)) @@ -403,7 +416,9 @@ printk("sym53c416: Warning: PIO Interrupt Error\n"); current_command->SCp.phase = idle; current_command->result = DID_ERROR << 16; + spin_lock_irqsave(&io_request_lock, flags); current_command->scsi_done(current_command); + spin_unlock_irqrestore(&io_request_lock, flags); return; } if(int_reg & DIS) /* Disconnect */ @@ -413,7 +428,10 @@ else current_command->result = (current_command->SCp.Status & 0xFF) | ((current_command->SCp.Message & 0xFF) << 8) | (DID_OK << 16); current_command->SCp.phase = idle; + + spin_lock_irqsave(&io_request_lock, flags); current_command->scsi_done(current_command); + spin_unlock_irqrestore(&io_request_lock, flags); return; } /* Now we handle SCSI phases */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/wd33c93.h linux.pre11.3/drivers/scsi/wd33c93.h --- linux.vanilla/drivers/scsi/wd33c93.h Sun Nov 8 15:07:54 1998 +++ linux.pre11.3/drivers/scsi/wd33c93.h Mon Jul 19 23:28:01 1999 @@ -190,6 +190,9 @@ typedef struct { volatile unsigned char SASR; char pad; +#ifdef CONFIG_SGI + char pad2,pad3; +#endif volatile unsigned char SCMD; } wd33c93_regs; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/wd7000.c linux.pre11.3/drivers/scsi/wd7000.c --- linux.vanilla/drivers/scsi/wd7000.c Sat Jan 9 21:50:44 1999 +++ linux.pre11.3/drivers/scsi/wd7000.c Tue Jul 20 00:03:54 1999 @@ -1561,19 +1561,16 @@ break; if (i == pass) { -#if (LINUX_VERSION_CODE < 0x020100) -#else void *biosaddr = ioremap (wd7000_biosaddr[biosaddr_ptr] + signatures[sig_ptr].ofs, signatures[sig_ptr].len); -#endif - short bios_match = memcmp ((char *) biosaddr, signatures[sig_ptr].sig, + short bios_match=0; + + if(biosaddr) + bios_match = memcmp ((char *) biosaddr, signatures[sig_ptr].sig, signatures[sig_ptr].len); -#if (LINUX_VERSION_CODE < 0x020100) -#else iounmap (biosaddr); -#endif if (! bios_match) goto bios_matched; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/Config.in linux.pre11.3/drivers/sgi/Config.in --- linux.vanilla/drivers/sgi/Config.in Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/sgi/Config.in Mon Jul 19 23:28:25 1999 @@ -0,0 +1,18 @@ +# +# Character device configuration +# +mainmenu_option next_comment +comment 'SGI devices' + +bool 'SGI Zilog85C30 serial support' CONFIG_SGI_SERIAL +if [ "$CONFIG_SGI_SERIAL" != "n" ]; then + define_bool CONFIG_SERIAL y +fi + +bool 'SGI DS1286 RTC support' CONFIG_SGI_DS1286 + +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'SGI Newport Graphics support' CONFIG_SGI_NEWPORT_GFX +fi + +endmenu diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/Makefile linux.pre11.3/drivers/sgi/Makefile --- linux.vanilla/drivers/sgi/Makefile Sun Nov 8 15:08:16 1998 +++ linux.pre11.3/drivers/sgi/Makefile Mon Jul 19 23:28:23 1999 @@ -8,13 +8,15 @@ # Note 2! The CFLAGS definitions are now in the main makefile... SUB_DIRS := -MOD_SUB_DIRS := $(SUB_DIRS) +MOD_SUB_DIRS := $(SUB_DIRS) char ALL_SUB_DIRS := $(SUB_DIRS) char + L_OBJS := L_TARGET := sgi.a +MOD_LIST_NAME := SGI_MODULES -# Character devices for SGI machines. +# Character and Audio devices for SGI machines. # SUB_DIRS += char L_OBJS += char/sgichar.o diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/Makefile linux.pre11.3/drivers/sgi/char/Makefile --- linux.vanilla/drivers/sgi/char/Makefile Sun Nov 8 15:08:16 1998 +++ linux.pre11.3/drivers/sgi/char/Makefile Mon Jul 19 23:28:23 1999 @@ -8,11 +8,25 @@ # Note 2! The CFLAGS definitions are now in the main makefile... O_TARGET := sgichar.o -O_OBJS := graphics.o streamable.o newport.o cons_newport.o sgicons.o \ - vga_font.o rrm.o shmiq.o usema.o +OX_OBJS := newport.o +O_OBJS := sgicons.o \ + usema.o shmiq.o streamable.o ifeq ($(CONFIG_SGI_SERIAL),y) O_OBJS += sgiserial.o +endif + +ifeq ($(CONFIG_SGI_DS1286),y) + O_OBJS += ds1286.o +endif + +ifeq ($(CONFIG_SGI_NEWPORT_GFX),y) + O_OBJS += graphics.o rrm.o +else +ifeq ($(CONFIG_SGI_NEWPORT_GFX),m) + OX_OBJS += graphics_syms.o + MX_OBJS += graphics.o rrm.o +endif endif include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/cons_newport.c linux.pre11.3/drivers/sgi/char/cons_newport.c --- linux.vanilla/drivers/sgi/char/cons_newport.c Sun Nov 8 15:08:16 1998 +++ linux.pre11.3/drivers/sgi/char/cons_newport.c Thu Jan 1 01:00:00 1970 @@ -1,611 +0,0 @@ -/* - * cons_newport.c: Newport graphics console code for the SGI. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: cons_newport.c,v 1.1 1998/01/10 19:05:47 ecd 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 "gconsole.h" -#include "newport.h" -#include "graphics.h" /* Just for now */ -#include -#include - -#if 0 -#include "linux_logo.h" -#endif - -#define BMASK(c) (c << 24) - -#define RENDER(regs, cp) do { \ -(regs)->go.zpattern = BMASK((cp)[0x0]); (regs)->go.zpattern = BMASK((cp)[0x1]); \ -(regs)->go.zpattern = BMASK((cp)[0x2]); (regs)->go.zpattern = BMASK((cp)[0x3]); \ -(regs)->go.zpattern = BMASK((cp)[0x4]); (regs)->go.zpattern = BMASK((cp)[0x5]); \ -(regs)->go.zpattern = BMASK((cp)[0x6]); (regs)->go.zpattern = BMASK((cp)[0x7]); \ -(regs)->go.zpattern = BMASK((cp)[0x8]); (regs)->go.zpattern = BMASK((cp)[0x9]); \ -(regs)->go.zpattern = BMASK((cp)[0xa]); (regs)->go.zpattern = BMASK((cp)[0xb]); \ -(regs)->go.zpattern = BMASK((cp)[0xc]); (regs)->go.zpattern = BMASK((cp)[0xd]); \ -(regs)->go.zpattern = BMASK((cp)[0xe]); (regs)->go.zpattern = BMASK((cp)[0xf]); \ -} while(0) - -#define REVERSE_RENDER(regs, cp) do { \ -(regs)->go.zpattern = BMASK((~(cp)[0x0])); (regs)->go.zpattern = BMASK((~(cp)[0x1])); \ -(regs)->go.zpattern = BMASK((~(cp)[0x2])); (regs)->go.zpattern = BMASK((~(cp)[0x3])); \ -(regs)->go.zpattern = BMASK((~(cp)[0x4])); (regs)->go.zpattern = BMASK((~(cp)[0x5])); \ -(regs)->go.zpattern = BMASK((~(cp)[0x6])); (regs)->go.zpattern = BMASK((~(cp)[0x7])); \ -(regs)->go.zpattern = BMASK((~(cp)[0x8])); (regs)->go.zpattern = BMASK((~(cp)[0x9])); \ -(regs)->go.zpattern = BMASK((~(cp)[0xa])); (regs)->go.zpattern = BMASK((~(cp)[0xb])); \ -(regs)->go.zpattern = BMASK((~(cp)[0xc])); (regs)->go.zpattern = BMASK((~(cp)[0xd])); \ -(regs)->go.zpattern = BMASK((~(cp)[0xe])); (regs)->go.zpattern = BMASK((~(cp)[0xf])); \ -} while(0) - -extern int default_red[16], default_grn[16], default_blu[16]; -extern unsigned char video_type; - -static int cursor_pos = -1; -struct newport_regs *npregs; - -#define TESTVAL 0xdeadbeef -#define XSTI_TO_FXSTART(val) (((val) & 0xffff) << 11) - -static inline void -newport_disable_video(void) -{ - unsigned short treg; - - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_EVIDEO))); -} - -static inline void -newport_enable_video(void) -{ - unsigned short treg; - - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_EVIDEO)); -} - -static inline void -newport_disable_cursor(void) -{ - unsigned short treg; - - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_ECDISP))); -} - -#if 0 -static inline void -newport_enable_cursor(void) -{ - unsigned short treg; - - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_ECDISP)); -} -#endif - -static inline void -newport_init_cmap(void) -{ - unsigned short i; - - for(i = 0; i < 16; i++) { - newport_bfwait(); - newport_cmap_setaddr(npregs, color_table[i]); - newport_cmap_setrgb(npregs, - default_red[i], - default_grn[i], - default_blu[i]); - } -} - -#if 0 -static inline void -newport_init_cursor(void) -{ - unsigned char cursor[256]; - unsigned short *cookie; - int i; - - for(i = 0; i < 256; i++) - cursor[i] = 0x0; - for(i = 211; i < 256; i+=4) { - cursor[i] = 0xff; -#if 0 - cursor[(i + 128) << 2] = 0xff; - cursor[((i + 128) << 2) + 1] = 0xff; -#endif - } - - /* Load the SRAM on the VC2 for this new GLYPH. */ - cookie = (unsigned short *) cursor; - newport_vc2_set(npregs, VC2_IREG_RADDR, VC2_CGLYPH_ADDR); - npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM | - NPORT_DMODE_W2 | VC2_PROTOCOL); - for(i = 0; i < 128; i++) { - newport_bfwait(); - npregs->set.dcbdata0.hwords.s1 = *cookie++; - } - - /* Place the cursor at origin. */ - newport_vc2_set(npregs, VC2_IREG_CURSX, 0); - newport_vc2_set(npregs, VC2_IREG_CURSY, 0); - newport_enable_cursor(); -} -#endif - -static inline void -newport_clear_screen(void) -{ - newport_wait(); - npregs->set.wrmask = 0xffffffff; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | - NPORT_DMODE0_STOPY); - npregs->set.colori = 0; - npregs->set.xystarti = 0; - npregs->go.xyendi = (((1280 + 63) << 16)|(1024)); - newport_bfwait(); -} - -static inline void -newport_render_version(void) -{ -#if 0 - unsigned short *ush; - int currcons = 0; - char *p; - - ush = (unsigned short *) video_mem_base + video_num_columns * 2 + 20; - for (p = "SGI/Linux version " UTS_RELEASE; *p; p++, ush++) { - *ush = (attr << 8) + *p; - newport_blitc (*ush, (unsigned long) ush); - } -#endif -} - -#if 0 -static inline void -newport_render_logo(void) -{ - int i, xpos, ypos; - unsigned char *bmap; - - xpos = 8; - ypos = 18; - - newport_wait(); - npregs->set.colori = 9; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | - NPORT_DMODE0_L32); - - for(i = 0; i < 80; i+=8) { - /* Set coordinates for bitmap operation. */ - npregs->set.xystarti = ((xpos + i) << 16) | ypos; - npregs->set.xyendi = (((xpos + i) + 7) << 16); - newport_wait(); - - bmap = linux_logo + (i * 80); - RENDER(npregs, bmap); bmap += 0x10; - RENDER(npregs, bmap); bmap += 0x10; - RENDER(npregs, bmap); bmap += 0x10; - RENDER(npregs, bmap); bmap += 0x10; - RENDER(npregs, bmap); - } - prom_getchar(); - prom_imode(); -} -#endif - -static inline void -newport_render_background(int xpos, int ypos, int ci) -{ - newport_wait(); - npregs->set.wrmask = 0xffffffff; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | - NPORT_DMODE0_STOPY); - npregs->set.colori = ci; - npregs->set.xystarti = (xpos << 16) | ypos; - npregs->go.xyendi = ((xpos + 7) << 16) | (ypos + 15); -} - -void -newport_set_origin(unsigned short offset) -{ - /* maybe this works... */ - __origin = offset; -} - -void -newport_hide_cursor(void) -{ - int xpos, ypos, idx; - unsigned long flags; - - if(vt_cons[fg_console]->vc_mode == KD_GRAPHICS) - return; - save_and_cli(flags); - - idx = cursor_pos; - if(idx == -1) { - restore_flags(flags); - return; - } - xpos = 8 + ((idx % video_num_columns) << 3); - ypos = 18 + ((idx / video_num_columns) << 4); - newport_render_background(xpos, ypos, 0); - restore_flags(flags); -} - -void -newport_set_cursor(int currcons) -{ - int xpos, ypos, idx, oldpos; - unsigned short *sp, *osp, cattr; - unsigned long flags; - unsigned char *p; - - if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS) - return; - - if (__real_origin != __origin) - __set_origin(__real_origin); - - save_and_cli(flags); - - idx = (pos - video_mem_base) >> 1; - sp = (unsigned short *) pos; - oldpos = cursor_pos; - cursor_pos = idx; - if(!deccm) { - hide_cursor(); - restore_flags(flags); - return; - } - xpos = 8 + ((idx % video_num_columns) << 3); - ypos = 18 + ((idx / video_num_columns) << 4); - if(oldpos != -1) { - int oxpos, oypos; - - /* Restore old location. */ - osp = (unsigned short *) ((oldpos << 1) + video_mem_base); - oxpos = 8 + ((oldpos % video_num_columns) << 3); - oypos = 18 + ((oldpos / video_num_columns) << 4); - cattr = *osp; - newport_render_background(oxpos, oypos, (cattr & 0xf000) >> 12); - p = &vga_font[(cattr & 0xff) << 4]; - newport_wait(); - npregs->set.colori = (cattr & 0x0f00) >> 8; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | - NPORT_DMODE0_L32); - npregs->set.xystarti = (oxpos << 16) | oypos; - npregs->set.xyendi = ((oxpos + 7) << 16); - newport_wait(); - RENDER(npregs, p); - } - cattr = *sp; - newport_render_background(xpos, ypos, (cattr & 0xf000) >> 12); - p = &vga_font[(cattr & 0xff) << 4]; - newport_wait(); - npregs->set.colori = (cattr & 0x0f00) >> 8; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | - NPORT_DMODE0_L32); - npregs->set.xystarti = (xpos << 16) | ypos; - npregs->set.xyendi = ((xpos + 7) << 16); - newport_wait(); - REVERSE_RENDER(npregs, p); - restore_flags (flags); - return; -} - -void -newport_get_scrmem(int currcons) -{ - memcpyw((unsigned short *)vc_scrbuf[currcons], - (unsigned short *)origin, video_screen_size); - origin = video_mem_start = (unsigned long)vc_scrbuf[currcons]; - scr_end = video_mem_end = video_mem_start + video_screen_size; - pos = origin + y*video_size_row + (x<<1); -} - -void -newport_set_scrmem(int currcons, long offset) -{ - if (video_mem_term - video_mem_base < offset + video_screen_size) - offset = 0; - memcpyw((unsigned short *)(video_mem_base + offset), - (unsigned short *) origin, video_screen_size); - video_mem_start = video_mem_base; - video_mem_end = video_mem_term; - origin = video_mem_base + offset; - scr_end = origin + video_screen_size; - pos = origin + y*video_size_row + (x<<1); - has_wrapped = 0; -} - -int -newport_set_get_cmap(unsigned char * arg, int set) -{ - unsigned short ent; - int i; - - i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, 16*3); - if (i) - return i; - - for (i=0; i<16; i++) { - if (set) { - __get_user(default_red[i], arg++); - __get_user(default_grn[i], arg++); - __get_user(default_blu[i], arg++); - } else { - __put_user (default_red[i], arg++); - __put_user (default_grn[i], arg++); - __put_user (default_blu[i], arg++); - } - } - if (set) { - for (i=0; ivc_palette[k++] = - default_red[j]; - vc_cons[i].d->vc_palette[k++] = - default_grn[j]; - vc_cons[i].d->vc_palette[k++] = - default_blu[j]; - } - } - } - if(console_blanked || vt_cons[fg_console]->vc_mode == KD_GRAPHICS) - return 0; - for(ent = 0; ent < 16; ent++) { - newport_bfwait(); - newport_cmap_setaddr(npregs, ent); - newport_cmap_setrgb(npregs, - default_red[ent], - default_grn[ent], - default_blu[ent]); - } - } - - return 0; -} - -void -newport_blitc(unsigned short charattr, unsigned long addr) -{ - int idx, xpos, ypos; - unsigned char *p; - - idx = (addr - (video_mem_base + (__origin<<1))) >> 1; - xpos = 8 + ((idx % video_num_columns) << 3); - ypos = 18 + ((idx / video_num_columns) << 4); - - p = &vga_font[(charattr & 0xff) << 4]; - charattr = (charattr >> 8) & 0xff; - - newport_render_background(xpos, ypos, (charattr & 0xf0) >> 4); - - /* Set the color and drawing mode. */ - newport_wait(); - npregs->set.colori = charattr & 0xf; - npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | - NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB | - NPORT_DMODE0_L32); - - /* Set coordinates for bitmap operation. */ - npregs->set.xystarti = (xpos << 16) | ypos; - npregs->set.xyendi = ((xpos + 7) << 16); - newport_wait(); - - /* Go, baby, go... */ - RENDER(npregs, p); -} - -void -newport_memsetw(void * s, unsigned short c, unsigned int count) -{ - unsigned short * addr = (unsigned short *) s; - - count /= 2; - if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS) { - while (count) { - count--; - *addr++ = c; - } - return; - } - if ((unsigned long) addr + count > video_mem_term || - (unsigned long) addr < video_mem_base) { - if ((unsigned long) addr + count <= video_mem_term || - (unsigned long) addr > video_mem_base) { - while (count) { - count--; - *addr++ = c; - } - return; - } else { - while (count) { - count--; - scr_writew(c, addr++); - } - } - } else { - while (count) { - count--; - if (*addr != c) { - newport_blitc(c, (unsigned long)addr); - *addr++ = c; - } else - addr++; - } - } -} - -void -newport_memcpyw(unsigned short *to, unsigned short *from, unsigned int count) -{ - if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS) { - memcpy(to, from, count); - return; - } - if ((unsigned long) to + count > video_mem_term || - (unsigned long) to < video_mem_base) { - if ((unsigned long) to + count <= video_mem_term || - (unsigned long) to > video_mem_base) - memcpy(to, from, count); - else { - count /= 2; - while (count) { - count--; - scr_writew(scr_readw(from++), to++); - } - } - } else { - count /= 2; - while (count) { - count--; - if (*to != *from) { - newport_blitc(*from, (unsigned long)to); - *to++ = *from++; - } else { - from++; - to++; - } - } - } -} - -struct console_ops newport_console = { - newport_set_origin, - newport_hide_cursor, - newport_set_cursor, - newport_get_scrmem, - newport_set_scrmem, - newport_set_get_cmap, - newport_blitc, - newport_memsetw, - newport_memcpyw -}; - -/* Currently hard-coded values that are the same as those found on my system */ -struct ng1_info newport_board_info = { - { "NG1", "" /* what is the label? */, 1280, 1024, sizeof (struct ng1_info) }, - 6, /* boardrev */ - 1, /* rex3rev */ - 0, /* vc2rev */ - 2, /* monitor type */ - 0, /* videoinstalled */ - 3, /* mcrev */ - 24, /* bitplanes */ - 0, /* xmap9rev */ - 2, /* cmaprev */ - { 256, 1280, 1024, 76}, /* ng1_vof_info */ - 13, /* paneltype */ - 0 -}; - -void -newport_reset (void) -{ - newport_wait(); - newport_enable_video(); - - /* Init the cursor disappear. */ - newport_wait(); -#if 0 - newport_init_cursor(); -#else - newport_disable_cursor(); -#endif - - newport_init_cmap(); - - /* Clear the screen. */ - newport_clear_screen(); -} - -/* right now the newport does not do anything at all */ -struct graphics_ops newport_graphic_ops = { - 0, /* owner */ - 0, /* current user */ - (void *) &newport_board_info, /* board info */ - sizeof (struct ng1_info), /* size of our data structure */ - 0, 0, /* g_regs, g_regs_size */ - newport_save, newport_restore, /* g_save_context, g_restore_context */ - newport_reset, newport_ioctl /* g_reset_console, g_ioctl */ -}; - -struct graphics_ops * -newport_probe (int slot, const char **name) -{ - struct newport_regs *p; - - npregs = (struct newport_regs *) (KSEG1 + 0x1f0f0000); - - p = npregs; - p->cset.config = NPORT_CFG_GD0; - - if(newport_wait()) { - prom_printf("whoops, timeout, no NEWPORT there?"); - return 0; - } - - p->set.xstarti = TESTVAL; if(p->set._xstart.i != XSTI_TO_FXSTART(TESTVAL)) { - prom_printf("newport_probe: read back wrong value ;-(\n"); - return 0; - } - - if (slot == 0){ - register_gconsole (&newport_console); - video_type = VIDEO_TYPE_SGI; - can_do_color = 1; - *name = "NEWPORT"; - } - - newport_reset (); - newport_render_version(); -#if 0 - newport_render_logo(); -#endif - newport_graphic_ops.g_regs = 0x1f0f0000; - newport_graphic_ops.g_regs_size = sizeof (struct newport_regs); - return &newport_graphic_ops; -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/ds1286.c linux.pre11.3/drivers/sgi/char/ds1286.c --- linux.vanilla/drivers/sgi/char/ds1286.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/sgi/char/ds1286.c Mon Jul 19 23:28:23 1999 @@ -0,0 +1,570 @@ +/* $Id: ds1286.c,v 1.3.2.3 1999/06/17 12:08:44 ralf Exp $ + * + * Real Time Clock interface for Linux + * + * Copyright (C) 1998, 1999 Ralf Baechle + * + * Based on code written by Paul Gortmaker. + * + * This driver allows use of the real time clock (built into + * nearly all computers) from user space. It exports the /dev/rtc + * interface supporting various ioctl() and also the /proc/rtc + * pseudo-file for status information. + * + * The ioctls can be used to set the interrupt behaviour and + * generation rate from the RTC via IRQ 8. Then the /dev/rtc + * interface can be used to make use of these timer interrupts, + * be they interval or alarm based. + * + * The /dev/rtc interface will block on reads until an interrupt + * has been received. If a RTC interrupt has already happened, + * it will output an unsigned long and then block. The output value + * contains the interrupt status in the low byte and the number of + * interrupts since the last read in the remaining high bytes. The + * /dev/rtc interface can also be used with the select(2) call. + * + * This program is free software; you can redistribute 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 + +#define DS1286_VERSION "1.0" + +/* + * We sponge a minor off of the misc major. No need slurping + * up another valuable major dev number for this. If you add + * an ioctl, make sure you don't conflict with SPARC's RTC + * ioctls. + */ + +static struct wait_queue *ds1286_wait; + +static long long ds1286_llseek(struct file *file, loff_t offset, int origin); + +static ssize_t ds1286_read(struct file *file, char *buf, + size_t count, loff_t *ppos); + +static int ds1286_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); + +static unsigned int ds1286_poll(struct file *file, poll_table *wait); + +void get_rtc_time (struct rtc_time *rtc_tm); +void get_rtc_alm_time (struct rtc_time *alm_tm); + +void set_rtc_irq_bit(unsigned char bit); +void clear_rtc_irq_bit(unsigned char bit); + +static inline unsigned char ds1286_is_updating(void); + +#ifdef __SMP__ +static spinlock_t ds1286_lock = SPIN_LOCK_UNLOCKED; +#endif + +/* + * Bits in rtc_status. (7 bits of room for future expansion) + */ + +#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ +#define RTC_TIMER_ON 0x02 /* missed irq timer active */ + +unsigned char ds1286_status = 0; /* bitmapped status byte. */ +unsigned long ds1286_freq = 0; /* Current periodic IRQ rate */ +unsigned long ds1286_irq_data = 0; /* our output to the world */ + +unsigned char days_in_mo[] = +{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +/* + * A very tiny interrupt handler. It runs with SA_INTERRUPT set, + * so that there is no possibility of conflicting with the + * set_rtc_mmss() call that happens during some timer interrupts. + * (See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.) + */ + +/* + * Now all the various file operations that we export. + */ + +static long long ds1286_llseek(struct file *file, loff_t offset, int origin) +{ + return -ESPIPE; +} + +static ssize_t ds1286_read(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ + struct wait_queue wait = { current, NULL }; + unsigned long data; + ssize_t retval; + + if (count < sizeof(unsigned long)) + return -EINVAL; + + add_wait_queue(&ds1286_wait, &wait); + + current->state = TASK_INTERRUPTIBLE; + + while ((data = xchg(&ds1286_irq_data, 0)) == 0) { + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + goto out; + } + if (signal_pending(current)) { + retval = -ERESTARTSYS; + goto out; + } + schedule(); + } + + retval = put_user(data, (unsigned long *)buf); + if (!retval) + retval = sizeof(unsigned long); + out: + current->state = TASK_RUNNING; + remove_wait_queue(&ds1286_wait, &wait); + + return retval; +} + +static int ds1286_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + + struct rtc_time wtime; + + switch (cmd) { + case RTC_AIE_OFF: /* Mask alarm int. enab. bit */ + { + unsigned int flags; + unsigned char val; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + spin_lock_irqsave(&ds1286_lock, flags); + val = CMOS_READ(RTC_CMD); + val |= RTC_TDM; + CMOS_WRITE(val, RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + return 0; + } + case RTC_AIE_ON: /* Allow alarm interrupts. */ + { + unsigned int flags; + unsigned char val; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + spin_lock_irqsave(&ds1286_lock, flags); + val = CMOS_READ(RTC_CMD); + val &= ~RTC_TDM; + CMOS_WRITE(val, RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + return 0; + } + case RTC_WIE_OFF: /* Mask watchdog int. enab. bit */ + { + unsigned int flags; + unsigned char val; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + spin_lock_irqsave(&ds1286_lock, flags); + val = CMOS_READ(RTC_CMD); + val |= RTC_WAM; + CMOS_WRITE(val, RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + return 0; + } + case RTC_WIE_ON: /* Allow watchdog interrupts. */ + { + unsigned int flags; + unsigned char val; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + spin_lock_irqsave(&ds1286_lock, flags); + val = CMOS_READ(RTC_CMD); + val &= ~RTC_WAM; + CMOS_WRITE(val, RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + return 0; + } + case RTC_ALM_READ: /* Read the present alarm time */ + { + /* + * This returns a struct rtc_time. Reading >= 0xc0 + * means "don't care" or "match all". Only the tm_hour, + * tm_min, and tm_sec values are filled in. + */ + + get_rtc_alm_time(&wtime); + break; + } + case RTC_ALM_SET: /* Store a time into the alarm */ + { + /* + * This expects a struct rtc_time. Writing 0xff means + * "don't care" or "match all". Only the tm_hour, + * tm_min and tm_sec are used. + */ + unsigned char hrs, min, sec; + struct rtc_time alm_tm; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + if (copy_from_user(&alm_tm, (struct rtc_time*)arg, + sizeof(struct rtc_time))) + return -EFAULT; + + hrs = alm_tm.tm_hour; + min = alm_tm.tm_min; + + if (hrs >= 24) + hrs = 0xff; + + if (min >= 60) + min = 0xff; + + BIN_TO_BCD(sec); + BIN_TO_BCD(min); + BIN_TO_BCD(hrs); + + spin_lock(&ds1286_lock); + CMOS_WRITE(hrs, RTC_HOURS_ALARM); + CMOS_WRITE(min, RTC_MINUTES_ALARM); + spin_unlock(&ds1286_lock); + + return 0; + } + case RTC_RD_TIME: /* Read the time/date from RTC */ + { + get_rtc_time(&wtime); + break; + } + case RTC_SET_TIME: /* Set the RTC */ + { + struct rtc_time rtc_tm; + unsigned char mon, day, hrs, min, sec, leap_yr; + unsigned char save_control; + unsigned int yrs, flags; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, + sizeof(struct rtc_time))) + return -EFAULT; + + yrs = rtc_tm.tm_year + 1900; + mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ + day = rtc_tm.tm_mday; + hrs = rtc_tm.tm_hour; + min = rtc_tm.tm_min; + sec = rtc_tm.tm_sec; + + if (yrs < 1970) + return -EINVAL; + + leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); + + if ((mon > 12) || (day == 0)) + return -EINVAL; + + if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) + return -EINVAL; + + if ((hrs >= 24) || (min >= 60) || (sec >= 60)) + return -EINVAL; + + if ((yrs -= 1940) > 255) /* They are unsigned */ + return -EINVAL; + + if (yrs >= 100) + yrs -= 100; + + BIN_TO_BCD(sec); + BIN_TO_BCD(min); + BIN_TO_BCD(hrs); + BIN_TO_BCD(day); + BIN_TO_BCD(mon); + BIN_TO_BCD(yrs); + + spin_lock_irqsave(&ds1286_lock, flags); + save_control = CMOS_READ(RTC_CMD); + CMOS_WRITE((save_control|RTC_TE), RTC_CMD); + + CMOS_WRITE(yrs, RTC_YEAR); + CMOS_WRITE(mon, RTC_MONTH); + CMOS_WRITE(day, RTC_DATE); + CMOS_WRITE(hrs, RTC_HOURS); + CMOS_WRITE(min, RTC_MINUTES); + CMOS_WRITE(sec, RTC_SECONDS); + CMOS_WRITE(0, RTC_HUNDREDTH_SECOND); + + CMOS_WRITE(save_control, RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + return 0; + } + default: + return -EINVAL; + } + return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; +} + +/* + * We enforce only one user at a time here with the open/close. + * Also clear the previous interrupt data on an open, and clean + * up things on a close. + */ + +static int ds1286_open(struct inode *inode, struct file *file) +{ + if(ds1286_status & RTC_IS_OPEN) + return -EBUSY; + + ds1286_status |= RTC_IS_OPEN; + ds1286_irq_data = 0; + return 0; +} + +static int ds1286_release(struct inode *inode, struct file *file) +{ + ds1286_status &= ~RTC_IS_OPEN; + return 0; +} + +static unsigned int ds1286_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &ds1286_wait, wait); + if (ds1286_irq_data != 0) + return POLLIN | POLLRDNORM; + return 0; +} + +/* + * The various file operations we support. + */ + +static struct file_operations ds1286_fops = { + ds1286_llseek, + ds1286_read, + NULL, /* No write */ + NULL, /* No readdir */ + ds1286_poll, + ds1286_ioctl, + NULL, /* No mmap */ + ds1286_open, + NULL, /* No flush */ + ds1286_release +}; + +static struct miscdevice ds1286_dev= +{ + RTC_MINOR, + "rtc", + &ds1286_fops +}; + +__initfunc(int ds1286_init(void)) +{ + printk(KERN_INFO "DS1286 Real Time Clock Driver v%s\n", DS1286_VERSION); + misc_register(&ds1286_dev); + + ds1286_wait = NULL; + + return 0; +} + +static char *days[] = { + "***", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + +/* + * Info exported via "/proc/rtc". + */ +int get_ds1286_status(char *buf) +{ + char *p, *s; + struct rtc_time tm; + unsigned char hundredth, month, cmd, amode; + + p = buf; + + get_rtc_time(&tm); + hundredth = CMOS_READ(RTC_HUNDREDTH_SECOND); + hundredth = BCD_TO_BIN(hundredth); + + p += sprintf(p, + "rtc_time\t: %02d:%02d:%02d.%02d\n" + "rtc_date\t: %04d-%02d-%02d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, hundredth, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); + + /* + * We implicitly assume 24hr mode here. Alarm values >= 0xc0 will + * match any value for that particular field. Values that are + * greater than a valid time, but less than 0xc0 shouldn't appear. + */ + get_rtc_alm_time(&tm); + p += sprintf(p, "alarm\t\t: %s ", days[tm.tm_wday]); + if (tm.tm_hour <= 24) + p += sprintf(p, "%02d:", tm.tm_hour); + else + p += sprintf(p, "**:"); + + if (tm.tm_min <= 59) + p += sprintf(p, "%02d\n", tm.tm_min); + else + p += sprintf(p, "**\n"); + + month = CMOS_READ(RTC_MONTH); + p += sprintf(p, + "oscillator\t: %s\n" + "square_wave\t: %s\n", + (month & RTC_EOSC) ? "disabled" : "enabled", + (month & RTC_ESQW) ? "disabled" : "enabled"); + + amode = ((CMOS_READ(RTC_MINUTES_ALARM) & 0x80) >> 5) | + ((CMOS_READ(RTC_HOURS_ALARM) & 0x80) >> 6) | + ((CMOS_READ(RTC_DAY_ALARM) & 0x80) >> 7); + if (amode == 7) s = "each minute"; + else if (amode == 3) s = "minutes match"; + else if (amode == 1) s = "hours and minutes match"; + else if (amode == 0) s = "days, hours and minutes match"; + else s = "invalid"; + p += sprintf(p, "alarm_mode\t: %s\n", s); + + cmd = CMOS_READ(RTC_CMD); + p += sprintf(p, + "alarm_enable\t: %s\n" + "wdog_alarm\t: %s\n" + "alarm_mask\t: %s\n" + "wdog_alarm_mask\t: %s\n" + "interrupt_mode\t: %s\n" + "INTB_mode\t: %s_active\n" + "interrupt_pins\t: %s\n", + (cmd & RTC_TDF) ? "yes" : "no", + (cmd & RTC_WAF) ? "yes" : "no", + (cmd & RTC_TDM) ? "disabled" : "enabled", + (cmd & RTC_WAM) ? "disabled" : "enabled", + (cmd & RTC_PU_LVL) ? "pulse" : "level", + (cmd & RTC_IBH_LO) ? "low" : "high", + (cmd & RTC_IPSW) ? "unswapped" : "swapped"); + + return p - buf; +} + +/* + * Returns true if a clock update is in progress + */ +static inline unsigned char ds1286_is_updating(void) +{ + return CMOS_READ(RTC_CMD) & RTC_TE; +} + +void get_rtc_time(struct rtc_time *rtc_tm) +{ + unsigned long uip_watchdog = jiffies; + unsigned char save_control; + unsigned int flags; + + /* + * read RTC once any update in progress is done. The update + * can take just over 2ms. We wait 10 to 20ms. There is no need to + * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP. + * If you need to know *exactly* when a second has started, enable + * periodic update complete interrupts, (via ioctl) and then + * immediately read /dev/rtc which will block until you get the IRQ. + * Once the read clears, read the RTC time (again via ioctl). Easy. + */ + + if (ds1286_is_updating() != 0) + while (jiffies - uip_watchdog < 2*HZ/100) + barrier(); + + /* + * Only the values that we read from the RTC are set. We leave + * tm_wday, tm_yday and tm_isdst untouched. Even though the + * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated + * by the RTC when initially set to a non-zero value. + */ + spin_lock_irqsave(&ds1286_lock, flags); + save_control = CMOS_READ(RTC_CMD); + CMOS_WRITE((save_control|RTC_TE), RTC_CMD); + + rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); + rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); + rtc_tm->tm_hour = CMOS_READ(RTC_HOURS) & 0x1f; + rtc_tm->tm_mday = CMOS_READ(RTC_DATE); + rtc_tm->tm_mon = CMOS_READ(RTC_MONTH) & 0x1f; + rtc_tm->tm_year = CMOS_READ(RTC_YEAR); + + CMOS_WRITE(save_control, RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + BCD_TO_BIN(rtc_tm->tm_sec); + BCD_TO_BIN(rtc_tm->tm_min); + BCD_TO_BIN(rtc_tm->tm_hour); + BCD_TO_BIN(rtc_tm->tm_mday); + BCD_TO_BIN(rtc_tm->tm_mon); + BCD_TO_BIN(rtc_tm->tm_year); + + /* + * Account for differences between how the RTC uses the values + * and how they are defined in a struct rtc_time; + */ + if (rtc_tm->tm_year < 45) + rtc_tm->tm_year += 30; + if ((rtc_tm->tm_year += 40) < 70) + rtc_tm->tm_year += 100; + + rtc_tm->tm_mon--; +} + +void get_rtc_alm_time(struct rtc_time *alm_tm) +{ + unsigned char cmd; + unsigned int flags; + + /* + * Only the values that we read from the RTC are set. That + * means only tm_wday, tm_hour, tm_min. + */ + spin_lock_irqsave(&ds1286_lock, flags); + alm_tm->tm_min = CMOS_READ(RTC_MINUTES_ALARM) & 0x7f; + alm_tm->tm_hour = CMOS_READ(RTC_HOURS_ALARM) & 0x1f; + alm_tm->tm_wday = CMOS_READ(RTC_DAY_ALARM) & 0x07; + cmd = CMOS_READ(RTC_CMD); + spin_unlock_irqrestore(&ds1286_lock, flags); + + BCD_TO_BIN(alm_tm->tm_min); + BCD_TO_BIN(alm_tm->tm_hour); + alm_tm->tm_sec = 0; +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/graphics.c linux.pre11.3/drivers/sgi/char/graphics.c --- linux.vanilla/drivers/sgi/char/graphics.c Sun Nov 8 15:08:17 1998 +++ linux.pre11.3/drivers/sgi/char/graphics.c Mon Jul 19 23:28:23 1999 @@ -1,7 +1,10 @@ -/* +/* $Id: graphics.c,v 1.16 1999/04/01 23:45:00 ulfc Exp $ + * * gfx.c: support for SGI's /dev/graphics, /dev/opengl * * Author: Miguel de Icaza (miguel@nuclecu.unam.mx) + * Ralf Baechle (ralf@gnu.org) + * Ulf Carlsson (ulfc@bun.falkenberg.se) * * On IRIX, /dev/graphics is [10, 146] * /dev/opengl is [10, 147] @@ -21,35 +24,56 @@ * We implement those misterious things, and tried not to think about * the reasons behind them. */ +#include #include +#include #include #include #include #include +#include +#include #include #include "gconsole.h" #include "graphics.h" +#include "usema.h" #include #include #include #include +#include -/* The boards */ -#include "newport.h" +#define DEBUG -#ifdef PRODUCTION_DRIVER -#define enable_gconsole() -#define disable_gconsole() -#endif +/* The boards */ +extern struct graphics_ops *newport_probe (int, const char **); static struct graphics_ops cards [MAXCARDS]; static int boards; #define GRAPHICS_CARD(inode) 0 +/* +void enable_gconsole(void) {}; +void disable_gconsole(void) {}; +*/ + + int sgi_graphics_open (struct inode *inode, struct file *file) { + struct newport_regs *nregs = + (struct newport_regs *) KSEG1ADDR(cards[0].g_regs); + + newport_wait(); + nregs->set.wrmask = 0xffffffff; + nregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK | + NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX | + NPORT_DMODE0_STOPY); + nregs->set.colori = 1; + nregs->set.xystarti = (0 << 16) | 0; + nregs->go.xyendi = (1280 << 16) | 1024; + return 0; } @@ -59,10 +83,10 @@ unsigned int board; unsigned int devnum = GRAPHICS_CARD (inode->i_rdev); int i; - + if ((cmd >= RRM_BASE) && (cmd <= RRM_CMD_LIMIT)) return rrm_command (cmd-RRM_BASE, (void *) arg); - + switch (cmd){ case GFX_GETNUM_BOARDS: return boards; @@ -113,7 +137,7 @@ printk ("Parameter board does not match the current board\n"); return -EINVAL; } - + if (board >= boards) return -EINVAL; @@ -126,11 +150,11 @@ * sgi_graphics_mmap */ disable_gconsole (); - r = do_mmap (file, (unsigned long)vaddr, cards [board].g_regs_size, - PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE, 0); + r = do_mmap (file, (unsigned long)vaddr, + cards[board].g_regs_size, PROT_READ|PROT_WRITE, + MAP_FIXED|MAP_PRIVATE, 0); if (r) return r; - } /* Strange, the real mapping seems to be done at GFX_ATTACH_BOARD, @@ -141,13 +165,13 @@ case GFX_LABEL: return 0; - + /* Version check * for my IRIX 6.2 X server, this is what the kernel returns */ case 1: return 3; - + /* Xsgi does not use this one, I assume minor is the board being queried */ case GFX_IS_MANAGED: if (devnum > boards) @@ -166,14 +190,15 @@ sgi_graphics_close (struct inode *inode, struct file *file) { int board = GRAPHICS_CARD (inode->i_rdev); - + /* Tell the rendering manager that one client is going away */ rrm_close (inode, file); /* Was this file handle from the board owner?, clear it */ if (current == cards [board].g_owner){ cards [board].g_owner = 0; - (*cards [board].g_reset_console)(); + if (cards [board].g_reset_console) + (*cards [board].g_reset_console)(); enable_gconsole (); } return 0; @@ -184,37 +209,42 @@ */ unsigned long -sgi_graphics_nopage (struct vm_area_struct *vma, unsigned long address, int write_access) +sgi_graphics_nopage (struct vm_area_struct *vma, unsigned long address, int + no_share) { - unsigned long page; + pgd_t *pgd; pmd_t *pmd; pte_t *pte; int board = GRAPHICS_CARD (vma->vm_dentry->d_inode->i_rdev); -#ifdef DEBUG_GRAPHICS - printk ("Got a page fault for board %d address=%lx guser=%lx\n", board, address, - cards [board].g_user); + unsigned long virt_add, phys_add; + +#ifdef DEBUG + printk ("Got a page fault for board %d address=%lx guser=%lx\n", board, + address, (unsigned long) cards[board].g_user); #endif - /* 1. figure out if another process has this mapped, - * and revoke the mapping in that case. - */ - if (cards [board].g_user && cards [board].g_user != current){ - /* FIXME: save graphics context here, dump it to rendering node? */ - remove_mapping (cards [board].g_user, vma->vm_start, vma->vm_end); + /* Figure out if another process has this mapped, and revoke the mapping + * in that case. */ + if (cards[board].g_user && cards[board].g_user != current) { + /* FIXME: save graphics context here, dump it to rendering + * node? */ + + remove_mapping(cards[board].g_user, vma->vm_start, vma->vm_end); } + cards [board].g_user = current; -#if DEBUG_GRAPHICS - printk ("Registers: 0x%lx\n", cards [board].g_regs); - printk ("vm_start: 0x%lx\n", vma->vm_start); - printk ("address: 0x%lx\n", address); - printk ("diff: 0x%lx\n", (address - vma->vm_start)); - printk ("page/pfn: 0x%lx\n", page); - printk ("TLB entry: %lx\n", pte_val (mk_pte (page + PAGE_OFFSET, PAGE_USERIO))); -#endif - - /* 2. Map this into the current process address space */ - page = ((cards [board].g_regs) + (address - vma->vm_start)); - return page + PAGE_OFFSET; + /* Map the physical address of the newport registers into the address + * space of this process */ + + virt_add = address & PAGE_MASK; + phys_add = cards[board].g_regs + virt_add - vma->vm_start; + remap_page_range(virt_add, phys_add, PAGE_SIZE, vma->vm_page_prot); + + pgd = pgd_offset(current->mm, address); + pmd = pmd_offset(pgd, address); + pte = pte_offset(pmd, address); + printk("page: %08lx\n", pte_page(*pte)); + return pte_page(*pte); } /* @@ -237,7 +267,7 @@ }; int -sgi_graphics_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma) +sgi_graphics_mmap (struct file *file, struct vm_area_struct *vma) { uint size; @@ -250,12 +280,13 @@ /* 2. Set the special tlb permission bits */ vma->vm_page_prot = PAGE_USERIO; - + /* final setup */ - vma->vm_dentry = dget (file->f_dentry); + vma->vm_file = file; return 0; } - + +#if 0 /* Do any post card-detection setup on graphics_ops */ static void graphics_ops_post_init (int slot) @@ -264,6 +295,7 @@ cards [slot].g_owner = (struct task_struct *) 0; cards [slot].g_user = (struct task_struct *) 0; } +#endif struct file_operations sgi_graphics_fops = { NULL, /* llseek */ @@ -284,33 +316,36 @@ /* /dev/graphics */ static struct miscdevice dev_graphics = { - SGI_GRAPHICS_MINOR, "sgi-graphics", &sgi_graphics_fops + SGI_GRAPHICS_MINOR, "sgi-graphics", &sgi_graphics_fops }; /* /dev/opengl */ static struct miscdevice dev_opengl = { - SGI_OPENGL_MINOR, "sgi-opengl", &sgi_graphics_fops + SGI_OPENGL_MINOR, "sgi-opengl", &sgi_graphics_fops }; /* This is called later from the misc-init routine */ -void -gfx_register (void) +__initfunc(void gfx_register (void)) { misc_register (&dev_graphics); misc_register (&dev_opengl); } -void -gfx_init (const char **name) +__initfunc(void gfx_init (const char **name)) { +#if 0 struct console_ops *console; struct graphics_ops *g; +#endif printk ("GFX INIT: "); shmiq_init (); usema_init (); - - if ((g = newport_probe (boards, name)) != 0){ + + boards++; + +#if 0 + if ((g = newport_probe (boards, name)) != 0) { cards [boards] = *g; graphics_ops_post_init (boards); boards++; @@ -318,11 +353,39 @@ } /* Add more graphic drivers here */ /* Keep passing console around */ - - if (boards > MAXCARDS){ - printk ("Too many cards found on the system\n"); - prom_halt (); +#endif + + if (boards > MAXCARDS) + printk (KERN_WARNING "Too many cards found on the system\n"); +} + +#ifdef MODULE +int init_module(void) { + static int initiated = 0; + + printk("SGI Newport Graphics version %i.%i.%i\n",42,54,69); + + if (!initiated++) { + shmiq_init(); + usema_init(); + printk("Adding first board\n"); + boards++; + cards[0].g_regs = 0x1f0f0000; + cards[0].g_regs_size = sizeof (struct newport_regs); } + + printk("Boards: %d\n", boards); + + misc_register (&dev_graphics); + misc_register (&dev_opengl); + + return 0; } +void cleanup_module(void) { + printk("Shutting down SGI Newport Graphics\n"); + misc_deregister (&dev_graphics); + misc_deregister (&dev_opengl); +} +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/graphics.h linux.pre11.3/drivers/sgi/char/graphics.h --- linux.vanilla/drivers/sgi/char/graphics.h Sun Nov 8 15:08:17 1998 +++ linux.pre11.3/drivers/sgi/char/graphics.h Mon Jul 19 23:28:23 1999 @@ -25,4 +25,3 @@ void shmiq_init (void); void streamable_init (void); -void usema_init (void); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/graphics_syms.c linux.pre11.3/drivers/sgi/char/graphics_syms.c --- linux.vanilla/drivers/sgi/char/graphics_syms.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/sgi/char/graphics_syms.c Mon Jul 19 23:28:25 1999 @@ -0,0 +1,37 @@ +/* + * graphics_syms.c: interfaces for SGI Indy newport graphics + * + * Copyright (C) 1999 Alex deVries + * + * We should not even be trying to compile this if we are not doing + * a module. + */ + +#define __NO_VERSION__ +#include +#include + +/* extern int rrm_command (unsigned int cmd, void *arg); +extern int rrm_close (struct inode *inode, struct file *file); +EXPORT_SYMBOL(rrm_command); +EXPORT_SYMBOL(rrm_close); + + +*/ +extern void shmiq_init (void); +extern void usema_init(void); + +EXPORT_SYMBOL(shmiq_init); +EXPORT_SYMBOL(usema_init); + +extern void disable_gconsole(void); +extern void enable_gconsole(void); +extern void remove_mapping (struct task_struct *task, unsigned long start, + unsigned long end); + +EXPORT_SYMBOL(disable_gconsole); +EXPORT_SYMBOL(enable_gconsole); +EXPORT_SYMBOL(remove_mapping); + + + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/newport.c linux.pre11.3/drivers/sgi/char/newport.c --- linux.vanilla/drivers/sgi/char/newport.c Sun Nov 8 15:08:17 1998 +++ linux.pre11.3/drivers/sgi/char/newport.c Mon Jul 19 23:28:23 1999 @@ -4,13 +4,20 @@ * * Author: Miguel de Icaza */ + #include #include #include #include #include #include -#include "newport.h" +#include +#include +#include + +struct newport_regs *npregs; + +EXPORT_SYMBOL(npregs); /* Kernel routines for supporting graphics context switching */ @@ -167,7 +174,6 @@ { switch (cmd){ case NG1_SETDISPLAYMODE: { - int i; struct ng1_setdisplaymode_args request; if (copy_from_user (&request, (void *) arg, sizeof (request))) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/newport.h linux.pre11.3/drivers/sgi/char/newport.h --- linux.vanilla/drivers/sgi/char/newport.h Sun Nov 8 15:08:17 1998 +++ linux.pre11.3/drivers/sgi/char/newport.h Thu Jan 1 01:00:00 1970 @@ -1,585 +0,0 @@ -/* $Id: newport.h,v 1.1 1998/01/10 19:05:58 ecd Exp $ - * newport.h: Defines and register layout for NEWPORT graphics - * hardware. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ - -#ifndef _SGI_NEWPORT_H -#define _SGI_NEWPORT_H - - -typedef volatile unsigned long npireg_t; - -union npfloat { - volatile float f; - npireg_t i; -}; - -typedef union npfloat npfreg_t; - -union np_dcb { - npireg_t all; - struct { volatile unsigned short s0, s1; } hwords; - struct { volatile unsigned char b0, b1, b2, b3; } bytes; -}; - -struct newport_rexregs { - npireg_t drawmode1; /* GL extra mode bits */ - -#define DM1_PLANES 0x00000007 -#define DM1_NOPLANES 0x00000000 -#define DM1_RGBPLANES 0x00000001 -#define DM1_RGBAPLANES 0x00000002 -#define DM1_OLAYPLANES 0x00000004 -#define DM1_PUPPLANES 0x00000005 -#define DM1_CIDPLANES 0x00000006 - -#define NPORT_DMODE1_DDMASK 0x00000018 -#define NPORT_DMODE1_DD4 0x00000000 -#define NPORT_DMODE1_DD8 0x00000008 -#define NPORT_DMODE1_DD12 0x00000010 -#define NPORT_DMODE1_DD24 0x00000018 -#define NPORT_DMODE1_DSRC 0x00000020 -#define NPORT_DMODE1_YFLIP 0x00000040 -#define NPORT_DMODE1_RWPCKD 0x00000080 -#define NPORT_DMODE1_HDMASK 0x00000300 -#define NPORT_DMODE1_HD4 0x00000000 -#define NPORT_DMODE1_HD8 0x00000100 -#define NPORT_DMODE1_HD12 0x00000200 -#define NPORT_DMODE1_HD32 0x00000300 -#define NPORT_DMODE1_RWDBL 0x00000400 -#define NPORT_DMODE1_ESWAP 0x00000800 /* Endian swap */ -#define NPORT_DMODE1_CCMASK 0x00007000 -#define NPORT_DMODE1_CCLT 0x00001000 -#define NPORT_DMODE1_CCEQ 0x00002000 -#define NPORT_DMODE1_CCGT 0x00004000 -#define NPORT_DMODE1_RGBMD 0x00008000 -#define NPORT_DMODE1_DENAB 0x00010000 /* Dither enable */ -#define NPORT_DMODE1_FCLR 0x00020000 /* Fast clear */ -#define NPORT_DMODE1_BENAB 0x00040000 /* Blend enable */ -#define NPORT_DMODE1_SFMASK 0x00380000 -#define NPORT_DMODE1_SF0 0x00000000 -#define NPORT_DMODE1_SF1 0x00080000 -#define NPORT_DMODE1_SFDC 0x00100000 -#define NPORT_DMODE1_SFMDC 0x00180000 -#define NPORT_DMODE1_SFSA 0x00200000 -#define NPORT_DMODE1_SFMSA 0x00280000 -#define NPORT_DMODE1_DFMASK 0x01c00000 -#define NPORT_DMODE1_DF0 0x00000000 -#define NPORT_DMODE1_DF1 0x00400000 -#define NPORT_DMODE1_DFSC 0x00800000 -#define NPORT_DMODE1_DFMSC 0x00c00000 -#define NPORT_DMODE1_DFSA 0x01000000 -#define NPORT_DMODE1_DFMSA 0x01400000 -#define NPORT_DMODE1_BBENAB 0x02000000 /* Back blend enable */ -#define NPORT_DMODE1_PFENAB 0x04000000 /* Pre-fetch enable */ -#define NPORT_DMODE1_ABLEND 0x08000000 /* Alpha blend */ -#define NPORT_DMODE1_LOMASK 0xf0000000 -#define NPORT_DMODE1_LOZERO 0x00000000 -#define NPORT_DMODE1_LOAND 0x10000000 -#define NPORT_DMODE1_LOANDR 0x20000000 -#define NPORT_DMODE1_LOSRC 0x30000000 -#define NPORT_DMODE1_LOANDI 0x40000000 -#define NPORT_DMODE1_LODST 0x50000000 -#define NPORT_DMODE1_LOXOR 0x60000000 -#define NPORT_DMODE1_LOOR 0x70000000 -#define NPORT_DMODE1_LONOR 0x80000000 -#define NPORT_DMODE1_LOXNOR 0x90000000 -#define NPORT_DMODE1_LONDST 0xa0000000 -#define NPORT_DMODE1_LOORR 0xb0000000 -#define NPORT_DMODE1_LONSRC 0xc0000000 -#define NPORT_DMODE1_LOORI 0xd0000000 -#define NPORT_DMODE1_LONAND 0xe0000000 -#define NPORT_DMODE1_LOONE 0xf0000000 - - npireg_t drawmode0; /* REX command register */ - - /* These bits define the graphics opcode being performed. */ -#define NPORT_DMODE0_OPMASK 0x00000003 /* Opcode mask */ -#define NPORT_DMODE0_NOP 0x00000000 /* No operation */ -#define NPORT_DMODE0_RD 0x00000001 /* Read operation */ -#define NPORT_DMODE0_DRAW 0x00000002 /* Draw operation */ -#define NPORT_DMODE0_S2S 0x00000003 /* Screen to screen operation */ - - /* The following decide what addressing mode(s) are to be used */ -#define NPORT_DMODE0_AMMASK 0x0000001c /* Address mode mask */ -#define NPORT_DMODE0_SPAN 0x00000000 /* Spanning address mode */ -#define NPORT_DMODE0_BLOCK 0x00000004 /* Block address mode */ -#define NPORT_DMODE0_ILINE 0x00000008 /* Iline address mode */ -#define NPORT_DMODE0_FLINE 0x0000000c /* Fline address mode */ -#define NPORT_DMODE0_ALINE 0x00000010 /* Aline address mode */ -#define NPORT_DMODE0_TLINE 0x00000014 /* Tline address mode */ -#define NPORT_DMODE0_BLINE 0x00000018 /* Bline address mode */ - - /* And now some misc. operation control bits. */ -#define NPORT_DMODE0_DOSETUP 0x00000020 -#define NPORT_DMODE0_CHOST 0x00000040 -#define NPORT_DMODE0_AHOST 0x00000080 -#define NPORT_DMODE0_STOPX 0x00000100 -#define NPORT_DMODE0_STOPY 0x00000200 -#define NPORT_DMODE0_SK1ST 0x00000400 -#define NPORT_DMODE0_SKLST 0x00000800 -#define NPORT_DMODE0_ZPENAB 0x00001000 -#define NPORT_DMODE0_LISPENAB 0x00002000 -#define NPORT_DMODE0_LISLST 0x00004000 -#define NPORT_DMODE0_L32 0x00008000 -#define NPORT_DMODE0_ZOPQ 0x00010000 -#define NPORT_DMODE0_LISOPQ 0x00020000 -#define NPORT_DMODE0_SHADE 0x00040000 -#define NPORT_DMODE0_LRONLY 0x00080000 -#define NPORT_DMODE0_XYOFF 0x00100000 -#define NPORT_DMODE0_CLAMP 0x00200000 -#define NPORT_DMODE0_ENDPF 0x00400000 -#define NPORT_DMODE0_YSTR 0x00800000 - - npireg_t lsmode; /* Mode for line stipple ops */ - npireg_t lspattern; /* Pattern for line stipple ops */ - npireg_t lspatsave; /* Backup save pattern */ - npireg_t zpattern; /* Pixel zpattern */ - npireg_t colorback; /* Background color */ - npireg_t colorvram; /* Clear color for fast vram */ - npireg_t alpharef; /* Reference value for afunctions */ - unsigned long pad0; - npireg_t smask0x; /* Window GL relative screen mask 0 */ - npireg_t smask0y; /* Window GL relative screen mask 0 */ - npireg_t _setup; - npireg_t _stepz; - npireg_t _lsrestore; - npireg_t _lssave; - - unsigned long _pad1[0x30]; - - /* Iterators, full state for context switch */ - npfreg_t _xstart; /* X-start point (current) */ - npfreg_t _ystart; /* Y-start point (current) */ - npfreg_t _xend; /* x-end point */ - npfreg_t _yend; /* y-end point */ - npireg_t xsave; /* copy of xstart integer value for BLOCk addressing MODE */ - npireg_t xymove; /* x.y offset from xstart, ystart for relative operations */ - npfreg_t bresd; - npfreg_t bress1;; - npireg_t bresoctinc1; - volatile int bresrndinc2; - npireg_t brese1; - npireg_t bress2; - npireg_t aweight0; - npireg_t aweight1; - npfreg_t xstartf; - npfreg_t ystartf; - npfreg_t xendf; - npfreg_t yendf; - npireg_t xstarti; - npfreg_t xendf1; - npireg_t xystarti; - npireg_t xyendi; - npireg_t xstartendi; - - unsigned long _unused2[0x29]; - - npfreg_t colorred; - npfreg_t coloralpha; - npfreg_t colorgrn; - npfreg_t colorblue; - npfreg_t slopered; - npfreg_t slopealpha; - npfreg_t slopegrn; - npfreg_t slopeblue; - npireg_t wrmask; - npireg_t colori; - npfreg_t colorx; - npfreg_t slopered1; - npireg_t hostrw0; - npireg_t hostrw1; - npireg_t dcbmode; -#define NPORT_DMODE_WMASK 0x00000003 -#define NPORT_DMODE_W4 0x00000000 -#define NPORT_DMODE_W1 0x00000001 -#define NPORT_DMODE_W2 0x00000002 -#define NPORT_DMODE_W3 0x00000003 -#define NPORT_DMODE_EDPACK 0x00000004 -#define NPORT_DMODE_ECINC 0x00000008 -#define NPORT_DMODE_CMASK 0x00000070 -#define NPORT_DMODE_AMASK 0x00000780 -#define NPORT_DMODE_AVC2 0x00000000 -#define NPORT_DMODE_ACMALL 0x00000080 -#define NPORT_DMODE_ACM0 0x00000100 -#define NPORT_DMODE_ACM1 0x00000180 -#define NPORT_DMODE_AXMALL 0x00000200 -#define NPORT_DMODE_AXM0 0x00000280 -#define NPORT_DMODE_AXM1 0x00000300 -#define NPORT_DMODE_ABT 0x00000380 -#define NPORT_DMODE_AVCC1 0x00000400 -#define NPORT_DMODE_AVAB1 0x00000480 -#define NPORT_DMODE_ALG3V0 0x00000500 -#define NPORT_DMODE_A1562 0x00000580 -#define NPORT_DMODE_ESACK 0x00000800 -#define NPORT_DMODE_EASACK 0x00001000 -#define NPORT_DMODE_CWMASK 0x0003e000 -#define NPORT_DMODE_CHMASK 0x007c0000 -#define NPORT_DMODE_CSMASK 0x0f800000 -#define NPORT_DMODE_SENDIAN 0x10000000 - - unsigned long _unused3; - - union np_dcb dcbdata0; - npireg_t dcbdata1; -}; - -struct newport_cregs { - npireg_t smask1x; - npireg_t smask1y; - npireg_t smask2x; - npireg_t smask2y; - npireg_t smask3x; - npireg_t smask3y; - npireg_t smask4x; - npireg_t smask4y; - npireg_t topscan; - npireg_t xywin; - npireg_t clipmode; -#define NPORT_CMODE_SM0 0x00000001 -#define NPORT_CMODE_SM1 0x00000002 -#define NPORT_CMODE_SM2 0x00000004 -#define NPORT_CMODE_SM3 0x00000008 -#define NPORT_CMODE_SM4 0x00000010 -#define NPORT_CMODE_CMSK 0x00001e00 - - unsigned long _unused0; - unsigned long config; -#define NPORT_CFG_G32MD 0x00000001 -#define NPORT_CFG_BWIDTH 0x00000002 -#define NPORT_CFG_ERCVR 0x00000004 -#define NPORT_CFG_BDMSK 0x00000078 -#define NPORT_CFG_GDMSK 0x00000f80 -#define NPORT_CFG_GD0 0x00000080 -#define NPORT_CFG_GD1 0x00000100 -#define NPORT_CFG_GD2 0x00000200 -#define NPORT_CFG_GD3 0x00000400 -#define NPORT_CFG_GD4 0x00000800 -#define NPORT_CFG_GFAINT 0x00001000 -#define NPORT_CFG_TOMSK 0x0000e000 -#define NPORT_CFG_VRMSK 0x00070000 -#define NPORT_CFG_FBTYP 0x00080000 - - npireg_t _unused1; - npireg_t stat; -#define NPORT_STAT_VERS 0x00000007 -#define NPORT_STAT_GBUSY 0x00000008 -#define NPORT_STAT_BBUSY 0x00000010 -#define NPORT_STAT_VRINT 0x00000020 -#define NPORT_STAT_VIDINT 0x00000040 -#define NPORT_STAT_GLMSK 0x00001f80 -#define NPORT_STAT_BLMSK 0x0007e000 -#define NPORT_STAT_BFIRQ 0x00080000 -#define NPORT_STAT_GFIRQ 0x00100000 - - npireg_t ustat; - npireg_t dreset; -}; - -struct newport_regs { - struct newport_rexregs set; - unsigned long _unused0[0x16e]; - struct newport_rexregs go; - unsigned long _unused1[0x22e]; - struct newport_cregs cset; - unsigned long _unused2[0x1ef]; - struct newport_cregs cgo; -}; -extern struct newport_regs *npregs; - - -typedef struct { - unsigned int drawmode1; - unsigned int drawmode0; - unsigned int lsmode; - unsigned int lspattern; - unsigned int lspatsave; - unsigned int zpattern; - unsigned int colorback; - unsigned int colorvram; - unsigned int alpharef; - unsigned int smask0x; - unsigned int smask0y; - unsigned int _xstart; - unsigned int _ystart; - unsigned int _xend; - unsigned int _yend; - unsigned int xsave; - unsigned int xymove; - unsigned int bresd; - unsigned int bress1; - unsigned int bresoctinc1; - unsigned int bresrndinc2; - unsigned int brese1; - unsigned int bress2; - - unsigned int aweight0; - unsigned int aweight1; - unsigned int colorred; - unsigned int coloralpha; - unsigned int colorgrn; - unsigned int colorblue; - unsigned int slopered; - unsigned int slopealpha; - unsigned int slopegrn; - unsigned int slopeblue; - unsigned int wrmask; - unsigned int hostrw0; - unsigned int hostrw1; - - /* configregs */ - - unsigned int smask1x; - unsigned int smask1y; - unsigned int smask2x; - unsigned int smask2y; - unsigned int smask3x; - unsigned int smask3y; - unsigned int smask4x; - unsigned int smask4y; - unsigned int topscan; - unsigned int xywin; - unsigned int clipmode; - unsigned int config; - - /* dcb registers */ - unsigned int dcbmode; - unsigned int dcbdata0; - unsigned int dcbdata1; -} newport_ctx; - -/* Reading/writing VC2 registers. */ -#define VC2_REGADDR_INDEX 0x00000000 -#define VC2_REGADDR_IREG 0x00000010 -#define VC2_REGADDR_RAM 0x00000030 -#define VC2_PROTOCOL (NPORT_DMODE_EASACK | 0x00800000 | 0x00040000) - -#define VC2_VLINET_ADDR 0x000 -#define VC2_VFRAMET_ADDR 0x400 -#define VC2_CGLYPH_ADDR 0x500 - -/* Now the Indexed registers of the VC2. */ -#define VC2_IREG_VENTRY 0x00 -#define VC2_IREG_CENTRY 0x01 -#define VC2_IREG_CURSX 0x02 -#define VC2_IREG_CURSY 0x03 -#define VC2_IREG_CCURSX 0x04 -#define VC2_IREG_DENTRY 0x05 -#define VC2_IREG_SLEN 0x06 -#define VC2_IREG_RADDR 0x07 -#define VC2_IREG_VFPTR 0x08 -#define VC2_IREG_VLSPTR 0x09 -#define VC2_IREG_VLIR 0x0a -#define VC2_IREG_VLCTR 0x0b -#define VC2_IREG_CTPTR 0x0c -#define VC2_IREG_WCURSY 0x0d -#define VC2_IREG_DFPTR 0x0e -#define VC2_IREG_DLTPTR 0x0f -#define VC2_IREG_CONTROL 0x10 -#define VC2_IREG_CONFIG 0x20 - -extern inline void newport_vc2_set(struct newport_regs *regs, unsigned char vc2ireg, - unsigned short val) -{ - regs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_INDEX | NPORT_DMODE_W3 | - NPORT_DMODE_ECINC | VC2_PROTOCOL); - regs->set.dcbdata0.all = (vc2ireg << 24) | (val << 8); -} - -extern inline unsigned short newport_vc2_get(struct newport_regs *regs, - unsigned char vc2ireg) -{ - regs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_INDEX | NPORT_DMODE_W1 | - NPORT_DMODE_ECINC | VC2_PROTOCOL); - regs->set.dcbdata0.bytes.b3 = vc2ireg; - regs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_IREG | NPORT_DMODE_W2 | - NPORT_DMODE_ECINC | VC2_PROTOCOL); - return regs->set.dcbdata0.hwords.s1; -} - -/* VC2 Control register bits */ -#define VC2_CTRL_EVIRQ 0x0001 -#define VC2_CTRL_EDISP 0x0002 -#define VC2_CTRL_EVIDEO 0x0004 -#define VC2_CTRL_EDIDS 0x0008 -#define VC2_CTRL_ECURS 0x0010 -#define VC2_CTRL_EGSYNC 0x0020 -#define VC2_CTRL_EILACE 0x0040 -#define VC2_CTRL_ECDISP 0x0080 -#define VC2_CTRL_ECCURS 0x0100 -#define VC2_CTRL_ECG64 0x0200 -#define VC2_CTRL_GLSEL 0x0400 - -/* Controlling the color map on NEWPORT. */ -#define NCMAP_REGADDR_AREG 0x00000000 -#define NCMAP_REGADDR_ALO 0x00000000 -#define NCMAP_REGADDR_AHI 0x00000010 -#define NCMAP_REGADDR_PBUF 0x00000020 -#define NCMAP_REGADDR_CREG 0x00000030 -#define NCMAP_REGADDR_SREG 0x00000040 -#define NCMAP_REGADDR_RREG 0x00000060 -#define NCMAP_PROTOCOL (0x00008000 | 0x00040000 | 0x00800000) - -static inline void newport_cmap_setaddr(struct newport_regs *regs, - unsigned short addr) -{ - regs->set.dcbmode = (NPORT_DMODE_ACMALL | NCMAP_PROTOCOL | - NPORT_DMODE_SENDIAN | NPORT_DMODE_ECINC | - NCMAP_REGADDR_AREG | NPORT_DMODE_W2); - regs->set.dcbdata0.hwords.s1 = addr; - regs->set.dcbmode = (NPORT_DMODE_ACMALL | NCMAP_PROTOCOL | - NCMAP_REGADDR_PBUF | NPORT_DMODE_W3); -} - -static inline void newport_cmap_setrgb(struct newport_regs *regs, - unsigned char red, - unsigned char green, - unsigned char blue) -{ - regs->set.dcbdata0.all = - (red << 24) | - (green << 16) | - (blue << 8); -} - -/* Miscellaneous NEWPORT routines. */ -#define BUSY_TIMEOUT 100000 -static inline int newport_wait(void) -{ - int i = 0; - - while(i < BUSY_TIMEOUT) - if(!(npregs->cset.stat & NPORT_STAT_GBUSY)) - break; - if(i == BUSY_TIMEOUT) - return 1; - return 0; -} - -static inline int newport_bfwait(void) -{ - int i = 0; - - while(i < BUSY_TIMEOUT) - if(!(npregs->cset.stat & NPORT_STAT_BBUSY)) - break; - if(i == BUSY_TIMEOUT) - return 1; - return 0; -} - -/* newport.c and cons_newport.c routines */ -extern struct graphics_ops *newport_probe (int, const char **); - -void newport_save (void *); -void newport_restore (void *); -void newport_reset (void); -int newport_ioctl (int card, int cmd, unsigned long arg); - -/* - * DCBMODE register defines: - */ - -/* Widht of the data being transfered for each DCBDATA[01] word */ -#define DCB_DATAWIDTH_4 0x0 -#define DCB_DATAWIDTH_1 0x1 -#define DCB_DATAWIDTH_2 0x2 -#define DCB_DATAWIDTH_3 0x3 - -/* If set, all of DCBDATA will be moved, otherwise only DATAWIDTH bytes */ -#define DCB_ENDATAPACK (1 << 2) - -/* Enables DCBCRS auto increment after each DCB transfer */ -#define DCB_ENCRSINC (1 << 3) - -/* shift for accessing the control register select address (DBCCRS, 3 bits) */ -#define DCB_CRS_SHIFT 4 - -/* DCBADDR (4 bits): display bus slave address */ -#define DCB_ADDR_SHIFT 7 -#define DCB_VC2 (0 << DCB_ADDR_SHIFT) -#define DCB_CMAP_ALL (1 << DCB_ADDR_SHIFT) -#define DCB_CMAP0 (2 << DCB_ADDR_SHIFT) -#define DCB_CMAP1 (3 << DCB_ADDR_SHIFT) -#define DCB_XMAP_ALL (4 << DCB_ADDR_SHIFT) -#define DCB_XMAP0 (5 << DCB_ADDR_SHIFT) -#define DCB_XMAP1 (6 << DCB_ADDR_SHIFT) -#define DCB_BT445 (7 << DCB_ADDR_SHIFT) -#define DCB_VCC1 (8 << DCB_ADDR_SHIFT) -#define DCB_VAB1 (9 << DCB_ADDR_SHIFT) -#define DCB_LG3_BDVERS0 (10 << DCB_ADDR_SHIFT) -#define DCB_LG3_ICS1562 (11 << DCB_ADDR_SHIFT) -#define DCB_RESERVED (15 << DCB_ADDR_SHIFT) - -/* DCB protocol ack types */ -#define DCB_ENSYNCACK (1 << 11) -#define DCB_ENASYNCACK (1 << 12) - -#define DCB_CSWIDTH_SHIFT 13 -#define DCB_CSHOLD_SHIFT 18 -#define DCB_CSSETUP_SHIFT 23 - -/* XMAP9 specific defines */ -/* XMAP9 -- registers as seen on the DCBMODE register*/ -# define XM9_CRS_CONFIG (0 << DCB_CRS_SHIFT) -# define XM9_PUPMODE (1 << 0) -# define XM9_ODD_PIXEL (1 << 1) -# define XM9_8_BITPLANES (1 << 2) -# define XM9_SLOW_DCB (1 << 3) -# define XM9_VIDEO_RGBMAP_MASK (3 << 4) -# define XM9_EXPRESS_VIDEO (1 << 6) -# define XM9_VIDEO_OPTION (1 << 7) -# define XM9_CRS_REVISION (1 << DCB_CRS_SHIFT) -# define XM9_CRS_FIFO_AVAIL (2 << DCB_CRS_SHIFT) -# define XM9_FIFO_0_AVAIL 0 -# define XM9_FIFO_1_AVAIL 1 -# define XM9_FIFO_2_AVAIL 3 -# define XM9_FIFO_3_AVAIL 2 -# define XM9_FIFO_FULL XM9_FIFO_0_AVAIL -# define XM9_FIFO_EMPTY XM9_FIFO_3_AVAIL -# define XM9_CRS_CURS_CMAP_MSB (3 << DCB_CRS_SHIFT) -# define XM9_CRS_PUP_CMAP_MSB (4 << DCB_CRS_SHIFT) -# define XM9_CRS_MODE_REG_DATA (5 << DCB_CRS_SHIFT) -# define XM9_CRS_MODE_REG_INDEX (7 << DCB_CRS_SHIFT) - - -#define DCB_CYCLES(setup,hold,width) \ - ((hold << DCB_CSHOLD_SHIFT) | \ - (setup << DCB_CSSETUP_SHIFT)| \ - (width << DCB_CSWIDTH_SHIFT)) - -#define W_DCB_XMAP9_PROTOCOL DCB_CYCLES (2, 1, 0) -#define WSLOW_DCB_XMAP9_PROTOCOL DCB_CYCLES (5, 5, 0) -#define WAYSLOW_DCB_XMAP9_PROTOCOL DCB_CYCLES (12, 12, 0) -#define R_DCB_XMAP9_PROTOCOL DCB_CYCLES (2, 1, 3) - -static inline void -xmap9FIFOWait (struct newport_regs *rex) -{ - rex->set.dcbmode = DCB_XMAP0 | XM9_CRS_FIFO_AVAIL | - DCB_DATAWIDTH_1 | R_DCB_XMAP9_PROTOCOL; - newport_bfwait (); - - while ((rex->set.dcbdata0.bytes.b3 & 3) != XM9_FIFO_EMPTY) - ; -} - -static inline void -xmap9SetModeReg (struct newport_regs *rex, unsigned int modereg, unsigned int data24, int cfreq) -{ - if (cfreq > 119) - rex->set.dcbmode = DCB_XMAP_ALL | XM9_CRS_MODE_REG_DATA | - DCB_DATAWIDTH_4 | W_DCB_XMAP9_PROTOCOL; - else if (cfreq > 59) - rex->set.dcbmode = DCB_XMAP_ALL | XM9_CRS_MODE_REG_DATA | - DCB_DATAWIDTH_4 | WSLOW_DCB_XMAP9_PROTOCOL; - else - rex->set.dcbmode = DCB_XMAP_ALL | XM9_CRS_MODE_REG_DATA | - DCB_DATAWIDTH_4 | WAYSLOW_DCB_XMAP9_PROTOCOL; - rex->set.dcbdata0.all = ((modereg) << 24) | (data24 & 0xffffff); -} - -#endif /* !(_SGI_NEWPORT_H) */ - diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/rrm.c linux.pre11.3/drivers/sgi/char/rrm.c --- linux.vanilla/drivers/sgi/char/rrm.c Sun Nov 8 15:08:17 1998 +++ linux.pre11.3/drivers/sgi/char/rrm.c Mon Jul 19 23:28:23 1999 @@ -12,6 +12,10 @@ #include #include +#ifdef MODULE +#include +#endif + int rrm_open_rn (int rnid, void *arg) { @@ -66,4 +70,3 @@ /* This routine is invoked when the device is closed */ return 0; } - diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/sgicons.c linux.pre11.3/drivers/sgi/char/sgicons.c --- linux.vanilla/drivers/sgi/char/sgicons.c Sun Nov 8 15:08:17 1998 +++ linux.pre11.3/drivers/sgi/char/sgicons.c Mon Jul 19 23:28:23 1999 @@ -1,14 +1,11 @@ -/* +/* $Id: sgicons.c,v 1.11 1999/01/04 16:07:19 ralf Exp $ + * * sgicons.c: Setting up and registering console I/O on the SGI. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * Copyright (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx) * * This implement a virtual console interface. - * - * This should be replaced with Gert's all-singing all-dancing - * graphics console code in the future - * */ #include #include @@ -17,7 +14,7 @@ #include "gconsole.h" /* To make psaux code cleaner */ -int aux_device_present = 0xaa; +unsigned char aux_device_present = 0xaa; /* This is the system graphics console (the first adapter found) */ struct console_ops *gconsole = 0; @@ -45,139 +42,4 @@ if (gconsole) return; gconsole = gc; -} - -void -__set_origin (unsigned short offset) -{ - if (gconsole) - (*gconsole->set_origin)(offset); -} - -void -hide_cursor (void) -{ - - if (gconsole) - (*gconsole->hide_cursor)(); -} - -void -set_cursor (int currcons) -{ - if (gconsole) - (*gconsole->set_cursor)(currcons); -} - -void -get_scrmem (int currcons) -{ - if (gconsole) - (*gconsole->get_scrmem)(currcons); -} - -void -set_scrmem (int currcons, long offset) -{ - if (gconsole) - (*gconsole->set_scrmem)(currcons, offset); -} - -int -set_get_cmap (unsigned char *arg, int set) -{ - if (gconsole) - return (*gconsole->set_get_cmap)(arg, set); - return 0; -} - -void -blitc (unsigned short charattr, unsigned long addr) -{ - if (gconsole) - (*gconsole->blitc)(charattr, addr); -} - -void -memsetw (void *s, unsigned short c, unsigned int count) -{ - if (gconsole) - (*gconsole->memsetw)(s, c, count); -} - -void -memcpyw (unsigned short *to, unsigned short *from, unsigned int count) -{ - if (gconsole) - (*gconsole->memcpyw)(to, from, count); -} - -int -con_adjust_height (unsigned long fontheight) -{ - return -EINVAL; -} - -int -set_get_font (char *arg, int set, int ch512) -{ - int error, i, line; - - if (!arg) - return -EINVAL; - error = verify_area (set ? VERIFY_READ : VERIFY_WRITE, (void *) arg, - ch512 ? 2* cmapsz : cmapsz); - if (error) - return error; - - /* download the current font */ - if (!set) { - memset (arg, 0, cmapsz); - for (i = 0; i < 256; i++) { - for (line = 0; line < CHAR_HEIGHT; line++) - __put_user (vga_font [i], arg+(i*32+line)); - } - return 0; - } - - /* set the font */ - for (i = 0; i < 256; i++) { - for (line = 0; line < CHAR_HEIGHT; line++) { - __get_user(vga_font [i*CHAR_HEIGHT + line], - arg + (i * 32 + line)); - } - } - return 0; -} - -/* - * dummy routines for the VESA blanking code, which is VGA only, - * so we don't have to carry that stuff around for the Sparc... */ -void vesa_blank(void) { } -void vesa_unblank(void) { } -void set_vesa_blanking(const unsigned long arg) { } -void vesa_powerdown(void) { } -void set_palette (void) { } - -extern unsigned long video_mem_base, video_screen_size, video_mem_term; - -__initfunc(unsigned long con_type_init(unsigned long start_mem, const char **name)) -{ - extern int serial_console; - - if (serial_console) - *name = "NONE"; - else { - gfx_init (name); - printk("Video screen size is %08lx at %08lx\n", - video_screen_size, start_mem); - video_mem_base = start_mem; - start_mem += (video_screen_size * 2); - video_mem_term = start_mem; - } - return start_mem; -} - -__initfunc(void con_type_init_finish(void)) -{ } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/sgiserial.c linux.pre11.3/drivers/sgi/char/sgiserial.c --- linux.vanilla/drivers/sgi/char/sgiserial.c Sun Nov 8 15:10:21 1998 +++ linux.pre11.3/drivers/sgi/char/sgiserial.c Mon Jul 19 23:28:23 1999 @@ -1,6 +1,7 @@ /* sgiserial.c: Serial port driver for SGI machines. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * */ #include /* for CONFIG_REMOTE_DEBUG */ @@ -18,6 +19,7 @@ #include #include #include +#include #include #include @@ -39,33 +41,16 @@ struct sgi_zschannel *zs_channels[NUM_CHANNELS] = { 0, 0, }; struct sgi_zschannel *zs_conschan; struct sgi_zschannel *zs_kgdbchan; -int zs_nodes[NUM_SERIAL] = { 0, }; struct sgi_serial zs_soft[NUM_CHANNELS]; struct sgi_serial *zs_chain; /* IRQ servicing chain */ static int zilog_irq = 21; -struct tty_struct zs_ttys[NUM_CHANNELS]; -/** struct tty_struct *zs_constty; **/ - /* Console hooks... */ static int zs_cons_chanout = 0; static int zs_cons_chanin = 0; struct sgi_serial *zs_consinfo = 0; -static struct console sgi_console_driver = { - "debug", - NULL, /* write */ - NULL, /* read */ - NULL, /* device */ - NULL, /* wait_key */ - NULL, /* unblank */ - NULL, /* setup */ - CON_PRINTBUFFER, - -1, - 0, - NULL -}; static unsigned char kgdb_regs[16] = { 0, 0, 0, /* write 0, 1, 2 */ (Rx8 | RxENABLE), /* write 3 */ @@ -80,6 +65,22 @@ (DCDIE) /* write 15 */ }; +static unsigned char zscons_regs[16] = { + 0, /* write 0 */ + (EXT_INT_ENAB | INT_ALL_Rx), /* write 1 */ + 0, /* write 2 */ + (Rx8 | RxENABLE), /* write 3 */ + (X16CLK), /* write 4 */ + (DTR | Tx8 | TxENAB), /* write 5 */ + 0, 0, 0, /* write 6, 7, 8 */ + (NV | MIE), /* write 9 */ + (NRZ), /* write 10 */ + (TCBR | RCBR), /* write 11 */ + 0, 0, /* BRG time constant, write 12 + 13 */ + (BRENABL), /* write 14 */ + (DCDIE | CTSIE | TxUIE | BRKIE) /* write 15 */ +}; + #define ZS_CLOCK 3672000 /* Zilog input clock rate */ DECLARE_TASK_QUEUE(tq_serial); @@ -161,6 +162,10 @@ * driver work on the Sun4 which needs a settling delay after each chip * register access, other machines handle this in hardware via auxiliary * flip-flops which implement the settle time we do in software. + * + * read_zsreg() and write_zsreg() may get called from rs_kgdb_hook() before + * interrupts are enabled. Therefore we have to check ioc_iocontrol before we + * access it. */ static inline unsigned char read_zsreg(struct sgi_zschannel *channel, unsigned char reg) { @@ -169,7 +174,8 @@ udelay(2); channel->control = reg; - junk = ioc_icontrol->istat0; + if (ioc_icontrol) + junk = ioc_icontrol->istat0; udelay(1); retval = channel->control; return retval; @@ -181,10 +187,12 @@ udelay(2); channel->control = reg; - junk = ioc_icontrol->istat0; + if (ioc_icontrol) + junk = ioc_icontrol->istat0; udelay(1); channel->control = value; - junk = ioc_icontrol->istat0; + if (ioc_icontrol) + junk = ioc_icontrol->istat0; return; } @@ -235,7 +243,7 @@ kgdb_regs[R1] = 0; kgdb_regs[R9] &= ~MIE; } - brg = BPS_TO_BRG(bps, ZS_CLOCK/16); + brg = BPS_TO_BRG(bps, ZS_CLOCK/ss->clk_divisor); kgdb_regs[R12] = (brg & 255); kgdb_regs[R13] = ((brg >> 8) & 255); load_zsregs(ss->zs_channel, kgdb_regs); @@ -552,7 +560,7 @@ struct sgi_serial * info = (struct sgi_serial *) dev_id; unsigned char zs_intreg; - zs_intreg = read_zsreg(info->zs_channel, 3); + zs_intreg = read_zsreg(info->zs_next->zs_channel, 3); /* NOTE: The read register 3, which holds the irq status, * does so for both channels on each chip. Although @@ -564,25 +572,25 @@ #define CHAN_B_IRQMASK (CHBRxIP | CHBTxIP | CHBEXT) /* *** Chip 1 *** */ - /* Channel A -- /dev/ttya, could be the console */ - if(zs_intreg & CHAN_A_IRQMASK) { - if (zs_intreg & CHARxIP) + /* Channel B -- /dev/ttyb, could be the console */ + if(zs_intreg & CHAN_B_IRQMASK) { + if (zs_intreg & CHBRxIP) receive_chars(info, regs); - if (zs_intreg & CHATxIP) + if (zs_intreg & CHBTxIP) transmit_chars(info); - if (zs_intreg & CHAEXT) + if (zs_intreg & CHBEXT) status_handle(info); } info=info->zs_next; - /* Channel B -- /dev/ttyb, could be the console */ - if(zs_intreg & CHAN_B_IRQMASK) { - if (zs_intreg & CHBRxIP) + /* Channel A -- /dev/ttya, could be the console */ + if(zs_intreg & CHAN_A_IRQMASK) { + if (zs_intreg & CHARxIP) receive_chars(info, regs); - if (zs_intreg & CHBTxIP) + if (zs_intreg & CHATxIP) transmit_chars(info); - if (zs_intreg & CHBEXT) + if (zs_intreg & CHAEXT) status_handle(info); } } @@ -904,7 +912,7 @@ /* These are for receiving and sending characters under the kgdb * source level kernel debugger. */ -void putDebugChar(char kgdb_char) +int putDebugChar(char kgdb_char) { struct sgi_zschannel *chan = zs_kgdbchan; volatile unsigned char junk; @@ -919,6 +927,8 @@ chan->data = kgdb_char; junk = ioc_icontrol->istat0; restore_flags(flags); + + return 1; } char getDebugChar(void) @@ -971,63 +981,6 @@ return; } -/* - * zs_console_print is registered for printk. - */ - -static void zs_console_print(struct console *co, const char *str, unsigned int count) -{ - - while(count--) { - if(*str == '\n') - rs_put_char('\r'); - rs_put_char(*str++); - } - - /* Comment this if you want to have a strict interrupt-driven output */ - rs_fair_output(); -} - -static void rs_flush_chars(struct tty_struct *tty) -{ - struct sgi_serial *info = (struct sgi_serial *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->device, "rs_flush_chars")) - return; - - if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || - !info->xmit_buf) - return; - - /* Enable transmitter */ - save_flags(flags); cli(); - info->curregs[1] |= TxINT_ENAB|EXT_INT_ENAB; - info->pendregs[1] |= TxINT_ENAB|EXT_INT_ENAB; - write_zsreg(info->zs_channel, 1, info->curregs[1]); - info->curregs[5] |= TxENAB; - info->pendregs[5] |= TxENAB; - write_zsreg(info->zs_channel, 5, info->curregs[5]); - - /* - * Send a first (bootstrapping) character. A best solution is - * to call transmit_chars() here which handles output in a - * generic way. Current transmit_chars() not only transmits, - * but resets interrupts also what we do not desire here. - * XXX Discuss with David. - */ - if (info->zs_channel->control & Tx_BUF_EMP) { - volatile unsigned char junk; - - /* Send char */ - udelay(2); - info->zs_channel->data = info->xmit_buf[info->xmit_tail++]; - junk = ioc_icontrol->istat0; - info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt--; - } - restore_flags(flags); -} static int rs_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) @@ -1117,6 +1070,47 @@ (tty->ldisc.write_wakeup)(tty); } +static void rs_flush_chars(struct tty_struct *tty) +{ + struct sgi_serial *info = (struct sgi_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_flush_chars")) + return; + + if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || + !info->xmit_buf) + return; + + /* Enable transmitter */ + save_flags(flags); cli(); + info->curregs[1] |= TxINT_ENAB|EXT_INT_ENAB; + info->pendregs[1] |= TxINT_ENAB|EXT_INT_ENAB; + write_zsreg(info->zs_channel, 1, info->curregs[1]); + info->curregs[5] |= TxENAB; + info->pendregs[5] |= TxENAB; + write_zsreg(info->zs_channel, 5, info->curregs[5]); + + /* + * Send a first (bootstrapping) character. A best solution is + * to call transmit_chars() here which handles output in a + * generic way. Current transmit_chars() not only transmits, + * but resets interrupts also what we do not desire here. + * XXX Discuss with David. + */ + if (info->zs_channel->control & Tx_BUF_EMP) { + volatile unsigned char junk; + + /* Send char */ + udelay(2); + info->zs_channel->data = info->xmit_buf[info->xmit_tail++]; + junk = ioc_icontrol->istat0; + info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt--; + } + restore_flags(flags); +} + /* * ------------------------------------------------------------ * rs_throttle() @@ -1614,7 +1608,7 @@ if (!(info->flags & ZILOG_CALLOUT_ACTIVE) && !(info->flags & ZILOG_CLOSING) && do_clocal) break; - if (current->signal & ~current->blocked) { + if (signal_pending(current)) { retval = -ERESTARTSYS; break; } @@ -1725,17 +1719,14 @@ } - static inline void rs_cons_check(struct sgi_serial *ss, int channel) { int i, o, io; - static consout_registered = 0; - static msg_printed = 0; + static int msg_printed = 0; i = o = io = 0; - /* Is this one of the serial console lines? */ if((zs_cons_chanout != channel) && (zs_cons_chanin != channel)) @@ -1744,18 +1735,6 @@ zs_consinfo = ss; - /* Register the console output putchar, if necessary */ - if((zs_cons_chanout == channel)) { - o = 1; - /* double whee.. */ - - if(!consout_registered) { - sgi_console_driver.write = zs_console_print; - register_console(&sgi_console_driver); - consout_registered = 1; - } - } - /* If this is console input, we handle the break received * status interrupt on this line to mean prom_halt(). @@ -1873,8 +1852,8 @@ if(!zs_chips[chip]) { zs_chips[chip] = get_zs(chip); /* Two channels per chip */ - zs_channels[(chip*2)] = &zs_chips[chip]->channelA; - zs_channels[(chip*2)+1] = &zs_chips[chip]->channelB; + zs_channels[(chip*2)] = &zs_chips[chip]->channelB; + zs_channels[(chip*2)+1] = &zs_chips[chip]->channelA; zs_soft[(chip*2)].kgdb_channel = 0; zs_soft[(chip*2)+1].kgdb_channel = 0; } @@ -1990,14 +1969,14 @@ if(chip) panic("rs_cons_hook called with chip not zero"); - if(line != 1 && line != 2) + if(line != 0 && line != 1) panic("rs_cons_hook called with line not ttya or ttyb"); - channel = line - 1; + channel = line; if(!zs_chips[chip]) { zs_chips[chip] = get_zs(chip); /* Two channels per chip */ - zs_channels[(chip*2)] = &zs_chips[chip]->channelA; - zs_channels[(chip*2)+1] = &zs_chips[chip]->channelB; + zs_channels[(chip*2)] = &zs_chips[chip]->channelB; + zs_channels[(chip*2)+1] = &zs_chips[chip]->channelA; } zs_soft[channel].zs_channel = zs_channels[channel]; zs_soft[channel].change_needed = 0; @@ -2041,3 +2020,176 @@ udelay(5); ZS_CLEARFIFO(zs_kgdbchan); } + +static void zs_console_write(struct console *co, const char *str, unsigned int count) +{ + + while(count--) { + if(*str == '\n') + rs_put_char('\r'); + rs_put_char(*str++); + } + + /* Comment this if you want to have a strict interrupt-driven output */ + rs_fair_output(); +} + +static int zs_console_wait_key(struct console *con) +{ + sleep_on(&keypress_wait); + return 0; +} + +static kdev_t zs_console_device(struct console *con) +{ + return MKDEV(TTY_MAJOR, 64 + con->index); +} + + +__initfunc(static int zs_console_setup(struct console *con, char *options)) +{ + struct sgi_serial *info; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int cflag = CREAD | HUPCL | CLOCAL; + char *s; + int i, brg; + + if (options) { + baud = simple_strtoul(options, NULL, 10); + s = options; + while(*s >= '0' && *s <= '9') + s++; + if (*s) parity = *s++; + if (*s) bits = *s - '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; + } + con->cflag = cflag; + + rs_cons_hook(0, 0, con->index); + info = zs_soft + con->index; + info->is_cons = 1; + + printk("Console: ttyS%d (Zilog8530)\n", info->line); + + i = con->cflag & CBAUD; + if (con->cflag & CBAUDEX) { + i &= ~CBAUDEX; + con->cflag &= ~CBAUDEX; + } + info->zs_baud = baud; + + switch (con->cflag & CSIZE) { + case CS5: + zscons_regs[3] = Rx5 | RxENABLE; + zscons_regs[5] = Tx5 | TxENAB; + break; + case CS6: + zscons_regs[3] = Rx6 | RxENABLE; + zscons_regs[5] = Tx6 | TxENAB; + break; + case CS7: + zscons_regs[3] = Rx7 | RxENABLE; + zscons_regs[5] = Tx7 | TxENAB; + break; + default: + case CS8: + zscons_regs[3] = Rx8 | RxENABLE; + zscons_regs[5] = Tx8 | TxENAB; + break; + } + zscons_regs[5] |= DTR; + + if (con->cflag & PARENB) + zscons_regs[4] |= PAR_ENA; + if (!(con->cflag & PARODD)) + zscons_regs[4] |= PAR_EVEN; + + if (con->cflag & CSTOPB) + zscons_regs[4] |= SB2; + else + zscons_regs[4] |= SB1; + + brg = BPS_TO_BRG(baud, ZS_CLOCK / info->clk_divisor); + zscons_regs[12] = brg & 0xff; + zscons_regs[13] = (brg >> 8) & 0xff; + memcpy(info->curregs, zscons_regs, sizeof(zscons_regs)); + memcpy(info->pendregs, zscons_regs, sizeof(zscons_regs)); + load_zsregs(info->zs_channel, zscons_regs); + ZS_CLEARERR(info->zs_channel); + ZS_CLEARFIFO(info->zs_channel); + return 0; +} + +static struct console sgi_console_driver = { + "ttyS", + zs_console_write, /* write */ + NULL, /* read */ + zs_console_device, /* device */ + zs_console_wait_key, /* wait_key */ + NULL, /* unblank */ + zs_console_setup, /* setup */ + CON_PRINTBUFFER, + -1, + 0, + NULL +}; + +/* + * Register console. + */ +__initfunc (long serial_console_init(long kmem_start, long kmem_end)) +{ + register_console(&sgi_console_driver); + return kmem_start; +} + + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/sgiserial.h linux.pre11.3/drivers/sgi/char/sgiserial.h --- linux.vanilla/drivers/sgi/char/sgiserial.h Sun Nov 8 15:08:17 1998 +++ linux.pre11.3/drivers/sgi/char/sgiserial.h Mon Jul 19 23:28:23 1999 @@ -412,7 +412,8 @@ udelay(2); channel->control = ERR_RES; - junk = ioc_icontrol->istat0; + if (ioc_icontrol) + junk = ioc_icontrol->istat0; } extern inline void ZS_CLEARFIFO(struct sgi_zschannel *channel) @@ -421,11 +422,17 @@ udelay(2); junk = channel->data; - udelay(2); junk = ioc_icontrol->istat0; + udelay(2); + if (ioc_icontrol) + junk = ioc_icontrol->istat0; junk = channel->data; - udelay(2); junk = ioc_icontrol->istat0; + udelay(2); + if (ioc_icontrol) + junk = ioc_icontrol->istat0; junk = channel->data; - udelay(2); junk = ioc_icontrol->istat0; + udelay(2); + if (ioc_icontrol) + junk = ioc_icontrol->istat0; } #if 0 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/shmiq.c linux.pre11.3/drivers/sgi/char/shmiq.c --- linux.vanilla/drivers/sgi/char/shmiq.c Sun Nov 8 15:08:17 1998 +++ linux.pre11.3/drivers/sgi/char/shmiq.c Mon Jul 19 23:28:23 1999 @@ -1,4 +1,5 @@ -/* +/* $Id: shmiq.c,v 1.11.2.2 1999/06/17 12:08:45 ralf Exp $ + * * shmiq.c: shared memory input queue driver * written 1997 Miguel de Icaza (miguel@nuclecu.unam.mx) * @@ -47,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -237,7 +239,7 @@ return -EBADF; } -extern sys_munmap(unsigned long addr, size_t len); +extern int sys_munmap(unsigned long addr, size_t len); static int qcntl_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg, int minor) @@ -394,12 +396,12 @@ } static int -shmiq_qcntl_fasync (struct file *file, int on) +shmiq_qcntl_fasync (int fd, struct file *file, int on) { int retval; int minor = MINOR (file->f_dentry->d_inode->i_rdev); - retval = fasync_helper (file, on, &shmiqs [minor].fasync); + retval = fasync_helper (fd, file, on, &shmiqs [minor].fasync); if (retval < 0) return retval; return 0; @@ -422,7 +424,7 @@ return -EINVAL; lock_kernel (); - shmiq_qcntl_fasync (filp, 0); + shmiq_qcntl_fasync (-1, filp, 0); shmiqs [minor].opened = 0; shmiqs [minor].mapped = 0; shmiqs [minor].events = 0; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/streamable.c linux.pre11.3/drivers/sgi/char/streamable.c --- linux.vanilla/drivers/sgi/char/streamable.c Sun Nov 8 15:08:17 1998 +++ linux.pre11.3/drivers/sgi/char/streamable.c Mon Jul 19 23:28:23 1999 @@ -1,4 +1,5 @@ -/* +/* $Id: streamable.c,v 1.9 1998/09/19 19:17:50 ralf Exp $ + * * streamable.c: streamable devices. /dev/gfx * (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx) * @@ -51,14 +52,14 @@ static int sgi_gfx_open (struct inode *inode, struct file *file) { - printk ("GFX: Opened by %d\n", current->pid); + printk ("GFX: Opened by %ld\n", current->pid); return 0; } static int sgi_gfx_close (struct inode *inode, struct file *file) { - printk ("GFX: Closed by %d\n", current->pid); + printk ("GFX: Closed by %ld\n", current->pid); return 0; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/usema.c linux.pre11.3/drivers/sgi/char/usema.c --- linux.vanilla/drivers/sgi/char/usema.c Sun Nov 8 15:08:17 1998 +++ linux.pre11.3/drivers/sgi/char/usema.c Mon Jul 19 23:28:23 1999 @@ -27,11 +27,13 @@ #include #include #include +#include #include #include #include #include #include +#include "usema.h" #include #include @@ -42,6 +44,7 @@ struct wait_queue *proc_list; }; + static int sgi_usema_attach (usattach_t * attach, struct irix_usema *usema) { @@ -64,7 +67,7 @@ struct irix_usema *usema = file->private_data; int retval; - printk("[%s:%d] wants ioctl 0x%xd (arg 0x%lx)", + printk("[%s:%ld] wants ioctl 0x%xd (arg 0x%lx)", current->comm, current->pid, cmd, arg); switch(cmd) { @@ -76,7 +79,7 @@ usattach_t *attach = (usattach_t *)arg; retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t)); if (retval) { - printk("[%s:%d] sgi_usema_ioctl(UIOCATTACHSEMA): " + printk("[%s:%ld] sgi_usema_ioctl(UIOCATTACHSEMA): " "verify_area failure", current->comm, current->pid); return retval; @@ -84,7 +87,8 @@ if (usema == 0) return -EINVAL; - printk("UIOCATTACHSEMA: attaching usema %p to process %d\n", usema, current->pid); + printk("UIOCATTACHSEMA: attaching usema %p to process %ld\n", + usema, current->pid); /* XXX what is attach->us_handle for? */ return sgi_usema_attach(attach, usema); break; @@ -97,12 +101,12 @@ retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t)); if (retval) { - printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): " + printk("[%s:%ld] sgi_usema_ioctl(UIOC*BLOCK): " "verify_area failure", current->comm, current->pid); return retval; } - printk("UIOC*BLOCK: putting process %d to sleep on usema %p", + printk("UIOC*BLOCK: putting process %ld to sleep on usema %p", current->pid, usema); if (cmd == UIOCNOIBLOCK) interruptible_sleep_on(&usema->proc_list); @@ -117,13 +121,13 @@ retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t)); if (retval) { - printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): " + printk("[%s:%ld] sgi_usema_ioctl(UIOC*BLOCK): " "verify_area failure", current->comm, current->pid); return retval; } - printk("[%s:%d] releasing usema %p", + printk("[%s:%ld] releasing usema %p", current->comm, current->pid, usema); wake_up(&usema->proc_list); return 0; @@ -137,7 +141,8 @@ { struct irix_usema *usema = filp->private_data; - printk("[%s:%d] wants to poll usema %p", current->comm, current->pid, usema); + printk("[%s:%ld] wants to poll usema %p", + current->comm, current->pid, usema); return 0; } @@ -187,6 +192,7 @@ void usema_init(void) { - printk("usemaclone misc device registered (minor: %d)\n", SGI_USEMACLONE); + printk("usemaclone misc device registered (minor: %d)\n", + SGI_USEMACLONE); misc_register(&dev_usemaclone); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/usema.h linux.pre11.3/drivers/sgi/char/usema.h --- linux.vanilla/drivers/sgi/char/usema.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/sgi/char/usema.h Mon Jul 19 23:28:23 1999 @@ -0,0 +1,10 @@ +/* usema.h + * + * Copyright (C) 1996 Alex deVries + */ +#ifndef _SGI_USEMA_H +#define _SGI_USEMA_H + +void usema_init (void); + +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/vga_font.c linux.pre11.3/drivers/sgi/char/vga_font.c --- linux.vanilla/drivers/sgi/char/vga_font.c Sun Nov 8 15:08:17 1998 +++ linux.pre11.3/drivers/sgi/char/vga_font.c Thu Jan 1 01:00:00 1970 @@ -1,346 +0,0 @@ -#include "gconsole.h" - -unsigned char vga_font[cmapsz] = { -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, -0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, -0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, -0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, -0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, -0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, -0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, -0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, -0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, -0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, -0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, -0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, -0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, -0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, -0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, -0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, -0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, -0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, -0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, -0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, -0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, -0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, -0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, -0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, -0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, -0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, -0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, -0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, -0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, -0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, -0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, -0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, -0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, -0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, -0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, -0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, -0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, -0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, -0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, -0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, -0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, -0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, -0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, -0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, -0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, -0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, -0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, -0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, -0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, -0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, -0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, -0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, -0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, -0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, -0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, -0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, -0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, -0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, -0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, -0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, -0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, -0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, -0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, -0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, -0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, -0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, -0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, -0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, -0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, -0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, -0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, -0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, -0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, -0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, -0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, -0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, -0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, -0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, -0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, -0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, -0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, -0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, -0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, -0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, -0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, -0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, -0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, -0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, -0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, -0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, -0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, -0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, -0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, -0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, -0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, -0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, -0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, -0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, -0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, -0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, -0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, -0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, -0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, -0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, -0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, -0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, -0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, -0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, -0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, -0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/dev_table.h linux.pre11.3/drivers/sound/dev_table.h --- linux.vanilla/drivers/sound/dev_table.h Fri Apr 16 22:10:56 1999 +++ linux.pre11.3/drivers/sound/dev_table.h Mon Jul 19 23:28:08 1999 @@ -25,30 +25,18 @@ #define SNDCARD_DESKPROXL 27 /* Compaq Deskpro XL */ #define SNDCARD_VIDC 28 /* ARMs VIDC */ #define SNDCARD_SBPNP 29 -#define SNDCARD_OPL3SA1 38 -#define SNDCARD_OPL3SA1_SB 39 -#define SNDCARD_OPL3SA1_MPU 40 #define SNDCARD_SOFTOSS 36 #define SNDCARD_VMIDI 37 +#define SNDCARD_OPL3SA1 38 /* Note: clash in msnd.h */ +#define SNDCARD_OPL3SA1_SB 39 +#define SNDCARD_OPL3SA1_MPU 40 #define SNDCARD_WAVEFRONT 41 #define SNDCARD_OPL3SA2 42 #define SNDCARD_OPL3SA2_MPU 43 #define SNDCARD_WAVEARTIST 44 +#define SNDCARD_OPL3SA2_MSS 45 /* Originally missed */ #define SNDCARD_AD1816 88 -void attach_opl3sa_wss (struct address_info *hw_config); -int probe_opl3sa_wss (struct address_info *hw_config); -void attach_opl3sa_sb (struct address_info *hw_config); -int probe_opl3sa_sb (struct address_info *hw_config); -void attach_opl3sa_mpu (struct address_info *hw_config); -int probe_opl3sa_mpu (struct address_info *hw_config); -void unload_opl3sa_wss(struct address_info *hw_info); -void unload_opl3sa_sb(struct address_info *hw_info); -void unload_opl3sa_mpu(struct address_info *hw_info); -void attach_softsyn_card (struct address_info *hw_config); -int probe_softsyn (struct address_info *hw_config); -void unload_softsyn (struct address_info *hw_config); - /* * NOTE! NOTE! NOTE! NOTE! * @@ -424,6 +412,7 @@ #ifdef CONFIG_SOUND_OPL3SA2 {"OPL3SA2", 0, SNDCARD_OPL3SA2, "OPL3SA2", attach_opl3sa2, probe_opl3sa2, unload_opl3sa2}, + {"OPL3SA2MSS", 1, SNDCARD_OPL3SA2_MSS, "OPL3SA2 MSS", attach_opl3sa2_mss, probe_opl3sa2_mss, unload_opl3sa2_mss}, {"OPL3SA2MPU", 0, SNDCARD_OPL3SA2_MPU, "OPL3SA2 MIDI", attach_opl3sa2_mpu, probe_opl3sa2_mpu, unload_opl3sa2_mpu}, #endif @@ -587,10 +576,11 @@ #ifndef CONFIG_OPL3SA2_DMA2 #define CONFIG_OPL3SA2_DMA2 CONFIG_OPL3SA2_DMA #endif + {SNDCARD_OPL3SA2, {CONFIG_OPL3SA2_CTRL_BASE, CONFIG_OPL3SA2_IRQ, CONFIG_OPL3SA2_DMA, CONFIG_OPL3SA2_DMA2}, SND_DEFAULT_ENABLE}, + {SNDCARD_OPL3SA2_MSS, {CONFIG_OPL3SA2_BASE, CONFIG_OPL3SA2_IRQ, CONFIG_OPL3SA2_DMA, CONFIG_OPL3SA2_DMA2}, SND_DEFAULT_ENABLE}, #ifdef CONFIG_OPL3SA2_MPU_BASE - {SNDCARD_OPL3SA2_MPU, {CONFIG_OPL3SA2_MPU_BASE, CONFIG_OPL3SA2_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, + {SNDCARD_OPL3SA2_MPU, {CONFIG_OPL3SA2_MPU_BASE, CONFIG_OPL3SA2_MPU_IRQ, CONFIG_OPL3SA2_DMA, -1}, SND_DEFAULT_ENABLE}, #endif - {SNDCARD_OPL3SA2, {CONFIG_OPL3SA2_BASE, CONFIG_OPL3SA2_IRQ, CONFIG_OPL3SA2_DMA, CONFIG_OPL3SA2_DMA2}, SND_DEFAULT_ENABLE}, #endif #ifdef CONFIG_SGALAXY diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/dmasound.c linux.pre11.3/drivers/sound/dmasound.c --- linux.vanilla/drivers/sound/dmasound.c Wed Mar 24 10:55:22 1999 +++ linux.pre11.3/drivers/sound/dmasound.c Tue Jul 20 00:04:07 1999 @@ -4579,7 +4579,7 @@ if (nbufs < 2 || nbufs > numBufs) nbufs = numBufs; size &= 0xffff; - if (size >= 8 && size <= 30) { + if (size >= 8 && size <= 29) { size = 1 << size; size *= sound.hard.size * (sound.hard.stereo + 1); size /= sound.soft.size * (sound.soft.stereo + 1); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/es1370.c linux.pre11.3/drivers/sound/es1370.c --- linux.vanilla/drivers/sound/es1370.c Tue Jun 15 16:49:52 1999 +++ linux.pre11.3/drivers/sound/es1370.c Tue Jul 20 00:04:07 1999 @@ -98,6 +98,9 @@ * (micz). From Kim.Berts@fisub.mail.abb.com * 11.05.99 0.22 Implemented the IMIX call to mute recording monitor. * Guenter Geiger + * 15.06.99 0.23 Fix bad allocation bug. + * Thanks to Deti Fliegl + * 28.06.99 0.24 Add pci_set_master * * some important things missing in Ensoniq documentation: * @@ -531,8 +534,9 @@ db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0; if (!db->rawbuf) { db->ready = db->mapped = 0; - for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER && !db->rawbuf; order--) - db->rawbuf = (void *)__get_free_pages(GFP_KERNEL, order); + for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) + if ((db->rawbuf = (void *)__get_free_pages(GFP_KERNEL, order))) + break; if (!db->rawbuf) return -ENOMEM; db->buforder = order; @@ -2317,7 +2321,7 @@ if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "es1370: version v0.22 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "es1370: version v0.24 time " __TIME__ " " __DATE__ "\n"); while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) { if (pcidev->base_address[0] == 0 || @@ -2381,6 +2385,7 @@ /* initialize the chips */ outl(s->ctrl, s->io+ES1370_REG_CONTROL); outl(s->sctrl, s->io+ES1370_REG_SERIAL_CONTROL); + pci_set_master(pcidev); /* enable bus mastering */ wrcodec(s, 0x16, 3); /* no RST, PD */ wrcodec(s, 0x17, 0); /* CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off the LRCLK2 PLL; program DAC_SYNC=0!! */ wrcodec(s, 0x18, 0); /* recording source is mixer */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/es1371.c linux.pre11.3/drivers/sound/es1371.c --- linux.vanilla/drivers/sound/es1371.c Fri Apr 16 22:10:56 1999 +++ linux.pre11.3/drivers/sound/es1371.c Tue Jul 20 00:04:07 1999 @@ -65,6 +65,9 @@ * reported by "Ivan N. Kokshaysky" * Note: joystick address handling might still be wrong on archs * other than i386 + * 15.06.99 0.12 Fix bad allocation bug. + * Thanks to Deti Fliegl + * 28.06.99 0.13 Add pci_set_master * */ @@ -759,8 +762,9 @@ db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0; if (!db->rawbuf) { db->ready = db->mapped = 0; - for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER && !db->rawbuf; order--) - db->rawbuf = (void *)__get_free_pages(GFP_KERNEL, order); + for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) + if ((db->rawbuf = (void *)__get_free_pages(GFP_KERNEL, order))) + break; if (!db->rawbuf) return -ENOMEM; db->buforder = order; @@ -2732,7 +2736,7 @@ if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "es1371: version v0.11 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "es1371: version v0.13 time " __TIME__ " " __DATE__ "\n"); while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) { if (pcidev->base_address[0] == 0 || @@ -2789,6 +2793,7 @@ outl(s->ctrl, s->io+ES1371_REG_CONTROL); outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL); outl(0, s->io+ES1371_REG_LEGACY); + pci_set_master(pcidev); /* enable bus mastering */ /* AC97 warm reset to start the bitclk */ outl(s->ctrl | CTRL_SYNCRES, s->io+ES1371_REG_CONTROL); udelay(2); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/mad16.c linux.pre11.3/drivers/sound/mad16.c --- linux.vanilla/drivers/sound/mad16.c Wed Mar 10 21:13:07 1999 +++ linux.pre11.3/drivers/sound/mad16.c Tue Jul 20 00:04:24 1999 @@ -668,7 +668,7 @@ * Set the IRQ and DMA addresses. */ - if (board_type == C930) + if (board_type == C930 || c924pnp) interrupt_bits[5] = 0x28; /* Also IRQ5 is possible on C930 */ bits = interrupt_bits[hw_config->irq]; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/maui.c linux.pre11.3/drivers/sound/maui.c --- linux.vanilla/drivers/sound/maui.c Sun Nov 8 15:10:21 1998 +++ linux.pre11.3/drivers/sound/maui.c Mon Jul 19 23:28:08 1999 @@ -15,9 +15,12 @@ * system * * Status: - * Untested + * Andrew J. Kroll Tested 06/01/1999 with: + * * OSWF.MOT File Version: 1.15 + * * OSWF.MOT File Dated: 09/12/94 + * * Older versions will cause problems. */ - + #include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/mpu401.c linux.pre11.3/drivers/sound/mpu401.c --- linux.vanilla/drivers/sound/mpu401.c Sun Nov 8 15:08:01 1998 +++ linux.pre11.3/drivers/sound/mpu401.c Mon Jul 19 23:28:08 1999 @@ -437,6 +437,15 @@ devc->m_busy = 0; } +int intchk_mpu401(void *dev_id) +{ + struct mpu_config *devc; + int dev = (int) dev_id; + + devc = &dev_conf[dev]; + return input_avail(devc); +} + void mpuintr(int irq, void *dev_id, struct pt_regs *dummy) { struct mpu_config *devc; @@ -1715,6 +1724,7 @@ EXPORT_SYMBOL(probe_mpu401); EXPORT_SYMBOL(attach_mpu401); EXPORT_SYMBOL(unload_mpu401); +EXPORT_SYMBOL(intchk_mpu401); EXPORT_SYMBOL(mpuintr); #ifdef MODULE diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/opl3sa2.c linux.pre11.3/drivers/sound/opl3sa2.c --- linux.vanilla/drivers/sound/opl3sa2.c Sat Jan 9 21:50:45 1999 +++ linux.pre11.3/drivers/sound/opl3sa2.c Mon Jul 19 23:28:10 1999 @@ -467,13 +467,13 @@ } -static int probe_opl3sa2_mss(struct address_info *hw_config) +int probe_opl3sa2_mss(struct address_info *hw_config) { return probe_ms_sound(hw_config); } -static void attach_opl3sa2_mss(struct address_info *hw_config) +void attach_opl3sa2_mss(struct address_info *hw_config) { char mixer_name[64]; @@ -516,7 +516,7 @@ } -static void unload_opl3sa2_mss(struct address_info *hw_config) +void unload_opl3sa2_mss(struct address_info *hw_config) { unload_ms_sound(hw_config); } @@ -592,6 +592,9 @@ { /* Generate a pretty name */ sprintf(chipset_name, "OPL3-SA%c", tag); +#if defined(CONFIG_OPL3SA2_MPU_BASE) && !defined(MODULE) + sound_getconf(SNDCARD_OPL3SA2_MPU)->always_detect = 1; +#endif return 1; } return 0; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/sb_ess.c linux.pre11.3/drivers/sound/sb_ess.c --- linux.vanilla/drivers/sound/sb_ess.c Thu May 27 22:11:56 1999 +++ linux.pre11.3/drivers/sound/sb_ess.c Tue Jul 20 00:04:49 1999 @@ -40,6 +40,10 @@ * recording problems for high samplerates. I * fixed this by removing ess_calc_best_speed () * and just doing what the documentation says. + * Andy Sloane (June 4 1999): Stole some code from ALSA to fix the playback + * andy@guildsoftware.com speed on ES1869, ES1879, ES1887, and ES1888. + * 1879's were previously ignored by this driver; + * added (untested) support for those. * * This files contains ESS chip specifics. It's based on the existing ESS * handling as it resided in sb_common.c, sb_mixer.c and sb_audio.c. This @@ -190,15 +194,23 @@ #define ESSTYPE_LIKE20 -1 /* Mimic 2.0 behaviour */ #define ESSTYPE_DETECT 0 /* Mimic 2.0 behaviour */ -int esstype = ESSTYPE_LIKE20; /* module parameter in sb_card.c */ +int esstype = ESSTYPE_DETECT; /* module parameter in sb_card.c */ #define SUBMDL_ES1788 0x10 /* Subtype ES1788 for specific handling */ #define SUBMDL_ES1868 0x11 /* Subtype ES1868 for specific handling */ #define SUBMDL_ES1869 0x12 /* Subtype ES1869 for specific handling */ #define SUBMDL_ES1878 0x13 /* Subtype ES1878 for specific handling */ +#define SUBMDL_ES1879 0x16 /* ES1879 was initially forgotten */ #define SUBMDL_ES1887 0x14 /* Subtype ES1887 for specific handling */ #define SUBMDL_ES1888 0x15 /* Subtype ES1888 for specific handling */ +#define SB_CAP_ES18XX_RATE 0x100 + +#define ES1688_CLOCK1 795444 /* 128 - div */ +#define ES1688_CLOCK2 397722 /* 256 - div */ +#define ES18XX_CLOCK1 793800 /* 128 - div */ +#define ES18XX_CLOCK2 768000 /* 256 - div */ + #ifdef FKS_LOGGING static void ess_show_mixerregs (sb_devc *devc); #endif @@ -323,7 +335,6 @@ return retval; } -#ifdef OBSOLETE static int ess_calc_best_speed (int clock1, int rev1, int clock2, int rev2, int *divp, int *speedp) { @@ -347,7 +358,6 @@ return retval; } -#endif /* * Depending on the audiochannel ESS devices can @@ -366,11 +376,14 @@ * The 0x80 is important for the first audio channel */ div = 0x80 | ess_calc_div (795500, 128, speedp, &diff); + } else if(devc->caps & SB_CAP_ES18XX_RATE) { + ess_calc_best_speed(ES18XX_CLOCK1, 128, ES18XX_CLOCK2, 256, + &div, speedp); } else { if (*speedp > 22000) { - div = 0x80 | ess_calc_div (795500, 256, speedp, &diff); + div = 0x80 | ess_calc_div (ES1688_CLOCK1, 256, speedp, &diff); } else { - div = 0x00 | ess_calc_div (397700, 128, speedp, &diff); + div = 0x00 | ess_calc_div (ES1688_CLOCK2, 128, speedp, &diff); } } *divp = div; @@ -1070,6 +1083,12 @@ case 1788: submodel = SUBMDL_ES1788; break; + case 1878: + submodel = SUBMDL_ES1878; + break; + case 1879: + submodel = SUBMDL_ES1879; + break; case 1887: submodel = SUBMDL_ES1887; break; @@ -1117,6 +1136,10 @@ chip = "ES1878"; devc->submodel = SUBMDL_ES1878; break; + case 0x1879: + chip = "ES1879"; + devc->submodel = SUBMDL_ES1879; + break; default: if ((type & 0x00ff) != ((type >> 8) & 0x00ff)) { printk ("ess_init: Unrecognized %04x\n", type); @@ -1173,6 +1196,17 @@ sprintf(name,"ESS %s AudioDrive (rev %d)", chip, ess_minor & 0x0f); } else { strcpy(name, "Jazz16"); + } + + /* AAS: info stolen from ALSA: these boards have different clocks */ + switch(devc->submodel) { +/* APPARENTLY NOT 1869 + case SUBMDL_ES1869: +*/ + case SUBMDL_ES1887: + case SUBMDL_ES1888: + devc->caps |= SB_CAP_ES18XX_RATE; + break; } hw_config->name = name; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/sb_mixer.c linux.pre11.3/drivers/sound/sb_mixer.c --- linux.vanilla/drivers/sound/sb_mixer.c Fri Apr 16 22:10:57 1999 +++ linux.pre11.3/drivers/sound/sb_mixer.c Mon Jul 19 23:28:08 1999 @@ -13,6 +13,7 @@ * * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) * Rolf Fokkens (Dec 20 1998) : Moved ESS stuff into sb_ess.[ch] + * Stanislav Voronyi : Support for AWE 3DSE device (Jun 7 1999) */ #include @@ -550,14 +551,37 @@ int val, ret; /* - * Use ioctl(fd, SOUND_MIXER_PRIVATE1, &mode) to turn AGC off (0) or on (1). + * Use ioctl(fd, SOUND_MIXER_AGC, &mode) to turn AGC off (0) or on (1). + * Use ioctl(fd, SOUND_MIXER_3DSE, &mode) to turn 3DSE off (0) or on (1) + * or mode==2 put 3DSE state to mode. */ - if (cmd == SOUND_MIXER_PRIVATE1 && devc->model == MDL_SB16) - { - if (get_user(val, (int *)arg)) - return -EFAULT; - sb_setmixer(devc, 0x43, (~val) & 0x01); - return 0; + if (devc->model == MDL_SB16) { + if (cmd == SOUND_MIXER_AGC) + { + if (get_user(val, (int *)arg)) + return -EFAULT; + sb_setmixer(devc, 0x43, (~val) & 0x01); + return 0; + } + if (cmd == SOUND_MIXER_3DSE) + { + /* I put here 15, but I don't know the exact version. + At least my 4.13 havn't 3DSE, 4.16 has it. */ + if (devc->minor < 15) + return -EINVAL; + if (get_user(val, (int *)arg)) + return -EFAULT; + if (val == 0 || val == 1) + sb_chgmixer(devc, AWE_3DSE, 0x01, val); + else if (val == 2) + { + ret = sb_getmixer(devc, AWE_3DSE)&0x01; + return put_user(ret, (int *)arg); + } + else + return -EINVAL; + return 0; + } } if (((cmd >> 8) & 0xff) == 'M') { diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/sb_mixer.h linux.pre11.3/drivers/sound/sb_mixer.h --- linux.vanilla/drivers/sound/sb_mixer.h Sat Jan 9 21:50:45 1999 +++ linux.pre11.3/drivers/sound/sb_mixer.h Mon Jul 19 23:28:08 1999 @@ -78,6 +78,11 @@ #define RIGHT_CHN 1 /* + * 3DSE register of AWE32/64 + */ +#define AWE_3DSE 0x90 + +/* * Mixer registers of ALS007 */ #define ALS007_RECORD_SRC 0x6c diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/sgalaxy.c linux.pre11.3/drivers/sound/sgalaxy.c --- linux.vanilla/drivers/sound/sgalaxy.c Fri Nov 13 01:37:15 1998 +++ linux.pre11.3/drivers/sound/sgalaxy.c Mon Jul 19 23:28:09 1999 @@ -2,7 +2,7 @@ * sound/sgalaxy.c * * Low level driver for Aztech Sound Galaxy cards. - * Copyright 1998 Artur Skawina + * Copyright 1998 Artur Skawina * * Supported cards: * Aztech Sound Galaxy Waverider Pro 32 - 3D diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/sonicvibes.c linux.pre11.3/drivers/sound/sonicvibes.c --- linux.vanilla/drivers/sound/sonicvibes.c Fri Apr 16 22:10:57 1999 +++ linux.pre11.3/drivers/sound/sonicvibes.c Tue Jul 20 00:04:49 1999 @@ -68,6 +68,9 @@ * SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; * Alpha fixes reported by Peter Jones * Note: dmaio hack might still be wrong on archs other than i386 + * 15.06.99 0.15 Fix bad allocation bug. + * Thanks to Deti Fliegl + * 28.06.99 0.16 Add pci_set_master * */ @@ -699,8 +702,9 @@ db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0; if (!db->rawbuf) { db->ready = db->mapped = 0; - for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER && !db->rawbuf; order--) - db->rawbuf = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order); + for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) + if ((db->rawbuf = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order))) + break; if (!db->rawbuf) return -ENOMEM; db->buforder = order; @@ -2321,7 +2325,7 @@ if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "sv: version v0.14 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "sv: version v0.16 time " __TIME__ " " __DATE__ "\n"); #if 0 if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT))) printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n"); @@ -2447,6 +2451,7 @@ goto err_dev3; if ((s->dev_dmfm = register_sound_special(&sv_dmfm_fops, 15 /* ?? */)) < 0) goto err_dev4; + pci_set_master(pcidev); /* enable bus mastering */ /* initialize the chips */ fs = get_fs(); set_fs(KERNEL_DS); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/sound_calls.h linux.pre11.3/drivers/sound/sound_calls.h --- linux.vanilla/drivers/sound/sound_calls.h Wed Jan 6 23:02:26 1999 +++ linux.pre11.3/drivers/sound/sound_calls.h Mon Jul 19 23:28:08 1999 @@ -157,6 +157,7 @@ /* From mpu401.c */ void attach_mpu401(struct address_info * hw_config); int probe_mpu401(struct address_info *hw_config); +int intchk_mpu401(void *dev_id); void mpuintr(int irq, void *dev_id, struct pt_regs * dummy); /* From uart6850.c */ @@ -256,21 +257,39 @@ void unload_trix_mpu(struct address_info *hw_info); void unload_cs4232(struct address_info *hw_info); void unload_cs4232_mpu(struct address_info *hw_info); +void unload_opl3sa_wss(struct address_info *hw_info); +void unload_opl3sa_sb(struct address_info *hw_info); +void unload_opl3sa_mpu(struct address_info *hw_info); void unload_opl3sa2(struct address_info *hw_info); void unload_opl3sa2_mpu(struct address_info *hw_info); +void unload_opl3sa2_mss(struct address_info *hw_info); +void unload_softsyn (struct address_info *hw_config); -/* From cs4232.c */ - +/* From cs4232.c */ int probe_cs4232 (struct address_info *hw_config); void attach_cs4232 (struct address_info *hw_config); int probe_cs4232_mpu (struct address_info *hw_config); void attach_cs4232_mpu (struct address_info *hw_config); -/* From opl3sa2.c */ +/* From opl3sa.c */ +void attach_opl3sa_wss (struct address_info *hw_config); +int probe_opl3sa_wss (struct address_info *hw_config); +void attach_opl3sa_sb (struct address_info *hw_config); +int probe_opl3sa_sb (struct address_info *hw_config); +void attach_opl3sa_mpu (struct address_info *hw_config); +int probe_opl3sa_mpu (struct address_info *hw_config); + +/* From opl3sa2.c */ int probe_opl3sa2 (struct address_info *hw_config); void attach_opl3sa2 (struct address_info *hw_config); int probe_opl3sa2_mpu (struct address_info *hw_config); void attach_opl3sa2_mpu (struct address_info *hw_config); +int probe_opl3sa2_mss (struct address_info *hw_config); +void attach_opl3sa2_mss (struct address_info *hw_config); + +/* From softoss.c */ +void attach_softsyn_card (struct address_info *hw_config); +int probe_softsyn (struct address_info *hw_config); /* From maui.c */ void attach_maui(struct address_info * hw_config); @@ -291,12 +310,12 @@ int probe_waveartist(struct address_info *hw_config); void unload_waveartist(struct address_info *hw_config); -/* From wavefront.c */ +/* From wavefront.c */ void attach_wavefront (struct address_info *hw_config); int probe_wavefront (struct address_info *hw_config); void unload_wavefront (struct address_info *hw_config); -/* From wf_midi.c */ +/* From wf_midi.c */ void attach_wf_mpu(struct address_info * hw_config); int probe_wf_mpu(struct address_info *hw_config); void unload_wf_mpu(struct address_info *hw_config); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/sound_syms.c linux.pre11.3/drivers/sound/sound_syms.c --- linux.vanilla/drivers/sound/sound_syms.c Wed Jan 6 23:02:26 1999 +++ linux.pre11.3/drivers/sound/sound_syms.c Mon Jul 19 23:28:08 1999 @@ -3,6 +3,9 @@ * modulespace. * * (C) Copyright 1997 Alan Cox, Licensed under the GNU GPL + * + * Thu May 27 1999 Andrew J. Kroll + * left out exported symbol... fixed */ #include @@ -43,6 +46,7 @@ EXPORT_SYMBOL(load_mixer_volumes); +EXPORT_SYMBOL(trace_init); /* oops! this is needed for maui.c -- AJK */ EXPORT_SYMBOL(conf_printf); EXPORT_SYMBOL(conf_printf2); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/trix.c linux.pre11.3/drivers/sound/trix.c --- linux.vanilla/drivers/sound/trix.c Wed Mar 10 21:13:08 1999 +++ linux.pre11.3/drivers/sound/trix.c Mon Jul 19 23:28:08 1999 @@ -42,6 +42,12 @@ static int mpu = 0; +#ifdef TRIX_JOYSTICK +static int joystick=1; +#else +static int joystick=0; +#endif + static unsigned char trix_read(int addr) { outb(((unsigned char) addr), 0x390); /* MT-0002-PC ASIC address */ @@ -196,9 +202,8 @@ if (ret) { -#ifdef TRIX_ENABLE_JOYSTICK - trix_write(0x15, 0x80); -#endif + if(joystick==1) + trix_write(0x15, 0x80); request_region(0x390, 2, "AudioTrix"); } return ret; @@ -477,7 +482,7 @@ MODULE_PARM(sb_irq,"i"); MODULE_PARM(mpu_io,"i"); MODULE_PARM(mpu_irq,"i"); - +MODULE_PARM(joystick, "i"); struct address_info config; struct address_info sb_config; struct address_info mpu_config; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/tc/Makefile linux.pre11.3/drivers/tc/Makefile --- linux.vanilla/drivers/tc/Makefile Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/tc/Makefile Mon Jul 19 23:28:26 1999 @@ -0,0 +1,33 @@ +# +# Makefile for the linux kernel. +# +# 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... + +SUB_DIRS := +MOD_SUB_DIRS := +ALL_SUB_DIRS := + +L_TARGET := tc.a +L_OBJS := tc.o + +# Nasty trick as nobody references tcsyms.o, but we still want it linked. +# Stolen from pci Makefile +ifeq ($(CONFIG_MODULES),y) +O_TARGET = tc_syms.o +OX_OBJS = tcsyms.o +O_OBJS = tc.o +L_OBJS := tc_syms.o +else +L_OBJS := tc.o +endif + +ifdef CONFIG_ZS +L_OBJS += zs.o +endif + +include $(TOPDIR)/Rules.make + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/tc/tc.c linux.pre11.3/drivers/tc/tc.c --- linux.vanilla/drivers/tc/tc.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/tc/tc.c Mon Jul 19 23:28:26 1999 @@ -0,0 +1,236 @@ +/* $Id: $ + * tc-init: We assume the TURBOchannel to be up and running so + * just probe for Modules and fill in the global data structure + * tc_bus. + * + * 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. + * + * Copyright (c) Harald Koerfgen, 1998 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define TC_DEBUG + +slot_info tc_bus[MAX_SLOT]; +static int max_tcslot = 0; +static tcinfo *info = (tcinfo *)0; + +unsigned long system_base = 0; + +extern void (*dbe_board_handler)(struct pt_regs *regs); +extern unsigned long *(*rex_slot_address)(int); +extern void *(*rex_gettcinfo)(void); + +/* + * Interface to the world. Read comment in include/asm-mips/tc.h. + */ + +int search_tc_card(char *name) +{ + int slot; + slot_info *sip; + + for (slot = 0; slot <= max_tcslot; slot++) { + sip = &tc_bus[slot]; + if ((sip->flags & FREE) && (strncmp(sip->name, name, strlen(name)) == 0)) { + return slot; + } + } + + return -ENODEV; +} + +void claim_tc_card(int slot) +{ + if (tc_bus[slot].flags & IN_USE) { + printk("claim_tc_card: attempting to claim a card already in use\n"); + return; + } + tc_bus[slot].flags &= ~FREE; + tc_bus[slot].flags |= IN_USE; +} + +void release_tc_card(int slot) +{ + if (tc_bus[slot].flags & FREE) { + printk("release_tc_card: attempting to release a card already free\n"); + return; + } + tc_bus[slot].flags &= ~IN_USE; + tc_bus[slot].flags |= FREE; +} + +unsigned long get_tc_base_addr(int slot) +{ + return tc_bus[slot].base_addr; +} + +unsigned long get_tc_irq_nr(int slot) +{ + return tc_bus[slot].interrupt; +} + +unsigned long get_tc_speed(void) +{ + return 100000 * (10000 / (unsigned long)info->clk_period); +} + +/* + * Probing for TURBOchannel modules + */ +__initfunc(static void my_dbe_handler(struct pt_regs *regs)) +{ + regs->cp0_epc += 4; +} + +__initfunc(static void tc_probe(unsigned long startaddr, unsigned long size, int max_slot)) +{ + int i, slot; + long offset; + unsigned char *module; + void (*old_be_handler)(struct pt_regs *regs); + + /* Install our exception handler temporarily */ + + old_be_handler = dbe_board_handler; + dbe_board_handler = my_dbe_handler; + for (slot = 0; slot <= max_slot; slot++) { + module = (char *)(startaddr + slot * size); + offset = -1; + if (module[OLDCARD + PATTERN0] == 0x55 && module[OLDCARD + PATTERN1] == 0x00 + && module[OLDCARD + PATTERN2] == 0xaa && module[OLDCARD + PATTERN3] == 0xff) + offset = OLDCARD; + if (module[PATTERN0] == 0x55 && module[PATTERN1] == 0x00 + && module[PATTERN2] == 0xaa && module[PATTERN3] == 0xff) + offset = 0; + + if (offset != -1) { + tc_bus[slot].base_addr = (unsigned long)module; + for(i = 0; i < 8; i++) { + tc_bus[slot].firmware[i] = module[FIRM_VER + offset + 4 * i]; + tc_bus[slot].vendor[i] = module[VENDOR + offset + 4 * i]; + tc_bus[slot].name[i] = module[MODULE + offset + 4 * i]; + } + tc_bus[slot].firmware[8] = 0; + tc_bus[slot].vendor[8] = 0; + tc_bus[slot].name[8] = 0; + /* + * Looks unneccesary, but we may change + * TC? in the future + */ + switch (slot) { + case 0: + tc_bus[slot].interrupt = TC0; + break; + case 1: + tc_bus[slot].interrupt = TC1; + break; + case 2: + tc_bus[slot].interrupt = TC2; + break; + /* + * Yuck! DS5000/200 onboard devices + */ + case 5: + tc_bus[slot].interrupt = SCSI_INT; + break; + case 6: + tc_bus[slot].interrupt = ETHER; + break; + default: + tc_bus[slot].interrupt = -1; + break; + } + } + } + + dbe_board_handler = old_be_handler; +} + +/* + * the main entry + */ +__initfunc(void tc_init(void)) +{ + int tc_clock; + int i; + unsigned long slot0addr; + unsigned long slot_size; + + if (!TURBOCHANNEL) + return; + + for (i = 0; i < MAX_SLOT; i++) { + tc_bus[i].base_addr = 0; + tc_bus[i].name[0] = 0; + tc_bus[i].vendor[0] = 0; + tc_bus[i].firmware[0] = 0; + tc_bus[i].interrupt = -1; + tc_bus[i].flags = FREE; + } + + info = (tcinfo *) rex_gettcinfo(); + slot0addr = (unsigned long)KSEG1ADDR(rex_slot_address(0)); + + switch (mips_machtype) { + case MACH_DS5000_200: + max_tcslot = 6; + break; + case MACH_DS5000_1XX: + case MACH_DS5000_2X0: + max_tcslot = 2; + break; + case MACH_DS5000_XX: + default: + max_tcslot = 1; + break; + } + + tc_clock = 10000 / info->clk_period; + + if (TURBOCHANNEL && info->slot_size && slot0addr) { + printk("TURBOchannel rev. %1d at %2d.%1d MHz ", info->revision, + tc_clock / 10, tc_clock % 10); + printk("(%sparity)\n", info->parity ? "" : "no "); + + slot_size = info->slot_size << 20; + + tc_probe(slot0addr, slot_size, max_tcslot); + + /* + * All TURBOchannel DECstations have the onboard devices + * where the (max_tcslot + 1 or 2 on DS5k/xx) Option Module + * would be. + */ + if(mips_machtype == MACH_DS5000_XX) + i = 2; + else + i = 1; + + system_base = slot0addr + slot_size * (max_tcslot + i); + +#ifdef TC_DEBUG + for (i = 0; i <= max_tcslot; i++) + if (tc_bus[i].base_addr) { + printk(" slot %d: ", i); + printk("%s %s %s\n", tc_bus[i].vendor, + tc_bus[i].name, tc_bus[i].firmware); + } +#endif + } + +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/tc/tcsyms.c linux.pre11.3/drivers/tc/tcsyms.c --- linux.vanilla/drivers/tc/tcsyms.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/tc/tcsyms.c Mon Jul 19 23:28:26 1999 @@ -0,0 +1,14 @@ +/* + * Turbo Channel Services -- Exported Symbols + * + */ + +#include +#include +#include + +EXPORT_SYMBOL(get_tc_irq_nr); +EXPORT_SYMBOL(claim_tc_card); +EXPORT_SYMBOL(search_tc_card); +EXPORT_SYMBOL(get_tc_speed); +EXPORT_SYMBOL(get_tc_base_addr); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/tc/zs.c linux.pre11.3/drivers/tc/zs.c --- linux.vanilla/drivers/tc/zs.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/tc/zs.c Mon Jul 19 23:28:26 1999 @@ -0,0 +1,2107 @@ +/* + * decserial.c: Serial port driver for IOASIC DECsatations. + * + * Derived from drivers/macintosh/macserial.c by Harald Koerfgen. + * Derived from drivers/sbus/char/sunserial.c by Paul Mackerras. + * + * DECstation changes + * Copyright (C) 1998 Harald Koerfgen (Harald.Koerfgen@home.ivm.de) + * + * For the rest of the code the original Copyright applies: + * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * + * Keyboard and mouse are not supported right now. If you want to change this, + * you might want to have a look at drivers/sbus/char/sunserial.c to see + * how this might be done. HK + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_SERIAL_CONSOLE +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_KGDB +#include +#endif + +#include "zs.h" + + +/* + * It would be nice to dynamically allocate everything that + * depends on NUM_SERIAL, so we could support any number of + * Z8530s, but for now... + */ +#define NUM_SERIAL 2 /* Max number of ZS chips supported */ +#define NUM_CHANNELS (NUM_SERIAL * 2) /* 2 channels per chip */ + +#define RECOVERY_DELAY udelay(2) + +struct dec_zschannel zs_channels[NUM_CHANNELS]; + +struct dec_serial zs_soft[NUM_CHANNELS]; +int zs_channels_found; +struct dec_serial *zs_chain; /* list of all channels */ + +struct tty_struct zs_ttys[NUM_CHANNELS]; + +#ifdef CONFIG_SERIAL_CONSOLE +static struct console sercons; +#endif + +#ifdef CONFIG_KGDB +struct dec_zschannel *zs_kgdbchan; +static unsigned char scc_inittab[] = { + 9, 0x80, /* reset A side (CHRA) */ + 13, 0, /* set baud rate divisor */ + 12, 1, + 14, 1, /* baud rate gen enable, src=rtxc (BRENABL) */ + 11, 0x50, /* clocks = br gen (RCBR | TCBR) */ + 5, 0x6a, /* tx 8 bits, assert RTS (Tx8 | TxENAB | RTS) */ + 4, 0x44, /* x16 clock, 1 stop (SB1 | X16CLK)*/ + 3, 0xc1, /* rx enable, 8 bits (RxENABLE | Rx8)*/ +}; +#endif + +static unsigned char zs_init_regs[16] __initdata = { + 0, /* write 0 */ + 0, /* write 1 */ + 0xf0, /* write 2 */ + (Rx8), /* write 3 */ + (X16CLK | SB1), /* write 4 */ + (Tx8), /* write 5 */ + 0, 0, 0, /* write 6, 7, 8 */ + (VIS), /* write 9 */ + (NRZ), /* write 10 */ + (TCBR | RCBR), /* write 11 */ + 0, 0, /* BRG time constant, write 12 + 13 */ + (BRSRC | BRENABL), /* write 14 */ + 0 /* write 15 */ +}; + +#define ZS_CLOCK 7372800 /* Z8530 RTxC input clock rate */ + +DECLARE_TASK_QUEUE(tq_zs_serial); + +struct tty_driver serial_driver, callout_driver; +static int serial_refcount; + +/* serial subtype definitions */ +#define SERIAL_TYPE_NORMAL 1 +#define SERIAL_TYPE_CALLOUT 2 + +/* number of characters left in xmit buffer before we ask for more */ +#define WAKEUP_CHARS 256 + +/* + * Debugging. + */ +#undef SERIAL_DEBUG_INTR +#undef SERIAL_DEBUG_OPEN +#undef SERIAL_DEBUG_FLOW +#undef SERIAL_DEBUG_THROTTLE +#undef SERIAL_PARANOIA_CHECK + +#define RS_STROBE_TIME 10 +#define RS_ISR_PASS_LIMIT 256 + +#define _INLINE_ inline + +static void probe_sccs(void); +static void change_speed(struct dec_serial *info); +static void rs_wait_until_sent(struct tty_struct *tty, int timeout); + +static struct tty_struct *serial_table[NUM_CHANNELS]; +static struct termios *serial_termios[NUM_CHANNELS]; +static struct termios *serial_termios_locked[NUM_CHANNELS]; + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* + * tmp_buf is used as a temporary buffer by serial_write. We need to + * lock it in case the copy_from_user blocks while swapping in a page, + * and some other program tries to do a serial write at the same time. + * Since the lock will only come under contention when the system is + * swapping and available memory is low, it makes sense to share one + * buffer across all the serial ports, since it significantly saves + * memory if large numbers of serial ports are open. + */ +static unsigned char tmp_buf[4096]; /* This is cheating */ +static struct semaphore tmp_buf_sem = MUTEX; + +static inline int serial_paranoia_check(struct dec_serial *info, + dev_t device, const char *routine) +{ +#ifdef SERIAL_PARANOIA_CHECK + static const char *badmagic = + "Warning: bad magic number for serial struct (%d, %d) in %s\n"; + static const char *badinfo = + "Warning: null mac_serial for (%d, %d) in %s\n"; + + if (!info) { + printk(badinfo, MAJOR(device), MINOR(device), routine); + return 1; + } + if (info->magic != SERIAL_MAGIC) { + printk(badmagic, MAJOR(device), MINOR(device), routine); + return 1; + } +#endif + return 0; +} + +/* + * This is used to figure out the divisor speeds and the timeouts + */ +static int baud_table[] = { + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, + 9600, 19200, 38400, 57600, 0, 0 }; + +/* + * Reading and writing Z8530 registers. + */ +static inline unsigned char read_zsreg(struct dec_zschannel *channel, + unsigned char reg) +{ + unsigned char retval; + + if (reg != 0) { + *channel->control = reg & 0xf; + RECOVERY_DELAY; + } + retval = *channel->control; + RECOVERY_DELAY; + return retval; +} + +static inline void write_zsreg(struct dec_zschannel *channel, + unsigned char reg, unsigned char value) +{ + if (reg != 0) { + *channel->control = reg & 0xf; + RECOVERY_DELAY; + } + *channel->control = value; + RECOVERY_DELAY; + return; +} + +static inline unsigned char read_zsdata(struct dec_zschannel *channel) +{ + unsigned char retval; + + retval = *channel->data; + RECOVERY_DELAY; + return retval; +} + +static inline void write_zsdata(struct dec_zschannel *channel, + unsigned char value) +{ + *channel->data = value; + RECOVERY_DELAY; + return; +} + +static inline void load_zsregs(struct dec_zschannel *channel, + unsigned char *regs) +{ +/* ZS_CLEARERR(channel); + ZS_CLEARFIFO(channel); */ + /* Load 'em up */ + write_zsreg(channel, R4, regs[R4]); + write_zsreg(channel, R3, regs[R3] & ~RxENABLE); + write_zsreg(channel, R5, regs[R5] & ~TxENAB); + write_zsreg(channel, R9, regs[R9]); + write_zsreg(channel, R1, regs[R1]); + write_zsreg(channel, R2, regs[R2]); + write_zsreg(channel, R10, regs[R10]); + write_zsreg(channel, R11, regs[R11]); + write_zsreg(channel, R12, regs[R12]); + write_zsreg(channel, R13, regs[R13]); + write_zsreg(channel, R14, regs[R14]); + write_zsreg(channel, R15, regs[R15]); + write_zsreg(channel, R3, regs[R3]); + write_zsreg(channel, R5, regs[R5]); + return; +} + +/* Sets or clears DTR/RTS on the requested line */ +static inline void zs_rtsdtr(struct dec_serial *ss, int set) +{ + if (ss->zs_channel != ss->zs_chan_a) { + if (set) + ss->zs_chan_a->curregs[5] |= (RTS | DTR); + else + ss->zs_chan_a->curregs[5] &= ~(RTS | DTR); + write_zsreg(ss->zs_chan_a, 5, ss->zs_chan_a->curregs[5]); + } + return; +} + +/* Utility routines for the Zilog */ +static inline int get_zsbaud(struct dec_serial *ss) +{ + struct dec_zschannel *channel = ss->zs_channel; + int brg; + + /* The baud rate is split up between two 8-bit registers in + * what is termed 'BRG time constant' format in my docs for + * the chip, it is a function of the clk rate the chip is + * receiving which happens to be constant. + */ + brg = (read_zsreg(channel, 13) << 8); + brg |= read_zsreg(channel, 12); + return BRG_TO_BPS(brg, (ZS_CLOCK/(ss->clk_divisor))); +} + +/* On receive, this clears errors and the receiver interrupts */ +static inline void rs_recv_clear(struct dec_zschannel *zsc) +{ + write_zsreg(zsc, 0, ERR_RES); + write_zsreg(zsc, 0, RES_H_IUS); /* XXX this is unnecessary */ +} + +/* + * ---------------------------------------------------------------------- + * + * Here starts the interrupt handling routines. All of the following + * subroutines are declared as inline and are folded into + * rs_interrupt(). They were separated out for readability's sake. + * + * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 + * ----------------------------------------------------------------------- + */ + +/* + * This routine is used by the interrupt handler to schedule + * processing in the software interrupt portion of the driver. + */ +static _INLINE_ void rs_sched_event(struct dec_serial *info, + int event) +{ + info->event |= 1 << event; + queue_task(&info->tqueue, &tq_zs_serial); + mark_bh(SERIAL_BH); +} + +static _INLINE_ void receive_chars(struct dec_serial *info, + struct pt_regs *regs) +{ + struct tty_struct *tty = info->tty; + unsigned char ch, stat, flag; + + while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) != 0) { + + stat = read_zsreg(info->zs_channel, R1); + ch = read_zsdata(info->zs_channel); + +#ifdef CONFIG_KGDB + if (info->kgdb_channel) { + if (ch == 0x03 || ch == '$') + breakpoint(); + if (stat & (Rx_OVR|FRM_ERR|PAR_ERR)) + write_zsreg(info->zs_channel, 0, ERR_RES); + return; + } +#endif + if (!tty) + continue; + + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + static int flip_buf_ovf; + ++flip_buf_ovf; + continue; + } + tty->flip.count++; + { + static int flip_max_cnt; + if (flip_max_cnt < tty->flip.count) + flip_max_cnt = tty->flip.count; + } + if (stat & Rx_OVR) { + flag = TTY_OVERRUN; + } else if (stat & FRM_ERR) { + flag = TTY_FRAME; + } else if (stat & PAR_ERR) { + flag = TTY_PARITY; + } else + flag = 0; + if (flag) + /* reset the error indication */ + write_zsreg(info->zs_channel, 0, ERR_RES); + *tty->flip.flag_buf_ptr++ = flag; + *tty->flip.char_buf_ptr++ = ch; + } + tty_flip_buffer_push(tty); +} + +static void transmit_chars(struct dec_serial *info) +{ + if ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0) + return; + info->tx_active = 0; + + if (info->x_char) { + /* Send next char */ + write_zsdata(info->zs_channel, info->x_char); + info->x_char = 0; + info->tx_active = 1; + return; + } + + if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tx_stopped) { + write_zsreg(info->zs_channel, 0, RES_Tx_P); + return; + } + /* Send char */ + write_zsdata(info->zs_channel, info->xmit_buf[info->xmit_tail++]); + info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt--; + info->tx_active = 1; + + if (info->xmit_cnt < WAKEUP_CHARS) + rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); +} + +static _INLINE_ void status_handle(struct dec_serial *info) +{ + unsigned char status; + + /* Get status from Read Register 0 */ + status = read_zsreg(info->zs_channel, 0); + + /* FIXEM: Check for DCD transitions */ + if (((status ^ info->read_reg_zero) & DCD) != 0 + && info->tty && !C_CLOCAL(info->tty)) { + if (status & DCD) { + wake_up_interruptible(&info->open_wait); + } else if (!(info->flags & ZILOG_CALLOUT_ACTIVE)) { + if (info->tty) + tty_hangup(info->tty); + } + } + + /* Check for CTS transitions */ + if (info->tty && C_CRTSCTS(info->tty)) { + /* + * For some reason, on the Power Macintosh, + * it seems that the CTS bit is 1 when CTS is + * *negated* and 0 when it is asserted. + * The DCD bit doesn't seem to be inverted + * like this. + */ + if ((status & CTS) != 0) { + if (info->tx_stopped) { + info->tx_stopped = 0; + if (!info->tx_active) + transmit_chars(info); + } + } else { + info->tx_stopped = 1; + } + } + + /* Clear status condition... */ + write_zsreg(info->zs_channel, 0, RES_EXT_INT); + info->read_reg_zero = status; +} + +/* + * This is the serial driver's generic interrupt routine + */ +void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + struct dec_serial *info = (struct dec_serial *) dev_id; + unsigned char zs_intreg; + int shift; + + /* NOTE: The read register 3, which holds the irq status, + * does so for both channels on each chip. Although + * the status value itself must be read from the A + * channel and is only valid when read from channel A. + * Yes... broken hardware... + */ +#define CHAN_IRQMASK (CHBRxIP | CHBTxIP | CHBEXT) + + if (info->zs_chan_a == info->zs_channel) + shift = 3; /* Channel A */ + else + shift = 0; /* Channel B */ + + for (;;) { + zs_intreg = read_zsreg(info->zs_chan_a, 3) >> shift; + if ((zs_intreg & CHAN_IRQMASK) == 0) + break; + + if (zs_intreg & CHBRxIP) { + receive_chars(info, regs); + } + if (zs_intreg & CHBTxIP) { + transmit_chars(info); + } + if (zs_intreg & CHBEXT) { + status_handle(info); + } + } +} + +/* + * ------------------------------------------------------------------- + * Here ends the serial interrupt routines. + * ------------------------------------------------------------------- + */ + +/* + * ------------------------------------------------------------ + * rs_stop() and rs_start() + * + * This routines are called before setting or resetting tty->stopped. + * ------------------------------------------------------------ + */ +static void rs_stop(struct tty_struct *tty) +{ + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_stop")) + return; + +#if 1 + save_flags(flags); cli(); + if (info->zs_channel->curregs[5] & TxENAB) { + info->zs_channel->curregs[5] &= ~TxENAB; + write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); + } + restore_flags(flags); +#endif +} + +static void rs_start(struct tty_struct *tty) +{ + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_start")) + return; + + save_flags(flags); cli(); +#if 1 + if (info->xmit_cnt && info->xmit_buf && !(info->zs_channel->curregs[5] & TxENAB)) { + info->zs_channel->curregs[5] |= TxENAB; + write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); + } +#else + if (info->xmit_cnt && info->xmit_buf && !info->tx_active) { + transmit_chars(info); + } +#endif + restore_flags(flags); +} + +/* + * This routine is used to handle the "bottom half" processing for the + * serial driver, known also the "software interrupt" processing. + * This processing is done at the kernel interrupt level, after the + * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This + * is where time-consuming activities which can not be done in the + * interrupt driver proper are done; the interrupt driver schedules + * them using rs_sched_event(), and they get done here. + */ +static void do_serial_bh(void) +{ + run_task_queue(&tq_zs_serial); +} + +static void do_softint(void *private_) +{ + struct dec_serial *info = (struct dec_serial *) private_; + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; + + if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); + } +} + +static void rs_timer(void) +{ +} + +static int startup(struct dec_serial * info) +{ + unsigned long flags; + + if (info->flags & ZILOG_INITIALIZED) + return 0; + + if (!info->xmit_buf) { + info->xmit_buf = (unsigned char *) get_free_page(GFP_KERNEL); + if (!info->xmit_buf) + return -ENOMEM; + } + + save_flags(flags); cli(); + +#ifdef SERIAL_DEBUG_OPEN + printk("starting up ttyS%d (irq %d)...", info->line, info->irq); +#endif + + /* + * Clear the receive FIFO. + */ + ZS_CLEARFIFO(info->zs_channel); + info->xmit_fifo_size = 1; + + /* + * Clear the interrupt registers. + */ + write_zsreg(info->zs_channel, 0, ERR_RES); + write_zsreg(info->zs_channel, 0, RES_H_IUS); + + /* + * Turn on RTS and DTR. + */ + zs_rtsdtr(info, 1); + + /* + * Finally, enable sequencing and interrupts + */ + info->zs_channel->curregs[1] = (info->zs_channel->curregs[1] & ~0x18) | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB); + info->zs_channel->curregs[3] |= (RxENABLE | Rx8); + info->zs_channel->curregs[5] |= (TxENAB | Tx8); + info->zs_channel->curregs[15] |= (DCDIE | CTSIE | TxUIE | BRKIE); + info->zs_channel->curregs[9] |= (VIS | MIE); + write_zsreg(info->zs_channel, 1, info->zs_channel->curregs[1]); + write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]); + write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); + write_zsreg(info->zs_channel, 15, info->zs_channel->curregs[15]); + write_zsreg(info->zs_channel, 9, info->zs_channel->curregs[9]); + + /* + * And clear the interrupt registers again for luck. + */ + write_zsreg(info->zs_channel, 0, ERR_RES); + write_zsreg(info->zs_channel, 0, RES_H_IUS); + + if (info->tty) + clear_bit(TTY_IO_ERROR, &info->tty->flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + /* + * Set the speed of the serial port + */ + change_speed(info); + + /* Save the current value of RR0 */ + info->read_reg_zero = read_zsreg(info->zs_channel, 0); + + info->flags |= ZILOG_INITIALIZED; + restore_flags(flags); + return 0; +} + +/* + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. + */ +static void shutdown(struct dec_serial * info) +{ + unsigned long flags; + + if (!(info->flags & ZILOG_INITIALIZED)) + return; + +#ifdef SERIAL_DEBUG_OPEN + printk("Shutting down serial port %d (irq %d)....", info->line, + info->irq); +#endif + + save_flags(flags); cli(); /* Disable interrupts */ + + if (info->xmit_buf) { + free_page((unsigned long) info->xmit_buf); + info->xmit_buf = 0; + } + + info->zs_channel->curregs[1] = 0; + write_zsreg(info->zs_channel, 1, info->zs_channel->curregs[1]); /* no interrupts */ + + info->zs_channel->curregs[3] &= ~RxENABLE; + write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]); + + info->zs_channel->curregs[5] &= ~TxENAB; + write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); + if (!info->tty || C_HUPCL(info->tty)) { + info->zs_chan_a->curregs[5] &= ~(DTR | RTS); + write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); + } + + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + + info->flags &= ~ZILOG_INITIALIZED; + restore_flags(flags); +} + +/* + * This routine is called to set the UART divisor registers to match + * the specified baud rate for a serial port. + */ +static void change_speed(struct dec_serial *info) +{ + unsigned short port; + unsigned cflag; + int i; + int brg; + unsigned long flags; + + if (!info->tty || !info->tty->termios) + return; + cflag = info->tty->termios->c_cflag; + if (!(port = info->port)) + return; + i = cflag & CBAUD; + + save_flags(flags); cli(); + info->zs_baud = baud_table[i]; + info->clk_divisor = 16; + + switch (info->zs_baud) { + default: + info->zs_channel->curregs[4] = X16CLK; + brg = BPS_TO_BRG(info->zs_baud, ZS_CLOCK/info->clk_divisor); + info->zs_channel->curregs[12] = (brg & 255); + info->zs_channel->curregs[13] = ((brg >> 8) & 255); + } + + /* byte size and parity */ + info->zs_channel->curregs[3] &= ~RxNBITS_MASK; + info->zs_channel->curregs[5] &= ~TxNBITS_MASK; + switch (cflag & CSIZE) { + case CS5: + info->zs_channel->curregs[3] |= Rx5; + info->zs_channel->curregs[5] |= Tx5; + break; + case CS6: + info->zs_channel->curregs[3] |= Rx6; + info->zs_channel->curregs[5] |= Tx6; + break; + case CS7: + info->zs_channel->curregs[3] |= Rx7; + info->zs_channel->curregs[5] |= Tx7; + break; + case CS8: + default: /* defaults to 8 bits */ + info->zs_channel->curregs[3] |= Rx8; + info->zs_channel->curregs[5] |= Tx8; + break; + } + + info->zs_channel->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN); + if (cflag & CSTOPB) { + info->zs_channel->curregs[4] |= SB2; + } else { + info->zs_channel->curregs[4] |= SB1; + } + if (cflag & PARENB) { + info->zs_channel->curregs[4] |= PAR_ENA; + } + if (!(cflag & PARODD)) { + info->zs_channel->curregs[4] |= PAR_EVEN; + } + + if (!(cflag & CLOCAL)) { + if (!(info->zs_channel->curregs[15] & DCDIE)) + info->read_reg_zero = read_zsreg(info->zs_channel, 0); + info->zs_channel->curregs[15] |= DCDIE; + } else + info->zs_channel->curregs[15] &= ~DCDIE; + if (cflag & CRTSCTS) { + info->zs_channel->curregs[15] |= CTSIE; + if ((read_zsreg(info->zs_channel, 0) & CTS) != 0) + info->tx_stopped = 1; + } else { + info->zs_channel->curregs[15] &= ~CTSIE; + info->tx_stopped = 0; + } + + /* Load up the new values */ + load_zsregs(info->zs_channel, info->zs_channel->curregs); + + restore_flags(flags); +} + +static void rs_flush_chars(struct tty_struct *tty) +{ + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_flush_chars")) + return; + + if (info->xmit_cnt <= 0 || tty->stopped || info->tx_stopped || + !info->xmit_buf) + return; + + /* Enable transmitter */ + save_flags(flags); cli(); + transmit_chars(info); + restore_flags(flags); +} + +static int rs_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + int c, total = 0; + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_write")) + return 0; + + if (!tty || !info->xmit_buf) + return 0; + + save_flags(flags); + while (1) { + cli(); + c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) + break; + + if (from_user) { + down(&tmp_buf_sem); + copy_from_user(tmp_buf, buf, c); + c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); + up(&tmp_buf_sem); + } else + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt += c; + restore_flags(flags); + buf += c; + count -= c; + total += c; + } + + if (info->xmit_cnt && !tty->stopped && !info->tx_stopped + && !info->tx_active) + transmit_chars(info); + restore_flags(flags); + return total; +} + +static int rs_write_room(struct tty_struct *tty) +{ + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + int ret; + + if (serial_paranoia_check(info, tty->device, "rs_write_room")) + return 0; + ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) + ret = 0; + return ret; +} + +static int rs_chars_in_buffer(struct tty_struct *tty) +{ + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer")) + return 0; + return info->xmit_cnt; +} + +static void rs_flush_buffer(struct tty_struct *tty) +{ + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_flush_buffer")) + return; + cli(); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + sti(); + wake_up_interruptible(&tty->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} + +/* + * ------------------------------------------------------------ + * rs_throttle() + * + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + * ------------------------------------------------------------ + */ +static void rs_throttle(struct tty_struct * tty) +{ + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + unsigned long flags; + +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + printk("throttle %s: %d....\n", _tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->device, "rs_throttle")) + return; + + if (I_IXOFF(tty)) { + save_flags(flags); cli(); + info->x_char = STOP_CHAR(tty); + if (!info->tx_active) + transmit_chars(info); + restore_flags(flags); + } + + if (C_CRTSCTS(tty)) { + /* + * Here we want to turn off the RTS line. On Macintoshes, + * we only get the DTR line, which goes to both DTR and + * RTS on the modem. RTS doesn't go out to the serial + * port socket. So you should make sure your modem is + * set to ignore DTR if you're using CRTSCTS. + */ + save_flags(flags); cli(); + info->zs_chan_a->curregs[5] &= ~(DTR | RTS); + write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); + restore_flags(flags); + } +} + +static void rs_unthrottle(struct tty_struct * tty) +{ + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + unsigned long flags; + +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + printk("unthrottle %s: %d....\n", _tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->device, "rs_unthrottle")) + return; + + if (I_IXOFF(tty)) { + save_flags(flags); cli(); + if (info->x_char) + info->x_char = 0; + else { + info->x_char = START_CHAR(tty); + if (!info->tx_active) + transmit_chars(info); + } + restore_flags(flags); + } + + if (C_CRTSCTS(tty)) { + /* Assert RTS and DTR lines */ + save_flags(flags); cli(); + info->zs_chan_a->curregs[5] |= DTR | RTS; + write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); + restore_flags(flags); + } +} + +/* + * ------------------------------------------------------------ + * rs_ioctl() and friends + * ------------------------------------------------------------ + */ + +static int get_serial_info(struct dec_serial * info, + struct serial_struct * retinfo) +{ + struct serial_struct tmp; + + if (!retinfo) + return -EFAULT; + memset(&tmp, 0, sizeof(tmp)); + tmp.type = info->type; + tmp.line = info->line; + tmp.port = info->port; + tmp.irq = info->irq; + tmp.flags = info->flags; + tmp.baud_base = info->baud_base; + tmp.close_delay = info->close_delay; + tmp.closing_wait = info->closing_wait; + tmp.custom_divisor = info->custom_divisor; + return copy_to_user(retinfo,&tmp,sizeof(*retinfo)); +} + +static int set_serial_info(struct dec_serial * info, + struct serial_struct * new_info) +{ + struct serial_struct new_serial; + struct dec_serial old_info; + int retval = 0; + + if (!new_info) + return -EFAULT; + copy_from_user(&new_serial,new_info,sizeof(new_serial)); + old_info = *info; + + if (!suser()) { + if ((new_serial.baud_base != info->baud_base) || + (new_serial.type != info->type) || + (new_serial.close_delay != info->close_delay) || + ((new_serial.flags & ~ZILOG_USR_MASK) != + (info->flags & ~ZILOG_USR_MASK))) + return -EPERM; + info->flags = ((info->flags & ~ZILOG_USR_MASK) | + (new_serial.flags & ZILOG_USR_MASK)); + info->custom_divisor = new_serial.custom_divisor; + goto check_and_exit; + } + + if (info->count > 1) + return -EBUSY; + + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + + info->baud_base = new_serial.baud_base; + info->flags = ((info->flags & ~ZILOG_FLAGS) | + (new_serial.flags & ZILOG_FLAGS)); + info->type = new_serial.type; + info->close_delay = new_serial.close_delay; + info->closing_wait = new_serial.closing_wait; + +check_and_exit: + retval = startup(info); + return retval; +} + +/* + * get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int get_lsr_info(struct dec_serial * info, unsigned int *value) +{ + unsigned char status; + + cli(); + status = read_zsreg(info->zs_channel, 0); + sti(); + put_user(status,value); + return 0; +} + +static int get_modem_info(struct dec_serial *info, unsigned int *value) +{ + unsigned char control, status; + unsigned int result; + + cli(); + control = info->zs_chan_a->curregs[5]; + status = read_zsreg(info->zs_channel, 0); + sti(); + result = ((control & RTS) ? TIOCM_RTS: 0) + | ((control & DTR) ? TIOCM_DTR: 0) + | ((status & DCD) ? TIOCM_CAR: 0) + | ((status & CTS) ? 0: TIOCM_CTS); + put_user(result,value); + return 0; +} + +static int set_modem_info(struct dec_serial *info, unsigned int cmd, + unsigned int *value) +{ + int error; + unsigned int arg, bits; + + error = verify_area(VERIFY_READ, value, sizeof(int)); + if (error) + return error; + get_user(arg, value); + bits = (arg & TIOCM_RTS? RTS: 0) + (arg & TIOCM_DTR? DTR: 0); + cli(); + switch (cmd) { + case TIOCMBIS: + info->zs_chan_a->curregs[5] |= bits; + break; + case TIOCMBIC: + info->zs_chan_a->curregs[5] &= ~bits; + break; + case TIOCMSET: + info->zs_chan_a->curregs[5] = (info->zs_chan_a->curregs[5] & ~(DTR | RTS)) | bits; + break; + default: + sti(); + return -EINVAL; + } + write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); + sti(); + return 0; +} + +/* + * rs_break - turn transmit break condition on/off + */ +static void rs_break(struct tty_struct *tty, int break_state) +{ + struct dec_serial *info = (struct dec_serial *) tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_break")) + return; + if (!info->port) + return; + + save_flags(flags); cli(); + if (break_state == -1) + info->zs_channel->curregs[5] |= SND_BRK; + else + info->zs_channel->curregs[5] &= ~SND_BRK; + write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); + restore_flags(flags); +} + +static int rs_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + int error; + struct dec_serial * info = (struct dec_serial *)tty->driver_data; + +#ifdef CONFIG_KGDB + if (info->kgdb_channel) + return -ENODEV; +#endif + if (serial_paranoia_check(info, tty->device, "rs_ioctl")) + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && + (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + case TIOCMGET: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(unsigned int)); + if (error) + return error; + return get_modem_info(info, (unsigned int *) arg); + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + return set_modem_info(info, cmd, (unsigned int *) arg); + case TIOCGSERIAL: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct serial_struct)); + if (error) + return error; + return get_serial_info(info, + (struct serial_struct *) arg); + case TIOCSSERIAL: + return set_serial_info(info, + (struct serial_struct *) arg); + case TIOCSERGETLSR: /* Get line status register */ + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(unsigned int)); + if (error) + return error; + else + return get_lsr_info(info, (unsigned int *) arg); + + case TIOCSERGSTRUCT: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct dec_serial)); + if (error) + return error; + copy_from_user((struct dec_serial *) arg, + info, sizeof(struct dec_serial)); + return 0; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + struct dec_serial *info = (struct dec_serial *)tty->driver_data; + int was_stopped; + + if (tty->termios->c_cflag == old_termios->c_cflag) + return; + was_stopped = info->tx_stopped; + + change_speed(info); + + if (was_stopped && !info->tx_stopped) + rs_start(tty); +} + +/* + * ------------------------------------------------------------ + * rs_close() + * + * This routine is called when the serial port gets closed. + * Wait for the last remaining data to be sent. + * ------------------------------------------------------------ + */ +static void rs_close(struct tty_struct *tty, struct file * filp) +{ + struct dec_serial * info = (struct dec_serial *)tty->driver_data; + unsigned long flags; + + if (!info || serial_paranoia_check(info, tty->device, "rs_close")) + return; + + save_flags(flags); cli(); + + if (tty_hung_up_p(filp)) { + restore_flags(flags); + return; + } + +#ifdef SERIAL_DEBUG_OPEN + printk("rs_close ttys%d, count = %d\n", info->line, info->count); +#endif + if ((tty->count == 1) && (info->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. Info->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk("rs_close: bad serial port count; tty->count is 1, " + "info->count is %d\n", info->count); + info->count = 1; + } + if (--info->count < 0) { + printk("rs_close: bad serial port count for ttys%d: %d\n", + info->line, info->count); + info->count = 0; + } + if (info->count) { + restore_flags(flags); + return; + } + info->flags |= ZILOG_CLOSING; + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & ZILOG_NORMAL_ACTIVE) + info->normal_termios = *tty->termios; + if (info->flags & ZILOG_CALLOUT_ACTIVE) + info->callout_termios = *tty->termios; + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + if (info->closing_wait != ZILOG_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->closing_wait); + /* + * At this point we stop accepting input. To do this, we + * disable the receiver and receive interrupts. + */ + info->zs_channel->curregs[3] &= ~RxENABLE; + write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]); + info->zs_channel->curregs[1] = 0; /* disable any rx ints */ + write_zsreg(info->zs_channel, 1, info->zs_channel->curregs[1]); + ZS_CLEARFIFO(info->zs_channel); + if (info->flags & ZILOG_INITIALIZED) { + /* + * Before we drop DTR, make sure the SCC transmitter + * has completely drained. + */ + rs_wait_until_sent(tty, info->timeout); + } + + shutdown(info); + if (tty->driver.flush_buffer) + tty->driver.flush_buffer(tty); + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + tty->closing = 0; + info->event = 0; + info->tty = 0; + if (info->blocked_open) { + if (info->close_delay) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(info->close_delay); + } + wake_up_interruptible(&info->open_wait); + } + info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CALLOUT_ACTIVE| + ZILOG_CLOSING); + wake_up_interruptible(&info->close_wait); + restore_flags(flags); +} + +/* + * rs_wait_until_sent() --- wait until the transmitter is empty + */ +static void rs_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct dec_serial *info = (struct dec_serial *) tty->driver_data; + unsigned long orig_jiffies, char_time; + + if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent")) + return; + + orig_jiffies = jiffies; + /* + * Set the check interval to be 1/5 of the estimated time to + * send a single character, and make it at least 1. The check + * interval should also be less than the timeout. + */ + char_time = (info->timeout - HZ/50) / info->xmit_fifo_size; + char_time = char_time / 5; + if (char_time == 0) + char_time = 1; + if (timeout) + char_time = MIN(char_time, timeout); + while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) { + current->state = TASK_INTERRUPTIBLE; + current->counter = 0; /* make us low-priority */ + schedule_timeout(char_time); + if (signal_pending(current)) + break; + if (timeout && ((orig_jiffies + timeout) < jiffies)) + break; + } + current->state = TASK_RUNNING; +} + +/* + * rs_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +void rs_hangup(struct tty_struct *tty) +{ + struct dec_serial * info = (struct dec_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_hangup")) + return; + + rs_flush_buffer(tty); + shutdown(info); + info->event = 0; + info->count = 0; + info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CALLOUT_ACTIVE); + info->tty = 0; + wake_up_interruptible(&info->open_wait); +} + +/* + * ------------------------------------------------------------ + * rs_open() and friends + * ------------------------------------------------------------ + */ +static int block_til_ready(struct tty_struct *tty, struct file * filp, + struct dec_serial *info) +{ + struct wait_queue wait = { current, NULL }; + int retval; + int do_clocal = 0; + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (info->flags & ZILOG_CLOSING) { + interruptible_sleep_on(&info->close_wait); +#ifdef SERIAL_DO_RESTART + return ((info->flags & ZILOG_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); +#else + return -EAGAIN; +#endif + } + + /* + * If this is a callout device, then just make sure the normal + * device isn't being used. + */ + if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { + if (info->flags & ZILOG_NORMAL_ACTIVE) + return -EBUSY; + if ((info->flags & ZILOG_CALLOUT_ACTIVE) && + (info->flags & ZILOG_SESSION_LOCKOUT) && + (info->session != current->session)) + return -EBUSY; + if ((info->flags & ZILOG_CALLOUT_ACTIVE) && + (info->flags & ZILOG_PGRP_LOCKOUT) && + (info->pgrp != current->pgrp)) + return -EBUSY; + info->flags |= ZILOG_CALLOUT_ACTIVE; + return 0; + } + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || + (tty->flags & (1 << TTY_IO_ERROR))) { + if (info->flags & ZILOG_CALLOUT_ACTIVE) + return -EBUSY; + info->flags |= ZILOG_NORMAL_ACTIVE; + return 0; + } + + if (info->flags & ZILOG_CALLOUT_ACTIVE) { + if (info->normal_termios.c_cflag & CLOCAL) + do_clocal = 1; + } else { + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + } + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, info->count is dropped by one, so that + * rs_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue(&info->open_wait, &wait); +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready before block: ttys%d, count = %d\n", + info->line, info->count); +#endif + cli(); + if (!tty_hung_up_p(filp)) + info->count--; + sti(); + info->blocked_open++; + while (1) { + cli(); + if (!(info->flags & ZILOG_CALLOUT_ACTIVE) && + (tty->termios->c_cflag & CBAUD)) + zs_rtsdtr(info, 1); + sti(); + current->state = TASK_INTERRUPTIBLE; + if (tty_hung_up_p(filp) || + !(info->flags & ZILOG_INITIALIZED)) { +#ifdef SERIAL_DO_RESTART + if (info->flags & ZILOG_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; +#else + retval = -EAGAIN; +#endif + break; + } + if (!(info->flags & ZILOG_CALLOUT_ACTIVE) && + !(info->flags & ZILOG_CLOSING) && + (do_clocal || (read_zsreg(info->zs_channel, 0) & DCD))) + break; + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready blocking: ttys%d, count = %d\n", + info->line, info->count); +#endif + schedule(); + } + current->state = TASK_RUNNING; + remove_wait_queue(&info->open_wait, &wait); + if (!tty_hung_up_p(filp)) + info->count++; + info->blocked_open--; +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready after blocking: ttys%d, count = %d\n", + info->line, info->count); +#endif + if (retval) + return retval; + info->flags |= ZILOG_NORMAL_ACTIVE; + return 0; +} + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port, linking in its ZILOG structure into + * the IRQ chain. It also performs the serial-specific + * initialization for the tty structure. + */ +int rs_open(struct tty_struct *tty, struct file * filp) +{ + struct dec_serial *info; + int retval, line; + + line = MINOR(tty->device) - tty->driver.minor_start; + if ((line < 0) || (line >= zs_channels_found)) + return -ENODEV; + info = zs_soft + line; + +#ifdef CONFIG_KGDB + if (info->kgdb_channel) + return -ENODEV; +#endif + if (serial_paranoia_check(info, tty->device, "rs_open")) + return -ENODEV; +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line, + info->count); +#endif + + info->count++; + tty->driver_data = info; + info->tty = tty; + + /* + * If the port is the middle of closing, bail out now + */ + if (tty_hung_up_p(filp) || + (info->flags & ZILOG_CLOSING)) { + if (info->flags & ZILOG_CLOSING) + interruptible_sleep_on(&info->close_wait); +#ifdef SERIAL_DO_RESTART + return ((info->flags & ZILOG_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); +#else + return -EAGAIN; +#endif + } + + /* + * Start up serial port + */ + retval = startup(info); + if (retval) + return retval; + + retval = block_til_ready(tty, filp, info); + if (retval) { +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open returning after block_til_ready with %d\n", + retval); +#endif + return retval; + } + + if ((info->count == 1) && (info->flags & ZILOG_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->normal_termios; + else + *tty->termios = info->callout_termios; + change_speed(info); + } +#ifdef CONFIG_SERIAL_CONSOLE + if (sercons.cflag && sercons.index == line) { + tty->termios->c_cflag = sercons.cflag; + sercons.cflag = 0; + change_speed(info); + } +#endif + + info->session = current->session; + info->pgrp = current->pgrp; + +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open ttys%d successful...", info->line); +#endif +/* tty->low_latency = 1; */ + return 0; +} + +/* Finally, routines used to initialize the serial driver. */ + +__initfunc(static void show_serial_version(void)) +{ + printk("DECstation Z8530 serial driver version 0.03\n"); +} + +/* Initialize Z8530s zs_channels + */ + +__initfunc(static void probe_sccs(void)) +{ + struct dec_serial **pp; + int i, n, n_chips = 0, n_channels, chip, channel; + unsigned long flags; + + /* + * did we get here by accident? + */ + if(!IOASIC) { + printk("Not on JUNKIO machine, skipping probe_sccs\n"); + return; + } + + /* + * When serial console is activated, tc_init has not been called yet + * and system_base is undefined. Unfortunately we have to hardcode + * system_base for this case :-(. HK + */ + switch(mips_machtype) { + case MACH_DS5000_2X0: + system_base = 0xbf800000; + n_chips = 2; + break; + case MACH_DS5000_1XX: + system_base = 0xbc000000; + n_chips = 2; + break; + case MACH_DS5000_XX: + system_base = 0xbc000000; + n_chips = 1; + break; + } + + pp = &zs_chain; + + n_channels = 0; + + for (chip = 0; chip < n_chips; chip++) { + for (channel = 0; channel <= 1; channel++) { + /* + * The sccs reside on the high byte of the 16 bit IOBUS + */ + zs_channels[n_channels].control = (volatile unsigned char *) + system_base + (0 == chip ? SCC0 : SCC1) + (0 == channel ? 1 : 9); + zs_channels[n_channels].data = zs_channels[n_channels].control + 4; + zs_soft[n_channels].zs_channel = &zs_channels[n_channels]; + zs_soft[n_channels].irq = SERIAL; + + if (0 == channel) + zs_soft[n_channels].zs_chan_a = &zs_channels[n_channels+1]; + else + zs_soft[n_channels].zs_chan_a = &zs_channels[n_channels]; + + *pp = &zs_soft[n_channels]; + pp = &zs_soft[n_channels].zs_next; + n_channels++; + } + } + + *pp = 0; + zs_channels_found = n_channels; + + for (n = 0; n < zs_channels_found; n++) { + for (i = 0; i < 16; i++) { + zs_soft[n].zs_channel->curregs[i] = zs_init_regs[i]; + } + } + +/* save_and_cli(flags); + for (n = 0; n < zs_channels_found; n++) { + if (((int)zs_channels[n].control & 0xf) == 1) { + write_zsreg(zs_soft[channel].zs_chan_a, R9, FHWRES); + udelay(10000); + write_zsreg(zs_soft[channel].zs_chan_a, R9, 0); + } + load_zsregs(zs_soft[n].zs_channel, zs_soft[n].zs_channel->curregs); + } + restore_flags(flags); */ +} + +/* zs_init inits the driver */ +__initfunc(int zs_init(void)) +{ + int channel, i; + unsigned long flags; + struct dec_serial *info; + + if(!IOASIC) + return -ENODEV; + + /* Setup base handler, and timer table. */ + init_bh(SERIAL_BH, do_serial_bh); + timer_table[RS_TIMER].fn = rs_timer; + timer_table[RS_TIMER].expires = 0; + + /* Find out how many Z8530 SCCs we have */ + if (zs_chain == 0) + probe_sccs(); + + show_serial_version(); + + /* Initialize the tty_driver structure */ + /* Not all of this is exactly right for us. */ + + memset(&serial_driver, 0, sizeof(struct tty_driver)); + serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.name = "ttyS"; + serial_driver.major = TTY_MAJOR; + serial_driver.minor_start = 64; + serial_driver.num = zs_channels_found; + serial_driver.type = TTY_DRIVER_TYPE_SERIAL; + serial_driver.subtype = SERIAL_TYPE_NORMAL; + serial_driver.init_termios = tty_std_termios; + + serial_driver.init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver.flags = TTY_DRIVER_REAL_RAW; + serial_driver.refcount = &serial_refcount; + serial_driver.table = serial_table; + serial_driver.termios = serial_termios; + serial_driver.termios_locked = serial_termios_locked; + + serial_driver.open = rs_open; + serial_driver.close = rs_close; + serial_driver.write = rs_write; + serial_driver.flush_chars = rs_flush_chars; + serial_driver.write_room = rs_write_room; + serial_driver.chars_in_buffer = rs_chars_in_buffer; + serial_driver.flush_buffer = rs_flush_buffer; + serial_driver.ioctl = rs_ioctl; + serial_driver.throttle = rs_throttle; + serial_driver.unthrottle = rs_unthrottle; + serial_driver.set_termios = rs_set_termios; + serial_driver.stop = rs_stop; + serial_driver.start = rs_start; + serial_driver.hangup = rs_hangup; + serial_driver.break_ctl = rs_break; + serial_driver.wait_until_sent = rs_wait_until_sent; + + /* + * The callout device is just like normal device except for + * major number and the subtype code. + */ + callout_driver = serial_driver; + callout_driver.name = "cua"; + callout_driver.major = TTYAUX_MAJOR; + callout_driver.subtype = SERIAL_TYPE_CALLOUT; + + if (tty_register_driver(&serial_driver)) + panic("Couldn't register serial driver\n"); + if (tty_register_driver(&callout_driver)) + panic("Couldn't register callout driver\n"); + + save_flags(flags); cli(); + + for (channel = 0; channel < zs_channels_found; ++channel) { +#ifdef CONFIG_KGDB + if (zs_soft[channel].kgdb_channel) { + continue; + } +#endif + zs_soft[channel].clk_divisor = 16; + zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]); + + if (request_irq(SERIAL, rs_interrupt, SA_SHIRQ, + "SCC", &zs_soft[channel])) + printk(KERN_ERR "decserial: can't get irq %d\n", + SERIAL); + + /* If console serial line, then enable interrupts. */ +/* if (zs_soft[channel].is_cons) { + write_zsreg(zs_soft[channel].zs_channel, R1, + (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB)); + write_zsreg(zs_soft[channel].zs_channel, R9, + (VIS | MIE)); + } +*/ + } + + for (info = zs_chain, i = 0; info; info = info->zs_next, i++) + { +#ifdef CONFIG_KGDB + if (info->kgdb_channel) { + continue; + } +#endif + info->magic = SERIAL_MAGIC; + info->port = (int) info->zs_channel->control; + info->line = i; + info->tty = 0; + info->custom_divisor = 16; + info->close_delay = 50; + info->closing_wait = 3000; + info->x_char = 0; + info->event = 0; + info->count = 0; + info->blocked_open = 0; + info->tqueue.routine = do_softint; + info->tqueue.data = info; + info->callout_termios =callout_driver.init_termios; + info->normal_termios = serial_driver.init_termios; + info->open_wait = 0; + info->close_wait = 0; + printk("tty%02d at 0x%08x (irq = %d)", info->line, + info->port, info->irq); + printk(" is a Z85C30 SCC\n"); + } + + restore_flags(flags); + + return 0; +} + +/* + * register_serial and unregister_serial allows for serial ports to be + * configured at run-time, to support PCMCIA modems. + */ +/* PowerMac: Unused at this time, just here to make things link. */ +int register_serial(struct serial_struct *req) +{ + return -1; +} + +void unregister_serial(int line) +{ + return; +} + +/* + * ------------------------------------------------------------ + * Serial console driver + * ------------------------------------------------------------ + */ +#ifdef CONFIG_SERIAL_CONSOLE + + +/* + * Print a string to the serial port trying not to disturb + * any possible real use of the port... + */ + +/* This is for console output */ +static void +zs_console_putchar(struct dec_serial *info, char ch) +{ + int loops = 10000; + unsigned long flags; + + if(!info->zs_channel) + return; + + save_flags(flags); cli(); + + while (!(*(info->zs_channel->control) & Tx_BUF_EMP) && --loops) + RECOVERY_DELAY; + *(info->zs_channel->data) = ch; + RECOVERY_DELAY; + + restore_flags(flags); +} + +static void serial_console_write(struct console *co, const char *s, + unsigned count) +{ + struct dec_serial *info; + int i; + unsigned char nine; + + info = zs_soft + co->index; + +#if 0 + /* + * disable master interrupt if necessary + */ + nine = info->zs_channel->curregs[9]; + if(nine & MIE) + write_zsreg(info->zs_channel, R9, nine & ~MIE); +#endif + /* + * do it + */ + for (i = 0; i < count; i++, s++) { + if(*s == '\n') + zs_console_putchar(info, '\r'); + zs_console_putchar(info, *s); + } + /* + * restore master interrupt enable + */ +#if 0 + write_zsreg(info->zs_channel, R9, nine); +#endif +} + +/* + * Receive character from the serial port + */ +static int serial_console_wait_key(struct console *co) +{ + return 0; +} + +static kdev_t serial_console_device(struct console *c) +{ + return MKDEV(TTY_MAJOR, 64 + c->index); +} + +/* + * Setup initial baud/bits/parity. We do two things here: + * - construct a cflag setting for the first rs_open() + * - initialize the serial port + * Return non-zero if we didn't find a serial port. + */ +__initfunc(static int serial_console_setup(struct console *co, char *options)) +{ + struct dec_serial *info; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int cflag = CREAD | HUPCL | CLOCAL; + char *s; + unsigned long flags; + + if(!IOASIC) + return -ENODEV; + + info = zs_soft + co->index; + + if (zs_chain == 0) + probe_sccs(); + + info->is_cons = 1; + + if (options) { + baud = simple_strtoul(options, NULL, 10); + s = options; + while(*s >= '0' && *s <= '9') + s++; + if (*s) + parity = *s++; + if (*s) + bits = *s - '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; + } + co->cflag = cflag; +#if 1 + save_and_cli(flags); + + /* + * Turn on RTS and DTR. + */ + zs_rtsdtr(info, 1); + + /* + * Finally, enable sequencing + */ + info->zs_channel->curregs[3] |= (RxENABLE | Rx8); + info->zs_channel->curregs[5] |= (TxENAB | Tx8); + info->zs_channel->curregs[9] |= (VIS); + write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]); + write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); + write_zsreg(info->zs_channel, 9, info->zs_channel->curregs[9]); + + /* + * Clear the interrupt registers. + */ + write_zsreg(info->zs_channel, 0, ERR_RES); + write_zsreg(info->zs_channel, 0, RES_H_IUS); + + /* + * Set the speed of the serial port + */ + change_speed(info); + + /* Save the current value of RR0 */ + info->read_reg_zero = read_zsreg(info->zs_channel, 0); + + zs_soft[co->index].clk_divisor = 16; + zs_soft[co->index].zs_baud = get_zsbaud(&zs_soft[co->index]); + + restore_flags(flags); +#endif + return 0; +} + +static struct console sercons = { + "ttyS", + serial_console_write, + NULL, + serial_console_device, + serial_console_wait_key, + NULL, + serial_console_setup, + CON_PRINTBUFFER, + -1, + 0, + NULL +}; + +/* + * Register console. + */ +__initfunc (long zs_serial_console_init(long kmem_start, long kmem_end)) +{ + register_console(&sercons); + return kmem_start; +} +#endif /* ifdef CONFIG_SERIAL_CONSOLE */ + +#ifdef CONFIG_KGDB +/* These are for receiving and sending characters under the kgdb + * source level kernel debugger. + */ +void putDebugChar(char kgdb_char) +{ + struct dec_zschannel *chan = zs_kgdbchan; + while ((read_zsreg(chan, 0) & Tx_BUF_EMP) == 0) + RECOVERY_DELAY; + write_zsdata(chan, kgdb_char); +} +char getDebugChar(void) +{ + struct dec_zschannel *chan = zs_kgdbchan; + while((read_zsreg(chan, 0) & Rx_CH_AV) == 0) + eieio(); /*barrier();*/ + return read_zsdata(chan); +} +void kgdb_interruptible(int yes) +{ + struct dec_zschannel *chan = zs_kgdbchan; + int one, nine; + nine = read_zsreg(chan, 9); + if (yes == 1) { + one = EXT_INT_ENAB|INT_ALL_Rx; + nine |= MIE; + printk("turning serial ints on\n"); + } else { + one = RxINT_DISAB; + nine &= ~MIE; + printk("turning serial ints off\n"); + } + write_zsreg(chan, 1, one); + write_zsreg(chan, 9, nine); +} +/* This sets up the serial port we're using, and turns on + * interrupts for that channel, so kgdb is usable once we're done. + */ +static inline void kgdb_chaninit(struct dec_zschannel *ms, int intson, int bps) +{ + int brg; + int i, x; + volatile char *sccc = ms->control; + brg = BPS_TO_BRG(bps, ZS_CLOCK/16); + printk("setting bps on kgdb line to %d [brg=%x]\n", bps, brg); + for (i = 20000; i != 0; --i) { + x = *sccc; eieio(); + } + for (i = 0; i < sizeof(scc_inittab); ++i) { + write_zsreg(ms, scc_inittab[i], scc_inittab[i+1]); + i++; + } +} +/* This is called at boot time to prime the kgdb serial debugging + * serial line. The 'tty_num' argument is 0 for /dev/ttya and 1 + * for /dev/ttyb which is determined in setup_arch() from the + * boot command line flags. + */ +__initfunc(void zs_kgdb_hook(int tty_num)) +{ + /* Find out how many Z8530 SCCs we have */ + if (zs_chain == 0) + probe_sccs(); + zs_soft[tty_num].zs_channel = &zs_channels[tty_num]; + zs_kgdbchan = zs_soft[tty_num].zs_channel; + zs_soft[tty_num].change_needed = 0; + zs_soft[tty_num].clk_divisor = 16; + zs_soft[tty_num].zs_baud = 38400; + zs_soft[tty_num].kgdb_channel = 1; /* This runs kgdb */ + zs_soft[tty_num ^ 1].kgdb_channel = 0; /* This does not */ + /* Turn on transmitter/receiver at 8-bits/char */ + kgdb_chaninit(zs_soft[tty_num].zs_channel, 1, 38400); + printk("KGDB: on channel %d initialized\n", tty_num); + set_debug_traps(); /* init stub */ +} +#endif /* ifdef CONFIG_KGDB */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/tc/zs.h linux.pre11.3/drivers/tc/zs.h --- linux.vanilla/drivers/tc/zs.h Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/tc/zs.h Mon Jul 19 23:28:26 1999 @@ -0,0 +1,405 @@ +/* + * macserial.h: Definitions for the Macintosh Z8530 serial driver. + * + * Adapted from drivers/sbus/char/sunserial.h by Paul Mackerras. + * + * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ +#ifndef _DECSERIAL_H +#define _DECSERIAL_H + +#define NUM_ZSREGS 16 + +struct serial_struct { + int type; + int line; + int port; + int irq; + int flags; + int xmit_fifo_size; + int custom_divisor; + int baud_base; + unsigned short close_delay; + char reserved_char[2]; + int hub6; + unsigned short closing_wait; /* time to wait before closing */ + unsigned short closing_wait2; /* no longer used... */ + int reserved[4]; +}; + +/* + * For the close wait times, 0 means wait forever for serial port to + * flush its output. 65535 means don't wait at all. + */ +#define ZILOG_CLOSING_WAIT_INF 0 +#define ZILOG_CLOSING_WAIT_NONE 65535 + +/* + * Definitions for ZILOG_struct (and serial_struct) flags field + */ +#define ZILOG_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes + on the callout port */ +#define ZILOG_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */ +#define ZILOG_SAK 0x0004 /* Secure Attention Key (Orange book) */ +#define ZILOG_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */ + +#define ZILOG_SPD_MASK 0x0030 +#define ZILOG_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */ + +#define ZILOG_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */ +#define ZILOG_SPD_CUST 0x0030 /* Use user-specified divisor */ + +#define ZILOG_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */ +#define ZILOG_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */ +#define ZILOG_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */ +#define ZILOG_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */ +#define ZILOG_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */ + +#define ZILOG_FLAGS 0x0FFF /* Possible legal ZILOG flags */ +#define ZILOG_USR_MASK 0x0430 /* Legal flags that non-privileged + * users can set or reset */ + +/* Internal flags used only by kernel/chr_drv/serial.c */ +#define ZILOG_INITIALIZED 0x80000000 /* Serial port was initialized */ +#define ZILOG_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */ +#define ZILOG_NORMAL_ACTIVE 0x20000000 /* Normal device is active */ +#define ZILOG_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */ +#define ZILOG_CLOSING 0x08000000 /* Serial port is closing */ +#define ZILOG_CTS_FLOW 0x04000000 /* Do CTS flow control */ +#define ZILOG_CHECK_CD 0x02000000 /* i.e., CLOCAL */ + +/* Software state per channel */ + +#ifdef __KERNEL__ +/* + * This is our internal structure for each serial port's state. + * + * Many fields are paralleled by the structure used by the serial_struct + * structure. + * + * For definitions of the flags field, see tty.h + */ + +struct dec_zschannel { + volatile unsigned char *control; + volatile unsigned char *data; + + /* Current write register values */ + unsigned char curregs[NUM_ZSREGS]; +}; + +struct dec_serial { + struct dec_serial *zs_next; /* For IRQ servicing chain */ + struct dec_zschannel *zs_channel; /* Channel registers */ + struct dec_zschannel *zs_chan_a; /* A side registers */ + unsigned char read_reg_zero; + + char soft_carrier; /* Use soft carrier on this channel */ + char break_abort; /* Is serial console in, so process brk/abrt */ + char kgdb_channel; /* Kgdb is running on this channel */ + char is_cons; /* Is this our console. */ + unsigned char tx_active; /* character is being xmitted */ + unsigned char tx_stopped; /* output is suspended */ + + /* We need to know the current clock divisor + * to read the bps rate the chip has currently + * loaded. + */ + unsigned char clk_divisor; /* May be 1, 16, 32, or 64 */ + int zs_baud; + + char change_needed; + + int magic; + int baud_base; + int port; + int irq; + int flags; /* defined in tty.h */ + int type; /* UART type */ + struct tty_struct *tty; + int read_status_mask; + int ignore_status_mask; + int timeout; + int xmit_fifo_size; + int custom_divisor; + int x_char; /* xon/xoff character */ + int close_delay; + unsigned short closing_wait; + unsigned short closing_wait2; + unsigned long event; + unsigned long last_active; + int line; + int count; /* # of fd on device */ + int blocked_open; /* # of blocked opens */ + long session; /* Session of opening process */ + long pgrp; /* pgrp of opening process */ + unsigned char *xmit_buf; + int xmit_head; + int xmit_tail; + int xmit_cnt; + struct tq_struct tqueue; + struct tq_struct tqueue_hangup; + struct termios normal_termios; + struct termios callout_termios; + struct wait_queue *open_wait; + struct wait_queue *close_wait; +}; + + +#define SERIAL_MAGIC 0x5301 + +/* + * The size of the serial xmit buffer is 1 page, or 4096 bytes + */ +#define SERIAL_XMIT_SIZE 4096 + +/* + * Events are used to schedule things to happen at timer-interrupt + * time, instead of at rs interrupt time. + */ +#define RS_EVENT_WRITE_WAKEUP 0 + +#endif /* __KERNEL__ */ + +/* Conversion routines to/from brg time constants from/to bits + * per second. + */ +#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2)) +#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2) + +/* The Zilog register set */ + +#define FLAG 0x7e + +/* Write Register 0 */ +#define R0 0 /* Register selects */ +#define R1 1 +#define R2 2 +#define R3 3 +#define R4 4 +#define R5 5 +#define R6 6 +#define R7 7 +#define R8 8 +#define R9 9 +#define R10 10 +#define R11 11 +#define R12 12 +#define R13 13 +#define R14 14 +#define R15 15 + +#define NULLCODE 0 /* Null Code */ +#define POINT_HIGH 0x8 /* Select upper half of registers */ +#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */ +#define SEND_ABORT 0x18 /* HDLC Abort */ +#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */ +#define RES_Tx_P 0x28 /* Reset TxINT Pending */ +#define ERR_RES 0x30 /* Error Reset */ +#define RES_H_IUS 0x38 /* Reset highest IUS */ + +#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */ +#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */ +#define RES_EOM_L 0xC0 /* Reset EOM latch */ + +/* Write Register 1 */ + +#define EXT_INT_ENAB 0x1 /* Ext Int Enable */ +#define TxINT_ENAB 0x2 /* Tx Int Enable */ +#define PAR_SPEC 0x4 /* Parity is special condition */ + +#define RxINT_DISAB 0 /* Rx Int Disable */ +#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */ +#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */ +#define INT_ERR_Rx 0x18 /* Int on error only */ + +#define WT_RDY_RT 0x20 /* Wait/Ready on R/T */ +#define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */ +#define WT_RDY_ENAB 0x80 /* Wait/Ready Enable */ + +/* Write Register #2 (Interrupt Vector) */ + +/* Write Register 3 */ + +#define RxENABLE 0x1 /* Rx Enable */ +#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */ +#define ADD_SM 0x4 /* Address Search Mode (SDLC) */ +#define RxCRC_ENAB 0x8 /* Rx CRC Enable */ +#define ENT_HM 0x10 /* Enter Hunt Mode */ +#define AUTO_ENAB 0x20 /* Auto Enables */ +#define Rx5 0x0 /* Rx 5 Bits/Character */ +#define Rx7 0x40 /* Rx 7 Bits/Character */ +#define Rx6 0x80 /* Rx 6 Bits/Character */ +#define Rx8 0xc0 /* Rx 8 Bits/Character */ +#define RxNBITS_MASK 0xc0 + +/* Write Register 4 */ + +#define PAR_ENA 0x1 /* Parity Enable */ +#define PAR_EVEN 0x2 /* Parity Even/Odd* */ + +#define SYNC_ENAB 0 /* Sync Modes Enable */ +#define SB1 0x4 /* 1 stop bit/char */ +#define SB15 0x8 /* 1.5 stop bits/char */ +#define SB2 0xc /* 2 stop bits/char */ +#define SB_MASK 0xc + +#define MONSYNC 0 /* 8 Bit Sync character */ +#define BISYNC 0x10 /* 16 bit sync character */ +#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */ +#define EXTSYNC 0x30 /* External Sync Mode */ + +#define X1CLK 0x0 /* x1 clock mode */ +#define X16CLK 0x40 /* x16 clock mode */ +#define X32CLK 0x80 /* x32 clock mode */ +#define X64CLK 0xC0 /* x64 clock mode */ +#define XCLK_MASK 0xC0 + +/* Write Register 5 */ + +#define TxCRC_ENAB 0x1 /* Tx CRC Enable */ +#define RTS 0x2 /* RTS */ +#define SDLC_CRC 0x4 /* SDLC/CRC-16 */ +#define TxENAB 0x8 /* Tx Enable */ +#define SND_BRK 0x10 /* Send Break */ +#define Tx5 0x0 /* Tx 5 bits (or less)/character */ +#define Tx7 0x20 /* Tx 7 bits/character */ +#define Tx6 0x40 /* Tx 6 bits/character */ +#define Tx8 0x60 /* Tx 8 bits/character */ +#define TxNBITS_MASK 0x60 +#define DTR 0x80 /* DTR */ + +/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */ + +/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */ + +/* Write Register 8 (transmit buffer) */ + +/* Write Register 9 (Master interrupt control) */ +#define VIS 1 /* Vector Includes Status */ +#define NV 2 /* No Vector */ +#define DLC 4 /* Disable Lower Chain */ +#define MIE 8 /* Master Interrupt Enable */ +#define STATHI 0x10 /* Status high */ +#define SOFTACK 0x20 /* Software Interrupt Acknowledge */ +#define NORESET 0 /* No reset on write to R9 */ +#define CHRB 0x40 /* Reset channel B */ +#define CHRA 0x80 /* Reset channel A */ +#define FHWRES 0xc0 /* Force hardware reset */ + +/* Write Register 10 (misc control bits) */ +#define BIT6 1 /* 6 bit/8bit sync */ +#define LOOPMODE 2 /* SDLC Loop mode */ +#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */ +#define MARKIDLE 8 /* Mark/flag on idle */ +#define GAOP 0x10 /* Go active on poll */ +#define NRZ 0 /* NRZ mode */ +#define NRZI 0x20 /* NRZI mode */ +#define FM1 0x40 /* FM1 (transition = 1) */ +#define FM0 0x60 /* FM0 (transition = 0) */ +#define CRCPS 0x80 /* CRC Preset I/O */ + +/* Write Register 11 (Clock Mode control) */ +#define TRxCXT 0 /* TRxC = Xtal output */ +#define TRxCTC 1 /* TRxC = Transmit clock */ +#define TRxCBR 2 /* TRxC = BR Generator Output */ +#define TRxCDP 3 /* TRxC = DPLL output */ +#define TRxCOI 4 /* TRxC O/I */ +#define TCRTxCP 0 /* Transmit clock = RTxC pin */ +#define TCTRxCP 8 /* Transmit clock = TRxC pin */ +#define TCBR 0x10 /* Transmit clock = BR Generator output */ +#define TCDPLL 0x18 /* Transmit clock = DPLL output */ +#define RCRTxCP 0 /* Receive clock = RTxC pin */ +#define RCTRxCP 0x20 /* Receive clock = TRxC pin */ +#define RCBR 0x40 /* Receive clock = BR Generator output */ +#define RCDPLL 0x60 /* Receive clock = DPLL output */ +#define RTxCX 0x80 /* RTxC Xtal/No Xtal */ + +/* Write Register 12 (lower byte of baud rate generator time constant) */ + +/* Write Register 13 (upper byte of baud rate generator time constant) */ + +/* Write Register 14 (Misc control bits) */ +#define BRENABL 1 /* Baud rate generator enable */ +#define BRSRC 2 /* Baud rate generator source */ +#define DTRREQ 4 /* DTR/Request function */ +#define AUTOECHO 8 /* Auto Echo */ +#define LOOPBAK 0x10 /* Local loopback */ +#define SEARCH 0x20 /* Enter search mode */ +#define RMC 0x40 /* Reset missing clock */ +#define DISDPLL 0x60 /* Disable DPLL */ +#define SSBR 0x80 /* Set DPLL source = BR generator */ +#define SSRTxC 0xa0 /* Set DPLL source = RTxC */ +#define SFMM 0xc0 /* Set FM mode */ +#define SNRZI 0xe0 /* Set NRZI mode */ + +/* Write Register 15 (external/status interrupt control) */ +#define ZCIE 2 /* Zero count IE */ +#define DCDIE 8 /* DCD IE */ +#define SYNCIE 0x10 /* Sync/hunt IE */ +#define CTSIE 0x20 /* CTS IE */ +#define TxUIE 0x40 /* Tx Underrun/EOM IE */ +#define BRKIE 0x80 /* Break/Abort IE */ + + +/* Read Register 0 */ +#define Rx_CH_AV 0x1 /* Rx Character Available */ +#define ZCOUNT 0x2 /* Zero count */ +#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */ +#define DCD 0x8 /* DCD */ +#define SYNC_HUNT 0x10 /* Sync/hunt */ +#define CTS 0x20 /* CTS */ +#define TxEOM 0x40 /* Tx underrun */ +#define BRK_ABRT 0x80 /* Break/Abort */ + +/* Read Register 1 */ +#define ALL_SNT 0x1 /* All sent */ +/* Residue Data for 8 Rx bits/char programmed */ +#define RES3 0x8 /* 0/3 */ +#define RES4 0x4 /* 0/4 */ +#define RES5 0xc /* 0/5 */ +#define RES6 0x2 /* 0/6 */ +#define RES7 0xa /* 0/7 */ +#define RES8 0x6 /* 0/8 */ +#define RES18 0xe /* 1/8 */ +#define RES28 0x0 /* 2/8 */ +/* Special Rx Condition Interrupts */ +#define PAR_ERR 0x10 /* Parity error */ +#define Rx_OVR 0x20 /* Rx Overrun Error */ +#define FRM_ERR 0x40 /* CRC/Framing Error */ +#define END_FR 0x80 /* End of Frame (SDLC) */ + +/* Read Register 2 (channel b only) - Interrupt vector */ + +/* Read Register 3 (interrupt pending register) ch a only */ +#define CHBEXT 0x1 /* Channel B Ext/Stat IP */ +#define CHBTxIP 0x2 /* Channel B Tx IP */ +#define CHBRxIP 0x4 /* Channel B Rx IP */ +#define CHAEXT 0x8 /* Channel A Ext/Stat IP */ +#define CHATxIP 0x10 /* Channel A Tx IP */ +#define CHARxIP 0x20 /* Channel A Rx IP */ + +/* Read Register 8 (receive data register) */ + +/* Read Register 10 (misc status bits) */ +#define ONLOOP 2 /* On loop */ +#define LOOPSEND 0x10 /* Loop sending */ +#define CLK2MIS 0x40 /* Two clocks missing */ +#define CLK1MIS 0x80 /* One clock missing */ + +/* Read Register 12 (lower byte of baud rate generator constant) */ + +/* Read Register 13 (upper byte of baud rate generator constant) */ + +/* Read Register 15 (value of WR 15) */ + +/* Misc macros */ +#define ZS_CLEARERR(channel) (write_zsreg(channel, 0, ERR_RES)) +#define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \ + garbage = read_zsdata(channel); \ + garbage = read_zsdata(channel); \ + garbage = read_zsdata(channel); \ + } while(0) + +#endif /* !(_DECSERIAL_H) */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/Config.in linux.pre11.3/drivers/video/Config.in --- linux.vanilla/drivers/video/Config.in Fri May 28 00:32:59 1999 +++ linux.pre11.3/drivers/video/Config.in Mon Jul 19 23:28:19 1999 @@ -74,6 +74,7 @@ fi if [ "$ARCH" = "i386" ]; then bool 'VESA VGA graphics console' CONFIG_FB_VESA + bool 'VGA 16-color graphics console' CONFIG_FB_VGA16 define_bool CONFIG_VIDEO_SELECT y fi if [ "$CONFIG_VISWS" = "y" ]; then @@ -141,6 +142,7 @@ tristate 'Atari interleaved bitplanes (8 planes) support' CONFIG_FBCON_IPLAN2P8 # tristate 'Atari interleaved bitplanes (16 planes) support' CONFIG_FBCON_IPLAN2P16 tristate 'Mac variable bpp packed pixels support' CONFIG_FBCON_MAC + bool 'VGA 16-color planar support' CONFIG_FBCON_VGA_PLANES tristate 'VGA characters/attributes support' CONFIG_FBCON_VGA else # Guess what we need @@ -282,6 +284,9 @@ if [ "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then define_bool CONFIG_FBCON_MAC m fi + fi + if [ "$CONFIG_FB_VGA16" = "y" ]; then + define_bool CONFIG_FBCON_VGA_PLANES y fi if [ "$CONFIG_FB_MDA" = "y" -o "$CONFIG_FB_VGA" = "y" ]; then define_bool CONFIG_FBCON_VGA y diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/Makefile linux.pre11.3/drivers/video/Makefile --- linux.vanilla/drivers/video/Makefile Fri May 28 00:32:59 1999 +++ linux.pre11.3/drivers/video/Makefile Tue Jul 20 00:05:06 1999 @@ -192,9 +192,11 @@ ifeq ($(CONFIG_FB_TGA),y) L_OBJS += tgafb.o +CONFIG_FBGEN_BUILTIN = y else ifeq ($(CONFIG_FB_TGA),m) M_OBJS += tgafb.o + CONFIG_FBGEN_MODULE = y endif endif @@ -202,6 +204,10 @@ L_OBJS += vesafb.o endif +ifeq ($(CONFIG_FB_VGA16),y) +L_OBJS += vga16fb.o +endif + ifeq ($(CONFIG_FB_VIRGE),y) L_OBJS += virgefb.o else @@ -462,6 +468,14 @@ endif endif +ifeq ($(CONFIG_FBCON_VGA_PLANES),y) +OX_OBJS += fbcon-vga-planes.o +else + ifeq ($(CONFIG_FBCON_VGA_PLANES),m) + MX_OBJS += fbcon-vga-planes.o + endif +endif + ifeq ($(CONFIG_FBCON_VGA),y) OX_OBJS += fbcon-vga.o else @@ -483,6 +497,16 @@ else ifeq ($(CONFIG_MDA_CONSOLE),m) M_OBJS += mdacon.o + endif +endif + +# Newport Text Console + +ifeq ($(CONFIG_SGI_NEWPORT_CONSOLE),y) +L_OBJS += newport_con.o vga_font.o +else + ifeq ($(CONFIG_SGI_NEWPORT_CONSOLE),m) + M_OBJS += newport_con.o vga_font.o endif endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/fbcon-vga-planes.c linux.pre11.3/drivers/video/fbcon-vga-planes.c --- linux.vanilla/drivers/video/fbcon-vga-planes.c Thu Jan 1 01:00:00 1970 +++ linux.pre11.3/drivers/video/fbcon-vga-planes.c Mon Jul 19 23:28:22 1999 @@ -0,0 +1,364 @@ +/* + * linux/drivers/video/fbcon-vga-planes.c -- Low level frame buffer operations + * for VGA 4-plane modes + * + * Copyright 1999 Ben Pfaff and Petr Vandrovec + * Based on code by Michael Schmitz + * Based on the old macfb.c 4bpp code by Alan Cox + * + * 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