diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/CREDITS linux.ac/CREDITS --- linux.vanilla/CREDITS Tue Jun 15 16:49:44 1999 +++ linux.ac/CREDITS Mon Jul 19 04:16:54 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 @@ -1306,6 +1318,13 @@ D: XF86_8514 D: cfdisk (curses based disk partitioning program) +N: Heinz Mauelshagen +E: mge@ez-darmstadt.telekom.de +D: Logical Volume Manager +S: Bartningstr. 12 +S: 64289 Darmstadt +S: Germany + N: Mike McLagan E: mike.mclagan@linux.org W: http://www.invlogic.com/~mmclagan @@ -1603,6 +1622,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 +1666,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 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/Changes linux.ac/Documentation/Changes --- linux.vanilla/Documentation/Changes Thu May 27 22:11:46 1999 +++ linux.ac/Documentation/Changes Mon Jul 19 03:52:36 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.ac/Documentation/Configure.help --- linux.vanilla/Documentation/Configure.help Tue Jun 15 16:49:44 1999 +++ linux.ac/Documentation/Configure.help Mon Jul 19 04:05:33 1999 @@ -87,13 +87,13 @@ a system with only one CPU, like most personal computers, say N. If you have a system with more than one CPU, say Y. - If you say N here, the kernel will run on single and multiprocessor - machines, but will use only one CPU of a multiprocessor machine. If + If you say N here, the kernel will run on single and multi-processor + machines, but will use only one CPU of a multi-processor machine. If you say Y here, the kernel will run on many, but not all, - singleprocessor machines. On a singleprocessor machine, the kernel + single-processor machines. On a single-processor machine, the kernel will run faster if you say N here. - Note that if you say Y here and choose architecture "586" or + Note that if you say Y here and choose architectures "586" or "Pentium" under "Processor family", the kernel will not work on 486 architectures. Similarly, multiprocessor kernels for the "PPro" architecture may not work on all Pentium based boards. @@ -136,7 +136,7 @@ If you are not sure, say Y; apart from resulting in a 45 KB bigger kernel, it won't hurt. - + Timer and CPU usage LEDs CONFIG_LEDS If you define this option, the LEDs on your machine will be used @@ -927,6 +927,29 @@ called on26.o. You must also have a high-level driver for the type of device that you want to support. +Logical Volume Manager (LVM) support +CONFIG_BLK_DEV_LVM + This driver lets you combine several hard disks, hard disk partitions + or even multiple devices into a volume group. Imagine a volume group as + a kind of virtual disk. Logical volumes, which can be thought of as + virtual partitions, can be created in the volume group. + You can resize volume groups and logical volumes after creation time, + corresponding to new capacity needs. Logical volumes are accessed as + block devices named /dev/VolumeGroupName/LogicalVolumeName. + + For details see /usr/src/linux/Documentation/LVM-HOWTO. + + To get the newest software see . + +Logical Volume Manager proc filesystem information +CONFIG_LVM_PROC_FS + If you say Y here, you are able to see overall Logical Volume Manager, + Volume Group, Logical and Physical Volume information in /proc/lvm. + + You must check, that the "proc filesystem support" (CONFIG_PROC_FS) is + enabled too, to use this option. + + Multiple devices driver support CONFIG_BLK_DEV_MD This driver lets you combine several hard disk partitions into one @@ -945,6 +968,13 @@ If unsure, say N. +Autodetect RAID partitions +CONFIG_AUTODETECT_RAID + This feature lets the kernel detect RAID partitions on bootup. + An autodetect RAID partition is a normal partition with partition + type 0xfd. Use this if you want to boot RAID devices, or want to + run them automatically. + Linear (append) mode CONFIG_MD_LINEAR If you say Y here, then your multiple devices driver will be able to @@ -1024,6 +1054,21 @@ If unsure, say Y. +Translucent Block Device Support (EXPERIMENTAL) +CONFIG_MD_TRANSLUCENT + DO NOT USE THIS STUFF YET! + + currently there is only a placeholder there as the implementation + is not yet usable. + +Logical Volume Manager support (EXPERIMENTAL) +CONFIG_MD_LVM + DO NOT USE THIS STUFF YET! + + i have released this so people can comment on the architecture, + but user-space tools are still unusable so there is nothing much + you can do with this. + Boot support (linear, striped) CONFIG_MD_BOOT To boot with an initial linear or striped md device you have to @@ -1844,6 +1889,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 @@ -2627,6 +2677,76 @@ The module will be called ip_masq_markfw.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +IP: masquerading virtual server support +CONFIG_IP_MASQUERADE_VS + IP Virtual Server support will let you build a virtual server + based on cluster of two or more real servers. This option must + be enabled for at least one of the clustered computers that will + take care of intercepting incomming connections to the virtual IP + and scheduling them to real servers. + Three request dispatching techniques are implemented, they are + virtual server via NAT, virtual server via tunneling and virtual + server via direct routing. The round-robin scheduling, the weighted + round-robin secheduling, or the weighted least-connection scheduling + algorithm can be used to choose which server the connection is + directed to, thus load balancing can be achieved among the servers. + For more information and its administration program, please visit + the following URL: + http://proxy.iinchina.net/~wensong/ippfvs/ + If you want this, say Y. + +IP masquerading VS table size (the Nth power of 2) +CONFIG_IP_MASQUERADE_VS_TAB_BITS + Using a big IP masquerading hash table for virtual server will greatly + reduce conflicts in the masquerading hash table when there are + thousands of active connections. + Note the table size must be power of 2. The table size will be the + value of 2 to the your input number power. For example, the default + number is 12, so the table size is 4096. Don't input the number too + small, otherwise you will lose performance on it. + You can adapt the table size yourself, according to your virtual + server application. It is good to set the table size larger than + the number of connections per second multiplying average lasting time + of connection in the table. For example, your virtual server gets + 20 connections per second, the connection lasts for 200 seconds in + average in the masquerading table, the table size should be larger + than 20x200, it is good to set the table size 4096 (2**12). + +IPVS: round-robin scheduling +CONFIG_IP_MASQUERADE_VS_RR + The robin-robin scheduling algorithm simply directs network + connections to different real servers in a round-robin manner. + If you want to compile it in kernel, say Y. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + +IPVS: weighted round-robin scheduling +CONFIG_IP_MASQUERADE_VS_WRR + The weighted robin-robin scheduling algorithm directs network + connections to different real servers based on server weights + in a round-robin manner. Servers with higher weights receive + new connections first than those with less weights, and servers + with higher weights get more connections than those with less + weights and servers with equal weights get equal connections. + If you want to compile it in kernel, say Y. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + +IPVS: weighted least-connection scheduling +CONFIG_IP_MASQUERADE_VS_WLC + The weighted least-connection scheduling algorithm directs network + connections to the server with the least number of alive connections + dividing the server weight. + If you want to compile it in kernel, say Y. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + +IPVS: persistent client connection scheduling +CONFIG_IP_MASQUERADE_VS_PCC + The persistent client connection feature means that after a client + establishs a connection to the selected server, all connections + from the same client will be directed to the same server in a + specified period. + If you want to compile it in kernel, say Y. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + IP: always defragment (required for masquerading) CONFIG_IP_ALWAYS_DEFRAG If you say Y here, then all incoming fragments (parts of IP packets @@ -3243,6 +3363,13 @@ ### Don't know what's going on here. ### # +YAM driver for AX.25 +CONFIG_YAM + Support for the YAM modem on serial port. If you want to compile this + as a module ( = code which can be inserted in and removed from the + running kernel whenever you want), say M here and read + Documentation/modules.txt. + BAYCOM picpar and par96 driver for AX.25 CONFIG_BAYCOM_PAR This is a driver for Baycom style simple amateur radio modems that @@ -4989,6 +5116,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 +5253,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 @@ -5478,9 +5625,12 @@ that has a program like lynx or netscape) is a family of intelligent multiprotocol WAN adapters with data transfer rates up to T1 (1.544 Mbps). They are also known as Synchronous Data Link Adapters (SDLA) - and designated S502E(A), S503 or S508. These cards support the X.25, - Frame Relay, and PPP protocols. If you have one or more of these - cards, say Y to this option; you may then also want to read the file + and designated S503 or S508. These cards support the X.25, Frame + Relay, PPP, Cisco HDLC protocols. The driver also offers API support + for protocols like HDLC (LAPB), HDLC Streaming and BiSync. + + If you have one or more of these cards, say Y to this option; you + may then also want to read the file Documentation/networking/wanpipe.txt. The next questions will ask you about the protocols you want the driver to support. @@ -5500,26 +5650,48 @@ WANPIPE X.25 support CONFIG_WANPIPE_X25 Say Y to this option if you are planning to connect a WANPIPE card - to an X.25 network. You should then also have said Y to "CCITT X.25 - Packet Layer" and "LAPB Data Link Driver", above. If you say N, the - X.25 support will not be included in the driver (saves about 16 KB - of kernel memory). + to an X.25 network. If you say N, the X.25 support will not be + included in the driver. The X.25 option is ONLY supported on S508 + cards. WANPIPE Frame Relay support CONFIG_WANPIPE_FR Say Y to this option if you are planning to connect a WANPIPE card - to a frame relay network. You should then also have said Y to "Frame - Relay (DLCI) support", above. If you say N, the frame relay - support will not be included in the driver (saves about 16 KB of - kernel memory). + to a frame relay network. If you say N, the frame relay support will + not be included in the driver. The Frame Relay option is ONLY + supported on S508 cards. WANPIPE PPP support CONFIG_WANPIPE_PPP Say Y to this option if you are planning to connect a WANPIPE card - to a leased line using Point-to-Point protocol (PPP). You should - then also have said Y to "PPP (point-to-point) support", above. If - you say N, the PPP support will not be included in the driver (saves - about 16 KB of kernel memory). + to a leased line using Point-to-Point protocol (PPP). If you say N, + the PPP support will not be included in the driver. The PPP option + is ONLY supported on S508 cards. + +WANPIPE Cisco HDLC support +CONFIG_WANPIPE_CHDLC + Say Y to this option if you are planning to connect a WANPIPE card + to a leased line using the Cisco HDLC protocol. This now supports + Dual Port Cisco HDLC on the S508 card ONLY. This support also allows + user to build applications using the HDLC streaming API. If you say + N, the Cisco HDLC support and HDLC streaming API will not be + included in the driver. + +WANPIPE BiSync Streaming API support +CONFIG_WANPIPE_BSTRM + Say Y to this option if you are planning to use a WANPIPE card to + develop user applications to send RAW BiSync data. This option + provides an API support for customers to build their own + applications. This API ONLY supports S503 cards. If you say N, then + BiSync API support will not be included in the driver. + +WANPIPE HDLC (LAPB) API support +CONFIG_WANPIPE_HDLC + Say Y to this option if you are planning to use a WANPIPE card to + develop user application to send HDLC (LAPB) data. This option + provides an API support for customers to build their own + applications. This API ONLY supports the S508 cards. If you say N, + then HDLC (LAPB) API support will not be included in the driver. Ethernet (10 or 100Mbit) CONFIG_NET_ETHERNET @@ -5734,7 +5906,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 +6664,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 @@ -7204,11 +7395,12 @@ If unsure, say N. -System V and Coherent filesystem support +System V, Version 7 and Coherent filesystem support CONFIG_SYSV_FS SCO, Xenix and Coherent are commercial Unix systems for Intel - machines. Saying Y here would allow you to read to and write from - their floppies and hard disk partitions. + machines, and Version 7 was used on the DEC PDP-11. Saying Y here + would allow you to read to and write from their floppies and hard + disk partitions. If you have floppies or hard disk partitions like that, it is likely that they contain binaries from those other Unix systems; in order @@ -7360,6 +7552,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 +8314,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 @@ -8731,9 +8945,15 @@ APM is a BIOS specification for saving power using several different techniques. This is mostly useful for battery powered laptops with APM compliant BIOSes. If you say Y here, the system time will be - reset after a USER RESUME operation, the /proc/apm device will - provide battery status information, and user-space programs will - receive notification of APM "events" (e.g., battery status change). + reset after a RESUME operation, the /proc/apm device will provide + battery status information, and user-space programs will receive + notification of APM "events" (e.g., battery status change). + + If you select "Y" here, you can disable actual use of the APM + BIOS by passing the "apm=off" option to the kernel at boot time. + + Note that the APM support is almost completely disabled for + machines with more than one CPU. Supporting software is available; for more information, read the Battery Powered Linux mini-HOWTO, available via FTP (user: @@ -8746,9 +8966,7 @@ This driver does not support the TI 4000M TravelMate and the ACER 486/DX4/75 because they don't have compliant BIOSes. Many "green" desktop machines also don't have compliant BIOSes, and this driver - will cause those machines to panic during the boot phase (typically, - these machines are using a data segment of 0040, which is reserved - for the Linux kernel). + may cause those machines to panic during the boot phase. If you are running Linux on a laptop, you may also want to read the Linux Laptop home page on the WWW at @@ -8825,18 +9043,6 @@ backlight at all, or it might print a lot of errors to the console, especially if you are using gpm. -Power off on shutdown -CONFIG_APM_POWER_OFF - Enable the ability to power off the computer after the Linux kernel - is halted. You will need software (e.g., a suitable version of the - halt(8) command ("man 8 halt")) to cause the computer to power down. - Recent versions of the sysvinit package available from - ftp://metalab.unc.edu/pub/Linux/system/daemons/init/ (user: - anonymous) contain support for this ("halt -p" shuts down Linux and - powers off the computer, if executed from runlevel 0). As with the - other APM options, this option may not work reliably with some APM - BIOS implementations. - Ignore multiple suspend/standby events CONFIG_APM_IGNORE_MULTIPLE_SUSPEND This option is necessary on the IBM Thinkpad 560, but should work on @@ -9191,7 +9397,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. @@ -9268,6 +9474,15 @@ You can say M here to compile this driver as a module; the module is called sb.o. +### +### Don't know what this is +### +#PCI Legacy soundblaster enabler +#CONFIG_SOUND_PCISB +# +#ESS-Tech Maestro support +#CONFIG_SOUND_ESSMAESTRO + Generic OPL2/OPL3 FM synthesizer support CONFIG_SOUND_ADLIB Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4). @@ -9764,6 +9979,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 @@ -10731,6 +10951,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 +11677,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/LVM-HOWTO linux.ac/Documentation/LVM-HOWTO --- linux.vanilla/Documentation/LVM-HOWTO Thu Jan 1 01:00:00 1970 +++ linux.ac/Documentation/LVM-HOWTO Wed Jun 16 14:25:27 1999 @@ -0,0 +1,118 @@ +Heinz Mauelshagen's LVM (Logical Volume Manager) howto. 01/28/1999 + + +Abstract: +--------- +The LVM adds a kind of virtual disks and virtual partitions functionality +to the Linux operating system + +It achieves this by adding an additional layer between the physical peripherals +and the i/o interface in the kernel. + +This allows the concatenation of several disk partitions or total disks +(so-called physical volumes or PVs) or even multiple devices +to form a storage pool (so-called Volume Group or VG) with +allocation units called physical extents (called PE). +You can think of the volume group as a virtual disk. +Please see scenario below. + +Some or all PEs of this VG then can be allocated to so-called Logical Volumes +or LVs in units called logical extents or LEs. +Each LE is mapped to a corresponding PE. +LEs and PEs are equal in size. +Logical volumes are a kind of virtual partitions. + + +The LVs can be used through device special files similar to the known +/dev/sd[a-z]* or /dev/hd[a-z]* named /dev/VolumeGroupName/LogicalVolumeName. + +But going beyond this, you are able to extend or reduce +VGs _AND_ LVs at runtime! + +So... +If for example the capacity of a LV gets too small and your VG containing +this LV is full, you could add another PV to that VG and simply extend +the LV afterwards. +If you reduce or delete a LV you can use the freed capacity for different +LVs in the same VG. + + +The above scenario looks like this: + + /------------------------------------------\ + | /--PV2---\ VG 1 /--PVn---\ | + | |-VGDA---| |-VGDA-- | | + | |PE1PE2..| |PE1PE2..| | + | | | ...... | | | + | | | | | | + | | /-----------------------\ | | + | | \-------LV 1------------/ | | + | | ..PEn| | ..PEn| | + | \--------/ \--------/ | + \------------------------------------------/ + +PV 1 could be /dev/sdc1 sized 3GB +PV n could be /dev/sde1 sized 4GB +VG 1 could be test_vg +LV 1 could be /dev/test_vg/test_lv +VGDA is the volume group descriptor area holding the LVM metadata +PE1 up to PEn is the number of physical extents on each disk(partition) + + + +Installation steps see INSTALL and insmod(1)/modprobe(1), kmod/kerneld(8) +to load the logical volume manager module if you did not bind it +into the kernel. + + +Configuration steps for getting the above scenario: + +1. Set the partition system id to 0xFE on /dev/sdc1 and /dev/sde1. + +2. do a "pvcreate /dev/sd[ce]1" + For testing purposes you can use more than one partition on a disk. + You should not use more than one partition because in the case of + a striped LV you'll have a performance breakdown. + +3. do a "vgcreate test_vg /dev/sd[ce]1" to create the new VG named "test_vg" + which has the total capacity of both partitions. + vgcreate activates (transfers the metadata into the LVM driver in the kernel) + the new volume group too to be able to create LVs in the next step. + +4. do a "lvcreate -L1500 -ntest_lv test_vg" to get a 1500MB linear LV named + "test_lv" and it's block device special "/dev/test_vg/test_lv". + + Or do a "lvcreate -i2 -I4 -l1500 -nanother_test_lv test_vg" to get a 100 LE + large logical volume with 2 stripes and stripesize 4 KB. + +5. For example generate a filesystem in one LV with + "mke2fs /dev/test_vg/test_lv" and mount it. + +6. extend /dev/test_vg/test_lv to 1600MB with relative size by + "lvextend -L+100 /dev/test_vg/test_lv" + or with absolute size by + "lvextend -L1600 /dev/test_vg/test_lv" + +7. reduce /dev/test_vg/test_lv to 900 logical extents with relative extents by + "lvreduce -l-700 /dev/test_vg/test_lv" + or with absolute extents by + "lvreduce -l900 /dev/test_vg/test_lv" + +9. rename a VG by deactivating it with + "vgchange -an test_vg" # only VGs with _no_ open LVs can be deactivated! + "vgrename test_vg whatever" + and reactivate it again by + "vgchange -ay whatever" + +9. rename a LV after closing it by + "lvchange -an /dev/whatever/test_lv" # only closed LVs can be deactivated + "lvrename /dev/whatever/test_lv /dev/whatever/whatvolume" + or by + "lvrename whatever test_lv whatvolume" + and reactivate it again by + "lvchange -ay /dev/whatever/whatvolume" + +10. if you own Ted Tso's resize2fs program, you are able to resize the + ext2 type filesystems contained in logical volumes without destroyiing + the data by + "e2fsadm -L+100 /dev/test_vg/another_test_lv" diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/cpqarray.txt linux.ac/Documentation/cpqarray.txt --- linux.vanilla/Documentation/cpqarray.txt Thu Jan 1 01:00:00 1970 +++ linux.ac/Documentation/cpqarray.txt Mon Jul 5 05:11:43 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/dcache.txt linux.ac/Documentation/filesystems/dcache.txt --- linux.vanilla/Documentation/filesystems/dcache.txt Thu Jan 1 01:00:00 1970 +++ linux.ac/Documentation/filesystems/dcache.txt Fri Jun 4 23:52:54 1999 @@ -0,0 +1,173 @@ +Some dcache details + +A traditional Unix system has inodes (`index nodes') as in-core +descriptors of files. An inode refers to the actual file, not +to a directory entry naming it. Linux v2.1.43 introduced dentries +(`directory entries') as in-core descriptors of file names. + +The entire purpose of dentries is to make the map +filename -> inode fast. An interesting side effect +is that the kernel knows what name was used to open a file +and that a system call getcwd() is possible. + +Thus, the central part of the dcache code are the lines + dentry = reserved_lookup(base, &this); + if (!dentry) { + dentry = cached_lookup(base, &this); + if (!dentry) + dentry = real_lookup(base, &this); + } +in namei.c. The reserved_lookup() takes care of . and ..; +the cached_lookup() is what we have the dcache for, +and the real_lookup() goes to the filesystem. + +The cached_lookup() returns the value of d_lookup(), +but does a d_revalidate() before returning, and if that fails +and the dentry has no children, it returns NULL. + [This is a rather obscure part. The d_revalidate() + is allowed to fail for any reason - for example, + autofs uses a timeout to make d_revalidate fail - + which means that the final dentry we come up with + need not be the dentry that d_lookup() found. + This causes bugs in the vfat filesystem. + Moreover, if d_revalidate(D) fails but D still has + children, then D is used anyway. + This also causes bugs in the vfat filesystem. + I think also nfs has problems.] + + + + +A struct dentry has five members of type struct list_head: + struct list_head d_hash; /* lookup hash list */ + struct list_head d_lru; /* d_count = 0 LRU list */ + struct list_head d_child; /* child of parent list */ + struct list_head d_subdirs; /* our children */ + struct list_head d_alias; /* inode alias list */ + + [Some of these names were very badly chosen, and lead + to confusion all the time. We should do a global replace + changing d_subdirs into d_children and d_child into d_sister.] + + + +1. d_hash + +The d_hash field of a dentry links the dentry into +the list of dentries for filenames with a given hash value +with list head dentry_hashtable[hashvalue] defined in dcache.c. +This list is used in d_lookup() to find a dentry with given name +and parent. It is used in d_validate() to find a dentry with +known hash and parent. + [The present code takes the parent into account when + computing a hash. Not doing this would make the code + simpler and faster, possibly at the expense of a few + more collisions. Has anyone investigated this?] +The d_hash field is an empty list when the file is a mount point +(cf. d_validate) or has been deleted, or when the dentry was +dropped for some other reason. + + +d_add(D,I) will put D into its hash chain and provide it +with the inode I. It is called by all filesystem lookup routines. + +d_drop(D) will remove D from its hash chain. A dentry is called +`unhashed' when its d_hash field is an empty list. +Sometimes dentries are dropped temporarily to make sure +no lookup will find them. The general routine vfs_rmdir(I,D) +will drop D if d_count=2, so that all filesystem rmdir() +routines can return -EBUSY when D still occurs in the hash list. +The filesystem routines for unlink and rmdir call d_delete() +which again calls d_drop(). + +[The d_hash field is referred to in many places that should +not know about its existence, in the phrase + if (list_empty(&dentry->d_hash)) ... +No doubt there should be a line + #define unhashed(d) (list_empty(&(d)->d_hash)) +in dcache.h, together with a comment describing the semantics +of being unhashed. Then all these occurrences of d_hash can +be removed. Next, d_drop() should be renamed d_unhash().] + +The dentry for the root of a mounted filesystem is returned by +d_alloc_root() and is unhashed. + + + +2. d_lru +The simplest list is the one joining the d_lru fields of +dentries that had d_count = 0 at some point in time. +The list head is the variable dentry_unused defined in dcache.c. +The number of elements in this list is dentry_stat.nr_unused. +There are no references to the d_lru field outside dcache.[ch]. + +Note that d_count is incremented by dget(), invoked by d_lookup(), +without removing the dentry from the LRU list. Thus, anyone hoping +to find unused dentries on this list must first check d_count. +If a dentry is not on the LRU list, its d_lru field is an +empty list (initialized by d_alloc()). + +dput(D) tries to get rid of D altogether when d_count = 0, but +puts D at the head of the LRU list if it is still on the hash list. +Thus, every D with d_count = 0 will be on the LRU list. + +select_dcache(ict,pct) removes D with d_count > 0 from the +LRU list, and moves D that are ready to be sacrificed for memory +to the end of the list. (If ict and/or pct is given, then we are +satisfied when the selected D's involve ict inodes or pct pages.) + +prune_dcache(ct) removes D with d_count > 0 from the LRU list, +and frees unused D, stopping when ct of them have been freed. + +shrink_dcache_sb(sb) removes all unused D with given superblock +from the LRU list. + +select_parent(D) move all unused descendants of D to the end +of the LRU list. + + + +3. d_child and d_subdirs +As already noted, the names are terrible. The d_child field +does not refer to a child but to a sibling, and the d_subdirs +field does not refer to a subdirectory but to a child, directory +or not. These two fields form a threaded tree: the d_subdirs field +points to the first child, and the d_child field is member of the +circularly linked list of all children of one parent. + +To be more precise: this circularly linked list of all children +of one parent P passes through the d_child fields of all children +and through the d_subdirs field of the parent P. + + + +4. d_alias +Somewhat similar to the above, where we had a circularly linked list +with one special element, we here have a circularly linked list +passing through the d_alias field of all dentries that are aliases +of one inode, and through the i_dentry field of the inode. + +The dentry is added to this list by d_instantiate(). +It is removed again by dentry_iput() which is called by dput() +and d_delete(). + + + + +So far about the lists in the dentry structure. +Some of the routines in dcache.c have been mentioned already. +Let me describe one of the more obscure ones. + +d_move(D,T) is the routine called by the filesystem code +just before finishing the rename(D,T) call. Since both +dentries D and T may be busy we cannot just throw one away. +Instead they are partially interchanged: +D and T interchange names, and D is put into T's hash queue, +and T is unhashed; D and T interchange parents, and are put +on the list of children of their new parent. +The result is that the file D that got renamed is now in perfect +shape again - it has been renamed. T, if it existed, lost its +name string, if it was short, but perhaps this is harmless - +let us hope no-one will ever ask for T's name anymore. + + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/filesystems/sysv-fs.txt linux.ac/Documentation/filesystems/sysv-fs.txt --- linux.vanilla/Documentation/filesystems/sysv-fs.txt Sun Nov 8 15:08:46 1998 +++ linux.ac/Documentation/filesystems/sysv-fs.txt Fri Jun 4 23:52:54 1999 @@ -2,20 +2,22 @@ It implements all of - Xenix FS, - SystemV/386 FS, + - Version 7 FS - Coherent FS. This is version beta 4. To install: -* Answer the 'System V and Coherent filesystem support' question with 'y' - when configuring the kernel. +* Answer the 'System V, Version 7 and Coherent filesystem support' question + with a 'y' when configuring the kernel. * To mount a disk or a partition, use mount [-r] -t sysv device mountpoint The file system type names -t sysv -t xenix + -t v7 -t coherent - may be used interchangeably, but the last two will eventually disappear. + the xenix and coherent options will eventually disappear. Bugs in the present implementation: - Coherent FS: diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/filesystems/ufs.txt linux.ac/Documentation/filesystems/ufs.txt --- linux.vanilla/Documentation/filesystems/ufs.txt Fri Apr 16 22:10:51 1999 +++ linux.ac/Documentation/filesystems/ufs.txt Mon Jul 19 03:46:35 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/locks.txt linux.ac/Documentation/locks.txt --- linux.vanilla/Documentation/locks.txt Sat Jan 9 21:50:34 1999 +++ linux.ac/Documentation/locks.txt Fri Jun 4 23:52:55 1999 @@ -13,12 +13,11 @@ The old flock(2) emulation in the kernel was swapped for proper BSD compatible flock(2) support in the 1.3.x series of kernels. With the -release of the 2.1.x kernel series, support for the old emulation has -been totally removed, so that we don't need to carry this baggage -forever. +release of the 2.1.x kernel series, support for the old emulation was +totally removed, so that we don't need to carry this baggage forever. -This should not cause problems for anybody, since everybody using a -2.1.x kernel should have updated their C library to a suitable version +This should not cause problems for anybody, since everybody using a 2.1.x +or 2.2.x kernel should have updated their C library to a suitable version anyway (see the file "linux/Documentation/Changes".) 1.2 Allow Mixed Locks Again @@ -31,9 +30,9 @@ for example. This gave rise to some other subtle problems if sendmail was configured to rebuild the alias file. Sendmail tried to lock the aliases.dir file with fcntl() at the same time as the GDBM routines tried to lock this -file with flock(). With pre 1.3.96 kernels this could result in deadlocks that, -over time, or under a very heavy mail load, would eventually cause the kernel -to lock solid with deadlocked processes. +file with flock(). With kernels before 1.3.96 this could result in deadlocks +that, over time or under a very heavy mail load, would eventually cause the +kernel to lock solid with deadlocked processes. 1.2.2 The Solution @@ -60,7 +59,7 @@ file for which a mandatory lock existed. From this release of the kernel, mandatory locking can be turned on and off -on a per-filesystem basis, using the mount options 'mand' and 'nomand'. +on a per-file-system basis, using the mount options 'mand' and 'nomand'. The default is to disallow mandatory locking. The intention is that mandatory locking only be enabled on a local filesystem as the specific need arises. diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/m68k/kernel-options.txt linux.ac/Documentation/m68k/kernel-options.txt --- linux.vanilla/Documentation/m68k/kernel-options.txt Thu May 27 22:11:47 1999 +++ linux.ac/Documentation/m68k/kernel-options.txt Fri Jun 4 23:52:55 1999 @@ -1,5 +1,3 @@ - - Command Line Options for Linux/m68k =================================== @@ -14,7 +12,7 @@ Often I've been asked which command line options the Linux/m68k kernel understands, or how the exact syntax for the ... option is, or ... about the option ... . I hope, this document supplies all the -answers... +answers. Note that some options might be outdated, their descriptions being incomplete or missing. Please update the information and send in the @@ -110,20 +108,19 @@ [Strange and maybe uninteresting stuff ON] This unusual translation of device names has some strange -consequences: If, for example, you have a symbolic link from /dev/fd +consequences: if, for example, you have a symbolic link from /dev/fd to /dev/fd0D720 as an abbreviation for floppy driver #0 in DD format, you cannot use this name for specifying the root device, because the kernel cannot see this symlink before mounting the root FS and it isn't in the table above. If you use it, the root device will not be -set at all, without an error message. Another example: You cannot use a +set at all, without an error message. Another example: you cannot use a partition on e.g. the sixth SCSI disk as the root filesystem, if you want to specify it by name. This is, because only the devices up to -/dev/sde are in the table above, but not /dev/sdf. Although, you can -use the sixth SCSI disk for the root FS, but you have to specify the -device by number... (see below). Or, even more strange, you can use the -fact that there is no range checking of the partition number, and your -knowledge that each disk uses 16 minors, and write "root=/dev/sde17" -(for /dev/sdf1). +/dev/sde are in the table above, but not /dev/sdf. You can use the sixth +SCSI disk for the root filesystem, but you have to specify the device by +number (see below). Even more strange, you can use the fact that there is +no range checking of the partition number, and your knowledge that each +disk uses 16 minors, and write "root=/dev/sde17" (for /dev/sdf1). [Strange and maybe uninteresting stuff OFF] @@ -181,7 +178,7 @@ Devices possible for Amiga: - "ser": built-in serial port; parameters: 9600bps, 8N1 - - "mem": Save the messages to a reserved area in chip mem. After + - "mem": Save the messages to a reserved area in chip memory. After rebooting, they can be read under AmigaOS with the tool 'dmesg'. @@ -205,7 +202,7 @@ Syntax: ramdisk= This option instructs the kernel to set up a ramdisk of the given -size in KBytes. Do not use this option if the ramdisk contents are +size in kilobytes. Do not use this option if the ramdisk contents are passed by bootstrap! In this case, the size is selected automatically and should not be overwritten. @@ -234,10 +231,10 @@ drivers/net/Space.c in the Linux source. Most prominent are eth0, ... eth3, sl0, ... sl3, ppp0, ..., ppp3, dummy, and lo. - The non-ethernet drivers (sl, ppp, dummy, lo) obviously ignore the -settings by this options. Also, the existing ethernet drivers for + The non-Ethernet drivers (sl, ppp, dummy, lo) obviously ignore the +settings by this options. Also, the existing Ethernet drivers for Linux/m68k (ariadne, a2065, hydra) don't use them because Zorro boards -are really Plug-'n-Play, so the "ether=" option is useless altogether +are really Plug-'n'-Play, so the "ether=" option is useless altogether for Linux/m68k. @@ -288,8 +285,8 @@ to use (minimum 4, default 4), is the size of each buffer in kilobytes (minimum 4, default 32) and says how much percent of error will be tolerated when setting a frequency -(maximum 10, default 0). For example with 3% you can play 8000Hz -AU-Files on the Falcon with its hardware frequency of 8195Hz and thus +(maximum 10, default 0). For example, with 3% you can play 8000 Hz Sun +audio files on the Falcon with its hardware frequency of 8195 Hz and thus don't need to expand the sound. @@ -482,7 +479,7 @@ xres_virtual must be set to 2048. For ET4000, xres_virtual depends on the initialisation of the video-card. If you're missing a corresponding yres_virtual: the external part is legacy, -therefore we don't support hardware-dependend functions like hardware-scroll, +therefore we don't support hardware-dependent functions like hardware scroll, panning or blanking. 4.1.7) eclock: @@ -653,7 +650,7 @@ "ov_midi", ... These options are meant for switching on an OverScan video extension. The difference to the bare option is that the switch-on is done after video initialization, and somehow synchronized -to the HBLANK. A speciality is that ov_ikbd and ov_midi are switched +to the HBLANK. A specialty is that ov_ikbd and ov_midi are switched off before rebooting, so that OverScan is disabled and TOS boots correctly. @@ -737,8 +734,8 @@ - vga70 : 640x400, 31 kHz, 70 Hz Please notice that the ECS and VGA modes require either an ECS or AGA -chipset, and that these modes are limited to 2-bit color for the ECS -chipset and 8-bit color for the AGA chipset. +chip set, and that these modes are limited to 2-bit color for the ECS +chip set and 8-bit color for the AGA chip set. 5.1.2) depth ------------ @@ -842,11 +839,11 @@ Syntax: clock:x x = clock input in MHz for WD33c93 chip. Normal values would be from -8 through 20. The default value depends on your hostadapter(s), +8 through 20. The default value depends on your host adapter(s), default for the A3000 internal controller is 14, for the A2091 it's 8 -and for the GVP hostadapters it's either 8 or 14, depending on the -hostadapter and the SCSI-clock jumper present on some GVP -hostadapters. +and for the GVP host adapters it's either 8 or 14, depending on the +host adapter and the SCSI-clock jumper present on some GVP +host adapters. 5.3.6) next ----------- @@ -875,8 +872,8 @@ The earlier versions of the GVP driver did not handle DMA address-mask settings correctly which made it necessary for some people to use this option, in order to get their GVP controller -running under Linux. These problems have hopefully been solved and the -use of this option is now highly unrecommended! +running under Linux. These problems should now be solved and +further use of this option is highly discouraged! Incorrect use can lead to unpredictable behavior, so please only use this option if you *know* what you are doing and have a reason to do diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/modules.txt linux.ac/Documentation/modules.txt --- linux.vanilla/Documentation/modules.txt Sun Nov 8 15:08:46 1998 +++ linux.ac/Documentation/modules.txt Fri Jun 4 23:52:54 1999 @@ -59,7 +59,7 @@ Most low-level SCSI drivers: (i.e. aha1542, in2000) All SCSI high-level drivers: disk, tape, cdrom, generic. - Most ethernet drivers: (too many to list, please see the file + Most Ethernet drivers: (too many to list, please see the file ./Documentation/networking/net-modules.txt) Most CDROM drivers: diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/mtrr.txt linux.ac/Documentation/mtrr.txt --- linux.vanilla/Documentation/mtrr.txt Thu May 27 22:11:47 1999 +++ linux.ac/Documentation/mtrr.txt Fri Jun 4 23:52:56 1999 @@ -40,7 +40,7 @@ reg01: base=0x08000000 ( 128MB), size= 64MB: write-back, count=1 reg02: base=0xf8000000 (3968MB), size= 4MB: write-combining, count=1 -This is for videoram at base address 0xf8000000 and size 4 MBytes. To +This is for video RAM at base address 0xf8000000 and size 4 megabytes. To find out your base address, you need to look at the output of your X server, which tells you where the linear framebuffer address is. A typical line that you may get is: @@ -56,7 +56,7 @@ (--) S3: videoram: 4096k -That's 4 MBytes, which is 0x400000 bytes (in hexadecimal). +That's 4 megabytes, which is 0x400000 bytes (in hexadecimal). A patch is being written for XFree86 which will make this automatic: in other words the X server will manipulate /proc/mtrr using the ioctl() interface, so users won't have to do anything. If you use a diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/nbd.txt linux.ac/Documentation/nbd.txt --- linux.vanilla/Documentation/nbd.txt Sun Nov 8 15:08:49 1998 +++ linux.ac/Documentation/nbd.txt Fri Jun 4 23:52:55 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/00-INDEX linux.ac/Documentation/networking/00-INDEX --- linux.vanilla/Documentation/networking/00-INDEX Sun Nov 8 15:08:47 1998 +++ linux.ac/Documentation/networking/00-INDEX Fri Jun 4 23:52:54 1999 @@ -13,9 +13,9 @@ alias.txt - info on using alias network devices arcnet-hardware.txt - - tons of info on arcnet, hubs, arcnet card jumper settings, etc. + - tons of info on ARCnet, hubs, jumper settings for ARCnet cards, etc. arcnet.txt - - info on the using the arcnet driver itself. + - info on the using the ARCnet driver itself. ax25.txt - info on using AX.25 and NET/ROM code for Linux baycom.txt @@ -69,13 +69,13 @@ smc9.txt - the driver for SMC's 9000 series of Ethernet cards soundmodem.txt - - Linux driver for soundcards as AX.25 modems + - Linux driver for sound cards as AX.25 modems tcp.txt - short blurb on how TCP output takes place. tulip.txt - info on using DEC 21040/21041/21140 based PCI Ethernet cards. vortex.txt - - info on using 3Com Vortex (3c590, 3c592, 3c595, 3c597) e'net cards. + - info on using 3Com Vortex (3c590, 3c592, 3c595, 3c597) Ethernet cards. wan-router.txt - Wan router documentation wanpipe.txt diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/CREDITS.ipvs linux.ac/Documentation/networking/CREDITS.ipvs --- linux.vanilla/Documentation/networking/CREDITS.ipvs Thu Jan 1 01:00:00 1970 +++ linux.ac/Documentation/networking/CREDITS.ipvs Tue Jun 1 16:26:00 1999 @@ -0,0 +1,26 @@ +The contributors of Linux Virtual Server project are listed +as follows in alphabetical order. + + Mike Douglas + Virtual Server Logo. + + Matthew Kellett + Added the loadable load-balancing module to VS-0.5 patch + for kernel 2.0. + + Peter Kese + Suggested the idea of the local-node feature and provided a + local-node prototype patch for VS via tunneling. + Port the VS patch to kernel 2.2 and rewrite of the code + The persistent client connection feature. + + Joseph Mack + Gaving a talk about Linux Virtual Server in the LinuxExpo'99. + + Rob Thomas + Wrote the the "Greased Turkey" document about how to setup a + load-sharing server. (a little bit stale, though) + + Wensong Zhang + Chief author and developer. + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/ChangeLog.ipvs linux.ac/Documentation/networking/ChangeLog.ipvs --- linux.vanilla/Documentation/networking/ChangeLog.ipvs Thu Jan 1 01:00:00 1970 +++ linux.ac/Documentation/networking/ChangeLog.ipvs Fri Jul 9 14:33:46 1999 @@ -0,0 +1,292 @@ +ChangeLog of Virtual Server patch for Linux 2.2 + +Virtual Server patch for Linux 2.2 - Version 0.7 - July 9, 1999 + +Changes: +- Added a separate masq hash table for IPVS. + +- Added slow timers to expire masq entries. + Slow timers are checked in one second by default. Most overhead + of cascading timers is avoided. + + With this new hash table and slow timers, the system can hold + huge number of masq entries, but make sure that you have + enough free memory. One masq entry costs 128 bytes memory + effectively (Thank Alan Cox), if your box holds 1 million masq + entries (it means that your box can receive 2000 connections per + second if masq expire time is 500 seconds in average.), make sure + that you have 128M free memory. And, thank Alan for suggesting + the early random drop algorithm for masq entries that prevents + the system from running out of memory, I will design and implement + this feature in the near future. + +- Fixed the unlocking bug in the ip_vs_del_dest(). + Thank Ted Pavlic for reporting it. + +---------------------------------------------------------------------- + +Virtual Server patch for Linux 2.2 - Version 0.6 - July 1, 1999 + +Changes: +- Fixed the overflow bug in the ip_vs_procinfo(). + Thank Ted Pavlic for reporting it. + +- Added the functionality to change weight and forwarding + (dispatching) method of existing real server. + This is useful for load-informed scheduling. + +- Added the functionality to change scheduler of virtual service + on the fly. + +- Reorganized some code and changed names of some functions. + This make the code more readable. + +---------------------------------------------------------------------- + +Virtual Server patch for Linux 2.2 - Version 0.5 - June 22, 1999 + +Changes: +- Fixed the bug that LocalNode doesn't work in vs-0.4-2.2.9. + Thank Changwon Kim for + reporting the bug and pointing me the checksum update + problem in the code. + +- some code of VS in the ip_fw_demasquerade was reorganized + so that the packets for VS-Tunneling, VS-DRouting and LocalNode + skip the checksum update. This make the code right and efficient + + +---------------------------------------------------------------------- + +Virtual Server patch for Linux 2.2 - Version 0.4 - June 1, 1999 + +Most of the code was rewritten. The locking and refcnt was changed +The violation of "no floats in kernel mode" rule in the weighted +least-connection scheduling was fixed. This patch is more efficient, +and should be more stable. + + +---------------------------------------------------------------------- + +Virtual Server patch for Linux 2.2 - Version 0.1~0.3 - May 1999 + +Peter Kese ported the VS patch to kernel 2.2, +rewrote the code and loadable scheduling modules. + +========================================================================== + +ChangeLog of Virtual Server patch for Linux 2.0 +---------------------------------------------------------------------- + +Virtual Server Patch for Linux - Version 0.9 - May 1, 1999 + +Differences with virtual server patch version 0.8: + +- Add Virtual Server via Direct Routing + This approach was first implemented in IBM's NetDispatcher. All real + servers have their loopback alias interface configured with the virtual + IP address, the load balancer and the real servers must have one of + their interfaces physically linked by a HUB/Switch. When the packets + destined for the virtual IP address arrives, the load balnacer directly + route them to the real servers, the real servers processing the requests + and return the reply packets directly to the clients. Compared to the + virtual server via IP tunneling approach, this approach doesn't have + tunneling overhead(In fact, this overhead is minimal in most situations), + but requires that one of the load balancer's interfaces and the real + servers' interfaces must be in physical segment. + +- Add more satistics information + The active connection counter and the total connection counter of + each real server were added for all the scheduling algorithms. + +- Add resetting(zeroing) counters + The total connection counters of all real servers can be reset to zero. + +- Change some statements in the masq_expire function and the + ip_fw_demasquerade function, so that ip_masq_free_ports won't become + abnormal number after the masquerading entries for virtual server + are released. + +- Fix the bug of "double unlock on device queue" + Remove the unnecessary function call of skb_device_unlock(skb) in the + ip_pfvs_encapsule function, which sometimes cause "kernel: double + unlock on device queue" waring in the virtual server via tunneling. + +- Many functions of virtual server patch was splitted into the + linux/net/ipv4/ip_masq_pfvs.c. + +- Upgrade ippfvsadm 1.0.2 to ippfvsadm 1.0.3 + Zeroing counters is supported in the new version. The ippfvsadm 1.0.3 + can be used for all kernel with different virtual server options + without rebuilding the program. + +-------------------------------------------------------------------- + +Virtual Server Patch for Linux - Version 0.8 - March 6, 1999 + +Differences with virtual server patch version 0.7: + +- Add virtual FTP server support + The original ippfvs via IP tunneling could not be used to + build a virtual FTP server, because the real servers could + not establish data connections to clients. The code was + added to parse the port number in the ftp control data + and create the corresponding masquerading entry for the + coming data connection. + Although the original ippfvs via NAT could be used to build + a virtual server, the data connection was established in + this way. + Real Server port:20 ----> ippfvs: allocate a free masq port + -----> the client port + It is not elegent but time-consuming. Now it was changed + as follows: + Real Server port:20 ----> ippfvs port: 20 + ----> the client port + +- Change the port checking order in the ip_fw_demasquerade() + If the size of masquerade hash table is well chosen, checking + a masquerading entry in the hash table will just require one + hit. It is much efficient than checking port for virtual + services, and there are at least 3 incoming packets for each + connection, which require port checking. So, it is efficient + to check the masquerading hash table first and then check + port for virtual services. + +- Remove a useless statement in the ip_masq_new_pfvs() + The useless statement in the ip_masq_new_pfvs function is + ip_masq_free_ports[masq_proto_num(proto)]++; + which may disturb system. + +- Change the header printing of the ip_pfvs_procinfo() + +-------------------------------------------------------------------- + +Virtual Server Patch for Linux - Version 0.7 - Febuary 10, 1999 + +Differences with virtual server patch version 0.6: + +- Fix a bug in detect the finish of connection for tunneling + or NATing to the local node. + Since the server reply the client directly in tunneling or + NATing to the local node, the load balancer (LinuxDirector) + can only detect a FIN segment. It is mistake that the masq + entry is removed only if both-side FIN segments are detected, + and then the masq entry expires in 15 minutes. For the + situation above, the code was changed to set the masq entry + expire in TCP_FIN_TIMEOUT (2min) when an incoming FIN segment + is detecting. +- Add the patch version printing in the ip_pfvs_procinfo() + It would be easy for users and hackers to know which + virtual server patch version they are running. Thank + Peter Kese for the suggestion. + +-------------------------------------------------------------------- + +Virtual Server Patch for Linux - Version 0.6 - Febuary 2, 1999 + +Differences with virtual server patch version 0.5: + +- Add the local node feature in virtual server. + If the local node feature is enabled, the load balancer can + not only redirect the packets of the specified port to the + other servers (remote nodes) to process it, but also can process + the packets locally (local node). Which node is chosen depends on + the scheduling algorithms. + This local node feature can be used to build a virtual server of + a few nodes, for example, 2, 3 or more sites, in which it is a + resource waste if the load balancer is only used to redirect + packets. It is wise to direct some packets to the local node to + process. This feature can also be used to build distributed + identical servers, in which one is too busy to handle requests + locally, then it can seamlessly forward requests to other servers + to process them. + This feature can be applied to both virtual server via NAT and + virtual server via IP tunneling. + Thank Peter Kese for idea of "Two node Virtual + Server" and his single line patch for virtual server via IP + tunneling. +- Remove a useless function call ip_send_check in the virtual + server via IP tunneling code. + +-------------------------------------------------------------------- + +Virtual Server Patch for Linux - Version 0.5 - November 25, 1998 + +Differences with virtual server patch version 0.4: + +- Add the feature of virtual server via IP tunneling. + If the ippfvs is enabled using IP tunneling, the load balancer + chooses a real server from a cluster based on a scheduling algorithm, + encapsules the packet and forwards it to the chosen server. All real + servers are configured with "ifconfig tunl0 up". + When the chosen server receives the encapsuled packet, it decapsules + the packet, processes the request and returns the reply packets + directly to the client without passing the load balancer. This can + greatly increase the scalability of virtual server. +- Fix a bug in the ip_portfw_del() for the weighted RR scheduling. + The bug in version 0.4 is when the weighted round-robin scheduling + is used, deleting the last rule for a virtual server will report + "setsockopt failed: Invalid argument" warning, in fact the last + rule is deleted but the gen_scheduling_seq() works on a null list + and causes that warning. +- Add and modify some description for virtual server options in + the Linux kernel configuration help texts. + +-------------------------------------------------------------------- + +Virtual Server Patch for Linux - Version 0.4 - November 12, 1998 + +Differences with virtual server patch version 0.3: + +- Fix a memory access error bug. + The set_serverpointer_null() function is added to scan all the existing + ip masquerading records for its server pointer which points to the + server specified and set it null. It is useful when administrators + delete a real server or all real servers, those pointers pointing to + the server must be set null. Otherwise, decreasing the connection + counter of the server may cause memory access error when the connection + terminates or timeout. + +-------------------------------------------------------------------- + +Virtual Server Patch for Linux - Version 0.3 - November 10, 1998 + +Differences with virtual server patch version 0.2: + +- Change the simple round-robin scheduling to the weighted round-robin + scheduling. Simple is a special instance of the weighted round-robin + scheduling when the weights of the servers are the same. +- The scheduling algorithm, originally called the weighted round-robin + scheduling in version 0.2, actually is the weighted least-connection + scheduling. So the concept is clarified here. +- Add the least-connection scheduling algorithm. Although it is a + special instance of the weighted least-connection scheduling algorithm, + it is used to avoid dividing the weight in looking up servers when + the weights of the servers are the same, so the overhead of scheduling + can be minimized in this case. +- Change the type of the server load variables, curr_load and least_load, + from integer to float in the weighted least-connection scheduling. + It can make a better load-balancing when the weights specified are high. +- Merge the original two patches into one. Users have to specify which + scheduling algorithm is used, the weighted round-robin scheduling, + the least-connection scheduling, or the weighted least-connection + scheduling, before rebuild the kernel. +- Change the ip_pfvs_proc function to make the output of the port + forwarding & virtual server table more beautiful. + +-------------------------------------------------------------------- + +Virtual Server Patch for Linux - Version 0.2 - May 28, 1998 + +Differences with virtual server patch version 0.1: + +- Add the weighted round-robin scheduling patch. + +-------------------------------------------------------------------- + +Virtual Server Patch for Linux - Version 0.1 - May 26, 1998 + +- Implement the infrastructure of virtual server. +- Implement the simple round-robin scheduling algorithm. + +-------------------------------------------------------------------- diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/Configurable linux.ac/Documentation/networking/Configurable --- linux.vanilla/Documentation/networking/Configurable Sun Nov 8 15:08:47 1998 +++ linux.ac/Documentation/networking/Configurable Fri Jun 4 23:52:54 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.ac/Documentation/networking/DLINK.txt --- linux.vanilla/Documentation/networking/DLINK.txt Sun Nov 8 15:08:47 1998 +++ linux.ac/Documentation/networking/DLINK.txt Fri Jun 4 23:52:54 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/README.ipvs linux.ac/Documentation/networking/README.ipvs --- linux.vanilla/Documentation/networking/README.ipvs Thu Jan 1 01:00:00 1970 +++ linux.ac/Documentation/networking/README.ipvs Fri Jul 9 13:51:54 1999 @@ -0,0 +1,93 @@ +README of Virtual Server Patch for Linux 2.2.10 +-------------------------------------------------------------------- + +Virtual Server Patch for Linux 2.2.10 - Version 0.7 - July 9, 1999 + +Copyright (c) 1998,1999 by Wensong Zhang, Peter Kese. +This is free software. See below for details. + +The ipvs is IP Virtual Server support in Linux kernel, which can be used +to build a high-performance and highly available server. Check out the +Linux Virtual Server Project homepage on the World Wide Web: + http://proxy.iinchina.net/~wensong/ippfvs/ +for the most recent information and original sources about ipvs. + +We now call the Linux box running ipvs LinuxDirector. Thank +Robert Thomas for this name, I love it. :-) + +This patch (Version 0.7) is for the Linux kernel 2.2.10. See the ChangeLog +for how the code has been improved and what new features it has now. + +To rebuild a Linux kernel with virtual server support, first get a clean +copy of the Linux kernel source of the right version and apply the patch +to the kernel. The commands can be as follows: + cd /usr/src/linux + cat /ipvs-0.7-2.2.10.patch | patch -p1 +Then make sure the following kernel compile options at least are selected +via "make menuconfig" or "make xconfig". + +Kernel Compile Options: + +Code maturity level options --- + [*] Prompt for development and/or incomplete code/drivers +Networking options --- + [*] Network firewalls + .... + [*] IP: firewalling + [*] IP: always defragment (required for masquerading) + .... + [*] IP: masquerading + .... + [*] IP: masquerading virtual server support + (12) IP masquerading table size (the Nth power of 2) + < > IPVS: round-robin scheduling + < > IPVS: weighted round-robin scheduling + < > IPVS: weighted least-connection scheduling + < > IPVS: persistent client connection scheduling +Note that you can compile scheduling algorithms in kernel or as modules. + +Finally, rebuild the kernel. Once you have your kernel properly built, +update your system kernel and reboot. + +Note that there are three request dispatching techniques existing together +in the LinuxDirector, and there are also three scheduling algorithms +implemented. Both the VS via IP Tunneling and the VS via Direct Routing +can greatly increase the scalability of virtual server. If the VS-Tunneling +is selected, it requires that all the servers must be configured with + ifconfig tunl0 netmask 255.255.255.255 +If the VS-DRouting is chosen, it requires that all servers must be configured +with the following command: + ifconfig lo:0 netmask 255.255.255.255 +The localnode feature can make that the LinuxDiretor can not only redirect +packets to other servers, but also process packets locally. + +Thanks must go to other contributors, check the CREDITS file to know +who they are. + +There is a mailing list for virtual server. You are welcome to talk about +building the virtual server kernel, using the virtual server and making +the virtual server better there. :-) To subscribe, send a message to + majordomo@iinchina.net +with the body of "subscribe linux-virtualserver". + + +Wensong Zhang + + +-------------------------------------------------------------------- + +This program is free software; you can redistribute 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. + +-------------------------------------------------------------------- diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/arcnet-hardware.txt linux.ac/Documentation/networking/arcnet-hardware.txt --- linux.vanilla/Documentation/networking/arcnet-hardware.txt Sat Jan 9 21:50:35 1999 +++ linux.ac/Documentation/networking/arcnet-hardware.txt Fri Jun 4 23:52:54 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.ac/Documentation/networking/arcnet.txt --- linux.vanilla/Documentation/networking/arcnet.txt Sun Nov 8 15:08:46 1998 +++ linux.ac/Documentation/networking/arcnet.txt Fri Jun 4 23:52:54 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/baycom.txt linux.ac/Documentation/networking/baycom.txt --- linux.vanilla/Documentation/networking/baycom.txt Sun Nov 8 15:08:47 1998 +++ linux.ac/Documentation/networking/baycom.txt Fri Jun 4 23:52:54 1999 @@ -31,7 +31,7 @@ Its devices are called bcp0 through bcp3. baycom_epp: - This driver supports the epp modem. + This driver supports the EPP modem. Its devices are called bce0 through bce3. This driver is work-in-progress. @@ -60,10 +60,10 @@ an additional power supply. Furthermore, it incorporates a carrier detect circuitry. -epp: This is a high speed modem adaptor that connects to an enhanced parallel port. +EPP: This is a high-speed modem adaptor that connects to an enhanced parallel port. Its target audience is users working over a high speed hub (76.8kbit/s). -eppfpga: This is a redesign of the epp adaptor. +eppfpga: This is a redesign of the EPP adaptor. diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/cs89x0.txt linux.ac/Documentation/networking/cs89x0.txt --- linux.vanilla/Documentation/networking/cs89x0.txt Sun Nov 8 15:08:47 1998 +++ linux.ac/Documentation/networking/cs89x0.txt Fri Jun 4 23:52:54 1999 @@ -203,7 +203,7 @@ * io=### - specify IO address (200h-360h) * irq=## - specify interrupt level * mmode=##### - specify memory base address -* dma=# - specify dma channel +* dma=# - specify DMA channel * media=rj45 - specify media type or media=2 or media=aui @@ -412,33 +412,33 @@ assigned during hardware configuration. The following tests are performed: * IO Register Read/Write Test - The IO Register Read/Write test insures that the CS8900/20 can be + The IO Register Read/Write test ensures that the CS8900/20 can be accessed in IO mode, and that the IO base address is correct. * Shared Memory Test - The Shared Memory test insures the CS8900/20 can be accessed in memory + The Shared Memory test ensures the CS8900/20 can be accessed in memory mode and that the range of memory addresses assigned does not conflict with other devices in the system. * Interrupt Test - The Interrupt test insures there are no conflicts with the assigned IRQ + The Interrupt test ensures there are no conflicts with the assigned IRQ signal. * EEPROM Test - The EEPROM test insures the EEPROM can be read. + The EEPROM test ensures the EEPROM can be read. * Chip RAM Test - The Chip RAM test insures the 4K of memory internal to the CS8900/20 is + The Chip RAM test ensures the 4 K of memory internal to the CS8900/20 is working properly. * Internal Loop-back Test - The Internal Loop Back test insures the adapter's transmitter and + The Internal Loop Back test ensures the adapter's transmitter and receiver are operating properly. If this test fails, make sure the adapter's cable is connected to the network (check for LED activity for example). * Boot PROM Test - The Boot PROM test insures the Boot PROM is present, and can be read. + The Boot PROM test ensures the Boot PROM is present, and can be read. Failure indicates the Boot PROM was not successfully read due to a hardware problem or due to a conflicts on the Boot PROM address assignment. (Test only applies if the adapter is configured to use the @@ -564,7 +564,7 @@ Telephone :(800) 888-5016 (from inside U.S. and Canada) :(512) 442-7555 (from outside the U.S. and Canada) Fax :(512) 912-3871 -Email :ethernet@crystal.cirrus.com +E-mail :ethernet@crystal.cirrus.com WWW :http://www.crystal.com diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/dgrs.txt linux.ac/Documentation/networking/dgrs.txt --- linux.vanilla/Documentation/networking/dgrs.txt Sun Nov 8 15:08:47 1998 +++ linux.ac/Documentation/networking/dgrs.txt Fri Jun 4 23:52:54 1999 @@ -1,4 +1,4 @@ - The Digi Intl. RightSwitch SE-X (dgrs) Device Driver + The Digi International RightSwitch SE-X (dgrs) Device Driver This is a Linux driver for the Digi International RightSwitch SE-X EISA and PCI boards. These are 4 (EISA) or 6 (PCI) port Ethernet diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/eql.txt linux.ac/Documentation/networking/eql.txt --- linux.vanilla/Documentation/networking/eql.txt Sun Nov 8 15:08:47 1998 +++ linux.ac/Documentation/networking/eql.txt Fri Jun 4 23:52:54 1999 @@ -471,58 +471,3 @@ able to data at over 48Kb/s [ISDN link -Simon]. I managed a transfer of up to 7.5 Kbyte/s on one go, but averaged around 6.4 Kbyte/s, which I think is pretty cool. :) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/load-balancing.txt linux.ac/Documentation/networking/load-balancing.txt --- linux.vanilla/Documentation/networking/load-balancing.txt Thu Jan 1 01:00:00 1970 +++ linux.ac/Documentation/networking/load-balancing.txt Fri Jun 4 23:52:54 1999 @@ -0,0 +1,122 @@ +Load balancing using multipaths (patch version: 4) +================================================== + +Contact Guus Sliepen if you need help, want to know +more, have remarks or further idea's with relation to this. + +Intro +----- + +If you have multiple physical network links to another computer, and you want +some kind of load balancing, you can now do so. Please note that this only +applies to IPv4 traffic, not for IPX, IPv6 or any other protocol (yet). + +Needed +----- + +* LATEST iproute package from ftp://ftp.inr.ac.ru/ip-routing/ +* CONFIG_IP_ROUTE_MULTIPATH enabled in kernel configuration (it's in + Networking options, below the Advanced Router option you'll have to enable + too) +* Ofcourse you must also have patched your kernel and recompiled it for this + feature to be enabled. + +To do +----- + +* Make sure the devices you want to combine are up, they all accept the + packets you want to send (ie, they must all have the same IP address/netmask + or something clever to get the same result) +* Just to make sure, remove any routes via those devices (route del ...) +* Now add all routes via one iproute command using the 'nexthops' statement: + + ip route add / equalize \\ + nexthop dev \\ + nexthop dev \\ + nexthop ... + +* Just to make sure, flush route cache: + + echo 1 >/proc/sys/net/ipv4/route/flush + +Example +------- + +This is an example showing how to make a 20 Mbit connection between two +computers using 2 10 Mbit ethernet cards per computer. Computer 1 has IP +192.168.1.1 and computer 2 has IP 192.168.1.2. We start from scratch: + +[computer1]~/>ifconfig eth0 192.168.1.1 netmask 255.255.255.0 +[computer1]~/>route del -net 192.168.1.0 netmask 255.255.255.0 +[computer1]~/>ifconfig eth1 192.168.1.1 netmask 255.255.255.0 +[computer1]~/>route del -net 192.168.1.0 netmask 255.255.255.0 +[computer1]~/>ip route add 192.168.1.0/24 equalize nexthop dev eth0 nexthop dev eth1 +[computer1]~/>echo 1 >/proc/sys/net/ipv4/route/flush + +[computer2]~/>ifconfig eth0 192.168.1.2 netmask 255.255.255.0 +[computer2]~/>route del -net 192.168.1.0 netmask 255.255.255.0 +[computer2]~/>ifconfig eth1 192.168.1.2 netmask 255.255.255.0 +[computer2]~/>route del -net 192.168.1.0 netmask 255.255.255.0 +[computer2]~/>ip route add 192.168.1.0/24 equalize nexthop dev eth0 nexthop dev eth1 +[computer2]~/>echo 1 >/proc/sys/net/ipv4/route/flush + +You can even add more computers, just replace the x in 192.168.1.x with the +number of your computer, and make sure all eth0's are connected to each other +and all eth1's. You can also use more devices, just ifconfig them all and +remove the default routes that are generated, and add extra nexthops. + +Notes +----- + +If you want to add a gateway entry in your routing table, and want it to be +balanced too, you first have to make singlepath entries for every network +interface you want to use, after that add the gateway with all the nexthops +filled in, then delete the singlepath routes and then add the normal +multipath route. + +Older patch versions used a /proc entry to control load-balancing. This does +not work anymore. You should use the 'equalize' flag instead while adding new +routes. You need a fresh version of iproute for that. + +Status +------ + +Packet type: Balanced? Note +---------------------------------------------------------------------- +ARP no But we don't want them to ;) +ICMP yes +Connectionless UDP yes +Connected UDP yes +Broadcast UDP no Would be nice if it would, + but this is rarely used for + high bandwith data transfers. +TCP yes At least all data packets are, + maybe some control packets are + not. + +Bugs +---- + +It is possible that under extreme conditions the kernel will run out of +memory for network buffers. This might be temporarily, but if you're unlucky +it is permanent and then your network will be dead. However, completely +flooding my 486/66 with 2.5 megabyte per second random traffic only gave an +occasional 'Couldn't allocate a sk_buff of size 1514' message, but that was +not permanent, and there were no crashes. + +Technically +----------- + +Load balancing needed a slight adjustment to the unpatched linux kernel, +because of the route cache. Multipath is an option already found in the old +2.1.x kernels. However, once a packet arrives, and it matches a multipath +route, a (quasi random) device out of the list of nexthops is taken for its +destination. That's okay, but after that the kernel puts everything into a +hash table, and the next time a packet with the same source/dest/tos arrives, +it finds it is in the hash table, and routes it via the same device as last +time. The adjustment I made is as follows: If the kernel sees that the route +to be taken has got the 'equalize' flag set, it not only selects the random +device, but also tags the packet with the RTCF_EQUALIZE flag. If another +packet of the same kind arrives, it is looked up in the hash table. It then +checks if our flag is set, and if so, it deletes the entry in the cache and +has to recalculate the destination again. diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/multicast.txt linux.ac/Documentation/networking/multicast.txt --- linux.vanilla/Documentation/networking/multicast.txt Sun Nov 8 15:08:47 1998 +++ linux.ac/Documentation/networking/multicast.txt Fri Jun 4 23:52:54 1999 @@ -1,11 +1,13 @@ -Behaviour of cards under Multicast. This is how they currently -behave not what the hardware can do - i.e. the lance driver doesn't -use its filter, even though the code for loading it is in the DEC -lance based driver. +Behaviour of Cards Under Multicast +================================== -The following multicast requirements are needed +This is how they currently behave, not what the hardware can do--for example, +the Lance driver doesn't use its filter, even though the code for loading +it is in the DEC Lance-based driver. + +The following are requirements for multicasting ----------------------------------------------- -Appletalk Multicast hardware filtering not important but +AppleTalk Multicast hardware filtering not important but avoid cards only doing promisc IP-Multicast Multicast hardware filters really help IP-MRoute AllMulti hardware filters are of no help diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/olympic.txt linux.ac/Documentation/networking/olympic.txt --- linux.vanilla/Documentation/networking/olympic.txt Thu Jan 1 01:00:00 1970 +++ linux.ac/Documentation/networking/olympic.txt Wed Jun 9 20:08:19 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.ac/Documentation/networking/policy-routing.txt --- linux.vanilla/Documentation/networking/policy-routing.txt Sun Nov 8 15:08:47 1998 +++ linux.ac/Documentation/networking/policy-routing.txt Fri Jun 4 23:52:54 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.ac/Documentation/networking/z8530drv.txt --- linux.vanilla/Documentation/networking/z8530drv.txt Sun Nov 8 15:08:46 1998 +++ linux.ac/Documentation/networking/z8530drv.txt Fri Jun 4 23:52:54 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.ac/Documentation/sound/Introduction --- linux.vanilla/Documentation/sound/Introduction Thu May 27 22:11:48 1999 +++ linux.ac/Documentation/sound/Introduction Fri Jul 2 19:32:40 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.ac/Documentation/sound/OPL3-SA2 --- linux.vanilla/Documentation/sound/OPL3-SA2 Tue Jan 19 02:57:22 1999 +++ linux.ac/Documentation/sound/OPL3-SA2 Sat Jun 12 20:06:07 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.ac/Documentation/sysctl/README --- linux.vanilla/Documentation/sysctl/README Fri Apr 16 22:10:51 1999 +++ linux.ac/Documentation/sysctl/README Tue Jun 29 02:37:57 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.ac/Documentation/sysctl/fs.txt --- linux.vanilla/Documentation/sysctl/fs.txt Fri Apr 16 22:10:51 1999 +++ linux.ac/Documentation/sysctl/fs.txt Tue Jun 29 02:37:22 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.ac/Documentation/sysctl/kernel.txt --- linux.vanilla/Documentation/sysctl/kernel.txt Fri Apr 16 22:10:51 1999 +++ linux.ac/Documentation/sysctl/kernel.txt Tue Jun 29 02:37:22 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.ac/Documentation/sysctl/sunrpc.txt --- linux.vanilla/Documentation/sysctl/sunrpc.txt Fri Apr 16 22:10:51 1999 +++ linux.ac/Documentation/sysctl/sunrpc.txt Tue Jun 29 02:37:22 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.ac/Documentation/sysctl/vm.txt --- linux.vanilla/Documentation/sysctl/vm.txt Thu May 27 22:11:48 1999 +++ linux.ac/Documentation/sysctl/vm.txt Tue Jun 29 02:37:22 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.ac/Documentation/sysrq.txt --- linux.vanilla/Documentation/sysrq.txt Sun Nov 8 15:08:50 1998 +++ linux.ac/Documentation/sysrq.txt Fri Jun 4 23:52:56 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/Documentation/video4linux/README.buz linux.ac/Documentation/video4linux/README.buz --- linux.vanilla/Documentation/video4linux/README.buz Thu Jan 1 01:00:00 1970 +++ linux.ac/Documentation/video4linux/README.buz Thu Jul 1 19:06:29 1999 @@ -0,0 +1,212 @@ +Iomega Buz Driver for Linux +=========================== + +by Rainer Johanni + +Compiling and Loading the Driver +================================ + +You must run a 2.2.x kernel in order to use this driver. + +To compile the driver, just type make. + +Besides the files in this directory, the driver needs the +'videodev' and the 'i2c' module from the Linux kernel. +In order to get these modules available, enable module support +for VIDEODEV and BTTV (which implies i2c) in your kernel +configuration. You find these devices in the menu +"Character Devices" in your Kernel Configuration. + +Before you load the driver you must have a video device +at major device node 81. If you don't have it yet, do the +following (as root!): + +cd /dev +mknod video0 c 81 0 +ln -s video0 video + +Edit the 'update' script if you want to give the driver +special options and then type (as root) + +./update + +to insert all the necessary modules into the kernel. + +If you want to make full use of the Video for Linux uncompressed +grabbing facilities, you must either + +- obtain and install the "big_physarea patch" for your kernel and + set aside the necessary memory during boot time. + There seem to be several versions of this patch against + various kernel versions floating around in the net, + you may obtain one e.g. from: + http://www.polyware.nl/~middelin/patch/bigphysarea-2.2.1.tar.gz + You also have to compile your driber AFTER installing that patch + in order to get it working + + or + +- start your kernel with the mem=xxx option, where xxx is your + real memory minus the memory needed for the buffers. + For doing this add an entry in lilo.conf (if you use lilo): + append "mem=xxxM" + or add a line in your linux.par file (if you use loadlin): + mem=xxxM + +The second method is by far easier, however it is dangerous +if more than one driver at a time has the idea to use the memory +leftover by setting the mem=xxx parameter below the actual +memory size. + +Read also below how to use this memory! + + + +Driver Options +============== + +You are able to customize the behavior of the driver by giving +it some options at start time. + +default_input, default_norm +--------------------------- + +As soon as the driver is loaded, the Buz samples video signals +from one of its input ports and displays it on its output. +The driver uses the Composite Input and the video norm PAL for this. +If you want to change this default behavior, set default_input=1 +(for S-VHS input) or default_norm=1 for NTSC. + +v4l_nbufs, v4l_bufsize +---------------------- + +In order to make to make full use of the Video for Linux picture +grabbing facilities of the driver (which are needed by many +Video for Linux applications), the driver needs a set of +physically contiguous buffers for grabbing. These parameters +determine how many buffers of which size the driver will +allocate at open (the open will fail if it is unable to do so!). + +These values do not affect the MJPEG grabbing facilities of the driver, +they are needed for uncompressed image grabbing only!!! + +v4l_nbufs is the number of buffers to allocate, a value of 2 (the default) +should be sufficient in allmost all cases. Only special applications +(streaming captures) will need more buffers and then mostly the +MJPEG capturing features of the Buz will be more apropriate. +So leave this parameter at it's default unless you know what you do. + +The things for v4l_bufsize are more complicated: +v4l_bufsize is set by default to 128 [KB] which is the maximum +amount of physically contiguous memory Linux is able to allocate +without kernel changes. This is sufficient for grabbing 24 bit color images +up to sizes of approx. 240x180 pixels (240*180*3 = 129600, 128 KB = 131072). + +In order to be able to capture bigger images you have either to +- obtain and install the "big_physarea patch" and set aside + the necessary memory during boot time or +- start your kernel with the mem=xxx option, where xxx is your + real memory minus the memory needed for the buffers. +In that case, usefull settings for v4l_bufsize are +- 1296 [Kb] for grabbing 24 bit images of max size 768*576 +- 1728 [Kb] for 32bit images of same size (4*768*576 = 1728 Kb!) +You may reduce these numbers accordingly if you know you are only +grabbing 720 pixels wide images or NTSC images (max height 480). + +In some cases it may happen that Linux isn't even able to obtain +the default 128 KB buffers. If you don't need uncompressed image +grabbing at all, set v4l_bufsize to an arbitrary small value (e.g. 4) +in order to be able to open the video device. + +vidmem +------ + +The video mem address of the video card. +The driver has a little database for some videocards +to determine it from there. If your video card is not in there +you have either to give it to the driver as a parameter +or set in in a VIDIOCSFBUF ioctl + +The videocard database is contained in the file "videocards.h" +Gernot Ziegler wants to keep an actual version of that file. +If your card is not contained in that file, look at +http://www.lysator.liu.se/~gz/buz/ for an actual version of +"videocards.h". + +triton, natoma +-------------- + +The driver tries to detect if you have a triton or natome chipset +in order to take special messures for these chipsets. +If this detection fails but you are sure you have such a chipset, +set the corresponding variable to 1. +This is a very special option and may go away in the future. + + + +Programming interface +===================== + +This driver should be fully compliant to Video for Linux, so all +tools working with Video for Linux should work with (hopefully) +no problems. + +A description of the Video for Linux programming interace can be found at: +http://roadrunner.swansea.linux.org.uk/v4lapi.shtml + +Besides the Video for Linux interface, the driver has a "proprietary" +interface for accessing the Buz's MJPEG capture and playback facilities. + +The ioctls for that interface are as follows: + +BUZIOC_G_PARAMS +BUZIOC_S_PARAMS + +Get and set the parameters of the buz. The user should allways +do a BUZIOC_G_PARAMS (with a struct buz_params) to obtain the default +settings, change what he likes and then make a BUZIOC_S_PARAMS call. +A typical application should at least set the members +input, norm and decimation of the struct buz_params. +For a full description of all members see "buz.h" + +BUZIOC_REQBUFS + +Before being able to capture/playback, the user has to request +the buffers he is wanting to use. Fill the structure +buz_requestbuffers with the size (recommended: 256*1024) and +the number (recommended 32 up to 256). There are no such restrictions +as for the Video for Linux buffers, you should LEAVE SUFFICIENT +MEMORY for your system however, else strange things will happen .... +On return, the buz_requestbuffers structure contains number and +size of the actually allocated buffers. +You should use these numbers for doing a mmap of the buffers +into the user space. +The BUZIOC_REQBUFS ioctl also makes it happen, that the next mmap +maps the MJPEG buffer instead of the V4L buffers. + +BUZIOC_QBUF_CAPT +BUZIOC_QBUF_PLAY + +Queue a buffer for capture or playback. The first call also starts +streaming capture. When streaming capture is going on, you may +only queue further buffers or issue syncs until streaming +capture is switched off again with a argument of -1 to +a BUZIOC_QBUF_CAPT/BUZIOC_QBUF_PLAY ioctl. + +BUZIOC_SYNC + +Issue this ioctl when all buffers are queued. This ioctl will +block until the first buffer becomes free for saving its +data to disk (after BUZIOC_QBUF_CAPT) or for reuse (after BUZIOC_QBUF_PLAY). + +BUZIOC_G_STATUS + +Get the status of the input lines (video source connected/norm). +This ioctl may be subject to change. + + + + + +See the examples directory delivered with this driver +for actual coding examples! diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/MAINTAINERS linux.ac/MAINTAINERS --- linux.vanilla/MAINTAINERS Tue Jun 15 16:49:45 1999 +++ linux.ac/MAINTAINERS Mon Jul 5 05:11:43 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,12 @@ 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 + EATA ISA/EISA/PCI SCSI DRIVER P: Dario Ballabio M: dario@milano.europe.dg.com @@ -447,6 +459,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 +578,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 +654,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 +683,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 +701,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.ac/Makefile --- linux.vanilla/Makefile Tue Jun 15 16:49:45 1999 +++ linux.ac/Makefile Mon Jul 19 03:45:42 1999 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 2 SUBLEVEL = 10 -EXTRAVERSION = +EXTRAVERSION = -ac11 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 @@ -65,12 +66,12 @@ # INSTALL_PATH specifies where to place the updated kernel and system map # images. Uncomment if you want to place them anywhere other than root. -#INSTALL_PATH=/boot +INSTALL_PATH=/boot # # 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/arch/alpha/boot/bootp.c linux.ac/arch/alpha/boot/bootp.c --- linux.vanilla/arch/alpha/boot/bootp.c Sun Nov 8 15:08:23 1998 +++ linux.ac/arch/alpha/boot/bootp.c Tue Jun 22 03:35:46 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.ac/arch/alpha/boot/main.c --- linux.vanilla/arch/alpha/boot/main.c Wed Mar 10 21:13:00 1999 +++ linux.ac/arch/alpha/boot/main.c Tue Jun 22 03:35:46 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.ac/arch/alpha/kernel/Makefile --- linux.vanilla/arch/alpha/kernel/Makefile Thu Jan 14 01:25:21 1999 +++ linux.ac/arch/alpha/kernel/Makefile Wed Jun 30 00:35:30 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/alpha_ksyms.c linux.ac/arch/alpha/kernel/alpha_ksyms.c --- linux.vanilla/arch/alpha/kernel/alpha_ksyms.c Tue Jun 15 16:49:45 1999 +++ linux.ac/arch/alpha/kernel/alpha_ksyms.c Mon Jun 7 01:13:17 1999 @@ -71,6 +71,10 @@ EXPORT_SYMBOL(_writel); EXPORT_SYMBOL(_memcpy_fromio); EXPORT_SYMBOL(_memcpy_toio); +#ifdef CONFIG_ALPHA_JENSEN +EXPORT_SYMBOL (_memcpy_fromio_g32a); +EXPORT_SYMBOL (_memcpy_toio_g32a); +#endif EXPORT_SYMBOL(_memset_c_io); EXPORT_SYMBOL(insb); EXPORT_SYMBOL(insw); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/core_cia.c linux.ac/arch/alpha/kernel/core_cia.c --- linux.vanilla/arch/alpha/kernel/core_cia.c Tue Jun 15 16:49:45 1999 +++ linux.ac/arch/alpha/kernel/core_cia.c Fri Jun 4 23:52:48 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.ac/arch/alpha/kernel/core_mcpcia.c --- linux.vanilla/arch/alpha/kernel/core_mcpcia.c Sun Nov 8 15:08:25 1998 +++ linux.ac/arch/alpha/kernel/core_mcpcia.c Wed Jun 30 00:48:06 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.ac/arch/alpha/kernel/core_pyxis.c --- linux.vanilla/arch/alpha/kernel/core_pyxis.c Sun Nov 8 15:08:25 1998 +++ linux.ac/arch/alpha/kernel/core_pyxis.c Wed Jun 30 00:35:55 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.ac/arch/alpha/kernel/entry.S --- linux.vanilla/arch/alpha/kernel/entry.S Thu May 27 22:11:48 1999 +++ linux.ac/arch/alpha/kernel/entry.S Fri Jun 4 23:52:48 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.ac/arch/alpha/kernel/es1888.c --- linux.vanilla/arch/alpha/kernel/es1888.c Sun Nov 8 15:08:24 1998 +++ linux.ac/arch/alpha/kernel/es1888.c Wed Jun 30 00:36:09 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.ac/arch/alpha/kernel/irq.h --- linux.vanilla/arch/alpha/kernel/irq.h Thu Dec 31 18:10:39 1998 +++ linux.ac/arch/alpha/kernel/irq.h Wed Jun 30 00:36:18 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.ac/arch/alpha/kernel/machvec.h --- linux.vanilla/arch/alpha/kernel/machvec.h Thu Jan 14 01:25:21 1999 +++ linux.ac/arch/alpha/kernel/machvec.h Wed Jun 30 00:48:06 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.ac/arch/alpha/kernel/osf_sys.c --- linux.vanilla/arch/alpha/kernel/osf_sys.c Thu May 27 22:11:48 1999 +++ linux.ac/arch/alpha/kernel/osf_sys.c Wed Jun 30 00:36:27 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.ac/arch/alpha/kernel/process.c --- linux.vanilla/arch/alpha/kernel/process.c Tue Jun 15 16:49:45 1999 +++ linux.ac/arch/alpha/kernel/process.c Thu Jul 8 02:02:28 1999 @@ -55,7 +55,6 @@ unsigned long init_user_stack[1024] = { STACK_MAGIC, }; static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; -static struct file * 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; @@ -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.ac/arch/alpha/kernel/proto.h --- linux.vanilla/arch/alpha/kernel/proto.h Tue Jun 15 16:49:45 1999 +++ linux.ac/arch/alpha/kernel/proto.h Sun Jun 13 19:58:21 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.ac/arch/alpha/kernel/setup.c --- linux.vanilla/arch/alpha/kernel/setup.c Tue Jun 15 16:49:45 1999 +++ linux.ac/arch/alpha/kernel/setup.c Tue Jun 22 03:35:46 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/smp.c linux.ac/arch/alpha/kernel/smp.c --- linux.vanilla/arch/alpha/kernel/smp.c Tue Jun 15 16:49:45 1999 +++ linux.ac/arch/alpha/kernel/smp.c Wed Jul 7 06:58:59 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.ac/arch/alpha/kernel/sys_dp264.c --- linux.vanilla/arch/alpha/kernel/sys_dp264.c Tue Jun 15 16:49:45 1999 +++ linux.ac/arch/alpha/kernel/sys_dp264.c Wed Jun 30 00:36:53 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.ac/arch/alpha/kernel/time.c --- linux.vanilla/arch/alpha/kernel/time.c Tue Jun 15 16:49:45 1999 +++ linux.ac/arch/alpha/kernel/time.c Wed Jun 30 00:36:53 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/lib/io.c linux.ac/arch/alpha/lib/io.c --- linux.vanilla/arch/alpha/lib/io.c Fri Apr 16 22:10:51 1999 +++ linux.ac/arch/alpha/lib/io.c Mon Jul 19 03:45:42 1999 @@ -2,6 +2,7 @@ * Alpha IO and memory functions.. Just expand the inlines in the header * files.. */ +#include #include #include #include @@ -451,6 +452,48 @@ from++; } } + +#ifdef CONFIG_ALPHA_JENSEN +/* Special memcopy for EISA-Cards that permit only + * 32-bit accesses. Two 16-bit words are combined and + * written as one 32-bit word to the IO space. + */ + +void _memcpy_fromio_g32a(void * to, unsigned long from, long count) +{ + + if ((((long)to&1)!=0)&&((from&3)!=0)&&((count&3)!=0)) + { + printk ("memcpy_fromio_g32: Unaligned Data!\n"); + return; + } + + count-=4; + do { + __readlua((u16 *)to, (u16 *)(to+2), from); + count -= 4; + to += 4; + from += 4; + } while (count >= 0); +} + +void _memcpy_toio_g32a(unsigned long to, void * from, long count) +{ + if ((((long)from&1)!=0)&&((to&3)!=0)&&((count&3)!=0)) + { + printk ("memcpy_toio_g32: Unaligned Data!\n"); + return; + } + + count-=4; + do { + __writelua(*(u16 *)from, *(u16 *)(from+2), to); + count -= 4; + to += 4; + from += 4; + } while (count >= 0); +} +#endif /* * "memset" on IO memory space. diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/math-emu/ieee-math.c linux.ac/arch/alpha/math-emu/ieee-math.c --- linux.vanilla/arch/alpha/math-emu/ieee-math.c Thu May 27 22:11:48 1999 +++ linux.ac/arch/alpha/math-emu/ieee-math.c Wed Jun 30 00:36:53 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.ac/arch/alpha/math-emu/ieee-math.h --- linux.vanilla/arch/alpha/math-emu/ieee-math.h Thu May 27 22:11:48 1999 +++ linux.ac/arch/alpha/math-emu/ieee-math.h Wed Jun 30 00:36:53 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.ac/arch/alpha/mm/fault.c --- linux.vanilla/arch/alpha/mm/fault.c Sun Nov 8 15:08:23 1998 +++ linux.ac/arch/alpha/mm/fault.c Wed Jul 7 06:58:59 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.ac/arch/alpha/mm/init.c --- linux.vanilla/arch/alpha/mm/init.c Tue Jun 15 16:49:46 1999 +++ linux.ac/arch/alpha/mm/init.c Wed Jun 30 00:48:14 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/i386/Makefile linux.ac/arch/i386/Makefile --- linux.vanilla/arch/i386/Makefile Thu Dec 31 18:10:39 1998 +++ linux.ac/arch/i386/Makefile Sun Jun 6 02:46:05 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.ac/arch/i386/boot/setup.S --- linux.vanilla/arch/i386/boot/setup.S Tue Jun 15 16:49:46 1999 +++ linux.ac/arch/i386/boot/setup.S Tue Jun 29 02:19:55 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 ! diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/config.in linux.ac/arch/i386/config.in --- linux.vanilla/arch/i386/config.in Wed Apr 28 19:14:24 1999 +++ linux.ac/arch/i386/config.in Mon Jun 7 00:10:09 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 @@ -105,7 +109,6 @@ bool ' Enable PM at boot time' CONFIG_APM_DO_ENABLE bool ' Make CPU Idle calls when idle' CONFIG_APM_CPU_IDLE bool ' Enable console blanking using APM' CONFIG_APM_DISPLAY_BLANK - bool ' Power off on shutdown' CONFIG_APM_POWER_OFF bool ' Ignore multiple suspend' CONFIG_APM_IGNORE_MULTIPLE_SUSPEND bool ' Ignore multiple suspend/resume cycles' CONFIG_APM_IGNORE_SUSPEND_BOUNCE bool ' RTC stores time in GMT' CONFIG_APM_RTC_IS_GMT diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/defconfig linux.ac/arch/i386/defconfig --- linux.vanilla/arch/i386/defconfig Fri Apr 16 22:10:51 1999 +++ linux.ac/arch/i386/defconfig Mon Jul 19 03:56:19 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 @@ -89,13 +91,23 @@ # # Additional Block Devices # +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_MD=y +CONFIG_AUTODETECT_RAID=y +CONFIG_MD_TRANSLUCENT=y +CONFIG_MD_LINEAR=y +CONFIG_MD_STRIPED=y +CONFIG_MD_MIRRORING=y +CONFIG_MD_RAID5=y +CONFIG_MD_BOOT=y +CONFIG_BLK_DEV_LVM=y # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_XD is not set CONFIG_PARIDE_PARPORT=y # CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_HD is not set # @@ -228,6 +240,7 @@ # CONFIG_TR is not set # CONFIG_HOSTESS_SV11 is not set # CONFIG_COSA is not set +# CONFIG_SEALEVEL_4021 is not set # CONFIG_RCPCI is not set # CONFIG_WAN_DRIVERS is not set # CONFIG_LAPBETHER is not set @@ -239,6 +252,11 @@ # CONFIG_HAMRADIO is not set # +# IrDA subsystem support +# +# CONFIG_IRDA is not set + +# # ISDN subsystem # # CONFIG_ISDN is not set @@ -285,6 +303,7 @@ # # CONFIG_JOYSTICK is not set # CONFIG_DTLK is not set +# CONFIG_DMARAM is not set # # Ftape, the floppy tape device driver diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/kernel/apm.c linux.ac/arch/i386/kernel/apm.c --- linux.vanilla/arch/i386/kernel/apm.c Tue Jan 19 02:57:23 1999 +++ linux.ac/arch/i386/kernel/apm.c Mon Jun 7 00:10:10 1999 @@ -1,6 +1,6 @@ /* -*- linux-c -*- * APM BIOS driver for Linux - * Copyright 1994-1998 Stephen Rothwell + * Copyright 1994-1999 Stephen Rothwell * (Stephen.Rothwell@canb.auug.org.au) * Development of this driver was funded by NEC Australia P/L * and NEC Corporation @@ -33,6 +33,7 @@ * Nov 1998, Version 1.7 * Jan 1999, Version 1.8 * Jan 1999, Version 1.9 + * Jun 1999, Version 1.10 * * History: * 0.6b: first version in official kernel, Linux 1.3.46 @@ -90,6 +91,12 @@ * Use CONFIG_SMP instead of __SMP__ * Ignore BOUNCES for three seconds. * Stephen Rothwell + * 1.10: Reset time across standby. + * Allow more inititialisation on SMP. + * Remove CONFIG_APM_POWER_OFF and make it boot time + * configurable (default on). + * Make debug only a boot time parameter (remove APM_DEBUG). + * Try to blank all devices on any error. * * APM 1.1 Reference: * @@ -144,51 +151,14 @@ */ #define APM_MINOR_DEV 134 -/* Configurable options: - * - * CONFIG_APM_IGNORE_USER_SUSPEND: define to ignore USER SUSPEND requests. - * This is necessary on the NEC Versa M series, which generates these when - * resuming from SYSTEM SUSPEND. However, enabling this on other laptops - * will cause the laptop to generate a CRITICAL SUSPEND when an appropriate - * USER SUSPEND is ignored -- this may prevent the APM driver from updating - * the system time on a RESUME. - * - * CONFIG_APM_DO_ENABLE: enable APM features at boot time. From page 36 of - * the specification: "When disabled, the APM BIOS does not automatically - * power manage devices, enter the Standby State, enter the Suspend State, - * or take power saving steps in response to CPU Idle calls." This driver - * will make CPU Idle calls when Linux is idle (unless this feature is - * turned off -- see below). This should always save battery power, but - * more complicated APM features will be dependent on your BIOS - * implementation. You may need to turn this option off if your computer - * hangs at boot time when using APM support, or if it beeps continuously - * instead of suspending. Turn this off if you have a NEC UltraLite Versa - * 33/C or a Toshiba T400CDT. This is off by default since most machines - * do fine without this feature. - * - * CONFIG_APM_CPU_IDLE: enable calls to APM CPU Idle/CPU Busy inside the - * idle loop. On some machines, this can activate improved power savings, - * such as a slowed CPU clock rate, when the machine is idle. These idle - * call is made after the idle loop has run for some length of time (e.g., - * 333 mS). On some machines, this will cause a hang at boot time or - * whenever the CPU becomes idle. - * - * CONFIG_APM_DISPLAY_BLANK: enable console blanking using the APM. Some - * laptops can use this to turn of the LCD backlight when the VC screen - * blanker blanks the screen. Note that this is only used by the VC screen - * blanker, and probably won't turn off the backlight when using X11. Some - * problems have been reported when using this option with gpm (if you'd - * like to debug this, please do so). - * - * CONFIG_APM_IGNORE_MULTIPLE_SUSPEND: The IBM TP560 bios seems to insist - * on returning multiple suspend/standby events whenever one occurs. We - * really only need one at a time, so just ignore any beyond the first. - * This is probably safe on most laptops. - * - * If you are debugging the APM support for your laptop, note that code for - * all of these options is contained in this file, so you can #define or - * #undef these on the next line to avoid recompiling the whole kernel. +/* + * See Documentation/Config.help for the configuration options. * + * Various options can be changed at boot time as follows: + * apm=on/off enable/disable APM + * [no-]debug log some debugging messages + * [no-]power-off power off on shutdown + * [no-]smp-power-off allow power off even for SMP */ /* KNOWN PROBLEM MACHINES: @@ -207,11 +177,6 @@ */ /* - * Define to have debug messages. - */ -#undef APM_DEBUG - -/* * Define to always call the APM BIOS busy routine even if the clock was * not slowed by the idle routine. */ @@ -266,27 +231,6 @@ __asm__ __volatile__("movl %%" #seg ",%0" : "=m" (where)) /* - * Forward declarations - */ -static void suspend(void); -static void standby(void); -static void set_time(void); - -static void check_events(void); -static void do_apm_timer(unsigned long); - -static int do_open(struct inode *, struct file *); -static int do_release(struct inode *, struct file *); -static ssize_t do_read(struct file *, char *, size_t , loff_t *); -static unsigned int do_poll(struct file *, poll_table *); -static int do_ioctl(struct inode *, struct file *, u_int, u_long); - -static int apm_get_info(char *, char **, off_t, int, int); - -extern int apm_register_callback(int (*)(apm_event_t)); -extern void apm_unregister_callback(int (*)(apm_event_t)); - -/* * Local variables */ static asmlinkage struct { @@ -313,15 +257,15 @@ #endif static int debug = 0; static int apm_disabled = 0; +static int power_off_enabled = 1; static struct wait_queue * process_list = NULL; static struct apm_bios_struct * user_list = NULL; static struct timer_list apm_timer; -static char driver_version[] = "1.9"; /* no spaces */ +static char driver_version[] = "1.10"; /* no spaces */ -#ifdef APM_DEBUG static char * apm_event_name[] = { "system standby", "system suspend", @@ -338,28 +282,6 @@ }; #define NR_APM_EVENT_NAME \ (sizeof(apm_event_name) / sizeof(apm_event_name[0])) -#endif - -static struct file_operations apm_bios_fops = { - NULL, /* lseek */ - do_read, - NULL, /* write */ - NULL, /* readdir */ - do_poll, - do_ioctl, - NULL, /* mmap */ - do_open, - NULL, /* flush */ - do_release, - NULL, /* fsync */ - NULL /* fasync */ -}; - -static struct miscdevice apm_device = { - APM_MINOR_DEV, - "apm", - &apm_bios_fops -}; typedef struct callback_list_t { int (* callback)(apm_event_t); @@ -502,7 +424,7 @@ return error; } -static int apm_driver_version(u_short *val) +static int __init apm_driver_version(u_short *val) { u32 eax; @@ -543,7 +465,7 @@ return set_power_state(0x0001, state); } -void apm_power_off(void) +void apm_power_off(int force) { /* * smp_hack == 2 means that we would have enabled APM support @@ -553,7 +475,8 @@ * they are doing because they booted with the smp-power-off * kernel option. */ - if (apm_enabled || (smp_hack == 2)) + if ((apm_enabled || (smp_hack == 2)) + && (power_off_enabled || force)) (void) apm_set_power_state(APM_STATE_OFF); } @@ -565,7 +488,7 @@ /* Blank the first display device */ error = set_power_state(0x0100, state); - if (error == APM_BAD_DEVICE) + if (error != APM_SUCCESS) /* try to blank them all instead */ error = set_power_state(0x01ff, state); return error; @@ -733,10 +656,8 @@ if (as->event_head == as->event_tail) { static int notified; - if (notified == 0) { + if (notified++ == 0) printk(KERN_ERR "apm: an event queue overflowed\n"); - notified = 1; - } as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS; } as->events[as->event_head] = event; @@ -764,21 +685,19 @@ { unsigned long flags; - if (!got_clock_diff) /* Don't know time zone, can't set clock */ - return; - - save_flags(flags); - cli(); - CURRENT_TIME = get_cmos_time() + clock_cmos_diff; - restore_flags(flags); + if (got_clock_diff) { /* Must know time zone in order to set clock */ + save_flags(flags); + cli(); + CURRENT_TIME = get_cmos_time() + clock_cmos_diff; + restore_flags(flags); + } } -static void suspend(void) +static void get_time_diff(void) { +#ifndef CONFIG_APM_RTC_IS_GMT unsigned long flags; - int err; -#ifndef CONFIG_APM_RTC_IS_GMT /* * Estimate time zone so that set_time can update the clock */ @@ -789,7 +708,14 @@ got_clock_diff = 1; restore_flags(flags); #endif +} + +static void suspend(void) +{ + unsigned long flags; + int err; + get_time_diff(); err = apm_set_power_state(APM_STATE_SUSPEND); if (err) apm_error("suspend", err); @@ -812,9 +738,11 @@ { int err; + get_time_diff(); err = apm_set_power_state(APM_STATE_STANDBY); if (err) apm_error("standby", err); + set_time(); /* should not be necessary ... */ } static apm_event_t get_event(void) @@ -864,14 +792,14 @@ #endif while ((event = get_event()) != 0) { -#ifdef APM_DEBUG - if (event <= NR_APM_EVENT_NAME) - printk(KERN_DEBUG "apm: received %s notify\n", - apm_event_name[event - 1]); - else - printk(KERN_DEBUG "apm: received unknown " - "event 0x%02x\n", event); -#endif + if (debug) { + if (event <= NR_APM_EVENT_NAME) + printk(KERN_DEBUG "apm: received %s notify\n", + apm_event_name[event - 1]); + else + printk(KERN_DEBUG "apm: received unknown " + "event 0x%02x\n", event); + } #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE if (ignore_bounce && ((jiffies - last_resume) > BOUNCE_INTERVAL)) @@ -1277,6 +1205,8 @@ str += 3; if (strncmp(str, "debug", 5) == 0) debug = !invert; + if (strncmp(str, "power-off", 9) == 0) + power_off_enabled = !invert; if (strncmp(str, "smp-power-off", 13) == 0) smp_hack = !invert; str = strchr(str, ','); @@ -1285,6 +1215,27 @@ } } +static struct file_operations apm_bios_fops = { + NULL, /* lseek */ + do_read, + NULL, /* write */ + NULL, /* readdir */ + do_poll, + do_ioctl, + NULL, /* mmap */ + do_open, + NULL, /* flush */ + do_release, + NULL, /* fsync */ + NULL /* fasync */ +}; + +static struct miscdevice apm_device = { + APM_MINOR_DEV, + "apm", + &apm_bios_fops +}; + void __init apm_bios_init(void) { unsigned short bx; @@ -1378,14 +1329,6 @@ (apm_bios_info.dseg_len - 1) & 0xffff); } #endif -#ifdef CONFIG_SMP - if (smp_num_cpus > 1) { - printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n"); - if (smp_hack) - smp_hack = 2; - return; - } -#endif if (apm_bios_info.version > 0x100) { /* * We only support BIOSs up to version 1.2 @@ -1459,6 +1402,14 @@ if (apm_engage_power_management(0x0001) == APM_SUCCESS) apm_bios_info.flags &= ~APM_BIOS_DISENGAGED; } +#ifdef CONFIG_SMP + if (smp_num_cpus > 1) { + printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n"); + if (smp_hack) + smp_hack = 2; + return; + } +#endif init_timer(&apm_timer); apm_timer.function = do_apm_timer; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/kernel/i386_ksyms.c linux.ac/arch/i386/kernel/i386_ksyms.c --- linux.vanilla/arch/i386/kernel/i386_ksyms.c Thu May 27 22:11:49 1999 +++ linux.ac/arch/i386/kernel/i386_ksyms.c Wed Jun 16 00:13:04 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/init_task.c linux.ac/arch/i386/kernel/init_task.c --- linux.vanilla/arch/i386/kernel/init_task.c Sun Nov 8 15:08:22 1998 +++ linux.ac/arch/i386/kernel/init_task.c Fri Jun 4 23:52:47 1999 @@ -7,7 +7,6 @@ static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; -static struct file * 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/i386/kernel/irq.c linux.ac/arch/i386/kernel/irq.c --- linux.vanilla/arch/i386/kernel/irq.c Thu May 27 22:11:49 1999 +++ linux.ac/arch/i386/kernel/irq.c Mon Jul 19 03:31:01 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.ac/arch/i386/kernel/irq.h --- linux.vanilla/arch/i386/kernel/irq.h Thu May 27 22:11:49 1999 +++ linux.ac/arch/i386/kernel/irq.h Mon Jul 19 05:16:15 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/kernel/process.c linux.ac/arch/i386/kernel/process.c --- linux.vanilla/arch/i386/kernel/process.c Thu May 27 22:11:49 1999 +++ linux.ac/arch/i386/kernel/process.c Mon Jun 7 00:10:10 1999 @@ -31,7 +31,7 @@ #include #include #include -#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF) +#if defined(CONFIG_APM) #include #endif @@ -52,11 +52,6 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); -#ifdef CONFIG_APM -extern int apm_do_idle(void); -extern void apm_do_busy(void); -#endif - static int hlt_counter=0; #define HARD_IDLE_TIMEOUT (HZ / 3) @@ -386,8 +381,8 @@ void machine_power_off(void) { -#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF) - apm_power_off(); +#if defined(CONFIG_APM) + apm_power_off(0); #endif } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/mm/ioremap.c linux.ac/arch/i386/mm/ioremap.c --- linux.vanilla/arch/i386/mm/ioremap.c Thu Dec 3 14:11:59 1998 +++ linux.ac/arch/i386/mm/ioremap.c Fri Jul 2 19:50:39 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.ac/arch/i386/vmlinux.lds --- linux.vanilla/arch/i386/vmlinux.lds Mon Dec 28 23:09:40 1998 +++ linux.ac/arch/i386/vmlinux.lds Mon Jul 19 06:26:01 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.ac/arch/i386/vmlinux.lds.S --- linux.vanilla/arch/i386/vmlinux.lds.S Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/i386/vmlinux.lds.S Sun Jun 6 02:44: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/m68k/kernel/process.c linux.ac/arch/m68k/kernel/process.c --- linux.vanilla/arch/m68k/kernel/process.c Thu May 27 22:11:49 1999 +++ linux.ac/arch/m68k/kernel/process.c Mon Jun 7 00:10:10 1999 @@ -40,7 +40,6 @@ */ static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; -static struct file * 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; @@ -87,9 +86,6 @@ void machine_power_off(void) { -#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF) - apm_set_power_state(APM_STATE_OFF); -#endif } void show_regs(struct pt_regs * regs) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/Makefile linux.ac/arch/mips/Makefile --- linux.vanilla/arch/mips/Makefile Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/Makefile Tue Jun 22 01:20:08 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.ac/arch/mips/algor/README --- linux.vanilla/arch/mips/algor/README Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/algor/README Tue Jun 22 01:20:08 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.ac/arch/mips/arc/Makefile --- linux.vanilla/arch/mips/arc/Makefile Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/arc/Makefile Tue Jun 22 01:20:08 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.ac/arch/mips/arc/cmdline.c --- linux.vanilla/arch/mips/arc/cmdline.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/arc/cmdline.c Tue Jun 22 01:20:08 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.ac/arch/mips/arc/console.c --- linux.vanilla/arch/mips/arc/console.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/arc/console.c Mon Jul 19 03:45:42 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.ac/arch/mips/arc/env.c --- linux.vanilla/arch/mips/arc/env.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/arc/env.c Tue Jun 22 01:20:08 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.ac/arch/mips/arc/file.c --- linux.vanilla/arch/mips/arc/file.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/arc/file.c Tue Jun 22 01:20:08 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.ac/arch/mips/arc/identify.c --- linux.vanilla/arch/mips/arc/identify.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/arc/identify.c Tue Jun 22 01:20:08 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.ac/arch/mips/arc/init.c --- linux.vanilla/arch/mips/arc/init.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/arc/init.c Tue Jun 22 01:20:08 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.ac/arch/mips/arc/memory.c --- linux.vanilla/arch/mips/arc/memory.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/arc/memory.c Mon Jul 19 03:45:42 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.ac/arch/mips/arc/misc.c --- linux.vanilla/arch/mips/arc/misc.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/arc/misc.c Tue Jun 22 01:20:08 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.ac/arch/mips/arc/printf.c --- linux.vanilla/arch/mips/arc/printf.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/arc/printf.c Mon Jul 19 03:45:42 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.ac/arch/mips/arc/salone.c --- linux.vanilla/arch/mips/arc/salone.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/arc/salone.c Tue Jun 22 01:20:08 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.ac/arch/mips/arc/time.c --- linux.vanilla/arch/mips/arc/time.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/arc/time.c Tue Jun 22 01:20:08 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.ac/arch/mips/arc/tree.c --- linux.vanilla/arch/mips/arc/tree.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/arc/tree.c Tue Jun 22 01:20:08 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.ac/arch/mips/baget/Makefile --- linux.vanilla/arch/mips/baget/Makefile Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/baget/Makefile Tue Jun 22 01:20:08 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.ac/arch/mips/baget/baget.c --- linux.vanilla/arch/mips/baget/baget.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/baget/baget.c Tue Jun 22 01:20:08 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.ac/arch/mips/baget/bagetIRQ.S --- linux.vanilla/arch/mips/baget/bagetIRQ.S Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/baget/bagetIRQ.S Tue Jun 22 01:20:08 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.ac/arch/mips/baget/balo.c --- linux.vanilla/arch/mips/baget/balo.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/baget/balo.c Tue Jun 22 01:20:08 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.ac/arch/mips/baget/balo_supp.S --- linux.vanilla/arch/mips/baget/balo_supp.S Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/baget/balo_supp.S Mon Jul 19 03:45:42 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.ac/arch/mips/baget/irq.c --- linux.vanilla/arch/mips/baget/irq.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/baget/irq.c Tue Jun 22 01:20:08 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.ac/arch/mips/baget/ld.script.balo --- linux.vanilla/arch/mips/baget/ld.script.balo Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/baget/ld.script.balo Tue Jun 22 01:20:08 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.ac/arch/mips/baget/print.c --- linux.vanilla/arch/mips/baget/print.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/baget/print.c Tue Jun 22 01:20:08 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.ac/arch/mips/baget/prom/Makefile --- linux.vanilla/arch/mips/baget/prom/Makefile Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/baget/prom/Makefile Tue Jun 22 01:20:08 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.ac/arch/mips/baget/prom/init.c --- linux.vanilla/arch/mips/baget/prom/init.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/baget/prom/init.c Mon Jul 19 03:45:42 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.ac/arch/mips/baget/reset.c --- linux.vanilla/arch/mips/baget/reset.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/baget/reset.c Tue Jun 22 01:20:08 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.ac/arch/mips/baget/setup.c --- linux.vanilla/arch/mips/baget/setup.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/baget/setup.c Mon Jul 19 03:45:42 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.ac/arch/mips/baget/time.c --- linux.vanilla/arch/mips/baget/time.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/baget/time.c Tue Jun 22 01:20:08 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.ac/arch/mips/baget/vacserial.c --- linux.vanilla/arch/mips/baget/vacserial.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/baget/vacserial.c Tue Jun 22 01:20:08 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.ac/arch/mips/baget/wbflush.c --- linux.vanilla/arch/mips/baget/wbflush.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/baget/wbflush.c Tue Jun 22 01:20:08 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.ac/arch/mips/boot/Makefile --- linux.vanilla/arch/mips/boot/Makefile Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/boot/Makefile Tue Jun 22 01:20:08 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.ac/arch/mips/boot/ecoff.h --- linux.vanilla/arch/mips/boot/ecoff.h Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/boot/ecoff.h Tue Jun 22 01:20:40 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.ac/arch/mips/boot/elf2ecoff.c --- linux.vanilla/arch/mips/boot/elf2ecoff.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/boot/elf2ecoff.c Tue Jun 22 01:20:40 1999 @@ -0,0 +1,640 @@ +/* + * 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 + +#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.ac/arch/mips/config.in --- linux.vanilla/arch/mips/config.in Tue Feb 23 14:21:32 1999 +++ linux.ac/arch/mips/config.in Tue Jun 22 01:20:40 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.ac/arch/mips/dec/Makefile --- linux.vanilla/arch/mips/dec/Makefile Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/dec/Makefile Tue Jun 22 01:20:40 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.ac/arch/mips/dec/boot/Makefile --- linux.vanilla/arch/mips/dec/boot/Makefile Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/dec/boot/Makefile Tue Jun 22 01:20:40 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.ac/arch/mips/dec/boot/decstation.c --- linux.vanilla/arch/mips/dec/boot/decstation.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/dec/boot/decstation.c Tue Jun 22 01:20:40 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.ac/arch/mips/dec/boot/ld.ecoff --- linux.vanilla/arch/mips/dec/boot/ld.ecoff Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/dec/boot/ld.ecoff Tue Jun 22 01:20:40 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.ac/arch/mips/dec/int-handler.S --- linux.vanilla/arch/mips/dec/int-handler.S Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/dec/int-handler.S Tue Jun 22 01:20:40 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.ac/arch/mips/dec/irq.c --- linux.vanilla/arch/mips/dec/irq.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/dec/irq.c Tue Jun 22 01:20:40 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.ac/arch/mips/dec/prom/Makefile --- linux.vanilla/arch/mips/dec/prom/Makefile Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/dec/prom/Makefile Tue Jun 22 01:20:40 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.ac/arch/mips/dec/prom/cmdline.c --- linux.vanilla/arch/mips/dec/prom/cmdline.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/dec/prom/cmdline.c Mon Jul 19 03:45:42 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.ac/arch/mips/dec/prom/dectypes.h --- linux.vanilla/arch/mips/dec/prom/dectypes.h Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/dec/prom/dectypes.h Tue Jun 22 01:20:40 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.ac/arch/mips/dec/prom/identify.c --- linux.vanilla/arch/mips/dec/prom/identify.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/dec/prom/identify.c Mon Jul 19 03:45:42 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.ac/arch/mips/dec/prom/init.c --- linux.vanilla/arch/mips/dec/prom/init.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/dec/prom/init.c Mon Jul 19 03:45:42 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.ac/arch/mips/dec/prom/locore.S --- linux.vanilla/arch/mips/dec/prom/locore.S Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/dec/prom/locore.S Tue Jun 22 01:20:40 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.ac/arch/mips/dec/prom/memory.c --- linux.vanilla/arch/mips/dec/prom/memory.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/dec/prom/memory.c Mon Jul 19 03:45:42 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.ac/arch/mips/dec/prom/prom.h --- linux.vanilla/arch/mips/dec/prom/prom.h Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/dec/prom/prom.h Tue Jun 22 01:20:40 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.ac/arch/mips/dec/promcon.c --- linux.vanilla/arch/mips/dec/promcon.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/dec/promcon.c Tue Jun 22 01:20:40 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.ac/arch/mips/dec/reset.c --- linux.vanilla/arch/mips/dec/reset.c Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/dec/reset.c Tue Jun 22 01:20:40 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.ac/arch/mips/dec/rtc-dec.c --- linux.vanilla/arch/mips/dec/rtc-dec.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/dec/rtc-dec.c Tue Jun 22 01:20:40 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.ac/arch/mips/dec/serial.c --- linux.vanilla/arch/mips/dec/serial.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/dec/serial.c Mon Jul 19 03:45:42 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.ac/arch/mips/dec/setup.c --- linux.vanilla/arch/mips/dec/setup.c Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/dec/setup.c Tue Jun 22 01:20:40 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.ac/arch/mips/dec/time.c --- linux.vanilla/arch/mips/dec/time.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/dec/time.c Tue Jun 22 01:20:40 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.ac/arch/mips/dec/wbflush.c --- linux.vanilla/arch/mips/dec/wbflush.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/dec/wbflush.c Tue Jun 22 01:20:40 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.ac/arch/mips/defconfig --- linux.vanilla/arch/mips/defconfig Wed Mar 10 21:13:00 1999 +++ linux.ac/arch/mips/defconfig Tue Jun 22 01:20:40 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.ac/arch/mips/jazz/Makefile --- linux.vanilla/arch/mips/jazz/Makefile Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/jazz/Makefile Tue Jun 22 01:20:40 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.ac/arch/mips/jazz/floppy-jazz.c --- linux.vanilla/arch/mips/jazz/floppy-jazz.c Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/jazz/floppy-jazz.c Tue Jun 22 01:20:40 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.ac/arch/mips/jazz/hw-access.c --- linux.vanilla/arch/mips/jazz/hw-access.c Sun Nov 8 15:08:31 1998 +++ linux.ac/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.ac/arch/mips/jazz/int-handler.S --- linux.vanilla/arch/mips/jazz/int-handler.S Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/jazz/int-handler.S Tue Jun 22 01:20:40 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.ac/arch/mips/jazz/jazzdma.c --- linux.vanilla/arch/mips/jazz/jazzdma.c Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/jazz/jazzdma.c Tue Jun 22 01:20:40 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.ac/arch/mips/jazz/kbd-jazz.c --- linux.vanilla/arch/mips/jazz/kbd-jazz.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/jazz/kbd-jazz.c Tue Jun 22 01:20:40 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.ac/arch/mips/jazz/reset.c --- linux.vanilla/arch/mips/jazz/reset.c Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/jazz/reset.c Tue Jun 22 01:20:40 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.ac/arch/mips/jazz/rtc-jazz.c --- linux.vanilla/arch/mips/jazz/rtc-jazz.c Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/jazz/rtc-jazz.c Tue Jun 22 01:20:40 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.ac/arch/mips/jazz/setup.c --- linux.vanilla/arch/mips/jazz/setup.c Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/jazz/setup.c Tue Jun 22 01:20:40 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.ac/arch/mips/kernel/Makefile --- linux.vanilla/arch/mips/kernel/Makefile Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/Makefile Tue Jun 22 01:42:44 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.ac/arch/mips/kernel/entry.S --- linux.vanilla/arch/mips/kernel/entry.S Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/entry.S Tue Jun 22 01:20:40 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.ac/arch/mips/kernel/fpe.c --- linux.vanilla/arch/mips/kernel/fpe.c Sun Nov 8 15:08:30 1998 +++ linux.ac/arch/mips/kernel/fpe.c Tue Jun 22 01:20:40 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.ac/arch/mips/kernel/gdb-low.S --- linux.vanilla/arch/mips/kernel/gdb-low.S Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/gdb-low.S Tue Jun 22 01:20:40 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.ac/arch/mips/kernel/gdb-stub.c --- linux.vanilla/arch/mips/kernel/gdb-stub.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/gdb-stub.c Tue Jun 22 01:20:40 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.ac/arch/mips/kernel/head.S --- linux.vanilla/arch/mips/kernel/head.S Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/head.S Tue Jun 22 01:20:40 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.ac/arch/mips/kernel/init_task.c --- linux.vanilla/arch/mips/kernel/init_task.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/init_task.c Fri Jun 4 23:52:50 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.ac/arch/mips/kernel/ipc.c --- linux.vanilla/arch/mips/kernel/ipc.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/ipc.c Wed Jul 7 07:06:16 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.ac/arch/mips/kernel/irix5sys.h --- linux.vanilla/arch/mips/kernel/irix5sys.h Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/irix5sys.h Tue Jun 22 01:20:40 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.ac/arch/mips/kernel/irixelf.c --- linux.vanilla/arch/mips/kernel/irixelf.c Fri Nov 13 01:37:10 1998 +++ linux.ac/arch/mips/kernel/irixelf.c Tue Jun 29 02:52:49 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.ac/arch/mips/kernel/irixinv.c --- linux.vanilla/arch/mips/kernel/irixinv.c Sun Nov 8 15:08:30 1998 +++ linux.ac/arch/mips/kernel/irixinv.c Tue Jun 22 01:21:37 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.ac/arch/mips/kernel/irixioctl.c --- linux.vanilla/arch/mips/kernel/irixioctl.c Thu May 27 22:11:50 1999 +++ linux.ac/arch/mips/kernel/irixioctl.c Tue Jun 22 01:22: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.ac/arch/mips/kernel/irixsig.c --- linux.vanilla/arch/mips/kernel/irixsig.c Sun Nov 8 15:10:06 1998 +++ linux.ac/arch/mips/kernel/irixsig.c Tue Jun 22 01:21:37 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.ac/arch/mips/kernel/irq.c --- linux.vanilla/arch/mips/kernel/irq.c Mon Dec 28 23:09:40 1998 +++ linux.ac/arch/mips/kernel/irq.c Tue Jun 22 01:22:56 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.ac/arch/mips/kernel/mips_ksyms.c --- linux.vanilla/arch/mips/kernel/mips_ksyms.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/mips_ksyms.c Tue Jun 22 01:23:09 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.ac/arch/mips/kernel/pci.c --- linux.vanilla/arch/mips/kernel/pci.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/pci.c Tue Jun 22 01:23:56 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.ac/arch/mips/kernel/process.c --- linux.vanilla/arch/mips/kernel/process.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/process.c Tue Jun 22 01:23:09 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.ac/arch/mips/kernel/ptrace.c --- linux.vanilla/arch/mips/kernel/ptrace.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/ptrace.c Tue Jun 22 01:23:09 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.ac/arch/mips/kernel/r2300_fpu.S --- linux.vanilla/arch/mips/kernel/r2300_fpu.S Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/r2300_fpu.S Tue Jun 22 03:31:49 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.ac/arch/mips/kernel/r2300_misc.S --- linux.vanilla/arch/mips/kernel/r2300_misc.S Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/r2300_misc.S Mon Jul 19 03:45:42 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.ac/arch/mips/kernel/r2300_switch.S --- linux.vanilla/arch/mips/kernel/r2300_switch.S Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/r2300_switch.S Tue Jun 22 01:25:25 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.ac/arch/mips/kernel/r4k_fpu.S --- linux.vanilla/arch/mips/kernel/r4k_fpu.S Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/r4k_fpu.S Tue Jun 22 01:25:31 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.ac/arch/mips/kernel/r4k_misc.S --- linux.vanilla/arch/mips/kernel/r4k_misc.S Sun Nov 8 15:08:30 1998 +++ linux.ac/arch/mips/kernel/r4k_misc.S Tue Jun 22 01:25:56 1999 @@ -6,7 +6,7 @@ * 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 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/r4k_switch.S linux.ac/arch/mips/kernel/r4k_switch.S --- linux.vanilla/arch/mips/kernel/r4k_switch.S Sun Nov 8 15:08:30 1998 +++ linux.ac/arch/mips/kernel/r4k_switch.S Tue Jun 22 01:25:56 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.ac/arch/mips/kernel/r6000_fpu.S --- linux.vanilla/arch/mips/kernel/r6000_fpu.S Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/r6000_fpu.S Tue Jun 22 01:26:15 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.ac/arch/mips/kernel/scall_o32.S --- linux.vanilla/arch/mips/kernel/scall_o32.S Sun Nov 8 15:08:30 1998 +++ linux.ac/arch/mips/kernel/scall_o32.S Tue Jun 22 01:26:15 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.ac/arch/mips/kernel/setup.c --- linux.vanilla/arch/mips/kernel/setup.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/setup.c Tue Jun 22 01:28:05 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 @@ -76,7 +76,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 +91,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 +138,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 +150,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 +162,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 +200,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 +210,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 +219,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.ac/arch/mips/kernel/signal.c --- linux.vanilla/arch/mips/kernel/signal.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/signal.c Tue Jun 22 01:28:15 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.ac/arch/mips/kernel/softfp.S --- linux.vanilla/arch/mips/kernel/softfp.S Sun Nov 8 15:08:30 1998 +++ linux.ac/arch/mips/kernel/softfp.S Tue Jun 22 01:28:21 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.ac/arch/mips/kernel/syscall.c --- linux.vanilla/arch/mips/kernel/syscall.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/syscall.c Tue Jun 22 01:28:21 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.ac/arch/mips/kernel/syscalls.h --- linux.vanilla/arch/mips/kernel/syscalls.h Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/syscalls.h Tue Jun 22 01:28:28 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.ac/arch/mips/kernel/sysirix.c --- linux.vanilla/arch/mips/kernel/sysirix.c Thu May 27 22:11:50 1999 +++ linux.ac/arch/mips/kernel/sysirix.c Tue Jun 22 03:31:56 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.ac/arch/mips/kernel/sysmips.c --- linux.vanilla/arch/mips/kernel/sysmips.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/sysmips.c Tue Jun 22 01:28:35 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.ac/arch/mips/kernel/time.c --- linux.vanilla/arch/mips/kernel/time.c Wed Mar 24 10:55:10 1999 +++ linux.ac/arch/mips/kernel/time.c Mon Jul 19 03:45:42 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.ac/arch/mips/kernel/traps.c --- linux.vanilla/arch/mips/kernel/traps.c Wed Jan 6 23:02:18 1999 +++ linux.ac/arch/mips/kernel/traps.c Tue Jun 22 01:28:35 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.ac/arch/mips/kernel/unaligned.c --- linux.vanilla/arch/mips/kernel/unaligned.c Sun Nov 8 15:08:30 1998 +++ linux.ac/arch/mips/kernel/unaligned.c Tue Jun 22 01:28:43 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.ac/arch/mips/lib/Makefile --- linux.vanilla/arch/mips/lib/Makefile Sun Nov 8 15:08:30 1998 +++ linux.ac/arch/mips/lib/Makefile Tue Jun 22 01:28:43 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.ac/arch/mips/lib/csum_partial.S --- linux.vanilla/arch/mips/lib/csum_partial.S Sun Nov 8 15:08:30 1998 +++ linux.ac/arch/mips/lib/csum_partial.S Tue Jun 22 01:29:55 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.ac/arch/mips/lib/csum_partial_copy.c --- linux.vanilla/arch/mips/lib/csum_partial_copy.c Sun Nov 8 15:08:30 1998 +++ linux.ac/arch/mips/lib/csum_partial_copy.c Tue Jun 22 01:29:55 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.ac/arch/mips/lib/floppy-std.c --- linux.vanilla/arch/mips/lib/floppy-std.c Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/lib/floppy-std.c Tue Jun 22 01:29:55 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.ac/arch/mips/lib/ide-no.c --- linux.vanilla/arch/mips/lib/ide-no.c Sun Nov 8 15:08:30 1998 +++ linux.ac/arch/mips/lib/ide-no.c Tue Jun 22 01:29:55 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.ac/arch/mips/lib/ide-std.c --- linux.vanilla/arch/mips/lib/ide-std.c Sun Nov 8 15:08:30 1998 +++ linux.ac/arch/mips/lib/ide-std.c Tue Jun 22 01:29:55 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.ac/arch/mips/lib/kbd-no.c --- linux.vanilla/arch/mips/lib/kbd-no.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/lib/kbd-no.c Tue Jun 22 01:29:55 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.ac/arch/mips/lib/kbd-std.c --- linux.vanilla/arch/mips/lib/kbd-std.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/lib/kbd-std.c Tue Jun 22 01:29:55 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.ac/arch/mips/lib/memcpy.S --- linux.vanilla/arch/mips/lib/memcpy.S Sun Nov 8 15:08:30 1998 +++ linux.ac/arch/mips/lib/memcpy.S Tue Jun 22 01:29:55 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.ac/arch/mips/lib/memset.S --- linux.vanilla/arch/mips/lib/memset.S Sun Nov 8 15:08:30 1998 +++ linux.ac/arch/mips/lib/memset.S Tue Jun 22 01:29:55 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.ac/arch/mips/lib/strlen_user.S --- linux.vanilla/arch/mips/lib/strlen_user.S Sun Nov 8 15:08:30 1998 +++ linux.ac/arch/mips/lib/strlen_user.S Tue Jun 22 01:29:55 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.ac/arch/mips/lib/strncpy_user.S --- linux.vanilla/arch/mips/lib/strncpy_user.S Sun Nov 8 15:08:30 1998 +++ linux.ac/arch/mips/lib/strncpy_user.S Tue Jun 22 01:29:55 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.ac/arch/mips/lib/tags.c --- linux.vanilla/arch/mips/lib/tags.c Sun Nov 8 15:08:30 1998 +++ linux.ac/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.ac/arch/mips/lib/watch.S --- linux.vanilla/arch/mips/lib/watch.S Sun Nov 8 15:08:30 1998 +++ linux.ac/arch/mips/lib/watch.S Fri Jun 4 23:52:50 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.ac/arch/mips/mm/Makefile --- linux.vanilla/arch/mips/mm/Makefile Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/mm/Makefile Tue Jun 22 01:31:04 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.ac/arch/mips/mm/andes.c --- linux.vanilla/arch/mips/mm/andes.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/mm/andes.c Tue Jun 22 01:31:04 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.ac/arch/mips/mm/fault.c --- linux.vanilla/arch/mips/mm/fault.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/mm/fault.c Tue Jun 22 01:31:04 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.ac/arch/mips/mm/init.c --- linux.vanilla/arch/mips/mm/init.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/mm/init.c Tue Jun 22 01:31:32 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.ac/arch/mips/mm/loadmmu.c --- linux.vanilla/arch/mips/mm/loadmmu.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/mm/loadmmu.c Tue Jun 22 01:31:48 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.ac/arch/mips/mm/r2300.c --- linux.vanilla/arch/mips/mm/r2300.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/mm/r2300.c Tue Jun 22 01:31:48 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.ac/arch/mips/mm/r4xx0.c --- linux.vanilla/arch/mips/mm/r4xx0.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/mm/r4xx0.c Tue Jun 22 01:31:48 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.ac/arch/mips/mm/r6000.c --- linux.vanilla/arch/mips/mm/r6000.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/mm/r6000.c Tue Jun 22 01:32:02 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.ac/arch/mips/mm/tfp.c --- linux.vanilla/arch/mips/mm/tfp.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/mm/tfp.c Tue Jun 22 01:32:02 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.ac/arch/mips/sgi/kernel/Makefile --- linux.vanilla/arch/mips/sgi/kernel/Makefile Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/sgi/kernel/Makefile Tue Jun 22 01:32:02 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.ac/arch/mips/sgi/kernel/indyIRQ.S --- linux.vanilla/arch/mips/sgi/kernel/indyIRQ.S Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/sgi/kernel/indyIRQ.S Tue Jun 22 01:32:02 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.ac/arch/mips/sgi/kernel/indy_hpc.c --- linux.vanilla/arch/mips/sgi/kernel/indy_hpc.c Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/sgi/kernel/indy_hpc.c Tue Jun 22 01:32:02 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.ac/arch/mips/sgi/kernel/indy_int.c --- linux.vanilla/arch/mips/sgi/kernel/indy_int.c Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/sgi/kernel/indy_int.c Mon Jul 19 03:45:43 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.ac/arch/mips/sgi/kernel/indy_mc.c --- linux.vanilla/arch/mips/sgi/kernel/indy_mc.c Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/sgi/kernel/indy_mc.c Tue Jun 22 01:32:02 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.ac/arch/mips/sgi/kernel/indy_sc.c --- linux.vanilla/arch/mips/sgi/kernel/indy_sc.c Sun Nov 8 15:10:06 1998 +++ linux.ac/arch/mips/sgi/kernel/indy_sc.c Tue Jun 22 01:32:02 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. * @@ -38,6 +38,7 @@ .set noreorder .set mips3 .set noat + mfc0 $2, $12 li $1, 0x80 # Go 64 bit mtc0 $1, $12 @@ -50,12 +51,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 +70,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 +84,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.ac/arch/mips/sgi/kernel/indy_timer.c --- linux.vanilla/arch/mips/sgi/kernel/indy_timer.c Wed Mar 24 10:55:10 1999 +++ linux.ac/arch/mips/sgi/kernel/indy_timer.c Tue Jun 22 01:32:02 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.ac/arch/mips/sgi/kernel/promcon.c --- linux.vanilla/arch/mips/sgi/kernel/promcon.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/mips/sgi/kernel/promcon.c Tue Jun 22 01:32:17 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.ac/arch/mips/sgi/kernel/reset.c --- linux.vanilla/arch/mips/sgi/kernel/reset.c Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/sgi/kernel/reset.c Tue Jun 22 01:32:17 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.ac/arch/mips/sgi/kernel/setup.c --- linux.vanilla/arch/mips/sgi/kernel/setup.c Sun Nov 8 15:10:06 1998 +++ linux.ac/arch/mips/sgi/kernel/setup.c Tue Jun 22 01:32:17 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.ac/arch/mips/sgi/kernel/system.c --- linux.vanilla/arch/mips/sgi/kernel/system.c Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/sgi/kernel/system.c Tue Jun 22 01:32:17 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.ac/arch/mips/sgi/kernel/time.c --- linux.vanilla/arch/mips/sgi/kernel/time.c Sun Nov 8 15:08:31 1998 +++ linux.ac/arch/mips/sgi/kernel/time.c Tue Jun 22 01:32:17 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.ac/arch/mips/sgi/prom/Makefile --- linux.vanilla/arch/mips/sgi/prom/Makefile Sun Nov 8 15:08:32 1998 +++ linux.ac/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.ac/arch/mips/sgi/prom/cmdline.c --- linux.vanilla/arch/mips/sgi/prom/cmdline.c Sun Nov 8 15:08:32 1998 +++ linux.ac/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.ac/arch/mips/sgi/prom/console.c --- linux.vanilla/arch/mips/sgi/prom/console.c Sun Nov 8 15:08:32 1998 +++ linux.ac/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.ac/arch/mips/sgi/prom/env.c --- linux.vanilla/arch/mips/sgi/prom/env.c Sun Nov 8 15:08:32 1998 +++ linux.ac/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.ac/arch/mips/sgi/prom/file.c --- linux.vanilla/arch/mips/sgi/prom/file.c Sun Nov 8 15:08:32 1998 +++ linux.ac/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.ac/arch/mips/sgi/prom/init.c --- linux.vanilla/arch/mips/sgi/prom/init.c Sun Nov 8 15:08:32 1998 +++ linux.ac/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.ac/arch/mips/sgi/prom/memory.c --- linux.vanilla/arch/mips/sgi/prom/memory.c Sun Nov 8 15:08:32 1998 +++ linux.ac/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.ac/arch/mips/sgi/prom/misc.c --- linux.vanilla/arch/mips/sgi/prom/misc.c Sun Nov 8 15:08:32 1998 +++ linux.ac/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.ac/arch/mips/sgi/prom/printf.c --- linux.vanilla/arch/mips/sgi/prom/printf.c Sun Nov 8 15:08:32 1998 +++ linux.ac/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.ac/arch/mips/sgi/prom/salone.c --- linux.vanilla/arch/mips/sgi/prom/salone.c Sun Nov 8 15:08:32 1998 +++ linux.ac/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.ac/arch/mips/sgi/prom/tags.c --- linux.vanilla/arch/mips/sgi/prom/tags.c Sun Nov 8 15:08:32 1998 +++ linux.ac/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.ac/arch/mips/sgi/prom/time.c --- linux.vanilla/arch/mips/sgi/prom/time.c Sun Nov 8 15:08:32 1998 +++ linux.ac/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.ac/arch/mips/sgi/prom/tree.c --- linux.vanilla/arch/mips/sgi/prom/tree.c Sun Nov 8 15:08:32 1998 +++ linux.ac/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.ac/arch/mips/sni/Makefile --- linux.vanilla/arch/mips/sni/Makefile Sun Nov 8 15:08:32 1998 +++ linux.ac/arch/mips/sni/Makefile Tue Jun 22 01:32:28 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.ac/arch/mips/sni/hw-access.c --- linux.vanilla/arch/mips/sni/hw-access.c Sun Nov 8 15:08:32 1998 +++ linux.ac/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.ac/arch/mips/sni/int-handler.S --- linux.vanilla/arch/mips/sni/int-handler.S Sun Nov 8 15:08:32 1998 +++ linux.ac/arch/mips/sni/int-handler.S Tue Jun 22 01:32:28 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.ac/arch/mips/sni/io.c --- linux.vanilla/arch/mips/sni/io.c Sun Nov 8 15:08:32 1998 +++ linux.ac/arch/mips/sni/io.c Tue Jun 22 01:32:28 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.ac/arch/mips/sni/pci.c --- linux.vanilla/arch/mips/sni/pci.c Sun Nov 8 15:08:32 1998 +++ linux.ac/arch/mips/sni/pci.c Tue Jun 22 01:32:28 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.ac/arch/mips/sni/pcimt_scache.c --- linux.vanilla/arch/mips/sni/pcimt_scache.c Sun Nov 8 15:08:32 1998 +++ linux.ac/arch/mips/sni/pcimt_scache.c Tue Jun 22 01:32:28 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.ac/arch/mips/sni/setup.c --- linux.vanilla/arch/mips/sni/setup.c Sun Nov 8 15:08:32 1998 +++ linux.ac/arch/mips/sni/setup.c Tue Jun 22 01:32:28 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.ac/arch/mips/tools/Makefile --- linux.vanilla/arch/mips/tools/Makefile Sun Nov 8 15:08:32 1998 +++ linux.ac/arch/mips/tools/Makefile Tue Jun 22 01:32:28 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.ac/arch/mips/tools/offset.c --- linux.vanilla/arch/mips/tools/offset.c Sun Nov 8 15:08:32 1998 +++ linux.ac/arch/mips/tools/offset.c Tue Jun 22 01:32:28 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.ac/arch/ppc/amiga/amiints.c --- linux.vanilla/arch/ppc/amiga/amiints.c Sat Jan 9 21:50:36 1999 +++ linux.ac/arch/ppc/amiga/amiints.c Fri Jun 4 23:52:51 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/kernel/pmac_setup.c linux.ac/arch/ppc/kernel/pmac_setup.c --- linux.vanilla/arch/ppc/kernel/pmac_setup.c Thu May 27 22:11:50 1999 +++ linux.ac/arch/ppc/kernel/pmac_setup.c Mon Jun 21 13:15:26 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/syscalls.c linux.ac/arch/ppc/kernel/syscalls.c --- linux.vanilla/arch/ppc/kernel/syscalls.c Tue Jun 15 16:49:47 1999 +++ linux.ac/arch/ppc/kernel/syscalls.c Sat Jun 12 20:10:42 1999 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/defconfig linux.ac/arch/sparc/defconfig --- linux.vanilla/arch/sparc/defconfig Tue Jun 15 16:49:47 1999 +++ linux.ac/arch/sparc/defconfig Wed Jun 30 19:42:48 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/init_task.c linux.ac/arch/sparc/kernel/init_task.c --- linux.vanilla/arch/sparc/kernel/init_task.c Sun Nov 8 15:10:06 1998 +++ linux.ac/arch/sparc/kernel/init_task.c Fri Jun 4 23:52:48 1999 @@ -6,7 +6,6 @@ static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; -static struct file * 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/sparc/mm/init.c linux.ac/arch/sparc/mm/init.c --- linux.vanilla/arch/sparc/mm/init.c Wed Apr 28 19:14:25 1999 +++ linux.ac/arch/sparc/mm/init.c Tue Jun 22 03:35:46 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.ac/arch/sparc64/config.in --- linux.vanilla/arch/sparc64/config.in Wed Apr 28 19:14:25 1999 +++ linux.ac/arch/sparc64/config.in Mon Jun 14 13:48:03 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.ac/arch/sparc64/defconfig --- linux.vanilla/arch/sparc64/defconfig Tue Jun 15 16:49:47 1999 +++ linux.ac/arch/sparc64/defconfig Wed Jun 30 19:42:48 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.ac/arch/sparc64/kernel/binfmt_aout32.c --- linux.vanilla/arch/sparc64/kernel/binfmt_aout32.c Wed Mar 24 10:55:13 1999 +++ linux.ac/arch/sparc64/kernel/binfmt_aout32.c Fri Jun 4 23:52:52 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/init_task.c linux.ac/arch/sparc64/kernel/init_task.c --- linux.vanilla/arch/sparc64/kernel/init_task.c Sun Nov 8 15:08:40 1998 +++ linux.ac/arch/sparc64/kernel/init_task.c Fri Jun 4 23:52:52 1999 @@ -6,7 +6,6 @@ static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; -static struct file * 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/sparc64/kernel/ioctl32.c linux.ac/arch/sparc64/kernel/ioctl32.c --- linux.vanilla/arch/sparc64/kernel/ioctl32.c Tue Jun 15 16:49:47 1999 +++ linux.ac/arch/sparc64/kernel/ioctl32.c Mon Jul 19 03:26:58 1999 @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -1992,11 +1992,24 @@ case BLKRASET: /* 0x09 */ - case REGISTER_DEV: - case REGISTER_DEV_NEW: - case START_MD: - case STOP_MD: - + case RAID_VERSION: + case GET_ARRAY_INFO: + case GET_DISK_INFO: + case CLEAR_ARRAY: + case ADD_NEW_DISK: + case HOT_REMOVE_DISK: + case SET_ARRAY_INFO: + case SET_DISK_INFO: + case WRITE_RAID_INFO: + case UNPROTECT_ARRAY: + case PROTECT_ARRAY: + case HOT_ADD_DISK: + case RUN_ARRAY: + case START_ARRAY: + case STOP_ARRAY: + case STOP_ARRAY_RO: + case RESTART_ARRAY_RW: + /* Big K */ case PIO_FONT: case GIO_FONT: diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/kernel/psycho.c linux.ac/arch/sparc64/kernel/psycho.c --- linux.vanilla/arch/sparc64/kernel/psycho.c Wed Apr 28 19:14:25 1999 +++ linux.ac/arch/sparc64/kernel/psycho.c Fri Jul 2 19:14:38 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.ac/arch/sparc64/kernel/sparc64_ksyms.c --- linux.vanilla/arch/sparc64/kernel/sparc64_ksyms.c Thu May 27 22:11:51 1999 +++ linux.ac/arch/sparc64/kernel/sparc64_ksyms.c Mon Jul 19 03:26:58 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) @@ -83,6 +83,7 @@ extern int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); extern int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg); extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *); +extern void VISenter(void); extern void bcopy (const char *, char *, int); extern int __ashrdi3(int, int); @@ -206,6 +207,7 @@ /* Kernel thread creation. */ EXPORT_SYMBOL(kernel_thread); +EXPORT_SYMBOL(init_mm); /* prom symbols */ EXPORT_SYMBOL(idprom); @@ -297,6 +299,9 @@ * and will always be 'void __ret_efault(void)'. */ EXPORT_SYMBOL_NOVERS(__ret_efault); +/* VISenter is defined in assembly as well. + */ +EXPORT_SYMBOL_NOVERS(VISenter); /* No version information on these, as gcc produces such symbols. */ EXPORT_SYMBOL_NOVERS(memcmp); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/mm/init.c linux.ac/arch/sparc64/mm/init.c --- linux.vanilla/arch/sparc64/mm/init.c Thu May 27 22:11:51 1999 +++ linux.ac/arch/sparc64/mm/init.c Wed Jun 30 19:42:49 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/drivers/Makefile linux.ac/drivers/Makefile --- linux.vanilla/drivers/Makefile Thu May 27 22:11:52 1999 +++ linux.ac/drivers/Makefile Tue Jun 22 01:35:01 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/block/Config.in linux.ac/drivers/block/Config.in --- linux.vanilla/drivers/block/Config.in Thu May 27 22:11:52 1999 +++ linux.ac/drivers/block/Config.in Mon Jul 19 03:26:58 1999 @@ -95,16 +95,23 @@ comment 'Additional Block Devices' +tristate 'Logical volume manager (LVM) support' CONFIG_BLK_DEV_LVM N +if [ "$CONFIG_BLK_DEV_LVM" != "n" ]; then + bool ' LVM information in proc filesystem' CONFIG_LVM_PROC_FS Y +fi tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP if [ "$CONFIG_NET" = "y" ]; then tristate 'Network block device support' CONFIG_BLK_DEV_NBD fi bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then + bool 'Autodetect RAID partitions' CONFIG_AUTODETECT_RAID tristate ' Linear (append) mode' CONFIG_MD_LINEAR tristate ' RAID-0 (striping) mode' CONFIG_MD_STRIPED tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 + tristate ' Translucent mode' CONFIG_MD_TRANSLUCENT + tristate ' Logical Volume Manager support' CONFIG_MD_LVM fi if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_STRIPED" = "y" ]; then bool ' Boot support (linear, striped)' CONFIG_MD_BOOT @@ -128,6 +135,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/Makefile linux.ac/drivers/block/Makefile --- linux.vanilla/drivers/block/Makefile Fri Apr 16 22:10:51 1999 +++ linux.ac/drivers/block/Makefile Mon Jul 19 03:26:57 1999 @@ -234,6 +234,22 @@ endif endif +ifeq ($(CONFIG_BLK_DEV_LVM),y) +L_OBJS += lvm.o +else + ifeq ($(CONFIG_BLK_DEV_LVM),m) + M_OBJS += lvm.o + 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_MD),y) LX_OBJS += md.o @@ -262,10 +278,28 @@ endif ifeq ($(CONFIG_MD_RAID5),y) +LX_OBJS += xor.o L_OBJS += raid5.o else ifeq ($(CONFIG_MD_RAID5),m) + LX_OBJS += xor.o M_OBJS += raid5.o + endif +endif + +ifeq ($(CONFIG_MD_TRANSLUCENT),y) +L_OBJS += translucent.o +else + ifeq ($(CONFIG_MD_TRANSLUCENT),m) + M_OBJS += translucent.o + endif +endif + +ifeq ($(CONFIG_MD_HSM),y) +L_OBJS += hsm.o +else + ifeq ($(CONFIG_MD_HSM),m) + M_OBJS += hsm.o endif endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/README.lvm linux.ac/drivers/block/README.lvm --- linux.vanilla/drivers/block/README.lvm Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/block/README.lvm Wed Jun 16 14:25:39 1999 @@ -0,0 +1,8 @@ + +This is the Logical Volume Manager driver for Linux, + +Tools, library that manage logical volumes can be found +at . + +There you can obtain actual driver versions too. + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/cpqarray.c linux.ac/drivers/block/cpqarray.c --- linux.vanilla/drivers/block/cpqarray.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/block/cpqarray.c Mon Jul 19 03:45:43 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.ac/drivers/block/cpqarray.h --- linux.vanilla/drivers/block/cpqarray.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/block/cpqarray.h Mon Jul 19 05:17:33 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.ac/drivers/block/genhd.c --- linux.vanilla/drivers/block/genhd.c Fri Apr 16 22:10:51 1999 +++ linux.ac/drivers/block/genhd.c Mon Jul 19 03:26:58 1999 @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -81,6 +82,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 +99,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 +113,16 @@ return buf; } } + if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) { + int ctlr = hd->major - COMPAQ_SMART2_MAJOR; + int disk = minor >> hd->minor_shift; + int part = minor & (( 1 << hd->minor_shift) - 1); + if (part == 0) + sprintf(buf, "%s/c%dd%d", maj, ctlr, disk); + else + sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, disk, part); + return buf; + } if (part) sprintf(buf, "%s%c%d", maj, unit, part); else @@ -115,11 +130,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 +160,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 +275,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 +340,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 +387,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 +454,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 +574,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 +642,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 +701,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 +714,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 +733,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 +794,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"); @@ -780,10 +810,8 @@ 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 +869,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"); @@ -923,27 +951,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 +1087,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 +1178,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 +1204,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 +1231,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 +1246,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 +1343,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 +1406,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 @@ -1347,6 +1431,9 @@ #ifdef CONFIG_SCSI scsi_dev_init(); #endif +#ifdef CONFIG_BLK_CPQ_DA + cpqarray_init(); +#endif #ifdef CONFIG_INET net_dev_init(); #endif @@ -1364,6 +1451,9 @@ #endif rd_load(); #endif +#ifdef CONFIG_BLK_DEV_MD + autodetect_raid(); +#endif #ifdef CONFIG_MD_BOOT md_setup_drive(); #endif @@ -1373,7 +1463,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/hsm.c linux.ac/drivers/block/hsm.c --- linux.vanilla/drivers/block/hsm.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/block/hsm.c Mon Jul 19 03:26:58 1999 @@ -0,0 +1,840 @@ +/* + hsm.c : HSM RAID driver for Linux + Copyright (C) 1998 Ingo Molnar + + HSM mode management functions. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + You should have received a copy of the GNU General Public License + (for example /usr/src/linux/COPYING); if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include + +#include +#include + +#include +#include + +#define MAJOR_NR MD_MAJOR +#define MD_DRIVER +#define MD_PERSONALITY + + +#define DEBUG_HSM 1 + +#if DEBUG_HSM +#define dprintk(x,y...) printk(x,##y) +#else +#define dprintk(x,y...) do { } while (0) +#endif + +void print_bh(struct buffer_head *bh) +{ + dprintk("bh %p: %lx %lx %x %x %lx %p %lx %p %x %p %x %lx\n", bh, + bh->b_blocknr, bh->b_size, bh->b_dev, bh->b_rdev, + bh->b_rsector, bh->b_this_page, bh->b_state, + bh->b_next_free, bh->b_count, bh->b_data, + bh->b_list, bh->b_flushtime + ); +} + +static int check_bg (pv_t *pv, pv_block_group_t * bg) +{ + int i, free = 0; + + dprintk("checking bg ...\n"); + + for (i = 0; i < pv->pv_sb->pv_bg_size-1; i++) { + if (pv_pptr_free(bg->blocks + i)) { + free++; + if (test_bit(i, bg->used_bitmap)) { + printk("hm, bit %d set?\n", i); + } + } else { + if (!test_bit(i, bg->used_bitmap)) { + printk("hm, bit %d not set?\n", i); + } + } + } + dprintk("%d free blocks in bg ...\n", free); + return free; +} + +static void get_bg (pv_t *pv, pv_bg_desc_t *desc, int nr) +{ + unsigned int bg_pos = nr * pv->pv_sb->pv_bg_size + 2; + struct buffer_head *bh; + + dprintk("... getting BG at %u ...\n", bg_pos); + + bh = bread (pv->dev, bg_pos, HSM_BLOCKSIZE); + if (!bh) { + MD_BUG(); + return; + } + desc->bg = (pv_block_group_t *) bh->b_data; + desc->free_blocks = check_bg(pv, desc->bg); +} + +static int find_free_block (lv_t *lv, pv_t *pv, pv_bg_desc_t *desc, int nr, + unsigned int lblock, lv_lptr_t * index) +{ + int i; + + for (i = 0; i < pv->pv_sb->pv_bg_size-1; i++) { + pv_pptr_t * bptr = desc->bg->blocks + i; + if (pv_pptr_free(bptr)) { + unsigned int bg_pos = nr * pv->pv_sb->pv_bg_size + 2; + + if (test_bit(i, desc->bg->used_bitmap)) { + MD_BUG(); + continue; + } + bptr->u.used.owner.log_id = lv->log_id; + bptr->u.used.owner.log_index = lblock; + index->data.phys_nr = pv->phys_nr; + index->data.phys_block = bg_pos + i + 1; + set_bit(i, desc->bg->used_bitmap); + desc->free_blocks--; + dprintk(".....free blocks left in bg %p: %d\n", + desc->bg, desc->free_blocks); + return 0; + } + } + return -ENOSPC; +} + +static int __get_free_block (lv_t *lv, pv_t *pv, + unsigned int lblock, lv_lptr_t * index) +{ + int i; + + dprintk("trying to get free block for lblock %d ...\n", lblock); + + for (i = 0; i < pv->pv_sb->pv_block_groups; i++) { + pv_bg_desc_t *desc = pv->bg_array + i; + + dprintk("looking at desc #%d (%p)...\n", i, desc->bg); + if (!desc->bg) + get_bg(pv, desc, i); + + if (desc->bg && desc->free_blocks) + return find_free_block(lv, pv, desc, i, + lblock, index); + } + dprintk("hsm: pv %s full!\n", partition_name(pv->dev)); + return -ENOSPC; +} + +static int get_free_block (lv_t *lv, unsigned int lblock, lv_lptr_t * index) +{ + int err; + + if (!lv->free_indices) + return -ENOSPC; + + /* fix me */ + err = __get_free_block(lv, lv->vg->pv_array + 0, lblock, index); + + if (err || !index->data.phys_block) { + MD_BUG(); + return -ENOSPC; + } + + lv->free_indices--; + + return 0; +} + +/* + * fix me: wordsize assumptions ... + */ +#define INDEX_BITS 8 +#define INDEX_DEPTH (32/INDEX_BITS) +#define INDEX_MASK ((1< [.", index->data.phys_nr, + index->data.phys_block, index->cpu_addr); + + tmp = index_child(index); + for (i = 0; i < HSM_LPTRS_PER_BLOCK; i++) { + if (index_block(lv, tmp)) + dprintk("(%d->%d)", i, index_block(lv, tmp)); + tmp++; + } + dprintk(".]\n"); +} + +static int read_index_group (lv_t *lv, lv_lptr_t *index) +{ + lv_lptr_t *index_group, *tmp; + struct buffer_head *bh; + int i; + + dprintk("reading index group <%s:%d>\n", + partition_name(index_dev(lv, index)), index_block(lv, index)); + + bh = bread(index_dev(lv, index), index_block(lv, index), HSM_BLOCKSIZE); + if (!bh) { + MD_BUG(); + return -EIO; + } + if (!buffer_uptodate(bh)) + MD_BUG(); + + index_group = (lv_lptr_t *) bh->b_data; + tmp = index_group; + for (i = 0; i < HSM_LPTRS_PER_BLOCK; i++) { + if (index_block(lv, tmp)) { + dprintk("index group has BLOCK %d, non-present.\n", i); + tmp->cpu_addr = 0; + } + tmp++; + } + index->cpu_addr = ptr_to_cpuaddr(index_group); + + dprintk("have read index group %p at block %d.\n", + index_group, index_block(lv, index)); + print_index_list(lv, index); + + return 0; +} + +static int alloc_index_group (lv_t *lv, unsigned int lblock, lv_lptr_t * index) +{ + struct buffer_head *bh; + lv_lptr_t * index_group; + + if (get_free_block(lv, lblock, index)) + return -ENOSPC; + + dprintk("creating block for index group <%s:%d>\n", + partition_name(index_dev(lv, index)), index_block(lv, index)); + + bh = getblk(index_dev(lv, index), + index_block(lv, index), HSM_BLOCKSIZE); + + index_group = (lv_lptr_t *) bh->b_data; + md_clear_page(index_group); + mark_buffer_uptodate(bh, 1); + + index->cpu_addr = ptr_to_cpuaddr(index_group); + + dprintk("allocated index group %p at block %d.\n", + index_group, index_block(lv, index)); + return 0; +} + +static lv_lptr_t * alloc_fixed_index (lv_t *lv, unsigned int lblock) +{ + lv_lptr_t * index = index_child(&lv->root_index); + int idx, l; + + for (l = INDEX_DEPTH-1; l >= 0; l--) { + idx = (lblock >> (INDEX_BITS*l)) & INDEX_MASK; + index += idx; + if (!l) + break; + if (!index_present(index)) { + dprintk("no group, level %u, pos %u\n", l, idx); + if (alloc_index_group(lv, lblock, index)) + return NULL; + } + index = index_child(index); + } + if (!index_block(lv,index)) { + dprintk("no data, pos %u\n", idx); + if (get_free_block(lv, lblock, index)) + return NULL; + return index; + } + MD_BUG(); + return index; +} + +static lv_lptr_t * find_index (lv_t *lv, unsigned int lblock) +{ + lv_lptr_t * index = index_child(&lv->root_index); + int idx, l; + + for (l = INDEX_DEPTH-1; l >= 0; l--) { + idx = (lblock >> (INDEX_BITS*l)) & INDEX_MASK; + index += idx; + if (!l) + break; + if (index_free(index)) + return NULL; + if (!index_present(index)) + read_index_group(lv, index); + if (!index_present(index)) { + MD_BUG(); + return NULL; + } + index = index_child(index); + } + if (!index_block(lv,index)) + return NULL; + return index; +} + +static int read_root_index(lv_t *lv) +{ + int err; + lv_lptr_t *index = &lv->root_index; + + if (!index_block(lv, index)) { + printk("LV has no root index yet, creating.\n"); + + err = alloc_index_group (lv, 0, index); + if (err) { + printk("could not create index group, err:%d\n", err); + return err; + } + lv->vg->vg_sb->lv_array[lv->log_id].lv_root_idx = + lv->root_index.data; + } else { + printk("LV already has a root index.\n"); + printk("... at <%s:%d>.\n", + partition_name(index_dev(lv, index)), + index_block(lv, index)); + + read_index_group(lv, index); + } + return 0; +} + +static int init_pv(pv_t *pv) +{ + struct buffer_head *bh; + pv_sb_t *pv_sb; + + bh = bread (pv->dev, 0, HSM_BLOCKSIZE); + if (!bh) { + MD_BUG(); + return -1; + } + + pv_sb = (pv_sb_t *) bh->b_data; + pv->pv_sb = pv_sb; + + if (pv_sb->pv_magic != HSM_PV_SB_MAGIC) { + printk("%s is not a PV, has magic %x instead of %x!\n", + partition_name(pv->dev), pv_sb->pv_magic, + HSM_PV_SB_MAGIC); + return -1; + } + printk("%s detected as a valid PV (#%d).\n", partition_name(pv->dev), + pv->phys_nr); + printk("... created under HSM version %d.%d.%d, at %x.\n", + pv_sb->pv_major, pv_sb->pv_minor, pv_sb->pv_patch, pv_sb->pv_ctime); + printk("... total # of blocks: %d (%d left unallocated).\n", + pv_sb->pv_total_size, pv_sb->pv_blocks_left); + + printk("... block size: %d bytes.\n", pv_sb->pv_block_size); + printk("... block descriptor size: %d bytes.\n", pv_sb->pv_pptr_size); + printk("... block group size: %d blocks.\n", pv_sb->pv_bg_size); + printk("... # of block groups: %d.\n", pv_sb->pv_block_groups); + + if (pv_sb->pv_block_groups*sizeof(pv_bg_desc_t) > PAGE_SIZE) { + MD_BUG(); + return 1; + } + pv->bg_array = (pv_bg_desc_t *)__get_free_page(GFP_KERNEL); + if (!pv->bg_array) { + MD_BUG(); + return 1; + } + memset(pv->bg_array, 0, PAGE_SIZE); + + return 0; +} + +static int free_pv(pv_t *pv) +{ + struct buffer_head *bh; + + dprintk("freeing PV %d ...\n", pv->phys_nr); + + if (pv->bg_array) { + int i; + + dprintk(".... freeing BGs ...\n"); + for (i = 0; i < pv->pv_sb->pv_block_groups; i++) { + unsigned int bg_pos = i * pv->pv_sb->pv_bg_size + 2; + pv_bg_desc_t *desc = pv->bg_array + i; + + if (desc->bg) { + dprintk(".... freeing BG %d ...\n", i); + bh = getblk (pv->dev, bg_pos, HSM_BLOCKSIZE); + mark_buffer_dirty(bh, 1); + brelse(bh); + brelse(bh); + } + } + free_page((unsigned long)pv->bg_array); + } else + MD_BUG(); + + bh = getblk (pv->dev, 0, HSM_BLOCKSIZE); + if (!bh) { + MD_BUG(); + return -1; + } + mark_buffer_dirty(bh, 1); + brelse(bh); + brelse(bh); + + return 0; +} + +struct semaphore hsm_sem = MUTEX; + +#define HSM_SECTORS (HSM_BLOCKSIZE/512) + +static int hsm_map (mddev_t *mddev, kdev_t dev, kdev_t *rdev, + unsigned long *rsector, unsigned long bsectors) +{ + lv_t *lv = kdev_to_lv(dev); + lv_lptr_t *index; + unsigned int lblock = *rsector / HSM_SECTORS; + unsigned int offset = *rsector % HSM_SECTORS; + int err = -EIO; + + if (!lv) { + printk("HSM: md%d not a Logical Volume!\n", mdidx(mddev)); + goto out; + } + if (offset + bsectors > HSM_SECTORS) { + MD_BUG(); + goto out; + } + down(&hsm_sem); + index = find_index(lv, lblock); + if (!index) { + printk("no block %u yet ... allocating\n", lblock); + index = alloc_fixed_index(lv, lblock); + } + + err = 0; + + printk(" %u <%s : %ld(%ld)> -> ", lblock, + partition_name(*rdev), *rsector, bsectors); + + *rdev = index_dev(lv, index); + *rsector = index_block(lv, index) * HSM_SECTORS + offset; + + printk(" <%s : %ld> %u\n", + partition_name(*rdev), *rsector, index_block(lv, index)); + + up(&hsm_sem); +out: + return err; +} + +static void free_index (lv_t *lv, lv_lptr_t * index) +{ + struct buffer_head *bh; + + printk("tryin to get cached block for index group <%s:%d>\n", + partition_name(index_dev(lv, index)), index_block(lv, index)); + + bh = getblk(index_dev(lv, index), index_block(lv, index),HSM_BLOCKSIZE); + + printk("....FREEING "); + print_index_list(lv, index); + + if (bh) { + if (!buffer_uptodate(bh)) + MD_BUG(); + if ((lv_lptr_t *)bh->b_data != index_child(index)) { + printk("huh? b_data is %p, index content is %p.\n", + bh->b_data, index_child(index)); + } else + printk("good, b_data == index content == %p.\n", + index_child(index)); + printk("b_count == %d, writing.\n", bh->b_count); + mark_buffer_dirty(bh, 1); + brelse(bh); + brelse(bh); + printk("done.\n"); + } else { + printk("FAILED!\n"); + } + print_index_list(lv, index); + index_child(index) = NULL; +} + +static void free_index_group (lv_t *lv, int level, lv_lptr_t * index_0) +{ + char dots [3*8]; + lv_lptr_t * index; + int i, nr_dots; + + nr_dots = (INDEX_DEPTH-level)*3; + memcpy(dots,"...............",nr_dots); + dots[nr_dots] = 0; + + dprintk("%s level %d index group block:\n", dots, level); + + + index = index_0; + for (i = 0; i < HSM_LPTRS_PER_BLOCK; i++) { + if (index->data.phys_block) { + dprintk("%s block <%u,%u,%x>\n", dots, + index->data.phys_nr, + index->data.phys_block, + index->cpu_addr); + if (level && index_present(index)) { + dprintk("%s==> deeper one level\n", dots); + free_index_group(lv, level-1, + index_child(index)); + dprintk("%s freeing index group block %p ...", + dots, index_child(index)); + free_index(lv, index); + } + } + index++; + } + dprintk("%s DONE: level %d index group block.\n", dots, level); +} + +static void free_lv_indextree (lv_t *lv) +{ + dprintk("freeing LV %d ...\n", lv->log_id); + dprintk("..root index: %p\n", index_child(&lv->root_index)); + dprintk("..INDEX TREE:\n"); + free_index_group(lv, INDEX_DEPTH-1, index_child(&lv->root_index)); + dprintk("..freeing root index %p ...", index_child(&lv->root_index)); + dprintk("root block <%u,%u,%x>\n", lv->root_index.data.phys_nr, + lv->root_index.data.phys_block, lv->root_index.cpu_addr); + free_index(lv, &lv->root_index); + dprintk("..INDEX TREE done.\n"); + fsync_dev(lv->vg->pv_array[0].dev); /* fix me */ + lv->vg->vg_sb->lv_array[lv->log_id].lv_free_indices = lv->free_indices; +} + +static void print_index_group (lv_t *lv, int level, lv_lptr_t * index_0) +{ + char dots [3*5]; + lv_lptr_t * index; + int i, nr_dots; + + nr_dots = (INDEX_DEPTH-level)*3; + memcpy(dots,"...............",nr_dots); + dots[nr_dots] = 0; + + dprintk("%s level %d index group block:\n", dots, level); + + + for (i = 0; i < HSM_LPTRS_PER_BLOCK; i++) { + index = index_0 + i; + if (index->data.phys_block) { + dprintk("%s block <%u,%u,%x>\n", dots, + index->data.phys_nr, + index->data.phys_block, + index->cpu_addr); + if (level && index_present(index)) { + dprintk("%s==> deeper one level\n", dots); + print_index_group(lv, level-1, + index_child(index)); + } + } + } + dprintk("%s DONE: level %d index group block.\n", dots, level); +} + +static void print_lv (lv_t *lv) +{ + dprintk("printing LV %d ...\n", lv->log_id); + dprintk("..root index: %p\n", index_child(&lv->root_index)); + dprintk("..INDEX TREE:\n"); + print_index_group(lv, INDEX_DEPTH-1, index_child(&lv->root_index)); + dprintk("..INDEX TREE done.\n"); +} + +static int map_lv (lv_t *lv) +{ + kdev_t dev = lv->dev; + unsigned int nr = MINOR(dev); + mddev_t *mddev = lv->vg->mddev; + + if (MAJOR(dev) != MD_MAJOR) { + MD_BUG(); + return -1; + } + if (kdev_to_mddev(dev)) { + MD_BUG(); + return -1; + } + md_hd_struct[nr].start_sect = 0; + md_hd_struct[nr].nr_sects = md_size[mdidx(mddev)] << 1; + md_size[nr] = md_size[mdidx(mddev)]; + add_mddev_mapping(mddev, dev, lv); + + return 0; +} + +static int unmap_lv (lv_t *lv) +{ + kdev_t dev = lv->dev; + unsigned int nr = MINOR(dev); + + if (MAJOR(dev) != MD_MAJOR) { + MD_BUG(); + return -1; + } + md_hd_struct[nr].start_sect = 0; + md_hd_struct[nr].nr_sects = 0; + md_size[nr] = 0; + del_mddev_mapping(lv->vg->mddev, dev); + + return 0; +} + +static int init_vg (vg_t *vg) +{ + int i; + lv_t *lv; + kdev_t dev; + vg_sb_t *vg_sb; + struct buffer_head *bh; + lv_descriptor_t *lv_desc; + + /* + * fix me: read all PVs and compare the SB + */ + dev = vg->pv_array[0].dev; + bh = bread (dev, 1, HSM_BLOCKSIZE); + if (!bh) { + MD_BUG(); + return -1; + } + + vg_sb = (vg_sb_t *) bh->b_data; + vg->vg_sb = vg_sb; + + if (vg_sb->vg_magic != HSM_VG_SB_MAGIC) { + printk("%s is not a valid VG, has magic %x instead of %x!\n", + partition_name(dev), vg_sb->vg_magic, + HSM_VG_SB_MAGIC); + return -1; + } + + vg->nr_lv = 0; + for (i = 0; i < HSM_MAX_LVS_PER_VG; i++) { + unsigned int id; + lv_desc = vg->vg_sb->lv_array + i; + + id = lv_desc->lv_id; + if (!id) { + printk("... LV desc %d empty\n", i); + continue; + } + if (id >= HSM_MAX_LVS_PER_VG) { + MD_BUG(); + continue; + } + + lv = vg->lv_array + id; + if (lv->vg) { + MD_BUG(); + continue; + } + lv->log_id = id; + lv->vg = vg; + lv->max_indices = lv_desc->lv_max_indices; + lv->free_indices = lv_desc->lv_free_indices; + lv->root_index.data = lv_desc->lv_root_idx; + lv->dev = MKDEV(MD_MAJOR, lv_desc->md_id); + + vg->nr_lv++; + + map_lv(lv); + if (read_root_index(lv)) { + vg->nr_lv--; + unmap_lv(lv); + memset(lv, 0, sizeof(*lv)); + } + } + if (vg->nr_lv != vg_sb->nr_lvs) + MD_BUG(); + + return 0; +} + +static int hsm_run (mddev_t *mddev) +{ + int i; + vg_t *vg; + mdk_rdev_t *rdev; + + MOD_INC_USE_COUNT; + + vg = kmalloc (sizeof (*vg), GFP_KERNEL); + if (!vg) + goto out; + memset(vg, 0, sizeof(*vg)); + mddev->private = vg; + vg->mddev = mddev; + + if (md_check_ordering(mddev)) { + printk("hsm: disks are not ordered, aborting!\n"); + goto out; + } + + set_blocksize (mddev_to_kdev(mddev), HSM_BLOCKSIZE); + + vg->nr_pv = mddev->nb_dev; + ITERATE_RDEV_ORDERED(mddev,rdev,i) { + pv_t *pv = vg->pv_array + i; + + pv->dev = rdev->dev; + fsync_dev (pv->dev); + set_blocksize (pv->dev, HSM_BLOCKSIZE); + pv->phys_nr = i; + if (init_pv(pv)) + goto out; + } + + init_vg(vg); + + return 0; + +out: + if (vg) { + kfree(vg); + mddev->private = NULL; + } + MOD_DEC_USE_COUNT; + + return 1; +} + +static int hsm_stop (mddev_t *mddev) +{ + lv_t *lv; + vg_t *vg; + int i; + + vg = mddev_to_vg(mddev); + + for (i = 0; i < HSM_MAX_LVS_PER_VG; i++) { + lv = vg->lv_array + i; + if (!lv->log_id) + continue; + print_lv(lv); + free_lv_indextree(lv); + unmap_lv(lv); + } + for (i = 0; i < vg->nr_pv; i++) + free_pv(vg->pv_array + i); + + kfree(vg); + + MOD_DEC_USE_COUNT; + + return 0; +} + + +static int hsm_status (char *page, mddev_t *mddev) +{ + int sz = 0, i; + lv_t *lv; + vg_t *vg; + + vg = mddev_to_vg(mddev); + + for (i = 0; i < HSM_MAX_LVS_PER_VG; i++) { + lv = vg->lv_array + i; + if (!lv->log_id) + continue; + sz += sprintf(page+sz, " ", lv->log_id, + lv->max_indices - lv->free_indices, lv->max_indices); + } + return sz; +} + + +static mdk_personality_t hsm_personality= +{ + "hsm", + hsm_map, + NULL, + NULL, + hsm_run, + hsm_stop, + hsm_status, + NULL, + 0, + NULL, + NULL, + NULL, + NULL +}; + +#ifndef MODULE + +md__initfunc(void hsm_init (void)) +{ + register_md_personality (HSM, &hsm_personality); +} + +#else + +int init_module (void) +{ + return (register_md_personality (HSM, &hsm_personality)); +} + +void cleanup_module (void) +{ + unregister_md_personality (HSM); +} + +#endif + +/* + * This Linus-trick catches bugs via the linker. + */ + +extern void __BUG__in__hsm_dot_c_1(void); +extern void __BUG__in__hsm_dot_c_2(void); +extern void __BUG__in__hsm_dot_c_3(void); +extern void __BUG__in__hsm_dot_c_4(void); +extern void __BUG__in__hsm_dot_c_5(void); +extern void __BUG__in__hsm_dot_c_6(void); +extern void __BUG__in__hsm_dot_c_7(void); + +void bugcatcher (void) +{ + if (sizeof(pv_block_group_t) != HSM_BLOCKSIZE) + __BUG__in__hsm_dot_c_1(); + if (sizeof(lv_index_block_t) != HSM_BLOCKSIZE) + __BUG__in__hsm_dot_c_2(); + + if (sizeof(pv_sb_t) != HSM_BLOCKSIZE) + __BUG__in__hsm_dot_c_4(); + if (sizeof(lv_sb_t) != HSM_BLOCKSIZE) + __BUG__in__hsm_dot_c_3(); + if (sizeof(vg_sb_t) != HSM_BLOCKSIZE) + __BUG__in__hsm_dot_c_6(); + + if (sizeof(lv_lptr_t) != 16) + __BUG__in__hsm_dot_c_5(); + if (sizeof(pv_pptr_t) != 16) + __BUG__in__hsm_dot_c_6(); +} + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ida_cmd.h linux.ac/drivers/block/ida_cmd.h --- linux.vanilla/drivers/block/ida_cmd.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/block/ida_cmd.h Mon Jul 19 05:17:33 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.ac/drivers/block/ida_ioctl.h --- linux.vanilla/drivers/block/ida_ioctl.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/block/ida_ioctl.h Mon Jul 19 05:17:33 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.ac/drivers/block/ide-cd.c --- linux.vanilla/drivers/block/ide-cd.c Fri Apr 16 22:10:51 1999 +++ linux.ac/drivers/block/ide-cd.c Mon Jul 19 03:24:24 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.ac/drivers/block/ide-floppy.c --- linux.vanilla/drivers/block/ide-floppy.c Mon Dec 28 23:09:41 1998 +++ linux.ac/drivers/block/ide-floppy.c Mon Jul 5 05:01:32 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.ac/drivers/block/ide-tape.c --- linux.vanilla/drivers/block/ide-tape.c Sat Jan 9 21:50:36 1999 +++ linux.ac/drivers/block/ide-tape.c Mon Jul 5 05:01:32 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.ac/drivers/block/ide.c --- linux.vanilla/drivers/block/ide.c Tue Jun 15 16:49:48 1999 +++ linux.ac/drivers/block/ide.c Mon Jul 19 03:26:58 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/linear.c linux.ac/drivers/block/linear.c --- linux.vanilla/drivers/block/linear.c Sun Nov 8 15:07:37 1998 +++ linux.ac/drivers/block/linear.c Mon Jul 19 03:26:58 1999 @@ -1,4 +1,3 @@ - /* linear.c : Multiple Devices driver for Linux Copyright (C) 1994-96 Marc ZYNGIER @@ -19,186 +18,207 @@ #include -#include +#include #include -#include -#include "linear.h" +#include #define MAJOR_NR MD_MAJOR #define MD_DRIVER #define MD_PERSONALITY -static int linear_run (int minor, struct md_dev *mddev) +static int linear_run (mddev_t *mddev) { - int cur=0, i, size, dev0_size, nb_zone; - struct linear_data *data; - - MOD_INC_USE_COUNT; - - mddev->private=kmalloc (sizeof (struct linear_data), GFP_KERNEL); - data=(struct linear_data *) mddev->private; - - /* - Find out the smallest device. This was previously done - at registry time, but since it violates modularity, - I moved it here... Any comment ? ;-) - */ - - data->smallest=mddev->devices; - for (i=1; inb_dev; i++) - if (data->smallest->size > mddev->devices[i].size) - data->smallest=mddev->devices+i; - - nb_zone=data->nr_zones= - md_size[minor]/data->smallest->size + - (md_size[minor]%data->smallest->size ? 1 : 0); - - data->hash_table=kmalloc (sizeof (struct linear_hash)*nb_zone, GFP_KERNEL); - - size=mddev->devices[cur].size; + linear_conf_t *conf; + struct linear_hash *table; + mdk_rdev_t *rdev; + int size, i, j, nb_zone; + unsigned int curr_offset; + + MOD_INC_USE_COUNT; + + conf = kmalloc (sizeof (*conf), GFP_KERNEL); + if (!conf) + goto out; + mddev->private = conf; + + if (md_check_ordering(mddev)) { + printk("linear: disks are not ordered, aborting!\n"); + goto out; + } + /* + * Find the smallest device. + */ + + conf->smallest = NULL; + curr_offset = 0; + ITERATE_RDEV_ORDERED(mddev,rdev,j) { + dev_info_t *disk = conf->disks + j; + + disk->dev = rdev->dev; + disk->size = rdev->size; + disk->offset = curr_offset; + + curr_offset += disk->size; + + if (!conf->smallest || (disk->size < conf->smallest->size)) + conf->smallest = disk; + } + + nb_zone = conf->nr_zones = + md_size[mdidx(mddev)] / conf->smallest->size + + ((md_size[mdidx(mddev)] % conf->smallest->size) ? 1 : 0); + + conf->hash_table = kmalloc (sizeof (struct linear_hash) * nb_zone, + GFP_KERNEL); + if (!conf->hash_table) + goto out; + + /* + * Here we generate the linear hash table + */ + table = conf->hash_table; + i = 0; + size = 0; + for (j = 0; j < mddev->nb_dev; j++) { + dev_info_t *disk = conf->disks + j; + + if (size < 0) { + table->dev1 = disk; + table++; + } + size += disk->size; + + while (size) { + table->dev0 = disk; + size -= conf->smallest->size; + if (size < 0) + break; + table->dev1 = NULL; + table++; + } + } + table->dev1 = NULL; + + return 0; + +out: + if (conf) + kfree(conf); + MOD_DEC_USE_COUNT; + return 1; +} + +static int linear_stop (mddev_t *mddev) +{ + linear_conf_t *conf = mddev_to_conf(mddev); + + kfree(conf->hash_table); + kfree(conf); - i=0; - while (curnb_dev) - { - data->hash_table[i].dev0=mddev->devices+cur; + MOD_DEC_USE_COUNT; - if (size>=data->smallest->size) /* If we completely fill the slot */ - { - data->hash_table[i++].dev1=NULL; - size-=data->smallest->size; - - if (!size) - { - if (++cur==mddev->nb_dev) continue; - size=mddev->devices[cur].size; - } - - continue; - } - - if (++cur==mddev->nb_dev) /* Last dev, set dev1 as NULL */ - { - data->hash_table[i].dev1=NULL; - continue; - } - - dev0_size=size; /* Here, we use a 2nd dev to fill the slot */ - size=mddev->devices[cur].size; - data->hash_table[i++].dev1=mddev->devices+cur; - size-=(data->smallest->size - dev0_size); - } - - return 0; -} - -static int linear_stop (int minor, struct md_dev *mddev) -{ - struct linear_data *data=(struct linear_data *) mddev->private; - - kfree (data->hash_table); - kfree (data); - - MOD_DEC_USE_COUNT; - - return 0; + return 0; } -static int linear_map (struct md_dev *mddev, kdev_t *rdev, +static int linear_map (mddev_t *mddev, kdev_t dev, kdev_t *rdev, unsigned long *rsector, unsigned long size) { - struct linear_data *data=(struct linear_data *) mddev->private; - struct linear_hash *hash; - struct real_dev *tmp_dev; - long block; - - block=*rsector >> 1; - hash=data->hash_table+(block/data->smallest->size); - - if (block >= (hash->dev0->size + hash->dev0->offset)) - { - if (!hash->dev1) - { - printk ("linear_map : hash->dev1==NULL for block %ld\n", block); - return (-1); - } - - tmp_dev=hash->dev1; - } - else - tmp_dev=hash->dev0; + linear_conf_t *conf = mddev_to_conf(mddev); + struct linear_hash *hash; + dev_info_t *tmp_dev; + long block; + + block = *rsector >> 1; + hash = conf->hash_table + (block / conf->smallest->size); + + if (block >= (hash->dev0->size + hash->dev0->offset)) + { + if (!hash->dev1) + { + printk ("linear_map : hash->dev1==NULL for block %ld\n", + block); + return -1; + } + tmp_dev = hash->dev1; + } else + tmp_dev = hash->dev0; - if (block >= (tmp_dev->size + tmp_dev->offset) || block < tmp_dev->offset) - printk ("Block %ld out of bounds on dev %s size %d offset %d\n", - block, kdevname(tmp_dev->dev), tmp_dev->size, tmp_dev->offset); + if (block >= (tmp_dev->size + tmp_dev->offset) + || block < tmp_dev->offset) + printk ("Block %ld out of bounds on dev %s size %d offset %d\n", + block, kdevname(tmp_dev->dev), tmp_dev->size, tmp_dev->offset); - *rdev=tmp_dev->dev; - *rsector=(block-(tmp_dev->offset)) << 1; + *rdev = tmp_dev->dev; + *rsector = (block - tmp_dev->offset) << 1; - return (0); + return 0; } -static int linear_status (char *page, int minor, struct md_dev *mddev) +static int linear_status (char *page, mddev_t *mddev) { - int sz=0; + int sz=0; #undef MD_DEBUG #ifdef MD_DEBUG - int j; - struct linear_data *data=(struct linear_data *) mddev->private; + int j; + linear_conf_t *conf = mddev_to_conf(mddev); - sz+=sprintf (page+sz, " "); - for (j=0; jnr_zones; j++) - { - sz+=sprintf (page+sz, "[%s", - partition_name (data->hash_table[j].dev0->dev)); - - if (data->hash_table[j].dev1) - sz+=sprintf (page+sz, "/%s] ", - partition_name(data->hash_table[j].dev1->dev)); - else - sz+=sprintf (page+sz, "] "); - } - - sz+=sprintf (page+sz, "\n"); + sz += sprintf(page+sz, " "); + for (j = 0; j < conf->nr_zones; j++) + { + sz += sprintf(page+sz, "[%s", + partition_name(conf->hash_table[j].dev0->dev)); + + if (conf->hash_table[j].dev1) + sz += sprintf(page+sz, "/%s] ", + partition_name(conf->hash_table[j].dev1->dev)); + else + sz += sprintf(page+sz, "] "); + } + sz += sprintf(page+sz, "\n"); #endif - sz+=sprintf (page+sz, " %dk rounding", 1<param.chunk_size/1024); + return sz; } -static struct md_personality linear_personality= +static mdk_personality_t linear_personality= { - "linear", - linear_map, - NULL, - NULL, - linear_run, - linear_stop, - linear_status, - NULL, /* no ioctls */ - 0 + "linear", + linear_map, + NULL, + NULL, + linear_run, + linear_stop, + linear_status, + NULL, + 0, + NULL, + NULL, + NULL, + NULL }; - #ifndef MODULE -__initfunc(void linear_init (void)) +md__initfunc(void linear_init (void)) { - register_md_personality (LINEAR, &linear_personality); + register_md_personality (LINEAR, &linear_personality); } #else int init_module (void) { - return (register_md_personality (LINEAR, &linear_personality)); + return (register_md_personality (LINEAR, &linear_personality)); } void cleanup_module (void) { - unregister_md_personality (LINEAR); + unregister_md_personality (LINEAR); } #endif + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/linear.h linux.ac/drivers/block/linear.h --- linux.vanilla/drivers/block/linear.h Sun Nov 8 15:07:37 1998 +++ linux.ac/drivers/block/linear.h Mon Jul 19 03:26:58 1999 @@ -1,16 +0,0 @@ -#ifndef _LINEAR_H -#define _LINEAR_H - -struct linear_hash -{ - struct real_dev *dev0, *dev1; -}; - -struct linear_data -{ - struct linear_hash *hash_table; /* Dynamically allocated */ - struct real_dev *smallest; - int nr_zones; -}; - -#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ll_rw_blk.c linux.ac/drivers/block/ll_rw_blk.c --- linux.vanilla/drivers/block/ll_rw_blk.c Wed Mar 24 10:55:15 1999 +++ linux.ac/drivers/block/ll_rw_blk.c Mon Jul 19 03:56:19 1999 @@ -21,9 +21,16 @@ #include #include #include +#include #include +#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) +#include + int ( *lvm_map_ptr) ( int, kdev_t *, unsigned long *, + unsigned long, int) = NULL; +#endif + /* * The request-struct contains all necessary data * to load a nr of sectors into memory @@ -51,6 +58,11 @@ spinlock_t io_request_lock = SPIN_LOCK_UNLOCKED; /* + * per-major idle-IO detection + */ +unsigned long io_events[MAX_BLKDEV] = {0, }; + +/* * used to wait on when there are no free requests */ struct wait_queue * wait_for_request = NULL; @@ -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) { @@ -348,6 +360,9 @@ /* for SCSI devices, call request_fn unconditionally */ if (scsi_blk_major(MAJOR(req->rq_dev))) queue_new_request = 1; + if (MAJOR(req->rq_dev) >= COMPAQ_SMART2_MAJOR+0 && + MAJOR(req->rq_dev) <= COMPAQ_SMART2_MAJOR+7) + queue_new_request = 1; out: if (queue_new_request) (dev->request_fn)(); @@ -375,7 +390,7 @@ 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; @@ -391,21 +406,28 @@ /* Maybe the above fixes it, and maybe it doesn't boot. Life is interesting */ lock_buffer(bh); + if (!buffer_lowprio(bh)) + io_events[major]++; if (blk_size[major]) { unsigned long maxsector = (blk_size[major][MINOR(bh->b_rdev)] << 1) + 1; 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 +459,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; @@ -461,7 +483,8 @@ if (!req) { /* MD and loop can't handle plugging without deadlocking */ if (major != MD_MAJOR && major != LOOP_MAJOR && - major != DDV_MAJOR && major != NBD_MAJOR) + major != DDV_MAJOR && major != NBD_MAJOR && + major != LVM_BLK_MAJOR) plug_device(blk_dev + major); /* is atomic */ } else switch (major) { case IDE0_MAJOR: /* same as HD_MAJOR */ @@ -483,7 +506,7 @@ * entry may be busy being processed and we thus can't change it. */ if (req == blk_dev[major].current_request) - req = req->next; + req = req->next; if (!req) break; /* fall through */ @@ -497,6 +520,14 @@ case SCSI_DISK6_MAJOR: case SCSI_DISK7_MAJOR: case SCSI_CDROM_MAJOR: + 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) @@ -611,13 +642,37 @@ /* Md remaps blocks now */ bh[i]->b_rdev = bh[i]->b_dev; bh[i]->b_rsector=bh[i]->b_blocknr*(bh[i]->b_size >> 9); +#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) + major = MAJOR(bh[i]->b_dev); + if ( major == LVM_BLK_MAJOR) { + int ret; + + if ( lvm_map_ptr == NULL) { + printk ( KERN_ERR + "Bad lvm_map_ptr in ll_rw_block\n"); + goto sorry; + } + if ( ( ret = ( lvm_map_ptr) ( MINOR ( bh[i]->b_dev), + &bh[i]->b_rdev, + &bh[i]->b_rsector, + bh[i]->b_size >> 9, + rw)) != 0) { + printk ( KERN_ERR + "Bad lvm_map in ll_rw_block\n"); + goto sorry; + } + /* remap major too ... */ + major = MAJOR(bh[i]->b_rdev); + } +#endif #ifdef CONFIG_BLK_DEV_MD if (major==MD_MAJOR && - md_map (MINOR(bh[i]->b_dev), &bh[i]->b_rdev, - &bh[i]->b_rsector, bh[i]->b_size >> 9)) { - printk (KERN_ERR + /* changed v to allow LVM to remap */ + md_map (bh[i]->b_rdev, &bh[i]->b_rdev, + &bh[i]->b_rsector, bh[i]->b_size >> 9)) { + printk (KERN_ERR "Bad md_map in ll_rw_block\n"); - goto sorry; + goto sorry; } #endif } @@ -632,8 +687,10 @@ if (bh[i]) { set_bit(BH_Req, &bh[i]->b_state); #ifdef CONFIG_BLK_DEV_MD - if (MAJOR(bh[i]->b_dev) == MD_MAJOR) { - md_make_request(MINOR (bh[i]->b_dev), rw, bh[i]); + /* changed v to allow LVM to remap */ + if (MAJOR(bh[i]->b_rdev) == MD_MAJOR) { + /* changed for LVM to remap v */ + md_make_request(bh[i], rw); continue; } #endif @@ -716,10 +773,10 @@ for (dev = blk_dev + MAX_BLKDEV; dev-- != blk_dev;) { dev->request_fn = NULL; - dev->queue = NULL; + dev->queue = NULL; dev->current_request = NULL; dev->plug.rq_status = RQ_INACTIVE; - dev->plug.cmd = -1; + dev->plug.cmd = -1; dev->plug.next = NULL; dev->plug_tq.sync = 0; dev->plug_tq.routine = &unplug_device; @@ -800,7 +857,7 @@ sbpcd_init(); #endif CONFIG_SBPCD #ifdef CONFIG_AZTCD - aztcd_init(); + aztcd_init(); #endif CONFIG_AZTCD #ifdef CONFIG_CDU535 sony535_init(); @@ -817,6 +874,9 @@ #ifdef CONFIG_SJCD sjcd_init(); #endif CONFIG_SJCD +#ifdef CONFIG_BLK_DEV_LVM + lvm_init(); +#endif #ifdef CONFIG_BLK_DEV_MD md_init(); #endif CONFIG_BLK_DEV_MD diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/loop.c linux.ac/drivers/block/loop.c --- linux.vanilla/drivers/block/loop.c Tue Jun 15 16:49:48 1999 +++ linux.ac/drivers/block/loop.c Wed Jul 7 07:04:23 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/lvm.c linux.ac/drivers/block/lvm.c --- linux.vanilla/drivers/block/lvm.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/block/lvm.c Mon Jul 5 18:05:40 1999 @@ -0,0 +1,1997 @@ +/* + * kernel/lvm.c + * + * Copyright (C) 1997 - 1999 Heinz Mauelshagen, Germany + * + * February-November 1997 + * April-May,July-August,November 1998 + * January,February 1999 + * + * Changes : + * Marcelo Tosatti + * #ifdef minor fixes + * + * + * LVM driver is free software; you can redistribute 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. + * + * LVM driver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU CC; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/* + * Changelog + * + * 09/11/1997 - added chr ioctls VG_STATUS_GET_COUNT + * and VG_STATUS_GET_NAMELIST + * 18/01/1998 - change lvm_chr_open/close lock handling + * 30/04/1998 - changed LV_STATUS ioctl to LV_STATUS_BYNAME and + * - added LV_STATUS_BYINDEX ioctl + * - used lvm_status_byname_req_t and + * lvm_status_byindex_req_t vars + * 04/05/1998 - added multiple device support + * 08/05/1998 - added support to set/clear extendable flag in volume group + * 09/05/1998 - changed output of lvm_proc_get_info() because of + * support for free (eg. longer) logical volume names + * 12/05/1998 - added spin_locks (thanks to Pascal van Dam + * ) + * 25/05/1998 - fixed handling of locked PEs in lvm_map() and lvm_chr_ioctl() + * 26/05/1998 - reactivated verify_area by access_ok + * 07/06/1998 - used vmalloc/vfree instead of kmalloc/kfree to go + * beyond 128/256 KB max allocation limit per call + * - #ifdef blocked spin_lock calls to avoid compile errors + * with 2.0.x + * 11/06/1998 - another enhancement to spinlock code in lvm_chr_open() + * and use of LVM_VERSION_CODE instead of my own macros + * (thanks to Michael Marxmeier ) + * 07/07/1998 - added statistics in lvm_map() + * 08/07/1998 - saved statistics in do_lv_extend_reduce() + * 25/07/1998 - used __initfunc macro + * 02/08/1998 - changes for official char/block major numbers + * 07/08/1998 - avoided init_module() and cleanup_module() to be static + * 30/08/1998 - changed VG lv_open counter from sum of LV lv_open counters + * to sum of LVs open (no matter how often each is) + * 01/09/1998 - fixed lvm_gendisk.part[] index error + * 07/09/1998 - added copying of lv_current_pe-array + * in LV_STATUS_BYINDEX ioctl + * 17/11/1998 - added KERN_* levels to printk + * 13/01/1999 - fixed LV index bug in do_lv_create() which hit lvrename + * 07/02/1999 - fixed spinlock handling bug in case of LVM_RESET + * by moving spinlock code from lvm_chr_open() + * to lvm_chr_ioctl() + * - added LVM_LOCK_LVM ioctl to lvm_chr_ioctl() + * - allowed LVM_RESET and retrieval commands to go ahead; + * only other update ioctls are blocked now + * - fixed pv->pe to NULL for pv_status + * - using lv_req structure in lvm_chr_ioctl() now + * - fixed NULL ptr reference bug in do_lv_extend_reduce() + * caused by uncontiguous PV array in lvm_chr_ioctl(VG_REDUCE) + * 09/02/1999 - changed BLKRASET and BLKRAGET in lvm_char_ioctl() to + * handle lgoical volume private read ahead sector + * - implemented LV read_ahead handling with lvm_blk_read() + * and lvm_blk_write() + * 10/02/1999 - implemented 2.[12].* support function lvm_hd_name() + * to be used in drivers/block/genhd.c by disk_name() + * 12/02/1999 - fixed index bug in lvm_blk_ioctl(), HDIO_GETGEO + * - enhanced gendisk insert/remove handling + * 16/02/1999 - changed to dynamic block minor number allocation to + * have as much as 99 volume groups with 256 logical volumes + * as the grand total; this allows having 1 volume group with + * up to 256 logical volumes in it + * 21/02/1999 - added LV open count information to proc filesystem + * - substituted redundant LVM_RESET code by calls + * to do_vg_remove() + * 22/02/1999 - used schedule_timeout() to be more responsive + * in case of do_vg_remove() with lots of logical volumes + * + */ + +/* + * TODO + * + * - implement special handling of unavailable physical volumes + * - implement RAID1/5,10/50 + * + */ + +char *lvm_version = "LVM version 0.6 by Heinz Mauelshagen (26/02/1999)\n"; +char *lvm_short_version = "version 0.6 (26/02/1999)"; + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#define LVM_CORRECT_READ_AHEAD( a) \ + if ( a < LVM_MIN_READ_AHEAD || \ + a > LVM_MAX_READ_AHEAD) a = LVM_MAX_READ_AHEAD; + +#define suser() ( current->uid == 0 && current->euid == 0) + + +/* + * External function prototypes + */ +#ifdef MODULE +int init_module(void); +void cleanup_module(void); +#else +extern int lvm_init(void); +#endif + +static void lvm_dummy_device_request(void); +static int lvm_blk_ioctl(struct inode *, struct file *, unsigned int, + unsigned long); +static int lvm_blk_open(struct inode *, struct file *); + +static ssize_t lvm_blk_read(struct file *, char *, size_t, loff_t *); +static ssize_t lvm_blk_write(struct file *, const char *, size_t, loff_t *); + +static int lvm_chr_open(struct inode *, struct file *); + +static int lvm_chr_close(struct inode *, struct file *); +static int lvm_blk_close(struct inode *, struct file *); + +static int lvm_chr_ioctl(struct inode *, struct file *, unsigned int, + unsigned long); + +#if defined(CONFIG_LVM_PROC_FS) && defined(CONFIG_PROC_FS) +static int lvm_proc_get_info(char *, char **, off_t, int, int); +#endif + +void lvm_hd_name(char *, struct gendisk *, int); + +/* End external function prototypes */ + +/* + * Internal function prototypes + */ +static void lvm_init_vars(void); +extern int (*lvm_map_ptr) (int, kdev_t *, unsigned long *, + unsigned long, int); +static int lvm_map(int, kdev_t *, unsigned long *, unsigned long, int); +static int do_vg_create(int, void *); +static int do_vg_remove(int); +static int do_lv_create(int, char *, lv_t *, struct inode *); +static int do_lv_remove(int, char *); +static int do_lv_extend_reduce(int, char *, lv_t *, struct inode *); +static void lvm_geninit(struct gendisk *); +static struct inode *lvm_get_inode(int); +inline int lvm_strlen(char *); +inline void lvm_memcpy(char *, char *, int); +inline int lvm_strcmp(char *, char *); +inline char *lvm_strrchr(char *, char c); +/* END Internal function prototypes */ + + +/* volume group descriptor area pointers */ +static vg_t *vg[ABS_MAX_VG + 1]; +static pv_t *pvp = NULL; +static lv_t *lvp = NULL; +static pe_t *pep = NULL; +static pe_t *pep1 = NULL; + +/* map from block minor number to VG and LV numbers */ +typedef struct { + int vg_number; + int lv_number; +} vg_lv_map_t; +static vg_lv_map_t vg_lv_map[ABS_MAX_LV]; + +/* Request structures (lvm_chr_ioctl()) */ +static pv_change_req_t pv_change_req; +static pv_flush_req_t pv_flush_req; +static pv_status_req_t pv_status_req; +static pe_lock_req_t pe_lock_req; +static le_remap_req_t le_remap_req; +static lv_req_t lv_req; + +#ifdef LVM_TOTAL_RESET +static int lvm_reset_spindown = 0; +#endif + +static char pv_name[NAME_LEN]; +static uint lv_open = 0; +static const char *const lvm_name = LVM_NAME; +static int lock = 0; +static int loadtime = 0; +static uint vg_count = 0; +static long lvm_chr_open_count = 0; +static ushort lvm_iop_version = LVM_DRIVER_IOP_VERSION; +struct wait_queue *lvm_wait = NULL; +struct wait_queue *lvm_map_wait = NULL; + +#if defined(CONFIG_LVM_PROC_FS) && defined(CONFIG_PROC_FS) + +static struct proc_dir_entry lvm_proc_entry = +{ + 0, 3, LVM_NAME, S_IFREG | S_IRUGO, + 1, 0, 0, 0, + NULL, + lvm_proc_get_info, + NULL, NULL, NULL, NULL, NULL, +}; +#endif + +static struct file_operations lvm_chr_fops = +{ + NULL, /* No lseek */ + NULL, /* No read */ + NULL, /* No write */ + NULL, /* No readdir */ + NULL, /* No select */ + lvm_chr_ioctl, + NULL, /* No mmap */ + lvm_chr_open, + NULL, /* No flush */ + lvm_chr_close, + NULL, /* No fsync */ + NULL, /* No fasync */ + NULL, /* No check_media_change */ + NULL, /* No revalidate */ + NULL, /* No lock */ +}; + +static struct file_operations lvm_blk_fops = +{ + NULL, /* No lseek */ + lvm_blk_read, /* read */ + lvm_blk_write, /* write */ + NULL, /* No readdir */ + NULL, /* No select */ + lvm_blk_ioctl, + NULL, /* No mmap */ + lvm_blk_open, + NULL, /* No flush */ + lvm_blk_close, + block_fsync, /* fsync */ + NULL, /* No fasync */ + NULL, /* No check_media_change */ + NULL, /* No revalidate */ + NULL /* No lock */ +}; + + +/* gendisk structures */ +static struct hd_struct lvm_hd_struct[MAX_LV]; +static int lvm_blocksizes[MAX_LV] = +{0,}; +static int lvm_size[MAX_LV] = +{0,}; + +static struct gendisk lvm_gendisk = +{ + LVM_BLOCK_MAJOR, /* major # */ + LVM_NAME, /* name of major */ + 0, /* number of times minor is shifted + to get real minor */ + 1, /* maximum partitions per device */ + MAX_LV, /* maximum number of real devices */ + lvm_geninit, /* initialization called before we + do other things */ + lvm_hd_struct, /* partition table */ + lvm_size, /* device size in blocks, copied + to block_size[] */ + MAX_LV, /* number or real devices */ + NULL, /* internal */ + NULL, /* pointer to next gendisk struct (internal) */ +}; + + +#ifdef MODULE +/* + * Module initialization... + */ +int __init init_module(void) +#else +/* + * Driver initialization... + */ +int __init lvm_init(void) +#endif /* #ifdef MODULE */ +{ + struct gendisk *gendisk_ptr = NULL; + + lvm_init_vars(); + + if (register_chrdev(LVM_CHAR_MAJOR, lvm_name, &lvm_chr_fops) < 0) { + printk(KERN_ERR "%s -- register_chrdev failed\n", lvm_name); + return -EIO; + } + if (register_blkdev(LVM_BLOCK_MAJOR, lvm_name, &lvm_blk_fops) < 0) { + printk("%s -- register_blkdev failed\n", lvm_name); + if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0) + printk(KERN_ERR "%s -- unregister_chrdev failed\n", lvm_name); + return -EIO; + } + +#if defined(CONFIG_LVM_PROC_FS) && defined(CONFIG_PROC_FS) + proc_register(&proc_root, &lvm_proc_entry); +#endif + +#ifdef DEBUG + printk(KERN_INFO "%s -- registered\n", lvm_name); +#endif + + blk_dev[LVM_BLOCK_MAJOR].request_fn = lvm_dummy_device_request; + blk_dev[LVM_BLOCK_MAJOR].current_request = NULL; + + /* insert our gendisk at the corresponding major */ + lvm_geninit(&lvm_gendisk); + gendisk_ptr = gendisk_head; + while (gendisk_ptr->next != NULL && gendisk_ptr->major > lvm_gendisk.major) + gendisk_ptr = gendisk_ptr->next; + lvm_gendisk.next = gendisk_ptr->next; + gendisk_ptr->next = &lvm_gendisk; + + /* reference from ll_rw_blk */ + lvm_map_ptr = lvm_map; + + printk(KERN_INFO + "%s%s -- " +#ifdef MODULE + "Module" +#else + "Driver" +#endif + " successfully initialized\n", + lvm_version, lvm_name); + + return 0; +} /* init_module () / lvm_init () */ + + +#ifdef MODULE +/* + * Module cleanup... + */ +void cleanup_module(void) +{ + struct gendisk *gendisk_ptr = NULL, *gendisk_ptr_prev = NULL; + + gendisk_ptr = gendisk_ptr_prev = gendisk_head; + while (gendisk_ptr != &lvm_gendisk && gendisk_ptr != NULL) { + gendisk_ptr_prev = gendisk_ptr; + gendisk_ptr = gendisk_ptr->next; + } + /* delete our gendisk from chain */ + gendisk_ptr_prev->next = gendisk_ptr->next; + + blk_size[LVM_BLOCK_MAJOR] = NULL; + blksize_size[LVM_BLOCK_MAJOR] = NULL; + +#if defined(CONFIG_LVM_PROC_FS) && defined(CONFIG_PROC_FS) + proc_unregister(&proc_root, lvm_proc_entry.low_ino); +#endif + + if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0) { + printk(KERN_ERR "%s -- unregister_chrdev failed\n", lvm_name); + } + if (unregister_blkdev(LVM_BLOCK_MAJOR, lvm_name) < 0) { + printk(KERN_ERR "%s -- unregister_blkdev failed\n", lvm_name); + } + /* reference from linux/drivers/block/ll_rw_blk.c */ + lvm_map_ptr = NULL; + + blk_dev[LVM_BLOCK_MAJOR].request_fn = NULL; + blk_dev[LVM_BLOCK_MAJOR].current_request = NULL; + + printk(KERN_INFO "%s -- Module successfully deactivated\n", lvm_name); + + return; +} /* void cleanup_module () */ +#endif /* #ifdef MODULE */ + + +/* + * support function to initialize lvm variables + */ +static void __init lvm_init_vars(void) +{ + int v; + + loadtime = CURRENT_TIME; + + pe_lock_req.lock = UNLOCK_PE; + pe_lock_req.data.lv_dev = \ + pe_lock_req.data.pv_dev = \ + pe_lock_req.data.pv_offset = 0; + + /* Initialize VG pointers */ + for (v = 0; v <= ABS_MAX_VG; v++) + vg[v] = NULL; + + /* Initialize LV -> VG association */ + for (v = 0; v < ABS_MAX_LV; v++) { + /* index ABS_MAX_VG never used for real VG */ + vg_lv_map[v].vg_number = ABS_MAX_VG; + vg_lv_map[v].lv_number = -1; + } + + return; +} /* lvm_init_vars () */ + + +/******************************************************************** + * + * Character device functions + * + ********************************************************************/ + +/* + * character device open routine + */ +static int lvm_chr_open(struct inode *inode, struct file *file) { + int minor = MINOR(inode->i_rdev); + +#ifdef DEBUG + printk(KERN_DEBUG + "%s -- lvm_chr_open MINOR: %d VG#: %d mode: 0x%X lock: %d\n", + lvm_name, minor, VG_CHR(minor), file->f_mode, lock); +#endif + + /* super user validation */ + if (!suser()) + return -EACCES; + + /* Group special file open */ + if (VG_CHR(minor) > MAX_VG) + return -ENXIO; + + MOD_INC_USE_COUNT; + lvm_chr_open_count++; + return 0; +} /* lvm_chr_open () *//* + * character device i/o-control routine + * + * Only one changing process can ioctl at one time, others will block. + * + */ +static int lvm_chr_ioctl(struct inode *inode, struct file *file, + uint command, ulong a) { + int minor = MINOR(inode->i_rdev); + int extendable; + ulong l, le, p, v; + ulong size; + void *arg = (void *) a; + lv_t lv; +#ifdef LVM_GET_INODE + struct inode *inode_sav; +#endif + lv_status_byname_req_t lv_status_byname_req; + lv_status_byindex_req_t lv_status_byindex_req; + spinlock_t lvm_lock = SPIN_LOCK_UNLOCKED; + +#ifdef DEBUG_IOCTL + printk(KERN_DEBUG + "%s -- lvm_chr_ioctl: command: 0x%X MINOR: %d " + "VG#: %d mode: 0x%X\n", + lvm_name, command, minor, VG_CHR(minor), file->f_mode); +#endif + +#ifdef LVM_TOTAL_RESET + if (lvm_reset_spindown > 0) + return -EACCES; +#endif + + + /* Main command switch */ + switch (command) { + /* lock the LVM */ + case LVM_LOCK_LVM: + lock_try_again: + spin_lock(&lvm_lock); + if (lock != 0 && lock != current->pid) { +#ifdef DEBUG_IOCTL + printk(KERN_INFO "lvm_chr_ioctl: %s is locked by pid %d ...\n", + lvm_name, lock); +#endif + spin_unlock(&lvm_lock); + interruptible_sleep_on(&lvm_wait); + if (signal_pending(current)) + return -EINTR; +#ifdef LVM_TOTAL_RESET + if (lvm_reset_spindown > 0) + return -EACCES; +#endif + goto lock_try_again; + } + lock = current->pid; + spin_unlock(&lvm_lock); + + return 0; + + + /* check lvm version to ensure driver/tools+lib interoperability */ + case LVM_GET_IOP_VERSION: + if (copy_to_user(arg, &lvm_iop_version, sizeof(ushort))) + return -EFAULT; + return 0; + + + /* lock/unlock i/o to a physical extent to move it to another + physical volume (move's done in user space's pvmove) */ + case PE_LOCK_UNLOCK: + if (vg[VG_CHR(minor)] == NULL) + return -ENXIO; + if (copy_from_user(&pe_lock_req, arg, sizeof(pe_lock_req_t))) + return -EFAULT; + + switch (pe_lock_req.lock) { + case LOCK_PE: + for (p = 0; p < vg[VG_CHR(minor)]->pv_max; p++) { + if (vg[VG_CHR(minor)]->pv[p] != NULL && + pe_lock_req.data.pv_dev == vg[VG_CHR(minor)]->pv[p]->pv_dev) + break; + } + + if (p == vg[VG_CHR(minor)]->pv_max) + return -ENXIO; + pe_lock_req.lock = UNLOCK_PE; + fsync_dev(pe_lock_req.data.lv_dev); + pe_lock_req.lock = LOCK_PE; + break; + + case UNLOCK_PE: + pe_lock_req.lock = UNLOCK_PE; + pe_lock_req.data.lv_dev = 0; + pe_lock_req.data.pv_dev = 0; + pe_lock_req.data.pv_offset = 0; + wake_up(&lvm_map_wait); + break; + + default: + return -EINVAL; + } + + return 0; + + + /* remap a logical extent (after moving the physical extent) */ + case LE_REMAP: + if (vg[VG_CHR(minor)] == NULL) + return -ENXIO; + if (copy_from_user(&le_remap_req, arg, sizeof(le_remap_req_t))) + return -EFAULT; + + for (l = 0; l < vg[VG_CHR(minor)]->lv_max; l++) { + if (vg[VG_CHR(minor)]->lv[l] != NULL && + lvm_strcmp(vg[VG_CHR(minor)]->lv[l]->lv_name, + le_remap_req.lv_name) == 0) { + for (le = 0; le < vg[VG_CHR(minor)]->lv[l]->lv_allocated_le; le++) { + if (vg[VG_CHR(minor)]->lv[l]->lv_current_pe[le].dev == le_remap_req.old_dev && + vg[VG_CHR(minor)]->lv[l]->lv_current_pe[le].pe == le_remap_req.old_pe) { + vg[VG_CHR(minor)]->lv[l]->lv_current_pe[le].dev = le_remap_req.new_dev; + vg[VG_CHR(minor)]->lv[l]->lv_current_pe[le].pe = le_remap_req.new_pe; + return 0; + } + } + return -EINVAL; + } + } + return -ENXIO; + + /* create a VGDA */ + case VG_CREATE: + return do_vg_create(minor, arg); + + /* remove an inactive VGDA */ + case VG_REMOVE: + return do_vg_remove(minor); + + /* extend a volume group */ + case VG_EXTEND: + if (vg[VG_CHR(minor)] == NULL) + return -ENXIO; + if (vg[VG_CHR(minor)]->pv_cur < vg[VG_CHR(minor)]->pv_max) { + for (p = 0; p < vg[VG_CHR(minor)]->pv_max; p++) { + if (vg[VG_CHR(minor)]->pv[p] == NULL) { + if ((vg[VG_CHR(minor)]->pv[p] = vmalloc(sizeof(pv_t))) == NULL) { + printk(KERN_WARNING "%s -- VG_EXTEND: vmalloc error PV\n", lvm_name); + return -ENOMEM; + } + if (copy_from_user(vg[VG_CHR(minor)]->pv[p], arg, + sizeof(pv_t))) + return -EFAULT; + + vg[VG_CHR(minor)]->pv[p]->pv_status = PV_ACTIVE; + /* We don't need the PE list + in kernel space like LVs pe_t list */ + vg[VG_CHR(minor)]->pv[p]->pe = NULL; + vg[VG_CHR(minor)]->pv_cur++; + vg[VG_CHR(minor)]->pv_act++; + vg[VG_CHR(minor)]->pe_total += vg[VG_CHR(minor)]->pv[p]->pe_total; +#ifdef LVM_GET_INODE + /* insert a dummy inode for fs_may_mount */ + vg[VG_CHR(minor)]->pv[p]->inode = lvm_get_inode(vg[VG_CHR(minor)]->pv[p]->pv_dev); +#endif + return 0; + } + } + } + return -EPERM; + + + /* reduce a volume group */ + case VG_REDUCE: + if (vg[VG_CHR(minor)] == NULL) + return -ENXIO; + if (copy_from_user(pv_name, arg, sizeof(pv_name))) + return -EFAULT; + + for (p = 0; p < vg[VG_CHR(minor)]->pv_max; p++) { + if (vg[VG_CHR(minor)]->pv[p] != NULL && + lvm_strcmp(vg[VG_CHR(minor)]->pv[p]->pv_name, pv_name) == 0) { + if (vg[VG_CHR(minor)]->pv[p]->lv_cur > 0) + return -EPERM; + vg[VG_CHR(minor)]->pe_total -= vg[VG_CHR(minor)]->pv[p]->pe_total; + vg[VG_CHR(minor)]->pv_cur--; + vg[VG_CHR(minor)]->pv_act--; +#ifdef DEBUG_VFREE + printk(KERN_DEBUG + "%s -- vfree %d\n", lvm_name, __LINE__); +#endif +#ifdef LVM_GET_INODE + clear_inode(vg[VG_CHR(minor)]->pv[p]->inode); +#endif + vfree(vg[VG_CHR(minor)]->pv[p]); + /* Make PV pointer array contiguous */ + for (; p < vg[VG_CHR(minor)]->pv_max - 1; p++) + vg[VG_CHR(minor)]->pv[p] = vg[VG_CHR(minor)]->pv[p + 1]; + vg[VG_CHR(minor)]->pv[p + 1] = NULL; + return 0; + } + } + return -ENXIO; + + + /* set/clear extendability flag of volume group */ + case VG_SET_EXTENDABLE: + if (vg[VG_CHR(minor)] == NULL) + return -ENXIO; + if (copy_from_user(&extendable, arg, sizeof(extendable))) + return -EFAULT; + + if (extendable == VG_EXTENDABLE || extendable == ~VG_EXTENDABLE) { + if (extendable == VG_EXTENDABLE) + vg[VG_CHR(minor)]->vg_status |= VG_EXTENDABLE; + else + vg[VG_CHR(minor)]->vg_status &= ~VG_EXTENDABLE; + } else + return -EINVAL; + return 0; + + + /* get volume group data (only the vg_t struct) */ + case VG_STATUS: + if (vg[VG_CHR(minor)] == NULL) + return -ENXIO; + if (copy_to_user(arg, vg[VG_CHR(minor)], sizeof(vg_t))) + return -EFAULT; + return 0; + + /* get volume group count */ + case VG_STATUS_GET_COUNT: + if (copy_to_user(arg, &vg_count, sizeof(vg_count))) + return -EFAULT; + return 0; + + + /* get volume group count */ + case VG_STATUS_GET_NAMELIST: + for (l = v = 0; v < ABS_MAX_VG; v++) { + if (vg[v] != NULL) + if (copy_to_user(arg + l++ * NAME_LEN, vg[v]->vg_name, NAME_LEN)) + return -EFAULT; + } + return 0; + + + /* create, remove, extend or reduce a logical volume */ + case LV_CREATE: + case LV_REMOVE: + case LV_EXTEND: + case LV_REDUCE: + if (vg[VG_CHR(minor)] == NULL) + return -ENXIO; + if (copy_from_user(&lv_req, arg, sizeof(lv_req))) + return -EFAULT; + + if (command != LV_REMOVE) { + if (copy_from_user(&lv, lv_req.lv, sizeof(lv_t))) + return -EFAULT; + } + switch (command) { + case LV_CREATE: + return do_lv_create(minor, lv_req.lv_name, &lv, inode); + + case LV_REMOVE: + return do_lv_remove(minor, lv_req.lv_name); + + case LV_EXTEND: + case LV_REDUCE: + return do_lv_extend_reduce(minor, lv_req.lv_name, &lv, inode); + } + + + /* get status of a logical volume by name */ + case LV_STATUS_BYNAME: + if (vg[VG_CHR(minor)] == NULL) + return -ENXIO; + if (copy_from_user(&lv_status_byname_req, arg, + sizeof(lv_status_byname_req_t))) + return -EFAULT; + + if (lv_status_byname_req.lv == NULL) + return -EINVAL; + + if (copy_from_user(&lv, lv_status_byname_req.lv, sizeof(lv_t))) + return -EFAULT; + + for (l = 0; l < vg[VG_CHR(minor)]->lv_max; l++) { + if (vg[VG_CHR(minor)]->lv[l] != NULL && + lvm_strcmp(vg[VG_CHR(minor)]->lv[l]->lv_name, lv_status_byname_req.lv_name) == 0) { + if (copy_to_user(lv_status_byname_req.lv, vg[VG_CHR(minor)]->lv[l], sizeof(lv_t))) + return -EFAULT; + if (lv.lv_current_pe != NULL) { + size = vg[VG_CHR(minor)]->lv[l]->lv_allocated_le * sizeof(pe_t); + if (copy_to_user(lv.lv_current_pe, vg[VG_CHR(minor)]->lv[l]->lv_current_pe, size)) + return -EFAULT; + } + return 0; + } + } + return -ENXIO; + + /* get status of a logical volume by index */ + case LV_STATUS_BYINDEX: + if (vg[VG_CHR(minor)] == NULL) + return -ENXIO; + if (copy_from_user(&lv_status_byindex_req, arg, sizeof(lv_status_byindex_req))) + return -EFAULT; + + if ((lvp = lv_status_byindex_req.lv) == NULL) + return -EINVAL; + l = lv_status_byindex_req.lv_index; + if (vg[VG_CHR(minor)]->lv[l] == NULL) + return -ENXIO; + + if (copy_from_user(&lv, lvp, sizeof(lv_t))) + return -EFAULT; + if (copy_to_user(lvp, vg[VG_CHR(minor)]->lv[l], sizeof(lv_t))) + return -EFAULT; + + if (lv.lv_current_pe != NULL) { + size = vg[VG_CHR(minor)]->lv[l]->lv_allocated_le * sizeof(pe_t); + if (copy_to_user(lv.lv_current_pe, vg[VG_CHR(minor)]->lv[l]->lv_current_pe, size)) + return -EFAULT; + } + return 0; + + + /* change a physical volume */ + case PV_CHANGE: + if (vg[VG_CHR(minor)] == NULL) + return -ENXIO; + if (copy_from_user(&pv_change_req, arg, sizeof(pv_change_req))) + return -EFAULT; + + for (p = 0; p < vg[VG_CHR(minor)]->pv_max; p++) { + if (vg[VG_CHR(minor)]->pv[p] != NULL && + lvm_strcmp(vg[VG_CHR(minor)]->pv[p]->pv_name, + pv_change_req.pv_name) == 0) { +#ifdef LVM_GET_INODE + inode_sav = vg[VG_CHR(minor)]->pv[p]->inode; +#endif + copy_from_user(vg[VG_CHR(minor)]->pv[p], pv_change_req.pv, sizeof(pv_t)); + /* We don't need the PE list + in kernel space as with LVs pe_t list */ + vg[VG_CHR(minor)]->pv[p]->pe = NULL; +#ifdef LVM_GET_INODE + vg[VG_CHR(minor)]->pv[p]->inode = inode_sav; +#endif + return 0; + } + } + return -ENXIO; + + + /* get physical volume data (pv_t structure only) */ + case PV_STATUS: + if (vg[VG_CHR(minor)] == NULL) + return -ENXIO; + if (copy_from_user(&pv_status_req, arg, sizeof(pv_status_req))) + return -EFAULT; + + for (p = 0; p < vg[VG_CHR(minor)]->pv_max; p++) { + if (vg[VG_CHR(minor)]->pv[p] != NULL) { + if (lvm_strcmp(vg[VG_CHR(minor)]->pv[p]->pv_name, pv_status_req.pv_name) == 0) { + if (copy_to_user(pv_status_req.pv, vg[VG_CHR(minor)]->pv[p], sizeof(pv_t))) + return -EFAULT; + return 0; + } + } + } + return -ENXIO; + + + /* physical volume buffer flush/invalidate */ + case PV_FLUSH: + if (copy_from_user(&pv_flush_req, arg, sizeof(pv_flush_req))) + return -EFAULT; + + for (v = 0; v < ABS_MAX_VG; v++) { + if (vg[v] == NULL) + continue; + for (p = 0; p < vg[v]->pv_max; p++) { + if (vg[v]->pv[p] != NULL && lvm_strcmp(vg[v]->pv[p]->pv_name, pv_flush_req.pv_name) == 0) { + fsync_dev(vg[v]->pv[p]->pv_dev); + invalidate_buffers(vg[v]->pv[p]->pv_dev); + return 0; + } + } + } + return 0; + + default: + return -EINVAL; + } + return 0; +} /* lvm_chr_ioctl */ + + +/* + * character device close routine + */ + +static int lvm_chr_close(struct inode *inode, struct file *file) { +#ifdef DEBUG + int minor = MINOR(inode->i_rdev); + printk(KERN_DEBUG + "%s -- lvm_chr_close VG#: %d\n", lvm_name, VG_CHR(minor)); +#endif + + MOD_DEC_USE_COUNT; + +#ifdef LVM_TOTAL_RESET + if (lvm_reset_spindown > 0) { + lvm_reset_spindown = 0; + lvm_chr_open_count = 1; + } +#endif /* if (lvm_chr_open_count > 0) */ lvm_chr_open_count--; + if (lock == current->pid) { + lock = 0; /* release lock */ + wake_up_interruptible(&lvm_wait); + } + return 0; +} /* lvm_chr_close () */ + + + +/******************************************************************** + * + * Block device functions + * + ********************************************************************/ + +/* + * block device open routine + */ +static int lvm_blk_open(struct inode *inode, struct file *file) { + int minor = MINOR(inode->i_rdev); + +#ifdef DEBUG_LVM_BLK_OPEN + printk(KERN_DEBUG + "%s -- lvm_blk_open MINOR: %d VG#: %d LV#: %d mode: 0x%X\n", + lvm_name, minor, VG_BLK(minor), LV_BLK(minor), file->f_mode); +#endif + +#ifdef LVM_TOTAL_RESET + if (lvm_reset_spindown > 0) + return -EPERM; +#endif + + if (vg[VG_BLK(minor)] != NULL && + (vg[VG_BLK(minor)]->vg_status & VG_ACTIVE) && + vg[VG_BLK(minor)]->lv[LV_BLK(minor)] != NULL && + LV_BLK(minor) >= 0 && + LV_BLK(minor) < vg[VG_BLK(minor)]->lv_max) { + /* Check parallel LV spindown (LV remove) */ + if (vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_status & LV_SPINDOWN) + return -EPERM; + + /* Check inactive LV and open for read/write */ + if (file->f_mode & O_RDWR) { + if (!(vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_status & LV_ACTIVE)) + return -EPERM; + if (!(vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_access & LV_WRITE)) + return -EACCES; + } + if (vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_open == 0) + vg[VG_BLK(minor)]->lv_open++; + vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_open++; + MOD_INC_USE_COUNT; + +#ifdef DEBUG_LVM_BLK_OPEN + printk(KERN_DEBUG + "%s -- lvm_blk_open MINOR: %d VG#: %d LV#: %d size: %d\n", + lvm_name, minor, VG_BLK(minor), LV_BLK(minor), + vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_size); +#endif + + return 0; + } + return -ENXIO; +} /* lvm_blk_open () */ + + +/* + * block device read + */ +static ssize_t lvm_blk_read(struct file *file, char *buffer, + size_t size, loff_t * offset) { + int major = MAJOR(file->f_dentry->d_inode->i_rdev); + int minor = MINOR(file->f_dentry->d_inode->i_rdev); + + read_ahead[major] = vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_read_ahead; + return block_read(file, buffer, size, offset); +} /* + * block device write + */ +static ssize_t lvm_blk_write(struct file *file, const char *buffer, + size_t size, loff_t * offset) { + int major = MAJOR(file->f_dentry->d_inode->i_rdev); + int minor = MINOR(file->f_dentry->d_inode->i_rdev); + + read_ahead[major] = vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_read_ahead; + return block_write(file, buffer, size, offset); +} /* + * block device i/o-control routine + */ +static int lvm_blk_ioctl(struct inode *inode, struct file *file, + uint command, ulong a) { + int minor = MINOR(inode->i_rdev); + void *arg = (void *) a; + struct hd_geometry *hd = (struct hd_geometry *) a; + +#ifdef DEBUG_IOCTL + printk(KERN_DEBUG + "%s -- lvm_blk_ioctl MINOR: %d command: 0x%X arg: %X " + "VG#:%dl LV#: %d\n", + lvm_name, minor, command, (ulong) arg, + VG_BLK(minor), LV_BLK(minor)); +#endif + + switch (command) { + /* return device size */ + case BLKGETSIZE: + if (copy_to_user((long *) arg, &vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_size, + sizeof(vg[VG_BLK(minor)]-> \ + lv[LV_BLK(minor)]->lv_size))) + return -EFAULT; + break; + + + /* flush buffer cache */ + case BLKFLSBUF: + fsync_dev(inode->i_rdev); + break; + + /* set read ahead for block device */ + case BLKRASET: + if (!suser()) + return -EACCES; + if ((long) arg < LVM_MIN_READ_AHEAD || + (long) arg > LVM_MAX_READ_AHEAD) + return -EINVAL; + vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_read_ahead = (long) arg; + break; + + /* get current read ahead setting */ + case BLKRAGET: + if (copy_to_user((long *) arg, + &vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_read_ahead, + sizeof(vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_read_ahead))) + return -EFAULT; + break; + + /* get disk geometry */ + case HDIO_GETGEO: + if (hd == NULL) + return -EINVAL; + { + unsigned char heads = 64; + unsigned char sectors = 32; + long start = 0; + short cylinders = vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_size / + heads / sectors; + + copy_to_user((char *) &hd->heads, &heads, sizeof(heads)); + copy_to_user((char *) &hd->sectors, §ors, sizeof(sectors)); + copy_to_user((short *) &hd->cylinders, &cylinders, sizeof(cylinders)); + copy_to_user((long *) &hd->start, &start, sizeof(start)); + } + break; + + + /* set access flags of a logical volume */ + case LV_SET_ACCESS: + if (!suser()) + return -EACCES; + vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_access = (ulong) arg; + break; + + /* set status flags of a logical volume */ + case LV_SET_STATUS: + if (!suser()) + return -EACCES; + if (!((ulong) arg & LV_ACTIVE) && vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_open > 1) + return -EPERM; + vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_status = (ulong) arg; + break; + + + /* set allocation flags of a logical volume */ + case LV_SET_ALLOCATION: + if (!suser()) + return -EACCES; + vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_allocation = (ulong) arg; + break; + + + default: + printk(KERN_WARNING + "%s -- lvm_blk_ioctl: unknown command %d\n", + lvm_name, command); + return -EINVAL; + } + + return 0; +} /* lvm_blk_ioctl () */ + + +/* + * block device close routine + */ +static int lvm_blk_close(struct inode *inode, struct file *file) { + int minor = MINOR(inode->i_rdev); + +#ifdef DEBUG + printk(KERN_DEBUG + "%s -- lvm_blk_close MINOR: %d VG#: %d LV#: %d\n", + lvm_name, minor, VG_BLK(minor), LV_BLK(minor)); +#endif + + sync_dev(inode->i_rdev); + if (vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_open == 1) + vg[VG_BLK(minor)]->lv_open--; + vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_open--; + + MOD_DEC_USE_COUNT; + + return 0; +} /* lvm_blk_close () */ +#if defined(CONFIG_LVM_PROC_FS) && defined(CONFIG_PROC_FS) /* + * Support function /proc-Filesystem + */ +#define LVM_PROC_BUF ( i == 0 ? dummy_buf : &buf[sz]) + +static int lvm_proc_get_info(char *page, char **start, off_t pos, int count, int whence) { + int c, i, l, p, v, vg_counter, pv_counter, lv_counter, lv_open_counter, lv_open_total, pe_t_bytes, seconds; + static off_t sz; + off_t sz_last; + char allocation_flag, inactive_flag, rw_flag, stripes_flag; + char *lv_name = NULL; + static char *buf = NULL; + static char dummy_buf[160]; /* sized for 2 lines */ + +#ifdef DEBUG_LVM_PROC_GET_INFO + printk(KERN_DEBUG + "%s - lvm_proc_get_info CALLED pos: %lu count: %d whence: %d\n", + lvm_name, pos, count, whence); +#endif + if (pos == 0 || buf == NULL) { + sz_last = vg_counter = pv_counter = lv_counter = lv_open_counter = lv_open_total = pe_t_bytes = 0; + /* search for activity */ + for (v = 0; v < ABS_MAX_VG; v++) { + if (vg[v] != NULL) { + vg_counter++; + pv_counter += vg[v]->pv_cur; + lv_counter += vg[v]->lv_cur; + if (vg[v]->lv_cur > 0) { + for (l = 0; l < vg[v]->lv_max; l++) { + if (vg[v]->lv[l] != NULL) { + pe_t_bytes += vg[v]->lv[l]->lv_allocated_le; + if (vg[v]->lv[l]->lv_open > 0) { + lv_open_counter++; + lv_open_total += vg[v]->lv[l]->lv_open; + } + } + } + } + } + } + pe_t_bytes *= sizeof(pe_t); + + if (buf != NULL) { +#ifdef DEBUG_VFREE + printk(KERN_DEBUG + "%s -- vfree %d\n", lvm_name, __LINE__); +#endif + vfree(buf); + buf = NULL; + } + /* 2 times: first to get size to allocate buffer, + 2nd to fill the vmalloced buffer */ + for (i = 0; i < 2; i++) { + sz = 0; + sz += sprintf(LVM_PROC_BUF, "LVM " +#ifdef MODULE + "module" +#else + "driver" +#endif + " %s\n\n" + "Total: %d VG%s %d PV%s %d LV%s ", + lvm_short_version, + vg_counter, vg_counter == 1 ? "" : "s", + pv_counter, pv_counter == 1 ? "" : "s", + lv_counter, lv_counter == 1 ? "" : "s"); + sz += sprintf(LVM_PROC_BUF, + "(%d LV%s open", + lv_open_counter, + lv_open_counter == 1 ? "" : "s"); + if (lv_open_total > 0) + sz += sprintf(LVM_PROC_BUF, + " %d times)\n", + lv_open_total); + else + sz += sprintf(LVM_PROC_BUF, ")"); + + sz += sprintf(LVM_PROC_BUF, + "\nGlobal: %lu bytes vmalloced IOP version: %d ", + vg_counter * sizeof(vg_t) + + pv_counter * sizeof(pv_t) + + lv_counter * sizeof(lv_t) + + pe_t_bytes + sz_last, + lvm_iop_version); + + seconds = CURRENT_TIME - loadtime; + if (seconds < 0) + loadtime = CURRENT_TIME + seconds; + if (seconds / 86400 > 0) { + sz += sprintf(LVM_PROC_BUF, "%d day%s ", + seconds / 86400, + seconds / 86400 == 0 || + seconds / 86400 > 1 ? "s" : ""); + } + sz += sprintf(LVM_PROC_BUF, "%d:%02d:%02d active\n", + (seconds % 86400) / 3600, + (seconds % 3600) / 60, + seconds % 60); + + if (vg_counter > 0) { + for (v = 0; v < ABS_MAX_VG; v++) { + /* volume group */ + if (vg[v] != NULL) { + inactive_flag = ' '; + if (!(vg[v]->vg_status & VG_ACTIVE)) + inactive_flag = 'I'; + sz += sprintf(LVM_PROC_BUF, + "\nVG: %c%s [%d PV, %d LV/%d open] " + " PE Size: %d KB\n" + " Usage [KB/PE]: %d /%d total " + "%d /%d used %d /%d free", + inactive_flag, + vg[v]->vg_name, + vg[v]->pv_cur, + vg[v]->lv_cur, + vg[v]->lv_open, + vg[v]->pe_size >> 1, + vg[v]->pe_size * vg[v]->pe_total >> 1, + vg[v]->pe_total, + vg[v]->pe_allocated * vg[v]->pe_size >> 1, + vg[v]->pe_allocated, + (vg[v]->pe_total - vg[v]->pe_allocated) * + vg[v]->pe_size >> 1, + vg[v]->pe_total - vg[v]->pe_allocated); + + /* physical volumes */ + sz += sprintf(LVM_PROC_BUF, + "\n PV%s ", + vg[v]->pv_cur == 1 ? ": " : "s:"); + c = 0; + for (p = 0; p < vg[v]->pv_max; p++) { + if (vg[v]->pv[p] != NULL) { + inactive_flag = 'A'; + if (!(vg[v]->pv[p]->pv_status & PV_ACTIVE)) + inactive_flag = 'I'; + allocation_flag = 'A'; + if (!(vg[v]->pv[p]->pv_allocatable & PV_ALLOCATABLE)) + allocation_flag = 'N'; + sz += sprintf(LVM_PROC_BUF, + "[%c%c] %-21s %8d /%-6d " + "%8d /%-6d %8d /%-6d", + inactive_flag, + allocation_flag, + vg[v]->pv[p]->pv_name, + vg[v]->pv[p]->pe_total * + vg[v]->pv[p]->pe_size >> 1, + vg[v]->pv[p]->pe_total, + vg[v]->pv[p]->pe_allocated * + vg[v]->pv[p]->pe_size >> 1, + vg[v]->pv[p]->pe_allocated, + (vg[v]->pv[p]->pe_total - + vg[v]->pv[p]->pe_allocated) * + vg[v]->pv[p]->pe_size >> 1, + vg[v]->pv[p]->pe_total - + vg[v]->pv[p]->pe_allocated); + c++; + if (c < vg[v]->pv_cur) + sz += sprintf(LVM_PROC_BUF, + "\n "); + } + } + + /* logical volumes */ + sz += sprintf(LVM_PROC_BUF, + "\n LV%s ", + vg[v]->lv_cur == 1 ? ": " : "s:"); + c = 0; + for (l = 0; l < vg[v]->lv_max; l++) { + if (vg[v]->lv[l] != NULL) { + inactive_flag = 'A'; + if (!(vg[v]->lv[l]->lv_status & LV_ACTIVE)) + inactive_flag = 'I'; + rw_flag = 'R'; + if (vg[v]->lv[l]->lv_access & LV_WRITE) + rw_flag = 'W'; + allocation_flag = 'D'; + if (vg[v]->lv[l]->lv_allocation & LV_CONTIGUOUS) + allocation_flag = 'C'; + stripes_flag = 'L'; + if (vg[v]->lv[l]->lv_stripes > 1) + stripes_flag = 'S'; + sz += sprintf(LVM_PROC_BUF, + "[%c%c%c%c", + inactive_flag, + rw_flag, + allocation_flag, + stripes_flag); + if (vg[v]->lv[l]->lv_stripes > 1) + sz += sprintf(LVM_PROC_BUF, "%-2d", + vg[v]->lv[l]->lv_stripes); + else + sz += sprintf(LVM_PROC_BUF, " "); + lv_name = lvm_strrchr(vg[v]->lv[l]->lv_name, '/'); + if (lv_name != NULL) + lv_name++; + else + lv_name = vg[v]->lv[l]->lv_name; + sz += sprintf(LVM_PROC_BUF, "] %-25s", lv_name); + if (lvm_strlen(lv_name) > 25) + sz += sprintf(LVM_PROC_BUF, + "\n "); + sz += sprintf(LVM_PROC_BUF, "%9d /%-6d ", + vg[v]->lv[l]->lv_size >> 1, + vg[v]->lv[l]->lv_size / vg[v]->pe_size); + + if (vg[v]->lv[l]->lv_open == 0) + sz += sprintf(LVM_PROC_BUF, "close"); + else + sz += sprintf(LVM_PROC_BUF, "%dx open", vg[v]->lv[l]->lv_open); + c++; + if (c < vg[v]->lv_cur) + sz += sprintf(LVM_PROC_BUF, "\n "); + } + } + if (vg[v]->lv_cur == 0) + sz += sprintf(LVM_PROC_BUF, "none"); + sz += sprintf(LVM_PROC_BUF, "\n"); + } + } + } + if (buf == NULL) { + if ((buf = vmalloc(sz)) == NULL) { + sz = 0; + return sprintf(page, "%s - vmalloc error at line %d\n", + lvm_name, __LINE__); + } + } + sz_last = sz; + } + } + if (pos > sz - 1) { + vfree(buf); + buf = NULL; + return -1; + } + *start = &buf[pos]; + + if (sz - pos < count) + return sz - pos; + else + return count; +} /* lvm_proc_get_info () */ +#endif /* #if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS */ + + +/* + * block device support function for /usr/src/linux/drivers/block/ll_rw_blk.c + * (see init_module/lvm_init) + */ +static int lvm_map(int minor, kdev_t * rdev, + ulong * rsector, ulong size, int rw) { + ulong index; + ulong rsector_sav; + kdev_t rdev_sav; + + if (!(vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_status & LV_ACTIVE)) { + printk(KERN_ALERT "%s - lvm_map: ll_rw_blk for inactive LV %s\n", + lvm_name, vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_name); + return -1; + } + if (rw == WRITE && + !(vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_access & LV_WRITE)) { + printk(KERN_CRIT + "%s - lvm_map: ll_rw_blk write for readonly LV %s\n", + lvm_name, vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_name); + return -1; + } +#ifdef DEBUG_MAP_SIZE + if (size != 2) + printk(KERN_DEBUG + "%s - lvm_map minor:%d size:%lu ", lvm_name, minor, size); +#endif + +#ifdef DEBUG_MAP + printk(KERN_DEBUG + "%s - lvm_map minor:%d *rdev: %02d:%02d *rsector: %lu " + "size:%lu\n", + lvm_name, minor, + MAJOR(*rdev), + MINOR(*rdev), + *rsector, size); +#endif + + if (*rsector + size > vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_size) { + printk(KERN_ALERT + "%s - lvm_map *rsector: %lu + size: %lu too large for" + " %02d:%02d\n", lvm_name, *rsector, size, + VG_BLK(minor), LV_BLK(minor)); + return -1; + } + rsector_sav = *rsector; + rdev_sav = *rdev; + + lvm_second_remap: + + /* linear mapping */ + if (vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_stripes < 2) { + index = *rsector / vg[VG_BLK(minor)]->pe_size; /* get the index */ + *rsector = vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_current_pe[index].pe + + (*rsector % vg[VG_BLK(minor)]->pe_size); + *rdev = vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_current_pe[index].dev; +#ifdef DEBUG_MAP + printk(KERN_DEBUG "lv_current_pe[%ld].pe: %ld rdev: %02d:%02d rsector:%ld\n", + index, vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_current_pe[index].pe, + MAJOR(*rdev), MINOR(*rdev), *rsector); +#endif + + /* striped mapping */ + } else { + ulong stripe_index; + ulong stripe_length; + + stripe_length = vg[VG_BLK(minor)]->pe_size * vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_stripes; + stripe_index = *rsector % stripe_length / vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_stripesize; + index = *rsector / stripe_length + (stripe_index % vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_stripes) * + (vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_allocated_le / + vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_stripes); + *rsector = vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_current_pe[index].pe + (*rsector % stripe_length) - + stripe_index % vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_stripes * vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_stripesize - + stripe_index / vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_stripes * (vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_stripes - 1) * + vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_stripesize; + *rdev = vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_current_pe[index].dev; + } + +#ifdef DEBUG_MAP + printk(KERN_DEBUG + "lv_current_pe[%ld].pe: %ld rdev: %02d:%02d rsector:%ld\n" + "stripe_length: %ld stripe_index: %ld\n", + index, vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_current_pe[index].pe, MAJOR(*rdev), MINOR(*rdev), *rsector, stripe_length, stripe_index); +#endif + + /* handle physical extents on the move */ + if (pe_lock_req.lock == LOCK_PE) { + if (*rdev == pe_lock_req.data.pv_dev && + *rsector >= pe_lock_req.data.pv_offset && + *rsector < (pe_lock_req.data.pv_offset + vg[VG_BLK(minor)]->pe_size)) { + sleep_on(&lvm_map_wait); + *rsector = rsector_sav; + *rdev = rsector_sav; + goto lvm_second_remap; + } + } + /* statistic */ + if (rw == WRITE || rw == WRITEA) + vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_current_pe[index].writes++; + else + vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_current_pe[index].reads++; + + return 0; +} /* lvm_map () */ + + +/* + * internal support functions + */ + +/* + * generate "hard disk" name + */ +void lvm_hd_name(char *buf, struct gendisk *gendisk, int minor) { + int len = 0; + + if (vg[VG_BLK(minor)] == NULL) + return; + if (vg[VG_BLK(minor)]->lv[LV_BLK(minor)] == NULL) + return; + len = lvm_strlen(vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_name) - 5; + lvm_memcpy(buf, &vg[VG_BLK(minor)]->lv[LV_BLK(minor)]->lv_name[5], len); + buf[len] = 0; + return; +} /* + * this one never should be called... + */ +static void lvm_dummy_device_request(void) { + printk(KERN_EMERG "%s -- oops, got lvm request?\n", lvm_name); + return; +} /* + * character device support function VGDA create + */ +int do_vg_create(int minor, void *arg) { + int error; + ulong l, p; + ulong size; + + if (vg[VG_CHR(minor)] != NULL) + return -EPERM; + + if ((vg[VG_CHR(minor)] = vmalloc(sizeof(vg_t))) == NULL) { + printk(KERN_CRIT "%s -- VG_CREATE: vmalloc error VG\n", lvm_name); + return -ENOMEM; + } + /* get the volume group structure */ if (copy_from_user(vg[VG_CHR(minor)], arg, sizeof(vg_t))) + return -EFAULT; + + /* we are not that active so far... */ + vg[VG_CHR(minor)]->vg_status &= ~VG_ACTIVE; + + error = FALSE; + if (vg[VG_CHR(minor)]->pv_max > ABS_MAX_PV) { + printk(KERN_WARNING "%s -- Can't activate VG: ABS_MAX_PV too small\n", lvm_name); + error = TRUE; + } + if (vg[VG_CHR(minor)]->lv_max > ABS_MAX_LV) { + printk(KERN_WARNING "%s -- Can't activate VG: ABS_MAX_LV too small for %u\n", lvm_name, vg[VG_CHR(minor)]->lv_max); + error = TRUE; + } + if (error == TRUE) { +#ifdef DEBUG_VFREE + printk(KERN_DEBUG + "%s -- vfree %d\n", lvm_name, __LINE__); +#endif + vfree(vg[VG_CHR(minor)]); + vg[VG_CHR(minor)] = NULL; + return -EPERM; + } + /* get the physical volume structures */ + vg[VG_CHR(minor)]->pv_act = vg[VG_CHR(minor)]->pv_cur = 0; + for (p = 0; p < vg[VG_CHR(minor)]->pv_max; p++) { + /* user space address */ + if ((pvp = vg[VG_CHR(minor)]->pv[p]) != NULL) { + vg[VG_CHR(minor)]->pv[p] = vmalloc(sizeof(pv_t)); + if (vg[VG_CHR(minor)]->pv[p] == NULL) { + printk(KERN_CRIT "%s -- VG_CREATE: vmalloc error PV\n", lvm_name); + for (; p < vg[VG_CHR(minor)]->pv_max; p++) + vg[VG_CHR(minor)]->pv[p] = NULL; + do_vg_remove(minor); + return -ENOMEM; + } + if (copy_from_user(vg[VG_CHR(minor)]->pv[p], pvp, sizeof(pv_t))) + return -EFAULT; + /* We don't need the PE list + in kernel space as with LVs pe_t list (see below) */ + vg[VG_CHR(minor)]->pv[p]->pe = NULL; + vg[VG_CHR(minor)]->pv[p]->pv_status = PV_ACTIVE; + vg[VG_CHR(minor)]->pv_act++; + vg[VG_CHR(minor)]->pv_cur++; + +#ifdef LVM_GET_INODE + /* insert a dummy inode for fs_may_mount */ + vg[VG_CHR(minor)]->pv[p]->inode = lvm_get_inode(vg[VG_CHR(minor)]->pv[p]->pv_dev); +#endif + } + } + + /* get the logical volume structures */ + vg[VG_CHR(minor)]->lv_cur = 0; + for (l = 0; l < vg[VG_CHR(minor)]->lv_max; l++) { + /* user space address */ + if ((lvp = vg[VG_CHR(minor)]->lv[l]) != NULL) { + if ((vg[VG_CHR(minor)]->lv[l] = vmalloc(sizeof(lv_t))) == NULL) { + printk(KERN_ERR "%s -- VG_CREATE: vmalloc error LV\n", lvm_name); + do_vg_remove(minor); + return -ENOMEM; + } + copy_from_user(vg[VG_CHR(minor)]->lv[l], lvp, sizeof(lv_t)); + vg[VG_CHR(minor)]->lv_cur++; + LVM_CORRECT_READ_AHEAD(vg[VG_CHR(minor)]->lv[l]->lv_read_ahead); + + if (vg_lv_map[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)].vg_number != ABS_MAX_VG) { + do_vg_remove(minor); + return -ENXIO; + } + lvm_gendisk.part[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)].start_sect = 0; + lvm_gendisk.part[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)].nr_sects = vg[VG_CHR(minor)]->lv[l]->lv_size; + lvm_size[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)] = vg[VG_CHR(minor)]->lv[l]->lv_size >> 1; + vg_lv_map[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)].vg_number = vg[VG_CHR(minor)]->vg_number; + vg_lv_map[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)].lv_number = vg[VG_CHR(minor)]->lv[l]->lv_number; + +#ifdef DEBUG_VG_CREATE + printk(KERN_DEBUG + "%s -- VG_CREATE: lvm_size[%d]: %d\n", + lvm_name, + minor + l + 1, + lvm_size[minor + l + 1]); +#endif + + /* Get the lv_current_pe list for device mapping */ + /* user address */ + if ((pep = vg[VG_CHR(minor)]->lv[l]->lv_current_pe) != NULL) { + size = vg[VG_CHR(minor)]->lv[l]->lv_allocated_le * sizeof(pe_t); + if ((vg[VG_CHR(minor)]->lv[l]->lv_current_pe = vmalloc(size)) == NULL) { + printk(KERN_ERR "%s -- VG_CREATE: vmalloc error LV_CURRENT_PE\n", + lvm_name); + for (; l < ABS_MAX_LV + 1; l++) + vg[VG_CHR(minor)]->lv[l] = NULL; + do_vg_remove(minor); + return -ENOMEM; + } + copy_from_user(vg[VG_CHR(minor)]->lv[l]->lv_current_pe, pep, size); + } else { + do_vg_remove(minor); + return -ENXIO; + } + } + } + vg_count++; + + /* let's go active */ + vg[VG_CHR(minor)]->vg_status |= VG_ACTIVE; + + MOD_INC_USE_COUNT; + return 0; +} + + +/* + * character device support function VGDA remove + */ +static int do_vg_remove(int minor) { + int l, p; + + if (vg[VG_CHR(minor)] == NULL) + return -ENXIO; +#ifdef LVM_TOTAL_RESET + if (vg[VG_CHR(minor)]->lv_open > 0 && lvm_reset_spindown == 0) +#else + if (vg[VG_CHR(minor)]->lv_open > 0) +#endif + return -EPERM; + + /* let's go inactive */ + vg[VG_CHR(minor)]->vg_status &= ~VG_ACTIVE; + + /* Free LVs */ + for (l = 0; l < vg[VG_CHR(minor)]->lv_max; l++) { + if (vg[VG_CHR(minor)]->lv[l] != NULL) { + do_lv_remove(minor, vg[VG_CHR(minor)]->lv[l]->lv_name); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } + } /* Free PVs */ + for (p = 0; p < vg[VG_CHR(minor)]->pv_max; p++) { + if (vg[VG_CHR(minor)]->pv[p] != NULL) { +#ifdef DEBUG_VFREE + printk(KERN_DEBUG + "%s -- vfree %d\n", lvm_name, __LINE__); +#endif +#ifdef LVM_GET_INODE + clear_inode(vg[VG_CHR(minor)]->pv[p]->inode); +#endif + vfree(vg[VG_CHR(minor)]->pv[p]); + vg[VG_CHR(minor)]->pv[p] = NULL; + } + } + +#ifdef DEBUG_VFREE + printk(KERN_DEBUG "%s -- vfree %d\n", lvm_name, __LINE__); +#endif + vfree(vg[VG_CHR(minor)]); + vg[VG_CHR(minor)] = NULL; + vg_count--; + + MOD_DEC_USE_COUNT; + return 0; +} /* do_vg_remove () */ + + +/* + * character device support function logical volume create + */ +static int do_lv_create(int minor, char *lv_name, lv_t * lv, + struct inode *inode) { + int l, le, l_new, p, size; + ulong lv_status_save; + + if ((pep = lv->lv_current_pe) == NULL) + return -EINVAL; + + l_new = -1; + /* in case of lv_remove(), lv_create() pair; for eg. lvrename does this */ + if (vg[VG_CHR(minor)]->lv[lv->lv_number] == NULL) + l_new = lv->lv_number; + else { + for (l = 0; l < vg[VG_CHR(minor)]->lv_max; l++) { + if (lvm_strcmp(vg[VG_CHR(minor)]->lv[l]->lv_name, lv_name) == 0) + return -EEXIST; + if (vg[VG_CHR(minor)]->lv[l] == NULL) + if (l_new == -1) + l_new = l; + } + } + if (l_new == -1) + return -EPERM; + l = l_new; + + if ((vg[VG_CHR(minor)]->lv[l] = vmalloc(sizeof(lv_t))) == NULL) { + printk(KERN_ERR "%s -- LV_CREATE: vmalloc error LV\n", lvm_name); + return -ENOMEM; + } + /* copy preloaded LV */ + lvm_memcpy((char *) vg[VG_CHR(minor)]->lv[l], + (char *) lv, sizeof(lv_t)); + lv_status_save = vg[VG_CHR(minor)]->lv[l]->lv_status; + vg[VG_CHR(minor)]->lv[l]->lv_status &= ~LV_ACTIVE; + + /* get the PE structures from user space */ + size = vg[VG_CHR(minor)]->lv[l]->lv_allocated_le * sizeof(pe_t); + if ((vg[VG_CHR(minor)]->lv[l]->lv_current_pe = vmalloc(size)) == NULL) { + printk(KERN_CRIT "%s -- LV_CREATE: vmalloc error LV_CURRENT_PE of %d Byte\n", lvm_name, size); +#ifdef DEBUG_VFREE + printk(KERN_DEBUG "%s -- vfree %d\n", lvm_name, __LINE__); +#endif + vfree(vg[VG_CHR(minor)]->lv[l]); + vg[VG_CHR(minor)]->lv[l] = NULL; + return -ENOMEM; + } + copy_from_user(vg[VG_CHR(minor)]->lv[l]->lv_current_pe, pep, size); + vg[VG_CHR(minor)]->lv_cur++; + + /* correct the PE count in PVs */ + for (le = 0; le < vg[VG_CHR(minor)]->lv[l]->lv_allocated_le; le++) { + vg[VG_CHR(minor)]->pe_allocated++; + for (p = 0; p < vg[VG_CHR(minor)]->pv_cur; p++) { + if (vg[VG_CHR(minor)]->pv[p]->pv_dev == + vg[VG_CHR(minor)]->lv[l]->lv_current_pe[le].dev) + vg[VG_CHR(minor)]->pv[p]->pe_allocated++; + } + } + + lvm_gendisk.part[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)].start_sect = 0; + lvm_gendisk.part[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)].nr_sects = vg[VG_CHR(minor)]->lv[l]->lv_size; + lvm_size[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)] = vg[VG_CHR(minor)]->lv[l]->lv_size >> 1; + vg_lv_map[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)].vg_number = vg[VG_CHR(minor)]->vg_number; + vg_lv_map[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)].lv_number = vg[VG_CHR(minor)]->lv[l]->lv_number; + + vg[VG_CHR(minor)]->lv[l]->lv_status = lv_status_save; + LVM_CORRECT_READ_AHEAD(vg[VG_CHR(minor)]->lv[l]->lv_read_ahead); + + return 0; +} /* do_lv_create () */ + + +/* + * character device support function logical volume remove + */ +static int do_lv_remove(int minor, char *lv_name) { + uint l, le, p; + + for (l = 0; l < vg[VG_CHR(minor)]->lv_max; l++) { + if (vg[VG_CHR(minor)]->lv[l] != NULL && + lvm_strcmp(vg[VG_CHR(minor)]->lv[l]->lv_name, lv_name) == 0) { +#ifdef LVM_TOTAL_RESET + if (vg[VG_CHR(minor)]->lv[l]->lv_open > 0 && lvm_reset_spindown == 0) +#else + if (vg[VG_CHR(minor)]->lv[l]->lv_open > 0) +#endif + return -EBUSY; +#ifdef DEBUG + printk(KERN_DEBUG + "%s -- fsync_dev and " + "invalidate_buffers for %s [%s] in %s\n", + lvm_name, vg[VG_CHR(minor)]->lv[l]->lv_name, + kdevname(vg[VG_CHR(minor)]->lv[l]->lv_dev), + vg[VG_CHR(minor)]->vg_name); +#endif + vg[VG_CHR(minor)]->lv[l]->lv_status |= LV_SPINDOWN; + fsync_dev(vg[VG_CHR(minor)]->lv[l]->lv_dev); + vg[VG_CHR(minor)]->lv[l]->lv_status &= ~LV_ACTIVE; + invalidate_buffers(vg[VG_CHR(minor)]->lv[l]->lv_dev); + lvm_gendisk.part[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)].start_sect = \ + -1; + lvm_gendisk.part[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)].nr_sects = 0; + lvm_size[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)] = 0; + vg_lv_map[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)].vg_number = + ABS_MAX_VG; + vg_lv_map[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)].lv_number = -1; + + for (le = 0; le < vg[VG_CHR(minor)]->lv[l]->lv_allocated_le; le++) { + vg[VG_CHR(minor)]->pe_allocated--; + for (p = 0; p < vg[VG_CHR(minor)]->pv_cur; p++) { + if (vg[VG_CHR(minor)]->pv[p]->pv_dev == + vg[VG_CHR(minor)]->lv[l]->lv_current_pe[le].dev) + vg[VG_CHR(minor)]->pv[p]->pe_allocated--; + } + } +#ifdef DEBUG_VFREE + printk(KERN_DEBUG "%s -- vfree %d\n", lvm_name, __LINE__); +#endif + vfree(vg[VG_CHR(minor)]->lv[l]->lv_current_pe); + +#ifdef DEBUG_VFREE + printk(KERN_DEBUG "%s -- vfree %d\n", lvm_name, __LINE__); +#endif + vfree(vg[VG_CHR(minor)]->lv[l]); + vg[VG_CHR(minor)]->lv[l] = NULL; + vg[VG_CHR(minor)]->lv_cur--; + return 0; + } + } + return -ENXIO; +} /* do_lv_remove () */ + + +/* + * character device support function logical volume extend / reduce + */ +static int do_lv_extend_reduce(int minor, char *lv_name, lv_t * lv, + struct inode *inode) { + int l, le, p, size; + uint32_t end, lv_status_save; + pe_t *pe; + + if ((pep = lv->lv_current_pe) == NULL) + return -EINVAL; + + for (l = 0; l < vg[VG_CHR(minor)]->lv_max; l++) { + if (vg[VG_CHR(minor)]->lv[l] != NULL && + lvm_strcmp(vg[VG_CHR(minor)]->lv[l]->lv_name, lv_name) == 0) + break; + } + if (l == vg[VG_CHR(minor)]->lv_max) + return -ENXIO; + + if ((pe = vmalloc(size = lv->lv_current_le * sizeof(pe_t))) == NULL) { + printk(KERN_CRIT + "%s -- do_lv_extend_reduce: vmalloc error LV_CURRENT_PE " + "of %d Byte\n", lvm_name, size); + return -ENOMEM; + } + +#ifdef DEBUG + printk(KERN_DEBUG + "%s -- fsync_dev and " + "invalidate_buffers for %s [%s] in %s\n", + lvm_name, vg[VG_CHR(minor)]->lv[l]->lv_name, + kdevname(vg[VG_CHR(minor)]->lv[l]->lv_dev), + vg[VG_CHR(minor)]->vg_name); +#endif + + vg[VG_CHR(minor)]->lv[l]->lv_status |= LV_SPINDOWN; + fsync_dev(vg[VG_CHR(minor)]->lv[l]->lv_dev); + vg[VG_CHR(minor)]->lv[l]->lv_status &= ~LV_ACTIVE; + invalidate_buffers(vg[VG_CHR(minor)]->lv[l]->lv_dev); + + /* reduce allocation counters on PV(s) */ + for (le = 0; le < vg[VG_CHR(minor)]->lv[l]->lv_allocated_le; le++) { + vg[VG_CHR(minor)]->pe_allocated--; + for (p = 0; p < vg[VG_CHR(minor)]->pv_cur; p++) { + if (vg[VG_CHR(minor)]->pv[p]->pv_dev == + vg[VG_CHR(minor)]->lv[l]->lv_current_pe[le].dev) { + vg[VG_CHR(minor)]->pv[p]->pe_allocated--; + break; + } + } + } + +#ifdef DEBUG_VFREE + printk(KERN_DEBUG "%s -- vfree %d\n", lvm_name, __LINE__); +#endif + + /* save pointer to "old" lv/pe pointer array */ + pep1 = vg[VG_CHR(minor)]->lv[l]->lv_current_pe; + end = vg[VG_CHR(minor)]->lv[l]->lv_current_le; + + lv_open = vg[VG_CHR(minor)]->lv[l]->lv_open; + + /* copy preloaded LV */ + lvm_memcpy((char *) vg[VG_CHR(minor)]->lv[l], (char *) lv, sizeof(lv_t)); + lv_status_save = vg[VG_CHR(minor)]->lv[l]->lv_status; + vg[VG_CHR(minor)]->lv[l]->lv_status |= LV_SPINDOWN; + vg[VG_CHR(minor)]->lv[l]->lv_status &= ~LV_ACTIVE; + vg[VG_CHR(minor)]->lv[l]->lv_current_pe = pe; + + /* get the PE structures from user space */ + copy_from_user(vg[VG_CHR(minor)]->lv[l]->lv_current_pe, pep, size); + + vg[VG_CHR(minor)]->lv[l]->lv_open = lv_open; + + /* Check what last LE shall be used */ + if (end > vg[VG_CHR(minor)]->lv[l]->lv_current_le) + end = vg[VG_CHR(minor)]->lv[l]->lv_current_le; + + /* save availiable i/o statistic data */ + for (le = 0; le < end; le++) { + vg[VG_CHR(minor)]->lv[l]->lv_current_pe[le].reads = pep1[le].reads; + vg[VG_CHR(minor)]->lv[l]->lv_current_pe[le].writes = pep1[le].writes; + } + vfree(pep1); + pep1 = NULL; + + + /* extend the PE count in PVs */ + for (le = 0; le < vg[VG_CHR(minor)]->lv[l]->lv_allocated_le; le++) { + vg[VG_CHR(minor)]->pe_allocated++; + for (p = 0; p < vg[VG_CHR(minor)]->pv_cur; p++) { + if (vg[VG_CHR(minor)]->pv[p]->pv_dev == + vg[VG_CHR(minor)]->lv[l]->lv_current_pe[le].dev) { + vg[VG_CHR(minor)]->pv[p]->pe_allocated++; + break; + } + } + } + + lvm_gendisk.part[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)].start_sect = 0; + lvm_gendisk.part[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)].nr_sects = + vg[VG_CHR(minor)]->lv[l]->lv_size; + lvm_size[MINOR(vg[VG_CHR(minor)]->lv[l]->lv_dev)] = + vg[VG_CHR(minor)]->lv[l]->lv_size >> 1; + /* vg_lv_map array doesn't have to be changed here */ + + vg[VG_CHR(minor)]->lv[l]->lv_status = lv_status_save; + LVM_CORRECT_READ_AHEAD(vg[VG_CHR(minor)]->lv[l]->lv_read_ahead); + + return 0; +} /* do_lv_extend_reduce () */ + + +/* + * support function initialize gendisk variables + */ + +static void __init lvm_geninit(struct gendisk *lvm_gdisk) { + int i = 0; + +#ifdef DEBUG_GENDISK + printk(KERN_DEBUG "%s -- lvm_gendisk\n", lvm_name); +#endif + + for (i = 0; i < MAX_LV; i++) { + lvm_gendisk.part[i].start_sect = -1; /* avoid partition check */ + lvm_size[i] = lvm_gendisk.part[i].nr_sects = 0; + lvm_blocksizes[i] = BLOCK_SIZE; + } + blksize_size[LVM_BLOCK_MAJOR] = lvm_blocksizes; + blk_size[LVM_BLOCK_MAJOR] = lvm_size; + + return; +} /* lvm_gen_init () */ + + +#ifdef LVM_GET_INODE +/* + * support function to get an empty inode + * + * Gets an empty inode to be inserted into the inode hash, + * so that a physical volume can't be mounted. + * This is analog to drivers/block/md.c + * + * Is this the real thing? + * + */ +struct inode *lvm_get_inode(int dev) { + struct inode *inode_this = NULL; + + /* Lock the device by inserting a dummy inode. */ + inode_this = get_empty_inode(); + inode_this->i_dev = dev; + insert_inode_hash(inode_this); + return inode_this; +} +#endif + +/* my strlen */ + +inline int lvm_strlen(char *s1) +{ + int len = 0; + + while (s1[len] != 0) + len++; + return len; +} + +/* my strcmp */ +inline int lvm_strcmp(char *s1, char *s2) { + while (*s1 != 0 && *s2 != 0) { + if (*s1 != *s2) + return -1; + s1++; + s2++; + } + if (*s1 == 0 && *s2 == 0) + return 0; + return -1; +} + + +/* my strrchr */ +inline char *lvm_strrchr(char *s1, char c) { + char *s2 = NULL; + + while (*s1 != 0) { + if (*s1 == c) + s2 = s1; + s1++; + } + return s2; +} + + +/* my memcpy */ +inline void lvm_memcpy(char *dest, char *source, int size) { + for (; size > 0; size--) + *dest++ = *source++; +} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/lvm_old.c linux.ac/drivers/block/lvm_old.c --- linux.vanilla/drivers/block/lvm_old.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/block/lvm_old.c Mon Jul 19 03:26:58 1999 @@ -0,0 +1,729 @@ + +/* + lvm.c : Logical Volume Manager for Linux + Copyright (C) 1998 Ingo Molnar + + LVM management functions. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + You should have received a copy of the GNU General Public License + (for example /usr/src/linux/COPYING); if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include + +#define MAJOR_NR LVM_MAJOR +#define LVM_DRIVER + +#include + +lvdev_t lv_devs[MAX_LVM_DEV]; + +static LVM_LIST_HEAD(lvm_managed_devices); + +static lvm_rdisk_t * find_rdisk_all (kdev_t dev) +{ + struct lvm_list_head *tmp; + lvm_rdisk_t *rdisk; + + tmp = lvm_managed_devices.next; + while (tmp != &lvm_managed_devices) { + rdisk = lvm_list_entry(tmp, lvm_rdisk_t, lvm_managed); + if (rdisk->dev == dev) + return rdisk; + tmp = tmp->next; + } + return NULL; +} + +/* + * Prevent the device from being mounted or otherwise reused + * in the LVM (or any other kernel subsystem), by adding a + * dummy inode. + */ +static void lock_rdisk (lvm_rdisk_t *rdisk) +{ + /* + * Insert dummy inode to 'lock' the device + */ + rdisk->inode = get_empty_inode(); + /* + * we dont care about other fields + */ + rdisk->inode->i_dev = rdisk->dev; + insert_inode_hash(rdisk->inode); +} + +static void unlock_rdisk (lvm_rdisk_t *rdisk) +{ + clear_inode(rdisk->inode); +} + +#define NO_SB KERN_ERR \ +"lvm: skipping device %s, could not read superblock.\n" + +#define BAD_MAGIC KERN_ERR \ +"lvm: invalid LVM superblock magic on %s\n" + +#define OUT_OF_MEM KERN_ALERT \ +"lvm: out of memory.\n" + +#define BAD_CSUM KERN_WARNING \ +"lvm: invalid superblock checksum on %s\n" + +static int alloc_rdisk_sb (lvm_rdisk_t * rdisk) +{ + if (rdisk->sb) + LVM_BUG(); + + rdisk->sb = (lvm_super_t *) __get_free_page(GFP_KERNEL); + if (!rdisk->sb) { + printk (OUT_OF_MEM); + return -EINVAL; + } + lvm_clear_page((unsigned long)rdisk->sb); + + return 0; +} + +static void free_rdisk_sb (lvm_rdisk_t * rdisk) +{ + if (rdisk->sb) { + free_page((unsigned long) rdisk->sb); + rdisk->sb = NULL; + rdisk->size = 0; + } else { + if (!rdisk->faulty) + LVM_BUG(); + } +} + +static unsigned int calc_sb_csum (lvm_super_t * sb) +{ + unsigned int disk_csum, csum; + + disk_csum = sb->sb_csum; + sb->sb_csum = 0; + csum = csum_partial((void *)sb, LVM_SB_BYTES, 0); + sb->sb_csum = disk_csum; + return csum; +} + +/* + * Check one LVM superblock for generic plausibility + */ + +static int check_rdisk_sb (lvm_rdisk_t * rdisk) +{ + lvm_super_t *sb; + int ret = -EINVAL; + + sb = rdisk->sb; + if (!sb) { + LVM_BUG(); + goto abort; + } + + if (sb->lvm_magic != LVM_SB_MAGIC) { + printk (BAD_MAGIC, partition_name(rdisk->dev)); + goto abort; + } + + if (calc_sb_csum(sb) != sb->sb_csum) + printk(BAD_CSUM, partition_name(rdisk->dev)); + ret = 0; +abort: + return ret; +} + +static int read_rdisk_sb (lvm_rdisk_t * rdisk) +{ + int ret = -EINVAL; + struct buffer_head *bh = NULL; + kdev_t dev = rdisk->dev; + lvm_super_t *sb; + + if (!rdisk->sb) { + LVM_BUG(); + goto abort; + } + + /* + * Read the superblock, it's at the beginning of the disk + */ + set_blocksize (dev, LVM_SB_BYTES); + bh = bread (dev, 0, LVM_SB_BYTES); + + if (bh) { + sb = (lvm_super_t *) bh->b_data; + memcpy (rdisk->sb, sb, LVM_SB_BYTES); + } else { + printk (NO_SB,partition_name(rdisk->dev)); + goto abort; + } + ret = 0; +abort: + if (bh) + brelse (bh); + return ret; +} + +#undef BAD_CSUM +#undef BAD_MAGIC +#undef OUT_OF_MEM +#undef NO_SB + + +#define GETBLK_FAILED KERN_ERR \ +"lvm: getblk failed for device %s\n" + +static int write_rdisk_sb(lvm_rdisk_t * rdisk) +{ + struct buffer_head *bh; + kdev_t dev; + lvm_super_t *sb; + + if (!rdisk->sb) { + LVM_BUG(); + return -1; + } + if (rdisk->sb->lvm_magic != LVM_SB_MAGIC) { + LVM_BUG(); + return -1; + } + + dev = rdisk->dev; + + printk("(write) %s\n", partition_name(dev)); + set_blocksize(dev, LVM_SB_BYTES); + bh = getblk(dev, 0, LVM_SB_BYTES); + if (!bh) { + printk(GETBLK_FAILED, partition_name(dev)); + return 1; + } + memset(bh->b_data,0,bh->b_size); + sb = (lvm_super_t *) bh->b_data; + memcpy(sb, rdisk->sb, LVM_SB_BYTES); + + mark_buffer_uptodate(bh, 1); + mark_buffer_dirty(bh, 1); + ll_rw_block(WRITE, 1, &bh); + wait_on_buffer(bh); + brelse(bh); + fsync_dev(dev); + return 0; +} +#undef GETBLK_FAILED KERN_ERR + +/* + * Import a device, sanity check the superblock + */ +static int lvm_import_device (kdev_t newdev) +{ + int err = 0; + lvm_rdisk_t *rdisk; + unsigned int size; + + if (find_rdisk_all(newdev)) + return -EEXIST; + + rdisk = (lvm_rdisk_t *) kmalloc(sizeof(*rdisk), GFP_KERNEL); + if (!rdisk) { + printk("could not alloc mem for %s!\n", partition_name(newdev)); + return -ENOMEM; + } + memset(rdisk, 0, sizeof(*rdisk)); + + if (!fs_may_mount(newdev)) { + printk("lvm: can not import %s, has active inodes!\n", + partition_name(newdev)); + err = -EBUSY; + goto abort_free; + } + + if ((err = alloc_rdisk_sb(rdisk))) + goto abort_free; + + rdisk->dev = newdev; + lock_rdisk(rdisk); + + size = blk_size[MAJOR(newdev)][MINOR(newdev)]; + if (!size) { + printk("lvm: %s has zero size, marking faulty!\n", + partition_name(newdev)); + rdisk->faulty = 1; + goto out_faulty; + } + + if ((err = read_rdisk_sb(rdisk))) { + printk("lvm: %s has zero size,marking faulty!\n", + partition_name(newdev)); + rdisk->faulty = 1; + goto out_faulty; + } + if ((err = check_rdisk_sb(rdisk))) { + printk("lvm: %s has invalid sb, skipping!\n", + partition_name(newdev)); + rdisk->faulty = 1; + goto out_faulty; + } + + rdisk->old_dev = MKDEV(rdisk->sb->this_major, + rdisk->sb->this_minor); + +out_faulty: + lvm_list_add(&rdisk->lvm_managed, &lvm_managed_devices); + if (rdisk->faulty && rdisk->sb) + free_rdisk_sb(rdisk); + return 0; + +abort_free: + kfree(rdisk); + return err; +} + +/* + * Searches all registered partitions for LVM devices + * at boot time. + */ +lvm__initfunc(void autodetect_lvm(void)) +{ + struct gendisk *disk; + int i; + + printk(KERN_INFO "autodetecting LVM devices\n"); + + for (disk = gendisk_head ; disk ; disk = disk->next) + for (i = 0; i < disk->max_p*disk->max_nr; i++) { + kdev_t dev = MKDEV(disk->major,i); + + if (disk->part[i].type == LINUX_LVM_PARTITION) { + printk(KERN_INFO "found raw LVM partition %s\n", + partition_name(dev)); + lvm_import_device(dev); + } + } +} + +static void do_lvm_request (void) +{ + printk(KERN_ALERT "Got LVM request, not good..."); + return; +} + +int lvm_size[MAX_LVM_DEV] = {0, }; +static struct hd_struct lvm_hd_struct[MAX_LVM_DEV]; +static int lvm_blocksizes[MAX_LVM_DEV]; +static int lvm_maxreadahead[MAX_LVM_DEV]; + +static void lvm_geninit (struct gendisk *); + +static struct gendisk lvm_gendisk= +{ + LVM_MAJOR, + "lvm", + 0, + 1, + MAX_LVM_DEV, + lvm_geninit, + lvm_hd_struct, + lvm_size, + MAX_LVM_DEV, + NULL, + NULL +}; + +static void lvm_geninit (struct gendisk *gdisk) +{ + int i; + + for(i = 0; i < MAX_LVM_DEV; i++) { + lvm_blocksizes[i] = 1024; + lvm_maxreadahead[i] = 128; + lvm_gendisk.part[i].start_sect = -1; /* avoid partition check */ + lvm_gendisk.part[i].nr_sects = 0; + } + + blksize_size[LVM_MAJOR] = lvm_blocksizes; + lvm_set_global_readahead(lvm_maxreadahead); +} + +static int get_version (void * arg) +{ + lvm_version_t ver; + + ver.major = LVM_MAJOR_VERSION; + ver.minor = LVM_MINOR_VERSION; + ver.patchlevel = LVM_PATCHLEVEL_VERSION; + + if (md_copy_to_user(arg, &ver, sizeof(ver))) + return -EFAULT; + + return 0; +} + +static int lvm_ioctl (struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + unsigned int minor; + int err = 0; + struct hd_geometry *loc = (struct hd_geometry *) arg; + + if (!lvm_capable_admin()) + return -EACCES; + + minor = MINOR(inode->i_rdev); + if (minor >= MAX_LVM_DEV) + return -EINVAL; + + switch (cmd) + { + case LVM_VERSION: + err = get_version((void *)arg); + break; + + case BLKGETSIZE: /* Return device size */ + if (!arg) { + err = -EINVAL; + break; + } + err = lvm_put_user(lvm_hd_struct[ + MINOR(inode->i_rdev)].nr_sects, (long *) arg); + break; + + case BLKFLSBUF: + fsync_dev (inode->i_rdev); + invalidate_buffers (inode->i_rdev); + break; + + case BLKRASET: + if (arg > 0xff) + err = -EINVAL; + read_ahead[MAJOR(inode->i_rdev)] = arg; + break; + + case BLKRAGET: + if (!arg) + err = -EINVAL; + err = lvm_put_user (read_ahead[ + MAJOR(inode->i_rdev)], (long *) arg); + break; + /* + * We have a problem here : there is no easy way to give a CHS + * virtual geometry. We currently pretend that we have a 2 heads + * 4 sectors (with a BIG number of cylinders...). This drives + * dosfs just mad... ;-) + */ + case HDIO_GETGEO: + if (!loc) { + err = -EINVAL; + break; + } + err = lvm_put_user (2, (char *) &loc->heads); + if (err) + break; + err = lvm_put_user (4, (char *) &loc->sectors); + if (err) + break; + err = lvm_put_user (lvm_hd_struct[minor].nr_sects/8, + (short *) &loc->cylinders); + if (err) + break; + err = lvm_put_user (lvm_hd_struct[MINOR(inode->i_rdev) + ].start_sect, (long *) &loc->start); + break; + + default: + printk(KERN_WARNING "%s(pid %d) used obsolete LVM ioctl, upgrade your software to use new ictls.\n", current->comm, current->pid); + err = -EINVAL; + } + return err; +} + +#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,0) + +static int lvm_open (struct inode *inode, struct file *file) +{ + /* + * Always succeed + */ + return (0); +} + +static void lvm_release (struct inode *inode, struct file *file) +{ + sync_dev(inode->i_rdev); +} + + +static int lvm_read (struct inode *inode, struct file *file, + char *buf, int count) +{ + if (!kdev_to_lvdev(LVM_FILE_TO_INODE(file)->i_rdev)->running) + return -ENXIO; + + return block_read (inode, file, buf, count); +} + +static int lvm_write (struct inode *inode, struct file *file, + const char *buf, int count) +{ + if (!kdev_to_lvdev(LVM_FILE_TO_INODE(file)->i_rdev)->running) + return -ENXIO; + + return block_write (inode, file, buf, count); +} + +static struct file_operations lvm_fops= +{ + NULL, + lvm_read, + lvm_write, + NULL, + NULL, + lvm_ioctl, + NULL, + lvm_open, + lvm_release, + block_fsync +}; + +#else + +static int lvm_open (struct inode *inode, struct file *file) +{ + /* + * Always succeed + */ + return (0); +} + +static int lvm_release (struct inode *inode, struct file *file) +{ + sync_dev(inode->i_rdev); + return 0; +} + +static ssize_t lvm_read (struct file *file, char *buf, size_t count, + loff_t *ppos) +{ + if (!kdev_to_lvdev(LVM_FILE_TO_INODE(file)->i_rdev)->running) + return -ENXIO; + + return block_read(file, buf, count, ppos); +} + +static ssize_t lvm_write (struct file *file, const char *buf, + size_t count, loff_t *ppos) +{ + if (!kdev_to_lvdev(LVM_FILE_TO_INODE(file)->i_rdev)->running) + return -ENXIO; + + return block_write(file, buf, count, ppos); +} + +static struct file_operations lvm_fops= +{ + NULL, + lvm_read, + lvm_write, + NULL, + NULL, + lvm_ioctl, + NULL, + lvm_open, + NULL, + lvm_release, + block_fsync +}; + +#endif + +static void extend_index_space (lvdev_t *lv) +{ +#warning not yet +} + +static inline unsigned int __get_free_block (pvdev_t *pv) +{ + if (pv->first_free_block == pv->max_blocks) { + printk("lvm: pv %s full!\n", partition_name(pv->rdev->dev)); + return 0; + } + return pv->first_free_block++; +} + +static unsigned int get_free_block (lvdev_t *lv) +{ + unsigned int idx; + + while (!lv->free_indices) + extend_index_space(lv); + + idx = __get_free_block(&lv->pv); + if (!idx) + LVM_BUG(); + + return idx; +} + +static inline lvm_lptr_t * __get_free_index (lvdev_t *lv) +{ +#warning not yet + return 0; +} + +static lvm_lptr_t * get_free_index (lvdev_t *lv) +{ + lvm_lptr_t *index; + + if (!lv->free_indices) + extend_index_space(lv); + + index = __get_free_index(lv); + if (!index) + LVM_BUG(); + + return index; +} + + +static unsigned int index_to_idx (lvm_lptr_t *index) +{ +#warning not yet + return 0; +} + +static void bind_block_to_index (lvm_lptr_t *index, + unsigned int block, lvdev_t *lv) +{ + index->data.phys_block = block; +} + +unsigned int alloc_index (kdev_t dev) +{ + lvdev_t *lv = kdev_to_lvdev(dev); + lvm_lptr_t *index; + unsigned int block; + + index = get_free_index(lv); + if (!index) { + LVM_BUG(); + return 0; + } + block = get_free_block(lv); + bind_block_to_index(index,block,lv); + + return index_to_idx(index); +} + +#define INDEX_BITS 8 +#define INDEX_DEPTH (32/INDEX_BITS) +#define INDEX_MASK ((1<root_index; + unsigned int idx, l; + + for (l = 0; l < INDEX_DEPTH; l++) { + idx = lblock & INDEX_MASK; + index += idx; + index = (lvm_lptr_t *) (index->cpu_addr); + if (!index) { + return NULL; + } + lblock >>= INDEX_BITS; + } + return index; +} + +static int lvm_map (kdev_t dev, kdev_t *rdev, + unsigned long *rsector, int bsize_bits) +{ + lvdev_t *lv = kdev_to_lvdev(dev); + lvm_lptr_t *index; + unsigned int lblock = *rsector >> bsize_bits; + int err = -EIO; + + index = find_index(lv, lblock); + if (!index) { + printk("no block %u yet ...\n", lblock); + goto out; + } + + err = 0; +out: + return err; +} + +lvm__initfunc(void lvm_init(void)) +{ + printk (KERN_INFO "Logical Volume Manager for Linux %d.%d.%d\n", + LVM_MAJOR_VERSION, LVM_MINOR_VERSION, LVM_PATCHLEVEL_VERSION); + if (register_blkdev (LVM_MAJOR, "lvm", &lvm_fops)) + { + printk (KERN_ALERT "Unable to get LVM major %d\n", LVM_MAJOR); + return; + } + + blk_dev[LVM_MAJOR].request_fn = DEVICE_REQUEST; + blk_dev[LVM_MAJOR].current_request = NULL; + read_ahead[LVM_MAJOR] = INT_MAX; + lvm_gendisk.next = gendisk_head; + + gendisk_head = &lvm_gendisk; +} + +void lvm_print_devices (void) +{ + struct lvm_list_head *tmp; + lvm_rdisk_t *rdisk; + + printk("\n"); + printk(" **********************************\n"); + printk(" * *\n"); + printk(" **********************************\n"); + + tmp = lvm_managed_devices.next; + while (tmp != &lvm_managed_devices) { + rdisk = lvm_list_entry(tmp, lvm_rdisk_t, lvm_managed); + printk("LVM device: <%s>\n", partition_name(rdisk->dev)); + tmp = tmp->next; + } + + printk(" **********************************\n"); + printk("\n"); +} + +/* + * This Linus-trick catches bugs via the linker. + */ + +extern void __BUG__in__lvm_dot_c_1(void); +extern void __BUG__in__lvm_dot_c_2(void); +extern void __BUG__in__lvm_dot_c_3(void); +extern void __BUG__in__lvm_dot_c_4(void); +extern void __BUG__in__lvm_dot_c_5(void); + +void bugcatcher (void) +{ + if (sizeof(lvm_block_group_t) != LVM_BLOCKSIZE) + __BUG__in__lvm_dot_c_1(); + if (sizeof(lvm_index_block_t) != LVM_BLOCKSIZE) + __BUG__in__lvm_dot_c_2(); + if (sizeof(lv_header_t) != LVM_BLOCKSIZE) + __BUG__in__lvm_dot_c_3(); + if (sizeof(lvm_super_t) != LVM_BLOCKSIZE) + __BUG__in__lvm_dot_c_4(); + if (sizeof(lvm_lptr_t) != 16) + __BUG__in__lvm_dot_c_5(); +} + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/md.c linux.ac/drivers/block/md.c --- linux.vanilla/drivers/block/md.c Sun Nov 8 15:10:09 1998 +++ linux.ac/drivers/block/md.c Mon Jul 19 03:26:58 1999 @@ -1,21 +1,17 @@ - /* md.c : Multiple Devices driver for Linux - Copyright (C) 1994-96 Marc ZYNGIER - or - + Copyright (C) 1998 Ingo Molnar - A lot of inspiration came from hd.c ... + completely rewritten, based on the MD driver code from Marc Zyngier - kerneld support by Boris Tobotras - boot support for linear and striped mode by Harald Hoyer + Changes: - RAID-1/RAID-5 extensions by: - Ingo Molnar, Miguel de Icaza, Gadi Oxman + - RAID-1/RAID-5 extensions by Miguel de Icaza, Gadi Oxman, Ingo Molnar + - boot support for linear and striped mode by Harald Hoyer + - kerneld support by Boris Tobotras + - kmod support by: Cyrus Durgin + - RAID0 bugfixes: Mark Anthony Lisher - Changes for kmod by: - Cyrus Durgin - This program is free software; you can redistribute 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) @@ -26,807 +22,2971 @@ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* - * Current RAID-1,4,5 parallel reconstruction speed limit is 1024 KB/sec, so - * the extra system load does not show up that much. Increase it if your - * system can take more. - */ -#define SPEED_LIMIT 1024 +#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #ifdef CONFIG_KMOD #include #endif -#include -#include #define __KERNEL_SYSCALLS__ #include +#include + +extern asmlinkage int sys_sched_yield(void); +extern asmlinkage int sys_setsid(void); + +extern unsigned long io_events[MAX_BLKDEV]; + #define MAJOR_NR MD_MAJOR #define MD_DRIVER #include -#include -#include -#include #ifdef CONFIG_MD_BOOT -extern kdev_t name_to_kdev_t(char *line) __init; +extern kdev_t name_to_kdev_t(char *line) md__init; #endif -static struct hd_struct md_hd_struct[MAX_MD_DEV]; -static int md_blocksizes[MAX_MD_DEV]; -int md_maxreadahead[MAX_MD_DEV]; -#if SUPPORT_RECONSTRUCTION -static struct md_thread *md_sync_thread = NULL; -#endif /* SUPPORT_RECONSTRUCTION */ +static mdk_personality_t *pers[MAX_PERSONALITY] = {NULL, }; + +/* + * these have to be allocated separately because external + * subsystems want to have a pre-defined structure + */ +struct hd_struct md_hd_struct[MAX_MD_DEVS]; +static int md_blocksizes[MAX_MD_DEVS]; +static int md_maxreadahead[MAX_MD_DEVS]; +static mdk_thread_t *md_recovery_thread = NULL; -int md_size[MAX_MD_DEV]={0, }; +int md_size[MAX_MD_DEVS] = {0, }; static void md_geninit (struct gendisk *); static struct gendisk md_gendisk= { - MD_MAJOR, - "md", - 0, - 1, - MAX_MD_DEV, - md_geninit, - md_hd_struct, - md_size, - MAX_MD_DEV, - NULL, - NULL + MD_MAJOR, + "md", + 0, + 1, + MAX_MD_DEVS, + md_geninit, + md_hd_struct, + md_size, + MAX_MD_DEVS, + NULL, + NULL }; -static struct md_personality *pers[MAX_PERSONALITY]={NULL, }; -struct md_dev md_dev[MAX_MD_DEV]; - -int md_thread(void * arg); +/* + * Current RAID-1,4,5 parallel reconstruction 'guaranteed speed limit' + * is 100 KB/sec, so the extra system load does not show up that much. + * Increase it if you want to have more _guaranteed_ speed. Note that + * the RAID driver will use the maximum available bandwith if the IO + * subsystem is idle. + * + * you can change it via /proc/sys/dev/speed-limit + */ -static struct gendisk *find_gendisk (kdev_t dev) -{ - struct gendisk *tmp=gendisk_head; +static int sysctl_speed_limit = 100; - while (tmp != NULL) - { - if (tmp->major==MAJOR(dev)) - return (tmp); - - tmp=tmp->next; - } +static struct ctl_table_header *md_table_header; - return (NULL); -} +static ctl_table md_table[] = { + {DEV_MD_SPEED_LIMIT, "speed-limit", + &sysctl_speed_limit, sizeof(int), 0644, NULL, &proc_dointvec}, + {0} +}; -char *partition_name (kdev_t dev) -{ - static char name[40]; /* This should be long - enough for a device name ! */ - struct gendisk *hd = find_gendisk (dev); +static ctl_table md_dir_table[] = { + {DEV_MD, "md", NULL, 0, 0555, md_table}, + {0} +}; - if (!hd) - { - sprintf (name, "[dev %s]", kdevname(dev)); - return (name); - } +static ctl_table md_root_table[] = { + {CTL_DEV, "dev", NULL, 0, 0555, md_dir_table}, + {0} +}; - return disk_name (hd, MINOR(dev), name); /* routine in genhd.c */ +static void md_register_sysctl(void) +{ + md_table_header = register_sysctl_table(md_root_table, 1); } -static int legacy_raid_sb (int minor, int pnum) +void md_unregister_sysctl(void) { - int i, factor; + unregister_sysctl_table(md_table_header); +} + +/* + * The mapping between kdev and mddev is not necessary a simple + * one! Eg. HSM uses several sub-devices to implement Logical + * Volumes. All these sub-devices map to the same mddev. + */ +dev_mapping_t mddev_map [MAX_MD_DEVS] = { {NULL, 0}, }; - factor = 1 << FACTOR_SHIFT(FACTOR((md_dev+minor))); +void add_mddev_mapping (mddev_t * mddev, kdev_t dev, void *data) +{ + unsigned int minor = MINOR(dev); - /***** - * do size and offset calculations. - */ - for (i=0; i> PERSONALITY_SHIFT) - md_maxreadahead[minor] = MD_DEFAULT_DISK_READAHEAD * md_dev[minor].nb_dev; - return 0; + if (mddev_map[minor].mddev != NULL) { + MD_BUG(); + return; + } + mddev_map[minor].mddev = mddev; + mddev_map[minor].data = data; } -static void free_sb (struct md_dev *mddev) +void del_mddev_mapping (mddev_t * mddev, kdev_t dev) { - int i; - struct real_dev *realdev; + unsigned int minor = MINOR(dev); - if (mddev->sb) { - free_page((unsigned long) mddev->sb); - mddev->sb = NULL; + if (MAJOR(dev) != MD_MAJOR) { + MD_BUG(); + return; } - for (i = 0; i nb_dev; i++) { - realdev = mddev->devices + i; - if (realdev->sb) { - free_page((unsigned long) realdev->sb); - realdev->sb = NULL; - } + if (mddev_map[minor].mddev != mddev) { + MD_BUG(); + return; } + mddev_map[minor].mddev = NULL; + mddev_map[minor].data = NULL; } /* - * Check one RAID superblock for generic plausibility + * Enables to iterate over all existing md arrays */ +static MD_LIST_HEAD(all_mddevs); -#define BAD_MAGIC KERN_ERR \ -"md: %s: invalid raid superblock magic (%x) on block %u\n" +static mddev_t * alloc_mddev (kdev_t dev) +{ + mddev_t * mddev; -#define OUT_OF_MEM KERN_ALERT \ -"md: out of memory.\n" + if (MAJOR(dev) != MD_MAJOR) { + MD_BUG(); + return 0; + } + mddev = (mddev_t *) kmalloc(sizeof(*mddev), GFP_KERNEL); + if (!mddev) + return NULL; + + memset(mddev, 0, sizeof(*mddev)); -#define NO_DEVICE KERN_ERR \ -"md: disabled device %s\n" + mddev->__minor = MINOR(dev); + mddev->reconfig_sem = MUTEX; + mddev->recovery_sem = MUTEX; + mddev->resync_sem = MUTEX; + MD_INIT_LIST_HEAD(&mddev->disks); + /* + * The 'base' mddev is the one with data NULL. + * personalities can create additional mddevs + * if necessary. + */ + add_mddev_mapping(mddev, dev, 0); + md_list_add(&mddev->all_mddevs, &all_mddevs); -#define SUCCESS 0 -#define FAILURE -1 + return mddev; +} -static int analyze_one_sb (struct real_dev * rdev) +static void free_mddev (mddev_t *mddev) { - int ret = FAILURE; - struct buffer_head *bh; - kdev_t dev = rdev->dev; - md_superblock_t *sb; + if (!mddev) { + MD_BUG(); + return; + } /* - * Read the superblock, it's at the end of the disk + * Make sure nobody else is using this mddev + * (careful, we rely on the global kernel lock here) */ - rdev->sb_offset = MD_NEW_SIZE_BLOCKS (blk_size[MAJOR(dev)][MINOR(dev)]); - set_blocksize (dev, MD_SB_BYTES); - bh = bread (dev, rdev->sb_offset / MD_SB_BLOCKS, MD_SB_BYTES); - - if (bh) { - sb = (md_superblock_t *) bh->b_data; - if (sb->md_magic != MD_SB_MAGIC) { - printk (BAD_MAGIC, kdevname(dev), - sb->md_magic, rdev->sb_offset); - goto abort; - } - rdev->sb = (md_superblock_t *) __get_free_page(GFP_KERNEL); - if (!rdev->sb) { - printk (OUT_OF_MEM); - goto abort; - } - memcpy (rdev->sb, bh->b_data, MD_SB_BYTES); + while (md_atomic_read(&mddev->resync_sem.count) != 1) + schedule(); + while (md_atomic_read(&mddev->recovery_sem.count) != 1) + schedule(); - rdev->size = sb->size; - } else - printk (NO_DEVICE,kdevname(rdev->dev)); - ret = SUCCESS; -abort: - if (bh) - brelse (bh); - return ret; + del_mddev_mapping(mddev, MKDEV(MD_MAJOR, mdidx(mddev))); + md_list_del(&mddev->all_mddevs); + MD_INIT_LIST_HEAD(&mddev->all_mddevs); + kfree(mddev); } -#undef SUCCESS -#undef FAILURE - -#undef BAD_MAGIC -#undef OUT_OF_MEM -#undef NO_DEVICE -/* - * Check a full RAID array for plausibility - */ +struct gendisk * find_gendisk (kdev_t dev) +{ + struct gendisk *tmp = gendisk_head; -#define INCONSISTENT KERN_ERR \ -"md: superblock inconsistency -- run ckraid\n" + while (tmp != NULL) { + if (tmp->major == MAJOR(dev)) + return (tmp); + tmp = tmp->next; + } + return (NULL); +} -#define OUT_OF_DATE KERN_ERR \ -"md: superblock update time inconsistenty -- using the most recent one\n" +mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr) +{ + mdk_rdev_t * rdev; + struct md_list_head *tmp; -#define OLD_VERSION KERN_ALERT \ -"md: %s: unsupported raid array version %d.%d.%d\n" + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->desc_nr == nr) + return rdev; + } + return NULL; +} -#define NOT_CLEAN KERN_ERR \ -"md: %s: raid array is not clean -- run ckraid\n" +mdk_rdev_t * find_rdev(mddev_t * mddev, kdev_t dev) +{ + struct md_list_head *tmp; + mdk_rdev_t *rdev; -#define NOT_CLEAN_IGNORE KERN_ERR \ -"md: %s: raid array is not clean -- reconstructing parity\n" + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->dev == dev) + return rdev; + } + return NULL; +} -#define UNKNOWN_LEVEL KERN_ERR \ -"md: %s: unsupported raid level %d\n" +static MD_LIST_HEAD(device_names); -static int analyze_sbs (int minor, int pnum) +char * partition_name (kdev_t dev) { - struct md_dev *mddev = md_dev + minor; - int i, N = mddev->nb_dev, out_of_date = 0; - struct real_dev * disks = mddev->devices; - md_superblock_t *sb, *freshest = NULL; + struct gendisk *hd; + static char nomem [] = ""; + dev_name_t *dname; + struct md_list_head *tmp = device_names.next; - /* - * RAID-0 and linear don't use a RAID superblock - */ - if (pnum == RAID0 >> PERSONALITY_SHIFT || - pnum == LINEAR >> PERSONALITY_SHIFT) - return legacy_raid_sb (minor, pnum); + while (tmp != &device_names) { + dname = md_list_entry(tmp, dev_name_t, list); + if (dname->dev == dev) + return dname->name; + tmp = tmp->next; + } + + dname = (dev_name_t *) kmalloc(sizeof(*dname), GFP_KERNEL); + if (!dname) + return nomem; /* - * Verify the RAID superblock on each real device + * ok, add this new device name to the list */ - for (i = 0; i < N; i++) - if (analyze_one_sb(disks+i)) - goto abort; + hd = find_gendisk (dev); + + if (!hd) + sprintf (dname->name, "[dev %s]", kdevname(dev)); + else + disk_name (hd, MINOR(dev), dname->name); + + dname->dev = dev; + md_list_add(&dname->list, &device_names); + + return dname->name; +} + +static unsigned int calc_dev_sboffset (kdev_t dev, mddev_t *mddev, + int persistent) +{ + unsigned int size = 0; + + if (blk_size[MAJOR(dev)]) + size = blk_size[MAJOR(dev)][MINOR(dev)]; + if (persistent) + size = MD_NEW_SIZE_BLOCKS(size); + return size; +} + +static unsigned int calc_dev_size (kdev_t dev, mddev_t *mddev, int persistent) +{ + unsigned int size; + + size = calc_dev_sboffset(dev, mddev, persistent); + if (!mddev->sb) { + MD_BUG(); + return size; + } + if (mddev->sb->chunk_size) + size &= ~(mddev->sb->chunk_size/1024 - 1); + return size; +} + +/* + * We check wether all devices are numbered from 0 to nb_dev-1. The + * order is guaranteed even after device name changes. + * + * Some personalities (raid0, linear) use this. Personalities that + * provide data have to be able to deal with loss of individual + * disks, so they do their checking themselves. + */ +int md_check_ordering (mddev_t *mddev) +{ + int i, c; + mdk_rdev_t *rdev; + struct md_list_head *tmp; /* - * The superblock constant part has to be the same - * for all disks in the array. + * First, all devices must be fully functional */ - sb = NULL; - for (i = 0; i < N; i++) { - if (!disks[i].sb) - continue; - if (!sb) { - sb = disks[i].sb; - continue; - } - if (memcmp(sb, - disks[i].sb, MD_SB_GENERIC_CONSTANT_WORDS * 4)) { - printk (INCONSISTENT); + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->faulty) { + printk("md: md%d's device %s faulty, aborting.\n", + mdidx(mddev), partition_name(rdev->dev)); goto abort; } } - /* - * OK, we have all disks and the array is ready to run. Let's - * find the freshest superblock, that one will be the superblock - * that represents the whole array. - */ - if ((sb = mddev->sb = (md_superblock_t *) __get_free_page (GFP_KERNEL)) == NULL) + c = 0; + ITERATE_RDEV(mddev,rdev,tmp) { + c++; + } + if (c != mddev->nb_dev) { + MD_BUG(); goto abort; - freshest = NULL; - for (i = 0; i < N; i++) { - if (!disks[i].sb) - continue; - if (!freshest) { - freshest = disks[i].sb; - continue; - } - /* - * Find the newest superblock version - */ - if (disks[i].sb->utime != freshest->utime) { - out_of_date = 1; - if (disks[i].sb->utime > freshest->utime) - freshest = disks[i].sb; - } } - if (out_of_date) - printk(OUT_OF_DATE); - memcpy (sb, freshest, sizeof(*freshest)); - - /* - * Check if we can support this RAID array - */ - if (sb->major_version != MD_MAJOR_VERSION || - sb->minor_version > MD_MINOR_VERSION) { - - printk (OLD_VERSION, kdevname(MKDEV(MD_MAJOR, minor)), - sb->major_version, sb->minor_version, - sb->patch_version); + if (mddev->nb_dev != mddev->sb->raid_disks) { + printk("md: md%d, array needs %d disks, has %d, aborting.\n", + mdidx(mddev), mddev->sb->raid_disks, mddev->nb_dev); goto abort; } - /* - * We need to add this as a superblock option. + * Now the numbering check */ -#if SUPPORT_RECONSTRUCTION - if (sb->state != (1 << MD_SB_CLEAN)) { - if (sb->level == 1) { - printk (NOT_CLEAN, kdevname(MKDEV(MD_MAJOR, minor))); + for (i = 0; i < mddev->nb_dev; i++) { + c = 0; + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->desc_nr == i) + c++; + } + if (c == 0) { + printk("md: md%d, missing disk #%d, aborting.\n", + mdidx(mddev), i); goto abort; - } else - printk (NOT_CLEAN_IGNORE, kdevname(MKDEV(MD_MAJOR, minor))); - } -#else - if (sb->state != (1 << MD_SB_CLEAN)) { - printk (NOT_CLEAN, kdevname(MKDEV(MD_MAJOR, minor))); - goto abort; - } -#endif /* SUPPORT_RECONSTRUCTION */ - - switch (sb->level) { - case 1: - md_size[minor] = sb->size; - md_maxreadahead[minor] = MD_DEFAULT_DISK_READAHEAD; - break; - case 4: - case 5: - md_size[minor] = sb->size * (sb->raid_disks - 1); - md_maxreadahead[minor] = MD_DEFAULT_DISK_READAHEAD * (sb->raid_disks - 1); - break; - default: - printk (UNKNOWN_LEVEL, kdevname(MKDEV(MD_MAJOR, minor)), - sb->level); + } + if (c > 1) { + printk("md: md%d, too many disks #%d, aborting.\n", + mdidx(mddev), i); goto abort; + } } return 0; abort: - free_sb(mddev); return 1; } -#undef INCONSISTENT -#undef OUT_OF_DATE -#undef OLD_VERSION -#undef NOT_CLEAN -#undef OLD_LEVEL - -int md_update_sb(int minor) +static unsigned int zoned_raid_size (mddev_t *mddev) { - struct md_dev *mddev = md_dev + minor; - struct buffer_head *bh; - md_superblock_t *sb = mddev->sb; - struct real_dev *realdev; - kdev_t dev; - int i; - u32 sb_offset; + unsigned int mask; + mdk_rdev_t * rdev; + struct md_list_head *tmp; - sb->utime = CURRENT_TIME; - for (i = 0; i < mddev->nb_dev; i++) { - realdev = mddev->devices + i; - if (!realdev->sb) - continue; - dev = realdev->dev; - sb_offset = realdev->sb_offset; - set_blocksize(dev, MD_SB_BYTES); - printk("md: updating raid superblock on device %s, sb_offset == %u\n", kdevname(dev), sb_offset); - bh = getblk(dev, sb_offset / MD_SB_BLOCKS, MD_SB_BYTES); - if (bh) { - sb = (md_superblock_t *) bh->b_data; - memcpy(sb, mddev->sb, MD_SB_BYTES); - memcpy(&sb->descriptor, sb->disks + realdev->sb->descriptor.number, MD_SB_DESCRIPTOR_WORDS * 4); - mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 1); - ll_rw_block(WRITE, 1, &bh); - wait_on_buffer(bh); - bforget(bh); - fsync_dev(dev); - invalidate_buffers(dev); - } else - printk(KERN_ERR "md: getblk failed for device %s\n", kdevname(dev)); + if (!mddev->sb) { + MD_BUG(); + return -EINVAL; + } + /* + * do size and offset calculations. + */ + mask = ~(mddev->sb->chunk_size/1024 - 1); +printk("mask %08x\n", mask); + + ITERATE_RDEV(mddev,rdev,tmp) { +printk(" rdev->size: %d\n", rdev->size); + rdev->size &= mask; +printk(" masked rdev->size: %d\n", rdev->size); + md_size[mdidx(mddev)] += rdev->size; +printk(" new md_size: %d\n", md_size[mdidx(mddev)]); } return 0; } -static int do_md_run (int minor, int repart) +static void remove_descriptor (mdp_disk_t *disk, mdp_super_t *sb) { - int pnum, i, min, factor, err; + if (disk_active(disk)) { + sb->working_disks--; + } else { + if (disk_spare(disk)) { + sb->spare_disks--; + sb->working_disks--; + } else { + sb->failed_disks--; + } + } + sb->nr_disks--; + disk->major = 0; + disk->minor = 0; + mark_disk_removed(disk); +} - if (!md_dev[minor].nb_dev) - return -EINVAL; - - if (md_dev[minor].pers) - return -EBUSY; +#define BAD_MAGIC KERN_ERR \ +"md: invalid raid superblock magic on %s\n" - md_dev[minor].repartition=repart; - - if ((pnum=PERSONALITY(&md_dev[minor]) >> (PERSONALITY_SHIFT)) - >= MAX_PERSONALITY) - return -EINVAL; - - /* Only RAID-1 and RAID-5 can have MD devices as underlying devices */ - if (pnum != (RAID1 >> PERSONALITY_SHIFT) && pnum != (RAID5 >> PERSONALITY_SHIFT)){ - for (i = 0; i < md_dev [minor].nb_dev; i++) - if (MAJOR (md_dev [minor].devices [i].dev) == MD_MAJOR) - return -EINVAL; - } - if (!pers[pnum]) - { -#ifdef CONFIG_KMOD - char module_name[80]; - sprintf (module_name, "md-personality-%d", pnum); - request_module (module_name); - if (!pers[pnum]) -#endif - return -EINVAL; - } - - factor = min = 1 << FACTOR_SHIFT(FACTOR((md_dev+minor))); - - for (i=0; irun (minor, md_dev+minor))) - { - md_dev[minor].pers=NULL; - free_sb(md_dev + minor); - return (err); - } - - if (pnum != RAID0 >> PERSONALITY_SHIFT && pnum != LINEAR >> PERSONALITY_SHIFT) - { - md_dev[minor].sb->state &= ~(1 << MD_SB_CLEAN); - md_update_sb(minor); - } - - /* FIXME : We assume here we have blocks - that are twice as large as sectors. - THIS MAY NOT BE TRUE !!! */ - md_hd_struct[minor].start_sect=0; - md_hd_struct[minor].nr_sects=md_size[minor]<<1; - - read_ahead[MD_MAJOR] = 128; - return (0); -} +#define OUT_OF_MEM KERN_ALERT \ +"md: out of memory.\n" + +#define NO_SB KERN_ERR \ +"md: disabled device %s, could not read superblock.\n" -static int do_md_stop (int minor, struct inode *inode) +#define BAD_CSUM KERN_WARNING \ +"md: invalid superblock checksum on %s\n" + +static int alloc_array_sb (mddev_t * mddev) { - int i; - - if (inode->i_count>1 || md_dev[minor].busy>1) { - /* - * ioctl : one open channel - */ - printk ("STOP_MD md%x failed : i_count=%d, busy=%d\n", - minor, inode->i_count, md_dev[minor].busy); - return -EBUSY; - } - - if (md_dev[minor].pers) { - /* - * It is safe to call stop here, it only frees private - * data. Also, it tells us if a device is unstoppable - * (eg. resyncing is in progress) - */ - if (md_dev[minor].pers->stop (minor, md_dev+minor)) - return -EBUSY; - /* - * The device won't exist anymore -> flush it now - */ - fsync_dev (inode->i_rdev); - invalidate_buffers (inode->i_rdev); - if (md_dev[minor].sb) { - md_dev[minor].sb->state |= 1 << MD_SB_CLEAN; - md_update_sb(minor); - } + if (mddev->sb) { + MD_BUG(); + return 0; } - - /* Remove locks. */ - if (md_dev[minor].sb) - free_sb(md_dev + minor); - for (i=0; isb = (mdp_super_t *) __get_free_page (GFP_KERNEL); + if (!mddev->sb) + return -ENOMEM; + md_clear_page((unsigned long)mddev->sb); + return 0; } -static int do_md_add (int minor, kdev_t dev) +static int alloc_disk_sb (mdk_rdev_t * rdev) { - int i; - int hot_add=0; - struct real_dev *realdev; + if (rdev->sb) + MD_BUG(); - if (md_dev[minor].nb_dev==MAX_REAL) + rdev->sb = (mdp_super_t *) __get_free_page(GFP_KERNEL); + if (!rdev->sb) { + printk (OUT_OF_MEM); return -EINVAL; + } + md_clear_page((unsigned long)rdev->sb); - if (!fs_may_mount (dev)) - return -EBUSY; + return 0; +} - if (blk_size[MAJOR(dev)] == NULL || blk_size[MAJOR(dev)][MINOR(dev)] == 0) { - printk("md_add(): zero device size, huh, bailing out.\n"); - return -EINVAL; +static void free_disk_sb (mdk_rdev_t * rdev) +{ + if (rdev->sb) { + free_page((unsigned long) rdev->sb); + rdev->sb = NULL; + rdev->sb_offset = 0; + rdev->size = 0; + } else { + if (!rdev->faulty) + MD_BUG(); } +} - if (md_dev[minor].pers) { - /* - * The array is already running, hot-add the drive, or - * bail out: - */ - if (!md_dev[minor].pers->hot_add_disk) - return -EBUSY; - else - hot_add=1; +static void mark_rdev_faulty (mdk_rdev_t * rdev) +{ + unsigned long flags; + + if (!rdev) { + MD_BUG(); + return; } + save_flags(flags); + cli(); + free_disk_sb(rdev); + rdev->faulty = 1; + restore_flags(flags); +} + +static int read_disk_sb (mdk_rdev_t * rdev) +{ + int ret = -EINVAL; + struct buffer_head *bh = NULL; + kdev_t dev = rdev->dev; + mdp_super_t *sb; + u32 sb_offset; + if (!rdev->sb) { + MD_BUG(); + goto abort; + } + /* - * Careful. We cannot increase nb_dev for a running array. + * Calculate the position of the superblock, + * it's at the end of the disk */ - i=md_dev[minor].nb_dev; - realdev = &md_dev[minor].devices[i]; - realdev->dev=dev; - - /* Lock the device by inserting a dummy inode. This doesn't - smell very good, but I need to be consistent with the - mount stuff, specially with fs_may_mount. If someone have - a better idea, please help ! */ - - realdev->inode=get_empty_inode (); - realdev->inode->i_dev=dev; /* don't care about other fields */ - insert_inode_hash (realdev->inode); - - /* Sizes are now rounded at run time */ - -/* md_dev[minor].devices[i].size=gen_real->sizes[MINOR(dev)]; HACKHACK*/ - - realdev->size=blk_size[MAJOR(dev)][MINOR(dev)]; + sb_offset = calc_dev_sboffset(rdev->dev, rdev->mddev, 1); + rdev->sb_offset = sb_offset; + printk("(read) %s's sb offset: %d", partition_name(dev), + sb_offset); + fsync_dev(dev); + set_blocksize (dev, MD_SB_BYTES); + bh = bread (dev, sb_offset / MD_SB_BLOCKS, MD_SB_BYTES); - if (hot_add) { + if (bh) { + sb = (mdp_super_t *) bh->b_data; + memcpy (rdev->sb, sb, MD_SB_BYTES); + } else { + printk (NO_SB,partition_name(rdev->dev)); + goto abort; + } + printk(" [events: %08lx]\n", (unsigned long)get_unaligned(&rdev->sb->events)); + ret = 0; +abort: + if (bh) + brelse (bh); + return ret; +} + +static unsigned int calc_sb_csum (mdp_super_t * sb) +{ + unsigned int disk_csum, csum; + + disk_csum = sb->sb_csum; + sb->sb_csum = 0; + csum = csum_partial((void *)sb, MD_SB_BYTES, 0); + sb->sb_csum = disk_csum; + return csum; +} + +/* + * Check one RAID superblock for generic plausibility + */ + +static int check_disk_sb (mdk_rdev_t * rdev) +{ + mdp_super_t *sb; + int ret = -EINVAL; + + sb = rdev->sb; + if (!sb) { + MD_BUG(); + goto abort; + } + + if (sb->md_magic != MD_SB_MAGIC) { + printk (BAD_MAGIC, partition_name(rdev->dev)); + goto abort; + } + + if (sb->md_minor >= MAX_MD_DEVS) { + printk (BAD_MINOR, partition_name(rdev->dev), + sb->md_minor); + goto abort; + } + + if (calc_sb_csum(sb) != sb->sb_csum) + printk(BAD_CSUM, partition_name(rdev->dev)); + ret = 0; +abort: + return ret; +} + +static kdev_t dev_unit(kdev_t dev) +{ + unsigned int mask; + struct gendisk *hd = find_gendisk(dev); + + if (!hd) + return 0; + mask = ~((1 << hd->minor_shift) - 1); + + return MKDEV(MAJOR(dev), MINOR(dev) & mask); +} + +static mdk_rdev_t * match_dev_unit(mddev_t *mddev, kdev_t dev) +{ + struct md_list_head *tmp; + mdk_rdev_t *rdev; + + ITERATE_RDEV(mddev,rdev,tmp) + if (dev_unit(rdev->dev) == dev_unit(dev)) + return rdev; + + return NULL; +} + +static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2) +{ + struct md_list_head *tmp; + mdk_rdev_t *rdev; + + ITERATE_RDEV(mddev1,rdev,tmp) + if (match_dev_unit(mddev2, rdev->dev)) + return 1; + + return 0; +} + +static MD_LIST_HEAD(all_raid_disks); +static MD_LIST_HEAD(pending_raid_disks); + +static void bind_rdev_to_array (mdk_rdev_t * rdev, mddev_t * mddev) +{ + mdk_rdev_t *same_pdev; + + if (rdev->mddev) { + MD_BUG(); + return; + } + same_pdev = match_dev_unit(mddev, rdev->dev); + if (same_pdev) + printk( KERN_WARNING +"md%d: WARNING: %s appears to be on the same physical disk as %s. True\n" +" protection against single-disk failure might be compromised.\n", + mdidx(mddev), partition_name(rdev->dev), + partition_name(same_pdev->dev)); + + md_list_add(&rdev->same_set, &mddev->disks); + rdev->mddev = mddev; + mddev->nb_dev++; + printk("bind<%s,%d>\n", partition_name(rdev->dev), mddev->nb_dev); +} + +static void unbind_rdev_from_array (mdk_rdev_t * rdev) +{ + if (!rdev->mddev) { + MD_BUG(); + return; + } + md_list_del(&rdev->same_set); + MD_INIT_LIST_HEAD(&rdev->same_set); + rdev->mddev->nb_dev--; + printk("unbind<%s,%d>\n", partition_name(rdev->dev), + rdev->mddev->nb_dev); + rdev->mddev = NULL; +} + +/* + * prevent the device from being mounted, repartitioned or + * otherwise reused by a RAID array (or any other kernel + * subsystem), by opening the device. [simply getting an + * inode is not enough, the SCSI module usage code needs + * an explicit open() on the device] + */ +static void lock_rdev (mdk_rdev_t *rdev) +{ + int err = 0; + + /* + * First insert a dummy inode. + */ + rdev->inode = get_empty_inode(); + /* + * we dont care about any other fields + */ + rdev->inode->i_dev = rdev->inode->i_rdev = rdev->dev; + insert_inode_hash(rdev->inode); + + memset(&rdev->filp, 0, sizeof(rdev->filp)); + rdev->filp.f_mode = 3; /* read write */ + err = blkdev_open(rdev->inode, &rdev->filp); + if (err) + printk("blkdev_open() failed: %d\n", err); +} + +static void unlock_rdev (mdk_rdev_t *rdev) +{ + blkdev_release(rdev->inode); +} + +static void export_rdev (mdk_rdev_t * rdev) +{ + printk("export_rdev(%s)\n",partition_name(rdev->dev)); + if (rdev->mddev) + MD_BUG(); + unlock_rdev(rdev); + free_disk_sb(rdev); + md_list_del(&rdev->all); + MD_INIT_LIST_HEAD(&rdev->all); + if (rdev->pending.next != &rdev->pending) { + printk("(%s was pending)\n",partition_name(rdev->dev)); + md_list_del(&rdev->pending); + MD_INIT_LIST_HEAD(&rdev->pending); + } + rdev->dev = 0; + rdev->faulty = 0; + kfree(rdev); +} + +static void kick_rdev_from_array (mdk_rdev_t * rdev) +{ + unbind_rdev_from_array(rdev); + export_rdev(rdev); +} + +static void export_array (mddev_t *mddev) +{ + struct md_list_head *tmp; + mdk_rdev_t *rdev; + mdp_super_t *sb = mddev->sb; + + if (mddev->sb) { + mddev->sb = NULL; + free_page((unsigned long) sb); + } + + ITERATE_RDEV(mddev,rdev,tmp) { + if (!rdev->mddev) { + MD_BUG(); + continue; + } + kick_rdev_from_array(rdev); + } + if (mddev->nb_dev) + MD_BUG(); +} + +#undef BAD_CSUM +#undef BAD_MAGIC +#undef OUT_OF_MEM +#undef NO_SB + +static void print_desc(mdp_disk_t *desc) +{ + printk(" DISK\n", desc->number, + partition_name(MKDEV(desc->major,desc->minor)), + desc->major,desc->minor,desc->raid_disk,desc->state); +} + +static void print_sb(mdp_super_t *sb) +{ + int i; + + printk(" SB: (V:%d.%d.%d) ID:<%08x.%08x.%08x.%08x> CT:%08x\n", + sb->major_version, sb->minor_version, sb->patch_version, + sb->set_uuid0, sb->set_uuid1, sb->set_uuid2, sb->set_uuid3, + sb->ctime); + printk(" L%d S%08d ND:%d RD:%d md%d LO:%d CS:%d\n", sb->level, + sb->size, sb->nr_disks, sb->raid_disks, sb->md_minor, + sb->layout, sb->chunk_size); + printk(" UT:%08x ST:%d AD:%d WD:%d FD:%d SD:%d CSUM:%08x E:%08lx\n", + sb->utime, sb->state, sb->active_disks, sb->working_disks, + sb->failed_disks, sb->spare_disks, + sb->sb_csum, (unsigned long)get_unaligned(&sb->events)); + + for (i = 0; i < MD_SB_DISKS; i++) { + mdp_disk_t *desc; + + desc = sb->disks + i; + printk(" D %2d: ", i); + print_desc(desc); + } + printk(" THIS: "); + print_desc(&sb->this_disk); + +} + +static void print_rdev(mdk_rdev_t *rdev) +{ + printk(" rdev %s: O:%s, SZ:%08d F:%d DN:%d ", + partition_name(rdev->dev), partition_name(rdev->old_dev), + rdev->size, rdev->faulty, rdev->desc_nr); + if (rdev->sb) { + printk("rdev superblock:\n"); + print_sb(rdev->sb); + } else + printk("no rdev superblock!\n"); +} + +void md_print_devices (void) +{ + struct md_list_head *tmp, *tmp2; + mdk_rdev_t *rdev; + mddev_t *mddev; + + printk("\n"); + printk(" **********************************\n"); + printk(" * *\n"); + printk(" **********************************\n"); + ITERATE_MDDEV(mddev,tmp) { + printk("md%d: ", mdidx(mddev)); + + ITERATE_RDEV(mddev,rdev,tmp2) + printk("<%s>", partition_name(rdev->dev)); + + if (mddev->sb) { + printk(" array superblock:\n"); + print_sb(mddev->sb); + } else + printk(" no array superblock.\n"); + + ITERATE_RDEV(mddev,rdev,tmp2) + print_rdev(rdev); + } + printk(" **********************************\n"); + printk("\n"); +} + +static int sb_equal ( mdp_super_t *sb1, mdp_super_t *sb2) +{ + int ret; + mdp_super_t *tmp1, *tmp2; + + tmp1 = kmalloc(sizeof(*tmp1),GFP_KERNEL); + tmp2 = kmalloc(sizeof(*tmp2),GFP_KERNEL); + + if (!tmp1 || !tmp2) { + ret = 0; + goto abort; + } + + *tmp1 = *sb1; + *tmp2 = *sb2; + + /* + * nr_disks is not constant + */ + tmp1->nr_disks = 0; + tmp2->nr_disks = 0; + + if (memcmp(tmp1, tmp2, MD_SB_GENERIC_CONSTANT_WORDS * 4)) + ret = 0; + else + ret = 1; + +abort: + if (tmp1) + kfree(tmp1); + if (tmp2) + kfree(tmp2); + + return ret; +} + +static int uuid_equal(mdk_rdev_t *rdev1, mdk_rdev_t *rdev2) +{ + if ( (rdev1->sb->set_uuid0 == rdev2->sb->set_uuid0) && + (rdev1->sb->set_uuid1 == rdev2->sb->set_uuid1) && + (rdev1->sb->set_uuid2 == rdev2->sb->set_uuid2) && + (rdev1->sb->set_uuid3 == rdev2->sb->set_uuid3)) + + return 1; + + return 0; +} + +static mdk_rdev_t * find_rdev_all (kdev_t dev) +{ + struct md_list_head *tmp; + mdk_rdev_t *rdev; + + tmp = all_raid_disks.next; + while (tmp != &all_raid_disks) { + rdev = md_list_entry(tmp, mdk_rdev_t, all); + if (rdev->dev == dev) + return rdev; + tmp = tmp->next; + } + return NULL; +} + +#define GETBLK_FAILED KERN_ERR \ +"md: getblk failed for device %s\n" + +static int write_disk_sb(mdk_rdev_t * rdev) +{ + struct buffer_head *bh; + kdev_t dev; + u32 sb_offset, size; + mdp_super_t *sb; + + if (!rdev->sb) { + MD_BUG(); + return -1; + } + if (rdev->faulty) { + MD_BUG(); + return -1; + } + if (rdev->sb->md_magic != MD_SB_MAGIC) { + MD_BUG(); + return -1; + } + + dev = rdev->dev; + sb_offset = calc_dev_sboffset(dev, rdev->mddev, 1); + if (rdev->sb_offset != sb_offset) { + printk("%s's sb offset has changed from %d to %d, skipping\n", partition_name(dev), rdev->sb_offset, sb_offset); + goto skip; + } + /* + * If the disk went offline meanwhile and it's just a spare, then + * it's size has changed to zero silently, and the MD code does + * not yet know that it's faulty. + */ + size = calc_dev_size(dev, rdev->mddev, 1); + if (size != rdev->size) { + printk("%s's size has changed from %d to %d since import, skipping\n", partition_name(dev), rdev->size, size); + goto skip; + } + + printk("(write) %s's sb offset: %d\n", partition_name(dev), sb_offset); + fsync_dev(dev); + set_blocksize(dev, MD_SB_BYTES); + bh = getblk(dev, sb_offset / MD_SB_BLOCKS, MD_SB_BYTES); + if (!bh) { + printk(GETBLK_FAILED, partition_name(dev)); + return 1; + } + memset(bh->b_data,0,bh->b_size); + sb = (mdp_super_t *) bh->b_data; + memcpy(sb, rdev->sb, MD_SB_BYTES); + + mark_buffer_uptodate(bh, 1); + mark_buffer_dirty(bh, 1); + ll_rw_block(WRITE, 1, &bh); + wait_on_buffer(bh); + brelse(bh); + fsync_dev(dev); +skip: + return 0; +} +#undef GETBLK_FAILED KERN_ERR + +static void set_this_disk(mddev_t *mddev, mdk_rdev_t *rdev) +{ + int i, ok = 0; + mdp_disk_t *desc; + + for (i = 0; i < MD_SB_DISKS; i++) { + desc = mddev->sb->disks + i; +#if 0 + if (disk_faulty(desc)) { + if (MKDEV(desc->major,desc->minor) == rdev->dev) + ok = 1; + continue; + } +#endif + if (MKDEV(desc->major,desc->minor) == rdev->dev) { + rdev->sb->this_disk = *desc; + rdev->desc_nr = desc->number; + ok = 1; + break; + } + } + + if (!ok) { + MD_BUG(); + } +} + +static int sync_sbs(mddev_t * mddev) +{ + mdk_rdev_t *rdev; + mdp_super_t *sb; + struct md_list_head *tmp; + + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->faulty) + continue; + sb = rdev->sb; + *sb = *mddev->sb; + set_this_disk(mddev, rdev); + sb->sb_csum = calc_sb_csum(sb); + } + return 0; +} + +int md_update_sb(mddev_t * mddev) +{ + int first, err, count = 100; + struct md_list_head *tmp; + mdk_rdev_t *rdev; + __u64 ev; + +repeat: + mddev->sb->utime = CURRENT_TIME; + ev = get_unaligned(&mddev->sb->events); + ++ev; + put_unaligned(ev,&mddev->sb->events); + if (ev == (__u64)0) { + /* + * oops, this 64-bit counter should never wrap. + * Either we are in around ~1 trillion A.C., assuming + * 1 reboot per second, or we have a bug: + */ + MD_BUG(); + --ev; + put_unaligned(ev,&mddev->sb->events); + } + sync_sbs(mddev); + + /* + * do not write anything to disk if using + * nonpersistent superblocks + */ + if (mddev->sb->not_persistent) + return 0; + + printk(KERN_INFO "md: updating md%d RAID superblock on device\n", + mdidx(mddev)); + + first = 1; + err = 0; + ITERATE_RDEV(mddev,rdev,tmp) { + if (!first) { + first = 0; + printk(", "); + } + if (rdev->faulty) + printk("(skipping faulty "); + printk("%s ", partition_name(rdev->dev)); + if (!rdev->faulty) { + printk("[events: %08lx]", + (unsigned long)get_unaligned(&rdev->sb->events)); + err += write_disk_sb(rdev); + } else + printk(")\n"); + } + printk(".\n"); + if (err) { + printk("errors occured during superblock update, repeating\n"); + if (--count) + goto repeat; + printk("excessive errors occured during superblock update, exiting\n"); + } + return 0; +} + +/* + * Import a device. If 'on_disk', then sanity check the superblock + * + * mark the device faulty if: + * + * - the device is nonexistent (zero size) + * - the device has no valid superblock + * + * a faulty rdev _never_ has rdev->sb set. + */ +static int md_import_device (kdev_t newdev, int on_disk) +{ + int err; + mdk_rdev_t *rdev; + unsigned int size; + + if (find_rdev_all(newdev)) + return -EEXIST; + + rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL); + if (!rdev) { + printk("could not alloc mem for %s!\n", partition_name(newdev)); + return -ENOMEM; + } + memset(rdev, 0, sizeof(*rdev)); + + if (!fs_may_mount(newdev)) { + printk("md: can not import %s, has active inodes!\n", + partition_name(newdev)); + err = -EBUSY; + goto abort_free; + } + + if ((err = alloc_disk_sb(rdev))) + goto abort_free; + + rdev->dev = newdev; + lock_rdev(rdev); + rdev->desc_nr = -1; + rdev->faulty = 0; + + size = 0; + if (blk_size[MAJOR(newdev)]) + size = blk_size[MAJOR(newdev)][MINOR(newdev)]; + if (!size) { + printk("md: %s has zero size, marking faulty!\n", + partition_name(newdev)); + err = -EINVAL; + goto abort_free; + } + + if (on_disk) { + if ((err = read_disk_sb(rdev))) { + printk("md: could not read %s's sb, not importing!\n", + partition_name(newdev)); + goto abort_free; + } + if ((err = check_disk_sb(rdev))) { + printk("md: %s has invalid sb, not importing!\n", + partition_name(newdev)); + goto abort_free; + } + + rdev->old_dev = MKDEV(rdev->sb->this_disk.major, + rdev->sb->this_disk.minor); + rdev->desc_nr = rdev->sb->this_disk.number; + } + md_list_add(&rdev->all, &all_raid_disks); + MD_INIT_LIST_HEAD(&rdev->pending); + + if (rdev->faulty && rdev->sb) + free_disk_sb(rdev); + return 0; + +abort_free: + if (rdev->sb) + free_disk_sb(rdev); + kfree(rdev); + return err; +} + +/* + * Check a full RAID array for plausibility + */ + +#define INCONSISTENT KERN_ERR \ +"md: fatal superblock inconsistency in %s -- removing from array\n" + +#define OUT_OF_DATE KERN_ERR \ +"md: superblock update time inconsistency -- using the most recent one\n" + +#define OLD_VERSION KERN_ALERT \ +"md: md%d: unsupported raid array version %d.%d.%d\n" + +#define NOT_CLEAN_IGNORE KERN_ERR \ +"md: md%d: raid array is not clean -- starting background reconstruction\n" + +#define UNKNOWN_LEVEL KERN_ERR \ +"md: md%d: unsupported raid level %d\n" + +static int analyze_sbs (mddev_t * mddev) +{ + int out_of_date = 0, i; + struct md_list_head *tmp, *tmp2; + mdk_rdev_t *rdev, *rdev2, *freshest; + mdp_super_t *sb; + + /* + * Verify the RAID superblock on each real device + */ + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->faulty) { + MD_BUG(); + goto abort; + } + if (!rdev->sb) { + MD_BUG(); + goto abort; + } + if (check_disk_sb(rdev)) + goto abort; + } + + /* + * The superblock constant part has to be the same + * for all disks in the array. + */ + sb = NULL; + + ITERATE_RDEV(mddev,rdev,tmp) { + if (!sb) { + sb = rdev->sb; + continue; + } + if (!sb_equal(sb, rdev->sb)) { + printk (INCONSISTENT, partition_name(rdev->dev)); + kick_rdev_from_array(rdev); + continue; + } + } + + /* + * OK, we have all disks and the array is ready to run. Let's + * find the freshest superblock, that one will be the superblock + * that represents the whole array. + */ + if (!mddev->sb) + if (alloc_array_sb(mddev)) + goto abort; + sb = mddev->sb; + freshest = NULL; + + ITERATE_RDEV(mddev,rdev,tmp) { + __u64 ev1, ev2; + /* + * if the checksum is invalid, use the superblock + * only as a last resort. (decrease it's age by + * one event) + */ + if (calc_sb_csum(rdev->sb) != rdev->sb->sb_csum) { + __u64 ev = get_unaligned(&rdev->sb->events); + if (ev != (__u64)0) { + --ev; + put_unaligned(ev,&rdev->sb->events); + } + } + + printk("%s's event counter: %08lx\n", partition_name(rdev->dev), + (unsigned long)get_unaligned(&rdev->sb->events)); + if (!freshest) { + freshest = rdev; + continue; + } + /* + * Find the newest superblock version + */ + ev1 = get_unaligned(&rdev->sb->events); + ev2 = get_unaligned(&freshest->sb->events); + if (ev1 != ev2) { + out_of_date = 1; + if (ev1 > ev2) + freshest = rdev; + } + } + if (out_of_date) { + printk(OUT_OF_DATE); + printk("freshest: %s\n", partition_name(freshest->dev)); + } + memcpy (sb, freshest->sb, sizeof(*sb)); + + /* + * at this point we have picked the 'best' superblock + * from all available superblocks. + * now we validate this superblock and kick out possibly + * failed disks. + */ + ITERATE_RDEV(mddev,rdev,tmp) { + /* + * Kick all non-fresh devices faulty + */ + __u64 ev1, ev2; + ev1 = get_unaligned(&rdev->sb->events); + ev2 = get_unaligned(&sb->events); + ++ev1; + if (ev1 < ev2) { + printk("md: kicking non-fresh %s from array!\n", + partition_name(rdev->dev)); + kick_rdev_from_array(rdev); + continue; + } + } + + /* + * Fix up changed device names ... but only if this disk has a + * recent update time. Use faulty checksum ones too. + */ + ITERATE_RDEV(mddev,rdev,tmp) { + __u64 ev1, ev2, ev3; + if (rdev->faulty) { /* REMOVEME */ + MD_BUG(); + goto abort; + } + ev1 = get_unaligned(&rdev->sb->events); + ev2 = get_unaligned(&sb->events); + ev3 = ev2; + --ev3; + if ((rdev->dev != rdev->old_dev) && + ((ev1 == ev2) || (ev1 == ev3))) { + mdp_disk_t *desc; + + printk("md: device name has changed from %s to %s since last import!\n", partition_name(rdev->old_dev), partition_name(rdev->dev)); + if (rdev->desc_nr == -1) { + MD_BUG(); + goto abort; + } + desc = &sb->disks[rdev->desc_nr]; + if (rdev->old_dev != MKDEV(desc->major, desc->minor)) { + MD_BUG(); + goto abort; + } + desc->major = MAJOR(rdev->dev); + desc->minor = MINOR(rdev->dev); + desc = &rdev->sb->this_disk; + desc->major = MAJOR(rdev->dev); + desc->minor = MINOR(rdev->dev); + } + } + + /* + * Remove unavailable and faulty devices ... + * + * note that if an array becomes completely unrunnable due to + * missing devices, we do not write the superblock back, so the + * administrator has a chance to fix things up. The removal thus + * only happens if it's nonfatal to the contents of the array. + */ + for (i = 0; i < MD_SB_DISKS; i++) { + int found; + mdp_disk_t *desc; + kdev_t dev; + + desc = sb->disks + i; + dev = MKDEV(desc->major, desc->minor); + + /* + * We kick faulty devices/descriptors immediately. + */ + if (disk_faulty(desc)) { + found = 0; + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->desc_nr != desc->number) + continue; + printk("md%d: kicking faulty %s!\n", + mdidx(mddev),partition_name(rdev->dev)); + kick_rdev_from_array(rdev); + found = 1; + break; + } + if (!found) { + if (dev == MKDEV(0,0)) + continue; + printk("md%d: removing former faulty %s!\n", + mdidx(mddev), partition_name(dev)); + } + remove_descriptor(desc, sb); + continue; + } + + if (dev == MKDEV(0,0)) + continue; + /* + * Is this device present in the rdev ring? + */ + found = 0; + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->desc_nr == desc->number) { + found = 1; + break; + } + } + if (found) + continue; + + printk("md%d: former device %s is unavailable, removing from array!\n", mdidx(mddev), partition_name(dev)); + remove_descriptor(desc, sb); + } + + /* + * Double check wether all devices mentioned in the + * superblock are in the rdev ring. + */ + for (i = 0; i < MD_SB_DISKS; i++) { + mdp_disk_t *desc; + kdev_t dev; + + desc = sb->disks + i; + dev = MKDEV(desc->major, desc->minor); + + if (dev == MKDEV(0,0)) + continue; + + if (disk_faulty(desc)) { + MD_BUG(); + goto abort; + } + + rdev = find_rdev(mddev, dev); + if (!rdev) { + MD_BUG(); + goto abort; + } + } + + /* + * Do a final reality check. + */ + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->desc_nr == -1) { + MD_BUG(); + goto abort; + } + /* + * is the desc_nr unique? + */ + ITERATE_RDEV(mddev,rdev2,tmp2) { + if ((rdev2 != rdev) && + (rdev2->desc_nr == rdev->desc_nr)) { + MD_BUG(); + goto abort; + } + } + /* + * is the device unique? + */ + ITERATE_RDEV(mddev,rdev2,tmp2) { + if ((rdev2 != rdev) && + (rdev2->dev == rdev->dev)) { + MD_BUG(); + goto abort; + } + } + } + + /* + * Check if we can support this RAID array + */ + if (sb->major_version != MD_MAJOR_VERSION || + sb->minor_version > MD_MINOR_VERSION) { + + printk (OLD_VERSION, mdidx(mddev), sb->major_version, + sb->minor_version, sb->patch_version); + goto abort; + } + + if ((sb->state != (1 << MD_SB_CLEAN)) && ((sb->level == 1) || + (sb->level == 4) || (sb->level == 5))) + printk (NOT_CLEAN_IGNORE, mdidx(mddev)); + + return 0; +abort: + return 1; +} + +#undef INCONSISTENT +#undef OUT_OF_DATE +#undef OLD_VERSION +#undef OLD_LEVEL + +static int device_size_calculation (mddev_t * mddev) +{ + int data_disks = 0, persistent; + unsigned int readahead; + mdp_super_t *sb = mddev->sb; + struct md_list_head *tmp; + mdk_rdev_t *rdev; + + /* + * Do device size calculation. Bail out if too small. + * (we have to do this after having validated chunk_size, + * because device size has to be modulo chunk_size) + */ + persistent = !mddev->sb->not_persistent; + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->faulty) + continue; + if (rdev->size) { + MD_BUG(); + continue; + } + rdev->size = calc_dev_size(rdev->dev, mddev, persistent); + if (rdev->size < sb->chunk_size / 1024) { + printk (KERN_WARNING + "Dev %s smaller than chunk_size: %dk < %dk\n", + partition_name(rdev->dev), + rdev->size, sb->chunk_size / 1024); + return -EINVAL; + } + } + + switch (sb->level) { + case -3: + data_disks = 1; + break; + case -2: + data_disks = 1; + break; + case -1: + zoned_raid_size(mddev); + data_disks = 1; + break; + case 0: + zoned_raid_size(mddev); + data_disks = sb->raid_disks; + break; + case 1: + data_disks = 1; + break; + case 4: + case 5: + data_disks = sb->raid_disks-1; + break; + default: + printk (UNKNOWN_LEVEL, mdidx(mddev), sb->level); + goto abort; + } + if (!md_size[mdidx(mddev)]) + md_size[mdidx(mddev)] = sb->size * data_disks; + + readahead = MD_READAHEAD; + if ((sb->level == 0) || (sb->level == 4) || (sb->level == 5)) + readahead = mddev->sb->chunk_size * 4 * data_disks; + if (readahead < data_disks * MAX_SECTORS*512*2) + readahead = data_disks * MAX_SECTORS*512*2; + else { + if (sb->level == -3) + readahead = 0; + } + md_maxreadahead[mdidx(mddev)] = readahead; + + printk(KERN_INFO "md%d: max total readahead window set to %dk\n", + mdidx(mddev), readahead/1024); + + printk(KERN_INFO + "md%d: %d data-disks, max readahead per data-disk: %dk\n", + mdidx(mddev), data_disks, readahead/data_disks/1024); + return 0; +abort: + return 1; +} + + +#define TOO_BIG_CHUNKSIZE KERN_ERR \ +"too big chunk_size: %d > %d\n" + +#define TOO_SMALL_CHUNKSIZE KERN_ERR \ +"too small chunk_size: %d < %ld\n" + +#define BAD_CHUNKSIZE KERN_ERR \ +"no chunksize specified, see 'man raidtab'\n" + +static int do_md_run (mddev_t * mddev) +{ + int pnum, err; + int chunk_size; + struct md_list_head *tmp; + mdk_rdev_t *rdev; + + + if (!mddev->nb_dev) { + MD_BUG(); + return -EINVAL; + } + + if (mddev->pers) + return -EBUSY; + + /* + * Resize disks to align partitions size on a given + * chunk size. + */ + md_size[mdidx(mddev)] = 0; + + /* + * Analyze all RAID superblock(s) + */ + if (analyze_sbs(mddev)) { + MD_BUG(); + return -EINVAL; + } + + chunk_size = mddev->sb->chunk_size; + pnum = level_to_pers(mddev->sb->level); + + mddev->param.chunk_size = chunk_size; + mddev->param.personality = pnum; + + if (chunk_size > MAX_CHUNK_SIZE) { + printk(TOO_BIG_CHUNKSIZE, chunk_size, MAX_CHUNK_SIZE); + return -EINVAL; + } + /* + * chunk-size has to be a power of 2 and multiples of PAGE_SIZE + */ + if ( (1 << ffz(~chunk_size)) != chunk_size) { + MD_BUG(); + return -EINVAL; + } + if (chunk_size < PAGE_SIZE) { + printk(TOO_SMALL_CHUNKSIZE, chunk_size, PAGE_SIZE); + return -EINVAL; + } + + if (pnum >= MAX_PERSONALITY) { + MD_BUG(); + return -EINVAL; + } + + if ((pnum != RAID1) && (pnum != LINEAR) && !chunk_size) { + /* + * 'default chunksize' in the old md code used to + * be PAGE_SIZE, baaad. + * we abort here to be on the safe side. We dont + * want to continue the bad practice. + */ + printk(BAD_CHUNKSIZE); + return -EINVAL; + } + + if (!pers[pnum]) + { +#ifdef CONFIG_KMOD + char module_name[80]; + sprintf (module_name, "md-personality-%d", pnum); + request_module (module_name); + if (!pers[pnum]) +#endif + return -EINVAL; + } + + if (device_size_calculation(mddev)) + return -EINVAL; + + /* + * Drop all container device buffers, from now on + * the only valid external interface is through the md + * device. + */ + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->faulty) + continue; + fsync_dev(rdev->dev); + invalidate_buffers(rdev->dev); + } + + mddev->pers = pers[pnum]; + + err = mddev->pers->run(mddev); + if (err) { + printk("pers->run() failed ...\n"); + mddev->pers = NULL; + return -EINVAL; + } + + mddev->sb->state &= ~(1 << MD_SB_CLEAN); + md_update_sb(mddev); + + /* + * md_size has units of 1K blocks, which are + * twice as large as sectors. + */ + md_hd_struct[mdidx(mddev)].start_sect = 0; + md_hd_struct[mdidx(mddev)].nr_sects = md_size[mdidx(mddev)] << 1; + + read_ahead[MD_MAJOR] = 1024; + return (0); +} + +#undef TOO_BIG_CHUNKSIZE +#undef BAD_CHUNKSIZE + +#define OUT(x) do { err = (x); goto out; } while (0) + +static int restart_array (mddev_t *mddev) +{ + int err = 0; + + /* + * Complain if it has no devices + */ + if (!mddev->nb_dev) + OUT(-ENXIO); + + if (mddev->pers) { + if (!mddev->ro) + OUT(-EBUSY); + + mddev->ro = 0; + set_device_ro(mddev_to_kdev(mddev), 0); + + printk (KERN_INFO + "md%d switched to read-write mode.\n", mdidx(mddev)); + /* + * Kick recovery or resync if necessary + */ + md_recover_arrays(); + if (mddev->pers->restart_resync) + mddev->pers->restart_resync(mddev); + } else + err = -EINVAL; + +out: + return err; +} + +#define STILL_MOUNTED KERN_WARNING \ +"md: md%d still mounted.\n" + +static int do_md_stop (mddev_t * mddev, int ro) +{ + int err = 0, resync_interrupted = 0; + kdev_t dev = mddev_to_kdev(mddev); + + if (!ro && !fs_may_mount (dev)) { + printk (STILL_MOUNTED, mdidx(mddev)); + OUT(-EBUSY); + } + + /* + * complain if it's already stopped + */ + if (!mddev->nb_dev) + OUT(-ENXIO); + + if (mddev->pers) { + /* + * It is safe to call stop here, it only frees private + * data. Also, it tells us if a device is unstoppable + * (eg. resyncing is in progress) + */ + if (mddev->pers->stop_resync) + if (mddev->pers->stop_resync(mddev)) + resync_interrupted = 1; + + if (mddev->recovery_running) + md_interrupt_thread(md_recovery_thread); + + /* + * This synchronizes with signal delivery to the + * resync or reconstruction thread. It also nicely + * hangs the process if some reconstruction has not + * finished. + */ + down(&mddev->recovery_sem); + up(&mddev->recovery_sem); + + /* + * sync and invalidate buffers because we cannot kill the + * main thread with valid IO transfers still around. + * the kernel lock protects us from new requests being + * added after invalidate_buffers(). + */ + fsync_dev (mddev_to_kdev(mddev)); + fsync_dev (dev); + invalidate_buffers (dev); + + if (ro) { + if (mddev->ro) + OUT(-ENXIO); + mddev->ro = 1; + } else { + if (mddev->ro) + set_device_ro(dev, 0); + if (mddev->pers->stop(mddev)) { + if (mddev->ro) + set_device_ro(dev, 1); + OUT(-EBUSY); + } + if (mddev->ro) + mddev->ro = 0; + } + if (mddev->sb) { + /* + * mark it clean only if there was no resync + * interrupted. + */ + if (!mddev->recovery_running && !resync_interrupted) { + printk("marking sb clean...\n"); + mddev->sb->state |= 1 << MD_SB_CLEAN; + } + md_update_sb(mddev); + } + if (ro) + set_device_ro(dev, 1); + } + + /* + * Free resources if final stop + */ + if (!ro) { + export_array(mddev); + md_size[mdidx(mddev)] = 0; + md_hd_struct[mdidx(mddev)].nr_sects = 0; + free_mddev(mddev); + + printk (KERN_INFO "md%d stopped.\n", mdidx(mddev)); + } else + printk (KERN_INFO + "md%d switched to read-only mode.\n", mdidx(mddev)); +out: + return err; +} + +#undef OUT + +/* + * We have to safely support old arrays too. + */ +int detect_old_array (mdp_super_t *sb) +{ + if (sb->major_version > 0) + return 0; + if (sb->minor_version >= 90) + return 0; + + return -EINVAL; +} + + +static void autorun_array (mddev_t *mddev) +{ + mdk_rdev_t *rdev; + struct md_list_head *tmp; + int err; + + if (mddev->disks.prev == &mddev->disks) { + MD_BUG(); + return; + } + + printk("running: "); + + ITERATE_RDEV(mddev,rdev,tmp) { + printk("<%s>", partition_name(rdev->dev)); + } + printk("\nnow!\n"); + + err = do_md_run (mddev); + if (err) { + printk("do_md_run() returned %d\n", err); + /* + * prevent the writeback of an unrunnable array + */ + mddev->sb_dirty = 0; + do_md_stop (mddev, 0); + } +} + +/* + * lets try to run arrays based on all disks that have arrived + * until now. (those are in the ->pending list) + * + * the method: pick the first pending disk, collect all disks with + * the same UUID, remove all from the pending list and put them into + * the 'same_array' list. Then order this list based on superblock + * update time (freshest comes first), kick out 'old' disks and + * compare superblocks. If everything's fine then run it. + */ +static void autorun_devices (void) +{ + struct md_list_head candidates; + struct md_list_head *tmp; + mdk_rdev_t *rdev0, *rdev; + mddev_t *mddev; + kdev_t md_kdev; + + + printk("autorun ...\n"); + while (pending_raid_disks.next != &pending_raid_disks) { + rdev0 = md_list_entry(pending_raid_disks.next, + mdk_rdev_t, pending); + + printk("considering %s ...\n", partition_name(rdev0->dev)); + MD_INIT_LIST_HEAD(&candidates); + ITERATE_RDEV_PENDING(rdev,tmp) { + if (uuid_equal(rdev0, rdev)) { + if (!sb_equal(rdev0->sb, rdev->sb)) { + printk("%s has same UUID as %s, but superblocks differ ...\n", partition_name(rdev->dev), partition_name(rdev0->dev)); + continue; + } + printk(" adding %s ...\n", partition_name(rdev->dev)); + md_list_del(&rdev->pending); + md_list_add(&rdev->pending, &candidates); + } + } /* - * Check the superblock for consistency. - * The personality itself has to check whether it's getting - * added with the proper flags. The personality has to be - * checked too. ;) + * now we have a set of devices, with all of them having + * mostly sane superblocks. It's time to allocate the + * mddev. */ - if (analyze_one_sb (realdev)) + md_kdev = MKDEV(MD_MAJOR, rdev0->sb->md_minor); + mddev = kdev_to_mddev(md_kdev); + if (mddev) { + printk("md%d already running, cannot run %s\n", + mdidx(mddev), partition_name(rdev0->dev)); + ITERATE_RDEV_GENERIC(candidates,pending,rdev,tmp) + export_rdev(rdev); + continue; + } + mddev = alloc_mddev(md_kdev); + printk("created md%d\n", mdidx(mddev)); + ITERATE_RDEV_GENERIC(candidates,pending,rdev,tmp) { + bind_rdev_to_array(rdev, mddev); + md_list_del(&rdev->pending); + MD_INIT_LIST_HEAD(&rdev->pending); + } + autorun_array(mddev); + } + printk("... autorun DONE.\n"); +} + +/* + * import RAID devices based on one partition + * if possible, the array gets run as well. + */ + +#define BAD_VERSION KERN_ERR \ +"md: %s has RAID superblock version 0.%d, autodetect needs v0.90 or higher\n" + +#define OUT_OF_MEM KERN_ALERT \ +"md: out of memory.\n" + +#define NO_DEVICE KERN_ERR \ +"md: disabled device %s\n" + +#define AUTOADD_FAILED KERN_ERR \ +"md: auto-adding devices to md%d FAILED (error %d).\n" + +#define AUTOADD_FAILED_USED KERN_ERR \ +"md: cannot auto-add device %s to md%d, already used.\n" + +#define AUTORUN_FAILED KERN_ERR \ +"md: auto-running md%d FAILED (error %d).\n" + +#define MDDEV_BUSY KERN_ERR \ +"md: cannot auto-add to md%d, already running.\n" + +#define AUTOADDING KERN_INFO \ +"md: auto-adding devices to md%d, based on %s's superblock.\n" + +#define AUTORUNNING KERN_INFO \ +"md: auto-running md%d.\n" + +static int autostart_array (kdev_t startdev) +{ + int err = -EINVAL, i; + mdp_super_t *sb = NULL; + mdk_rdev_t *start_rdev = NULL, *rdev; + + if (md_import_device(startdev, 1)) { + printk("could not import %s!\n", partition_name(startdev)); + goto abort; + } + + start_rdev = find_rdev_all(startdev); + if (!start_rdev) { + MD_BUG(); + goto abort; + } + if (start_rdev->faulty) { + printk("can not autostart based on faulty %s!\n", + partition_name(startdev)); + goto abort; + } + md_list_add(&start_rdev->pending, &pending_raid_disks); + + sb = start_rdev->sb; + + err = detect_old_array(sb); + if (err) { + printk("array version is too old to be autostarted, use raidtools 0.90 mkraid --upgrade\nto upgrade the array without data loss!\n"); + goto abort; + } + + for (i = 0; i < MD_SB_DISKS; i++) { + mdp_disk_t *desc; + kdev_t dev; + + desc = sb->disks + i; + dev = MKDEV(desc->major, desc->minor); + + if (dev == MKDEV(0,0)) + continue; + if (dev == startdev) + continue; + if (md_import_device(dev, 1)) { + printk("could not import %s, trying to run array nevertheless.\n", partition_name(dev)); + continue; + } + rdev = find_rdev_all(dev); + if (!rdev) { + MD_BUG(); + goto abort; + } + md_list_add(&rdev->pending, &pending_raid_disks); + } + + /* + * possibly return codes + */ + autorun_devices(); + return 0; + +abort: + if (start_rdev) + export_rdev(start_rdev); + return err; +} + +#undef BAD_VERSION +#undef OUT_OF_MEM +#undef NO_DEVICE +#undef AUTOADD_FAILED_USED +#undef AUTOADD_FAILED +#undef AUTORUN_FAILED +#undef AUTOADDING +#undef AUTORUNNING + +struct { + int set; + int noautodetect; + +} raid_setup_args md__initdata = { 0, 0 }; + +/* + * Searches all registered partitions for autorun RAID arrays + * at boot time. + */ +md__initfunc(void autodetect_raid(void)) +{ +#ifdef CONFIG_AUTODETECT_RAID + struct gendisk *disk; + mdk_rdev_t *rdev; + int i; + + if (raid_setup_args.noautodetect) { + printk(KERN_INFO "skipping autodetection of RAID arrays\n"); + return; + } + printk(KERN_INFO "autodetecting RAID arrays\n"); + + for (disk = gendisk_head ; disk ; disk = disk->next) { + for (i = 0; i < disk->max_p*disk->max_nr; i++) { + kdev_t dev = MKDEV(disk->major,i); + + if (disk->part[i].type == LINUX_OLD_RAID_PARTITION) { + printk(KERN_ALERT +"md: %s's partition type has to be changed from type 0x86 to type 0xfd\n" +" to maintain interoperability with other OSs! Autodetection support for\n" +" type 0x86 will be deleted after some migration timeout. Sorry.\n", + partition_name(dev)); + disk->part[i].type = LINUX_RAID_PARTITION; + } + if (disk->part[i].type != LINUX_RAID_PARTITION) + continue; + + if (md_import_device(dev,1)) { + printk(KERN_ALERT "could not import %s!\n", + partition_name(dev)); + continue; + } + /* + * Sanity checks: + */ + rdev = find_rdev_all(dev); + if (!rdev) { + MD_BUG(); + continue; + } + if (rdev->faulty) { + MD_BUG(); + continue; + } + md_list_add(&rdev->pending, &pending_raid_disks); + } + } + + autorun_devices(); +#endif +} + +static int get_version (void * arg) +{ + mdu_version_t ver; + + ver.major = MD_MAJOR_VERSION; + ver.minor = MD_MINOR_VERSION; + ver.patchlevel = MD_PATCHLEVEL_VERSION; + + if (md_copy_to_user(arg, &ver, sizeof(ver))) + return -EFAULT; + + return 0; +} + +#define SET_FROM_SB(x) info.x = mddev->sb->x +static int get_array_info (mddev_t * mddev, void * arg) +{ + mdu_array_info_t info; + + if (!mddev->sb) + return -EINVAL; + + SET_FROM_SB(major_version); + SET_FROM_SB(minor_version); + SET_FROM_SB(patch_version); + SET_FROM_SB(ctime); + SET_FROM_SB(level); + SET_FROM_SB(size); + SET_FROM_SB(nr_disks); + SET_FROM_SB(raid_disks); + SET_FROM_SB(md_minor); + SET_FROM_SB(not_persistent); + + SET_FROM_SB(utime); + SET_FROM_SB(state); + SET_FROM_SB(active_disks); + SET_FROM_SB(working_disks); + SET_FROM_SB(failed_disks); + SET_FROM_SB(spare_disks); + + SET_FROM_SB(layout); + SET_FROM_SB(chunk_size); + + if (md_copy_to_user(arg, &info, sizeof(info))) + return -EFAULT; + + return 0; +} +#undef SET_FROM_SB + +#define SET_FROM_SB(x) info.x = mddev->sb->disks[nr].x +static int get_disk_info (mddev_t * mddev, void * arg) +{ + mdu_disk_info_t info; + unsigned int nr; + + if (!mddev->sb) + return -EINVAL; + + if (md_copy_from_user(&info, arg, sizeof(info))) + return -EFAULT; + + nr = info.number; + if (nr >= mddev->sb->nr_disks) + return -EINVAL; + + SET_FROM_SB(major); + SET_FROM_SB(minor); + SET_FROM_SB(raid_disk); + SET_FROM_SB(state); + + if (md_copy_to_user(arg, &info, sizeof(info))) + return -EFAULT; + + return 0; +} +#undef SET_FROM_SB + +#define SET_SB(x) mddev->sb->disks[nr].x = info.x + +static int add_new_disk (mddev_t * mddev, void * arg) +{ + int err, size, persistent; + mdu_disk_info_t info; + mdk_rdev_t *rdev; + unsigned int nr; + kdev_t dev; + + if (!mddev->sb) + return -EINVAL; + + if (md_copy_from_user(&info, arg, sizeof(info))) + return -EFAULT; + + nr = info.number; + if (nr >= mddev->sb->nr_disks) + return -EINVAL; + + dev = MKDEV(info.major,info.minor); + + if (find_rdev_all(dev)) { + printk("device %s already used in a RAID array!\n", + partition_name(dev)); + return -EBUSY; + } + + SET_SB(number); + SET_SB(major); + SET_SB(minor); + SET_SB(raid_disk); + SET_SB(state); + + if ((info.state & (1<old_dev = dev; + rdev->desc_nr = info.number; + + bind_rdev_to_array(rdev, mddev); + + persistent = !mddev->sb->not_persistent; + if (!persistent) + printk("nonpersistent superblock ...\n"); + if (!mddev->sb->chunk_size) + printk("no chunksize?\n"); + + size = calc_dev_size(dev, mddev, persistent); + rdev->sb_offset = calc_dev_sboffset(dev, mddev, persistent); + + if (!mddev->sb->size || (mddev->sb->size > size)) + mddev->sb->size = size; + } + + /* + * sync all other superblocks with the main superblock + */ + sync_sbs(mddev); + + return 0; +} +#undef SET_SB + +static int hot_remove_disk (mddev_t * mddev, kdev_t dev) +{ + int err; + mdk_rdev_t *rdev; + mdp_disk_t *disk; + + if (!mddev->pers) + return -ENODEV; + + printk("trying to remove %s from md%d ... \n", + partition_name(dev), mdidx(mddev)); + + if (!mddev->pers->diskop) { + printk("md%d: personality does not support diskops!\n", + mdidx(mddev)); + return -EINVAL; + } + + rdev = find_rdev(mddev, dev); + if (!rdev) + return -ENXIO; + + if (rdev->desc_nr == -1) { + MD_BUG(); + return -EINVAL; + } + disk = &mddev->sb->disks[rdev->desc_nr]; + if (disk_active(disk)) + goto busy; + if (disk_removed(disk)) { + MD_BUG(); + return -EINVAL; + } + + err = mddev->pers->diskop(mddev, &disk, DISKOP_HOT_REMOVE_DISK); + if (err == -EBUSY) + goto busy; + if (err) { + MD_BUG(); + return -EINVAL; + } + + remove_descriptor(disk, mddev->sb); + kick_rdev_from_array(rdev); + mddev->sb_dirty = 1; + md_update_sb(mddev); + + return 0; +busy: + printk("cannot remove active disk %s from md%d ... \n", + partition_name(dev), mdidx(mddev)); + return -EBUSY; +} + +static int hot_add_disk (mddev_t * mddev, kdev_t dev) +{ + int i, err, persistent; + unsigned int size; + mdk_rdev_t *rdev; + mdp_disk_t *disk; + + if (!mddev->pers) + return -ENODEV; + + printk("trying to hot-add %s to md%d ... \n", + partition_name(dev), mdidx(mddev)); + + if (!mddev->pers->diskop) { + printk("md%d: personality does not support diskops!\n", + mdidx(mddev)); + return -EINVAL; + } + + persistent = !mddev->sb->not_persistent; + size = calc_dev_size(dev, mddev, persistent); + + if (size < mddev->sb->size) { + printk("md%d: disk size %d blocks < array size %d\n", + mdidx(mddev), size, mddev->sb->size); + return -ENOSPC; + } + + rdev = find_rdev(mddev, dev); + if (rdev) + return -EBUSY; + + err = md_import_device (dev, 0); + if (err) { + printk("md: error, md_import_device() returned %d\n", err); + return -EINVAL; + } + rdev = find_rdev_all(dev); + if (!rdev) { + MD_BUG(); + return -EINVAL; + } + if (rdev->faulty) { + printk("md: can not hot-add faulty %s disk to md%d!\n", + partition_name(dev), mdidx(mddev)); + err = -EINVAL; + goto abort_export; + } + bind_rdev_to_array(rdev, mddev); + + /* + * The rest should better be atomic, we can have disk failures + * noticed in interrupt contexts ... + */ + cli(); + rdev->old_dev = dev; + rdev->size = size; + rdev->sb_offset = calc_dev_sboffset(dev, mddev, persistent); + + disk = mddev->sb->disks + mddev->sb->raid_disks; + for (i = mddev->sb->raid_disks; i < MD_SB_DISKS; i++) { + disk = mddev->sb->disks + i; + + if (!disk->major && !disk->minor) + break; + if (disk_removed(disk)) + break; + } + if (i == MD_SB_DISKS) { + sti(); + printk("md%d: can not hot-add to full array!\n", mdidx(mddev)); + err = -EBUSY; + goto abort_unbind_export; + } + + if (disk_removed(disk)) { /* - * hot_add has to bump up nb_dev itself + * reuse slot */ - if (md_dev[minor].pers->hot_add_disk (&md_dev[minor], dev)) { - /* - * FIXME: here we should free up the inode and stuff - */ - printk ("FIXME\n"); - return -EINVAL; + if (disk->number != i) { + sti(); + MD_BUG(); + err = -EINVAL; + goto abort_unbind_export; } - } else - md_dev[minor].nb_dev++; + } else { + disk->number = i; + } - printk ("REGISTER_DEV %s to md%x done\n", partition_name(dev), minor); - return (0); + disk->raid_disk = disk->number; + disk->major = MAJOR(dev); + disk->minor = MINOR(dev); + + if (mddev->pers->diskop(mddev, &disk, DISKOP_HOT_ADD_DISK)) { + sti(); + MD_BUG(); + err = -EINVAL; + goto abort_unbind_export; + } + + mark_disk_spare(disk); + mddev->sb->nr_disks++; + mddev->sb->spare_disks++; + mddev->sb->working_disks++; + + mddev->sb_dirty = 1; + + sti(); + md_update_sb(mddev); + + /* + * Kick recovery, maybe this spare has to be added to the + * array immediately. + */ + md_recover_arrays(); + + return 0; + +abort_unbind_export: + unbind_rdev_from_array(rdev); + +abort_export: + export_rdev(rdev); + return err; +} + +#define SET_SB(x) mddev->sb->x = info.x +static int set_array_info (mddev_t * mddev, void * arg) +{ + mdu_array_info_t info; + + if (mddev->sb) { + printk("array md%d already has a superblock!\n", + mdidx(mddev)); + return -EBUSY; + } + + if (md_copy_from_user(&info, arg, sizeof(info))) + return -EFAULT; + + if (alloc_array_sb(mddev)) + return -ENOMEM; + + mddev->sb->major_version = MD_MAJOR_VERSION; + mddev->sb->minor_version = MD_MINOR_VERSION; + mddev->sb->patch_version = MD_PATCHLEVEL_VERSION; + mddev->sb->ctime = CURRENT_TIME; + + SET_SB(level); + SET_SB(size); + SET_SB(nr_disks); + SET_SB(raid_disks); + SET_SB(md_minor); + SET_SB(not_persistent); + + SET_SB(state); + SET_SB(active_disks); + SET_SB(working_disks); + SET_SB(failed_disks); + SET_SB(spare_disks); + + SET_SB(layout); + SET_SB(chunk_size); + + mddev->sb->md_magic = MD_SB_MAGIC; + + /* + * Generate a 128 bit UUID + */ + get_random_bytes(&mddev->sb->set_uuid0, 4); + get_random_bytes(&mddev->sb->set_uuid1, 4); + get_random_bytes(&mddev->sb->set_uuid2, 4); + get_random_bytes(&mddev->sb->set_uuid3, 4); + + return 0; +} +#undef SET_SB + +static int set_disk_info (mddev_t * mddev, void * arg) +{ + printk("not yet"); + return -EINVAL; +} + +static int clear_array (mddev_t * mddev) +{ + printk("not yet"); + return -EINVAL; +} + +static int write_raid_info (mddev_t * mddev) +{ + printk("not yet"); + return -EINVAL; +} + +static int protect_array (mddev_t * mddev) +{ + printk("not yet"); + return -EINVAL; +} + +static int unprotect_array (mddev_t * mddev) +{ + printk("not yet"); + return -EINVAL; } static int md_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - int minor, err; - struct hd_geometry *loc = (struct hd_geometry *) arg; + unsigned int minor; + int err = 0; + struct hd_geometry *loc = (struct hd_geometry *) arg; + mddev_t *mddev = NULL; + kdev_t dev; - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; + if (!md_capable_admin()) + return -EACCES; - if (((minor=MINOR(inode->i_rdev)) & 0x80) && - (minor & 0x7f) < MAX_PERSONALITY && - pers[minor & 0x7f] && - pers[minor & 0x7f]->ioctl) - return (pers[minor & 0x7f]->ioctl (inode, file, cmd, arg)); - - if (minor >= MAX_MD_DEV) - return -EINVAL; + dev = inode->i_rdev; + minor = MINOR(dev); + if (minor >= MAX_MD_DEVS) + return -EINVAL; - switch (cmd) - { - case REGISTER_DEV: - return do_md_add (minor, to_kdev_t ((dev_t) arg)); + /* + * Commands dealing with the RAID driver but not any + * particular array: + */ + switch (cmd) + { + case RAID_VERSION: + err = get_version((void *)arg); + goto done; + + case PRINT_RAID_DEBUG: + err = 0; + md_print_devices(); + goto done_unlock; + + case BLKGETSIZE: /* Return device size */ + if (!arg) { + err = -EINVAL; + goto abort; + } + err = md_put_user(md_hd_struct[minor].nr_sects, + (long *) arg); + goto done; - case START_MD: - return do_md_run (minor, (int) arg); + case BLKFLSBUF: + fsync_dev(dev); + invalidate_buffers(dev); + goto done; - case STOP_MD: - return do_md_stop (minor, inode); - - case BLKGETSIZE: /* Return device size */ - if (!arg) return -EINVAL; - err = put_user (md_hd_struct[MINOR(inode->i_rdev)].nr_sects, (long *) arg); - if (err) - return err; - break; - - case BLKFLSBUF: - fsync_dev (inode->i_rdev); - invalidate_buffers (inode->i_rdev); - break; - - case BLKRASET: - if (arg > 0xff) - return -EINVAL; - read_ahead[MAJOR(inode->i_rdev)] = arg; - return 0; - - case BLKRAGET: - if (!arg) return -EINVAL; - err = put_user (read_ahead[MAJOR(inode->i_rdev)], (long *) arg); - if (err) - return err; - break; - - /* We have a problem here : there is no easy way to give a CHS - virtual geometry. We currently pretend that we have a 2 heads - 4 sectors (with a BIG number of cylinders...). This drives dosfs - just mad... ;-) */ - - case HDIO_GETGEO: - if (!loc) return -EINVAL; - err = put_user (2, (char *) &loc->heads); - if (err) - return err; - err = put_user (4, (char *) &loc->sectors); - if (err) - return err; - err = put_user (md_hd_struct[minor].nr_sects/8, (short *) &loc->cylinders); - if (err) - return err; - err = put_user (md_hd_struct[MINOR(inode->i_rdev)].start_sect, - (long *) &loc->start); - if (err) - return err; - break; - - RO_IOCTLS(inode->i_rdev,arg); + case BLKRASET: + if (arg > 0xff) { + err = -EINVAL; + goto abort; + } + read_ahead[MAJOR(dev)] = arg; + goto done; - default: - return -EINVAL; - } + case BLKRAGET: + if (!arg) { + err = -EINVAL; + goto abort; + } + err = md_put_user (read_ahead[ + MAJOR(dev)], (long *) arg); + goto done; + default: + } + + /* + * Commands creating/starting a new array: + */ + + mddev = kdev_to_mddev(dev); + + switch (cmd) + { + case SET_ARRAY_INFO: + case START_ARRAY: + if (mddev) { + printk("array md%d already exists!\n", + mdidx(mddev)); + err = -EEXIST; + goto abort; + } + default: + } + + switch (cmd) + { + case SET_ARRAY_INFO: + mddev = alloc_mddev(dev); + if (!mddev) { + err = -ENOMEM; + goto abort; + } + /* + * alloc_mddev() should possibly self-lock. + */ + err = lock_mddev(mddev); + if (err) { + printk("ioctl, reason %d, cmd %d\n",err, cmd); + goto abort; + } + err = set_array_info(mddev, (void *)arg); + goto done_unlock; + + case START_ARRAY: + /* + * possibly make it lock the array ... + */ + err = autostart_array((kdev_t)arg); + if (err) { + printk("autostart %s failed!\n", + partition_name((kdev_t)arg)); + } + goto done; + + default: + } + + /* + * Commands querying/configuring an existing array: + */ + + if (!mddev) { + err = -ENODEV; + goto abort; + } + err = lock_mddev(mddev); + if (err) { + printk("ioctl lock interrupted, reason %d, cmd %d\n",err, cmd); + goto abort; + } + + /* + * Commands even a read-only array can execute: + */ + switch (cmd) + { + case GET_ARRAY_INFO: + err = get_array_info(mddev, (void *)arg); + goto done_unlock; + + case GET_DISK_INFO: + err = get_disk_info(mddev, (void *)arg); + goto done_unlock; + + case RESTART_ARRAY_RW: + err = restart_array(mddev); + goto done_unlock; + + case STOP_ARRAY: + err = do_md_stop (mddev, 0); + goto done_unlock; + + case STOP_ARRAY_RO: + err = do_md_stop (mddev, 1); + goto done_unlock; + + /* + * We have a problem here : there is no easy way to give a CHS + * virtual geometry. We currently pretend that we have a 2 heads + * 4 sectors (with a BIG number of cylinders...). This drives + * dosfs just mad... ;-) + */ + case HDIO_GETGEO: + if (!loc) { + err = -EINVAL; + goto abort_unlock; + } + err = md_put_user (2, (char *) &loc->heads); + if (err) + goto abort_unlock; + err = md_put_user (4, (char *) &loc->sectors); + if (err) + goto abort_unlock; + err = md_put_user (md_hd_struct[mdidx(mddev)].nr_sects/8, + (short *) &loc->cylinders); + if (err) + goto abort_unlock; + err = md_put_user (md_hd_struct[minor].start_sect, + (long *) &loc->start); + goto done_unlock; + } + + /* + * The remaining ioctls are changing the state of the + * superblock, so we do not allow read-only arrays + * here: + */ + if (mddev->ro) { + err = -EROFS; + goto abort_unlock; + } - return (0); + switch (cmd) + { + case CLEAR_ARRAY: + err = clear_array(mddev); + goto done_unlock; + + case ADD_NEW_DISK: + err = add_new_disk(mddev, (void *)arg); + goto done_unlock; + + case HOT_REMOVE_DISK: + err = hot_remove_disk(mddev, (kdev_t)arg); + goto done_unlock; + + case HOT_ADD_DISK: + err = hot_add_disk(mddev, (kdev_t)arg); + goto done_unlock; + + case SET_DISK_INFO: + err = set_disk_info(mddev, (void *)arg); + goto done_unlock; + + case WRITE_RAID_INFO: + err = write_raid_info(mddev); + goto done_unlock; + + case UNPROTECT_ARRAY: + err = unprotect_array(mddev); + goto done_unlock; + + case PROTECT_ARRAY: + err = protect_array(mddev); + goto done_unlock; + + case RUN_ARRAY: + { + mdu_param_t param; + + err = md_copy_from_user(¶m, (mdu_param_t *)arg, + sizeof(param)); + if (err) + goto abort_unlock; + + err = do_md_run (mddev); + /* + * we have to clean up the mess if + * the array cannot be run for some + * reason ... + */ + if (err) { + mddev->sb_dirty = 0; + do_md_stop (mddev, 0); + } + goto done_unlock; + } + + default: + printk(KERN_WARNING "%s(pid %d) used obsolete MD ioctl, upgrade your software to use new ictls.\n", current->comm, current->pid); + err = -EINVAL; + goto abort_unlock; + } + +done_unlock: +abort_unlock: + if (mddev) + unlock_mddev(mddev); + else + printk("huh11?\n"); + + return err; +done: + if (err) + printk("huh12?\n"); +abort: + return err; } + +#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,0) + static int md_open (struct inode *inode, struct file *file) { - int minor=MINOR(inode->i_rdev); + /* + * Always succeed + */ + return (0); +} - md_dev[minor].busy++; - return (0); /* Always succeed */ +static void md_release (struct inode *inode, struct file *file) +{ + sync_dev(inode->i_rdev); } -static int md_release (struct inode *inode, struct file *file) +static int md_read (struct inode *inode, struct file *file, + char *buf, int count) +{ + mddev_t *mddev = kdev_to_mddev(MD_FILE_TO_INODE(file)->i_rdev); + + if (!mddev || !mddev->pers) + return -ENXIO; + + return block_read (inode, file, buf, count); +} + +static int md_write (struct inode *inode, struct file *file, + const char *buf, int count) +{ + mddev_t *mddev = kdev_to_mddev(MD_FILE_TO_INODE(file)->i_rdev); + + if (!mddev || !mddev->pers) + return -ENXIO; + + return block_write (inode, file, buf, count); +} + +static struct file_operations md_fops= { - int minor=MINOR(inode->i_rdev); + NULL, + md_read, + md_write, + NULL, + NULL, + md_ioctl, + NULL, + md_open, + md_release, + block_fsync +}; + +#else - sync_dev (inode->i_rdev); - md_dev[minor].busy--; - return 0; +static int md_open (struct inode *inode, struct file *file) +{ + /* + * Always succeed + */ + return (0); } +static int md_release (struct inode *inode, struct file *file) +{ + sync_dev(inode->i_rdev); + return 0; +} static ssize_t md_read (struct file *file, char *buf, size_t count, loff_t *ppos) { - int minor=MINOR(file->f_dentry->d_inode->i_rdev); + mddev_t *mddev = kdev_to_mddev(MD_FILE_TO_INODE(file)->i_rdev); - if (!md_dev[minor].pers) /* Check if device is being run */ - return -ENXIO; + if (!mddev || !mddev->pers) + return -ENXIO; - return block_read(file, buf, count, ppos); + return block_read(file, buf, count, ppos); } static ssize_t md_write (struct file *file, const char *buf, size_t count, loff_t *ppos) { - int minor=MINOR(file->f_dentry->d_inode->i_rdev); + mddev_t *mddev = kdev_to_mddev(MD_FILE_TO_INODE(file)->i_rdev); - if (!md_dev[minor].pers) /* Check if device is being run */ - return -ENXIO; + if (!mddev || !mddev->pers) + return -ENXIO; - return block_write(file, buf, count, ppos); + return block_write(file, buf, count, ppos); } static struct file_operations md_fops= { - NULL, - md_read, - md_write, - NULL, - NULL, - md_ioctl, - NULL, - md_open, - NULL, - md_release, - block_fsync + NULL, + md_read, + md_write, + NULL, + NULL, + md_ioctl, + NULL, + md_open, + NULL, + md_release, + block_fsync }; -int md_map (int minor, kdev_t *rdev, unsigned long *rsector, unsigned long size) +#endif + +int md_map (kdev_t dev, kdev_t *rdev, + unsigned long *rsector, unsigned long size) { - if ((unsigned int) minor >= MAX_MD_DEV) - { - printk ("Bad md device %d\n", minor); - return (-1); - } - - if (!md_dev[minor].pers) - { - printk ("Oops ! md%d not running, giving up !\n", minor); - return (-1); - } + int err; + mddev_t *mddev = kdev_to_mddev(dev); - return (md_dev[minor].pers->map(md_dev+minor, rdev, rsector, size)); + if (!mddev || !mddev->pers) { + err = -ENXIO; + goto out; + } + + err = mddev->pers->map(mddev, dev, rdev, rsector, size); +out: + return err; } -int md_make_request (int minor, int rw, struct buffer_head * bh) +int md_make_request (struct buffer_head * bh, int rw) { - if (md_dev [minor].pers->make_request) { - if (buffer_locked(bh)) - return 0; + int err; + mddev_t *mddev = kdev_to_mddev(bh->b_dev); + + if (!mddev || !mddev->pers) { + err = -ENXIO; + goto out; + } + + if (mddev->pers->make_request) { + if (buffer_locked(bh)) { + err = 0; + goto out; + } set_bit(BH_Lock, &bh->b_state); if (rw == WRITE || rw == WRITEA) { if (!buffer_dirty(bh)) { - bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state)); - return 0; + bh->b_end_io(bh, buffer_uptodate(bh)); + err = 0; + goto out; } } if (rw == READ || rw == READA) { if (buffer_uptodate(bh)) { - bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state)); - return 0; + bh->b_end_io(bh, buffer_uptodate(bh)); + err = 0; + goto out; } } - return (md_dev[minor].pers->make_request(md_dev+minor, rw, bh)); + err = mddev->pers->make_request(mddev, rw, bh); } else { make_request (MAJOR(bh->b_rdev), rw, bh); - return 0; + err = 0; } +out: + return err; } static void do_md_request (void) { - printk ("Got md request, not good..."); - return; + printk(KERN_ALERT "Got md request, not good..."); + return; +} + +int md_thread(void * arg) +{ + mdk_thread_t *thread = arg; + + md_lock_kernel(); + exit_mm(current); + exit_files(current); + exit_fs(current); + + /* + * Detach thread + */ + sys_setsid(); + sprintf(current->comm, thread->name); + md_init_signals(); + md_flush_signals(); + thread->tsk = current; + + /* + * md_thread is a 'system-thread', it's priority should be very + * high. We avoid resource deadlocks individually in each + * raid personality. (RAID5 does preallocation) We also use RR and + * the very same RT priority as kswapd, thus we will never get + * into a priority inversion deadlock. + * + * we definitely have to have equal or higher priority than + * bdflush, otherwise bdflush will deadlock if there are too + * many dirty RAID5 blocks. + */ + current->policy = SCHED_OTHER; + current->priority = 40; + + up(thread->sem); + + for (;;) { + cli(); + if (!test_bit(THREAD_WAKEUP, &thread->flags)) { + if (!thread->run) + break; + interruptible_sleep_on(&thread->wqueue); + } + sti(); + clear_bit(THREAD_WAKEUP, &thread->flags); + if (thread->run) { + thread->run(thread->data); + run_task_queue(&tq_disk); + } + if (md_signal_pending(current)) { + printk("%8s(%d) flushing signals.\n", current->comm, + current->pid); + md_flush_signals(); + } + } + sti(); + up(thread->sem); + return 0; } -void md_wakeup_thread(struct md_thread *thread) +void md_wakeup_thread(mdk_thread_t *thread) { set_bit(THREAD_WAKEUP, &thread->flags); wake_up(&thread->wqueue); } -struct md_thread *md_register_thread (void (*run) (void *), void *data) +mdk_thread_t *md_register_thread (void (*run) (void *), + void *data, const char *name) { - struct md_thread *thread = (struct md_thread *) - kmalloc(sizeof(struct md_thread), GFP_KERNEL); + mdk_thread_t *thread; int ret; struct semaphore sem = MUTEX_LOCKED; - if (!thread) return NULL; + thread = (mdk_thread_t *) kmalloc + (sizeof(mdk_thread_t), GFP_KERNEL); + if (!thread) + return NULL; - memset(thread, 0, sizeof(struct md_thread)); + memset(thread, 0, sizeof(mdk_thread_t)); init_waitqueue(&thread->wqueue); thread->sem = &sem; thread->run = run; thread->data = data; + thread->name = name; ret = kernel_thread(md_thread, thread, 0); if (ret < 0) { kfree(thread); @@ -836,270 +2996,405 @@ return thread; } -void md_unregister_thread (struct md_thread *thread) +void md_interrupt_thread (mdk_thread_t *thread) +{ + if (!thread->tsk) { + MD_BUG(); + return; + } + printk("interrupting MD-thread pid %d\n", thread->tsk->pid); + send_sig(SIGKILL, thread->tsk, 1); +} + +void md_unregister_thread (mdk_thread_t *thread) { struct semaphore sem = MUTEX_LOCKED; thread->sem = &sem; thread->run = NULL; - if (thread->tsk) - printk("Killing md_thread %d %p %s\n", - thread->tsk->pid, thread->tsk, thread->tsk->comm); - else - printk("Aiee. md_thread has 0 tsk\n"); - send_sig(SIGKILL, thread->tsk, 1); - printk("downing on %p\n", &sem); + thread->name = NULL; + if (!thread->tsk) { + MD_BUG(); + return; + } + md_interrupt_thread(thread); down(&sem); } -#define SHUTDOWN_SIGS (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM)) - -int md_thread(void * arg) +void md_recover_arrays (void) { - struct md_thread *thread = arg; - - lock_kernel(); - exit_mm(current); - exit_files(current); - exit_fs(current); - - current->session = 1; - current->pgrp = 1; - sprintf(current->comm, "md_thread"); - siginitsetinv(¤t->blocked, SHUTDOWN_SIGS); - thread->tsk = current; - up(thread->sem); - - for (;;) { - cli(); - if (!test_bit(THREAD_WAKEUP, &thread->flags)) { - do { - spin_lock(¤t->sigmask_lock); - flush_signals(current); - spin_unlock(¤t->sigmask_lock); - interruptible_sleep_on(&thread->wqueue); - cli(); - if (test_bit(THREAD_WAKEUP, &thread->flags)) - break; - if (!thread->run) { - sti(); - up(thread->sem); - return 0; - } - } while (signal_pending(current)); - } - sti(); - clear_bit(THREAD_WAKEUP, &thread->flags); - if (thread->run) { - thread->run(thread->data); - run_task_queue(&tq_disk); - } + if (!md_recovery_thread) { + MD_BUG(); + return; } + md_wakeup_thread(md_recovery_thread); } -EXPORT_SYMBOL(md_size); -EXPORT_SYMBOL(md_maxreadahead); -EXPORT_SYMBOL(register_md_personality); -EXPORT_SYMBOL(unregister_md_personality); -EXPORT_SYMBOL(partition_name); -EXPORT_SYMBOL(md_dev); -EXPORT_SYMBOL(md_error); -EXPORT_SYMBOL(md_register_thread); -EXPORT_SYMBOL(md_unregister_thread); -EXPORT_SYMBOL(md_update_sb); -EXPORT_SYMBOL(md_map); -EXPORT_SYMBOL(md_wakeup_thread); -EXPORT_SYMBOL(md_do_sync); -#ifdef CONFIG_PROC_FS -static struct proc_dir_entry proc_md = { - PROC_MD, 6, "mdstat", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_array_inode_operations, -}; +int md_error (kdev_t dev, kdev_t rdev) +{ + mddev_t *mddev = kdev_to_mddev(dev); + mdk_rdev_t * rrdev; + int rc; + + if (!mddev) { + MD_BUG(); + return 0; + } + rrdev = find_rdev(mddev, rdev); + mark_rdev_faulty(rrdev); + /* + * if recovery was running, stop it now. + */ + if (mddev->pers->stop_resync) + mddev->pers->stop_resync(mddev); + if (mddev->pers->error_handler) { + rc = mddev->pers->error_handler(mddev, rdev); + md_recover_arrays(); + return rc; + } +#if 0 + /* + * Drop all buffers in the failed array. + * _not_. This is called from IRQ handlers ... + */ + invalidate_buffers(rdev); #endif + return 0; +} -static void md_geninit (struct gendisk *gdisk) +static int status_unused (char * page) { - int i; - - for(i=0;isame_set.next && !rdev->same_set.prev) { + /* + * The device is not yet used by any array. + */ + i++; + sz += sprintf(page + sz, "%s ", + partition_name(rdev->dev)); + } + } + if (!i) + sz += sprintf(page + sz, ""); + + sz += sprintf(page + sz, "\n"); + return sz; } -int md_error (kdev_t mddev, kdev_t rdev) + +static int status_resync (char * page, mddev_t * mddev) { - unsigned int minor = MINOR (mddev); - int rc; + int sz = 0; + unsigned int blocksize, max_blocks, resync, res, dt, tt, et; + + resync = mddev->curr_resync; + blocksize = blksize_size[MD_MAJOR][mdidx(mddev)]; + max_blocks = blk_size[MD_MAJOR][mdidx(mddev)] / (blocksize >> 10); + + /* + * Should not happen. + */ + if (!max_blocks) { + MD_BUG(); + return 0; + } + res = resync*100/max_blocks; + if (!mddev->recovery_running) + /* + * true resync + */ + sz += sprintf(page + sz, " resync=%u%%", res); + else + /* + * recovery ... + */ + sz += sprintf(page + sz, " recovery=%u%%", res); + + /* + * We do not want to overflow, so the order of operands and + * the * 100 / 100 trick are important. We do a +1 to be + * safe against division by zero. We only estimate anyway. + * + * dt: time until now + * tt: total time + * et: estimated finish time + */ + dt = ((jiffies - mddev->resync_start) / HZ); + tt = (dt * (max_blocks / (resync/100+1)))/100; + if (tt > dt) + et = tt - dt; + else + /* + * ignore rounding effects near finish time + */ + et = 0; + + sz += sprintf(page + sz, " finish=%u.%umin", et / 60, (et % 60)/6); - if (MAJOR(mddev) != MD_MAJOR || minor > MAX_MD_DEV) - panic ("md_error gets unknown device\n"); - if (!md_dev [minor].pers) - panic ("md_error gets an error for an unknown device\n"); - if (md_dev [minor].pers->error_handler) { - rc = md_dev [minor].pers->error_handler (md_dev+minor, rdev); -#if SUPPORT_RECONSTRUCTION - md_wakeup_thread(md_sync_thread); -#endif /* SUPPORT_RECONSTRUCTION */ - return rc; - } - return 0; + return sz; } int get_md_status (char *page) { - int sz=0, i, j, size; - - sz+=sprintf( page+sz, "Personalities : "); - for (i=0; iname); - - page[sz-1]='\n'; - - sz+=sprintf (page+sz, "read_ahead "); - if (read_ahead[MD_MAJOR]==INT_MAX) - sz+=sprintf (page+sz, "not set\n"); - else - sz+=sprintf (page+sz, "%d sectors\n", read_ahead[MD_MAJOR]); + int sz = 0, j, size; + struct md_list_head *tmp, *tmp2; + mdk_rdev_t *rdev; + mddev_t *mddev; + + sz += sprintf(page + sz, "Personalities : "); + for (j = 0; j < MAX_PERSONALITY; j++) + if (pers[j]) + sz += sprintf(page+sz, "[%s] ", pers[j]->name); + + sz += sprintf(page+sz, "\n"); + + + sz += sprintf(page+sz, "read_ahead "); + if (read_ahead[MD_MAJOR] == INT_MAX) + sz += sprintf(page+sz, "not set\n"); + else + sz += sprintf(page+sz, "%d sectors\n", read_ahead[MD_MAJOR]); - for (i=0; iname); + ITERATE_MDDEV(mddev,tmp) { + sz += sprintf(page + sz, "md%d : %sactive", mdidx(mddev), + mddev->pers ? "" : "in"); + if (mddev->pers) { + if (mddev->ro) + sz += sprintf(page + sz, " (read-only)"); + sz += sprintf(page + sz, " %s", mddev->pers->name); + } - size=0; - for (j=0; jdev), rdev->desc_nr); + if (rdev->faulty) { + sz += sprintf(page + sz, "(F)"); + continue; + } + size += rdev->size; + } - if (md_dev[i].nb_dev) { - if (md_dev[i].pers) - sz+=sprintf (page+sz, " %d blocks", md_size[i]); - else - sz+=sprintf (page+sz, " %d blocks", size); - } + if (mddev->nb_dev) { + if (mddev->pers) + sz += sprintf(page + sz, " %d blocks", + md_size[mdidx(mddev)]); + else + sz += sprintf(page + sz, " %d blocks", size); + } - if (!md_dev[i].pers) - { - sz+=sprintf (page+sz, "\n"); - continue; - } + if (!mddev->pers) { + sz += sprintf(page+sz, "\n"); + continue; + } - if (md_dev[i].pers->max_invalid_dev) - sz+=sprintf (page+sz, " maxfault=%ld", MAX_FAULT(md_dev+i)); + sz += mddev->pers->status (page+sz, mddev); - sz+=md_dev[i].pers->status (page+sz, i, md_dev+i); - sz+=sprintf (page+sz, "\n"); - } + if (mddev->curr_resync) + sz += status_resync (page+sz, mddev); + else { + if (md_atomic_read(&mddev->resync_sem.count) != 1) + sz += sprintf(page + sz, " resync=DELAYED"); + } + sz += sprintf(page + sz, "\n"); + } + sz += status_unused (page + sz); - return (sz); + return (sz); } -int register_md_personality (int p_num, struct md_personality *p) +int register_md_personality (int pnum, mdk_personality_t *p) { - int i=(p_num >> PERSONALITY_SHIFT); - - if (i >= MAX_PERSONALITY) - return -EINVAL; + if (pnum >= MAX_PERSONALITY) + return -EINVAL; - if (pers[i]) - return -EBUSY; + if (pers[pnum]) + return -EBUSY; - pers[i]=p; - printk ("%s personality registered\n", p->name); - return 0; + pers[pnum] = p; + printk(KERN_INFO "%s personality registered\n", p->name); + return 0; } -int unregister_md_personality (int p_num) +int unregister_md_personality (int pnum) { - int i=(p_num >> PERSONALITY_SHIFT); - - if (i >= MAX_PERSONALITY) - return -EINVAL; + if (pnum >= MAX_PERSONALITY) + return -EINVAL; - printk ("%s personality unregistered\n", pers[i]->name); - pers[i]=NULL; - return 0; + printk(KERN_INFO "%s personality unregistered\n", pers[pnum]->name); + pers[pnum] = NULL; + return 0; } -static md_descriptor_t *get_spare(struct md_dev *mddev) +static mdp_disk_t *get_spare(mddev_t *mddev) { - int i; - md_superblock_t *sb = mddev->sb; - md_descriptor_t *descriptor; - struct real_dev *realdev; - - for (i = 0; i < mddev->nb_dev; i++) { - realdev = &mddev->devices[i]; - if (!realdev->sb) + mdp_super_t *sb = mddev->sb; + mdp_disk_t *disk; + mdk_rdev_t *rdev; + struct md_list_head *tmp; + + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->faulty) + continue; + if (!rdev->sb) { + MD_BUG(); continue; - descriptor = &sb->disks[realdev->sb->descriptor.number]; - if (descriptor->state & (1 << MD_FAULTY_DEVICE)) + } + disk = &sb->disks[rdev->desc_nr]; + if (disk_faulty(disk)) { + MD_BUG(); continue; - if (descriptor->state & (1 << MD_ACTIVE_DEVICE)) + } + if (disk_active(disk)) continue; - return descriptor; + return disk; } return NULL; } +static int is_mddev_idle (mddev_t *mddev) +{ + mdk_rdev_t * rdev; + struct md_list_head *tmp; + int idle; + unsigned long curr_events; + + idle = 1; + ITERATE_RDEV(mddev,rdev,tmp) { + curr_events = io_events[MAJOR(rdev->dev)]; + + if (curr_events != rdev->last_events) { +// printk("!I(%d)", curr_events-rdev->last_events); + rdev->last_events = curr_events; + idle = 0; + } + } + return idle; +} + /* * parallel resyncing thread. - * - * FIXME: - make it abort with a dirty array on mdstop, now it just blocks - * - fix read error handing */ -int md_do_sync(struct md_dev *mddev) +/* + * Determine correct block size for this device. + */ +unsigned int device_bsize (kdev_t dev) +{ + unsigned int i, correct_size; + + correct_size = BLOCK_SIZE; + if (blksize_size[MAJOR(dev)]) { + i = blksize_size[MAJOR(dev)][MINOR(dev)]; + if (i) + correct_size = i; + } + + return correct_size; +} + +static struct wait_queue *resync_wait = (struct wait_queue *)NULL; + +#define RA_ORDER (1) +#define RA_PAGE_SIZE (PAGE_SIZE*(1<resync_sem); + if (err) + goto out_nolock; + +recheck: + serialize = 0; + ITERATE_MDDEV(mddev2,tmp) { + if (mddev2 == mddev) + continue; + if (mddev2->curr_resync && match_mddev_units(mddev,mddev2)) { + printk(KERN_INFO "md: serializing resync, md%d has overlapping physical units with md%d!\n", mdidx(mddev), mdidx(mddev2)); + serialize = 1; + break; + } + } + if (serialize) { + interruptible_sleep_on(&resync_wait); + if (md_signal_pending(current)) { + md_flush_signals(); + err = -EINTR; + goto out; + } + goto recheck; + } + + mddev->curr_resync = 1; - blocksize = blksize_size[major][minor]; + blocksize = device_bsize(read_disk); max_blocks = blk_size[major][minor] / (blocksize >> 10); - printk("... resync log\n"); - printk(" .... mddev->nb_dev: %d\n", mddev->nb_dev); - printk(" .... raid array: %s\n", kdevname(read_disk)); - printk(" .... max_blocks: %d blocksize: %d\n", max_blocks, blocksize); - printk("md: syncing RAID array %s\n", kdevname(read_disk)); + printk(KERN_INFO "md: syncing RAID array md%d\n", mdidx(mddev)); + printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed: %d KB/sec.\n", + sysctl_speed_limit); + printk(KERN_INFO "md: using maximum available idle IO bandwith for reconstruction.\n"); + + /* + * Resync has low priority. + */ + current->priority = 1; + + is_mddev_idle(mddev); /* this also initializes IO event counters */ + starttime = jiffies; + mddev->resync_start = starttime; - mddev->busy++; + /* + * Tune reconstruction: + */ + window = md_maxreadahead[mdidx(mddev)]/1024; + nr_blocks = window / (blocksize >> 10); + if (!nr_blocks || (nr_blocks > MAX_NR_BLOCKS)) + nr_blocks = MAX_NR_BLOCKS; + printk(KERN_INFO "md: using %dk window.\n",window); - starttime=jiffies; - for (j = 0; j < max_blocks; j++) { + for (j = 0; j < max_blocks; j += nr_blocks) { + if (j) + mddev->curr_resync = j; /* * B careful. When some1 mounts a non-'blocksize' filesystem * then we get the blocksize changed right under us. Go deal * with it transparently, recalculate 'blocksize', 'j' and * 'max_blocks': */ - curr_bsize = blksize_size[major][minor]; + curr_bsize = device_bsize(read_disk); if (curr_bsize != blocksize) { - diff_blocksize: + printk(KERN_INFO "md%d: blocksize changed\n", + mdidx(mddev)); +retry_read: if (curr_bsize > blocksize) /* * this is safe, rounds downwards. @@ -1109,114 +3404,384 @@ j *= blocksize/curr_bsize; blocksize = curr_bsize; + nr_blocks = window / (blocksize >> 10); + if (!nr_blocks || (nr_blocks > MAX_NR_BLOCKS)) + nr_blocks = MAX_NR_BLOCKS; max_blocks = blk_size[major][minor] / (blocksize >> 10); - } - if ((bh = breada (read_disk, j, blocksize, j * blocksize, - max_blocks * blocksize)) != NULL) { - mark_buffer_dirty(bh, 1); - brelse(bh); - } else { + printk("nr_blocks changed to %d (blocksize %d, j %d, max_blocks %d)\n", + nr_blocks, blocksize, j, max_blocks); /* - * FIXME: Ugly, but set_blocksize() isnt safe ... + * We will retry the current block-group */ - curr_bsize = blksize_size[major][minor]; - if (curr_bsize != blocksize) - goto diff_blocksize; + } - /* - * It's a real read problem. FIXME, handle this - * a better way. - */ - printk ( KERN_ALERT - "read error, stopping reconstruction.\n"); - mddev->busy--; - return 1; + /* + * Cleanup routines expect this + */ + for (k = 0; k < nr_blocks; k++) + bh[k] = NULL; + + chunk = nr_blocks; + if (chunk > max_blocks-j) + chunk = max_blocks-j; + + /* + * request buffer heads ... + */ + for (i = 0; i < chunk; i++) { + bh[i] = getblk (read_disk, j+i, blocksize); + if (!bh[i]) + goto read_error; + if (!buffer_dirty(bh[i])) + mark_buffer_lowprio(bh[i]); } /* - * Let's sleep some if we are faster than our speed limit: + * read buffer heads ... */ - while (blocksize*j/(jiffies-starttime+1)*HZ/1024 > SPEED_LIMIT) - { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); + ll_rw_block (READ, chunk, bh); + run_task_queue(&tq_disk); + + /* + * verify that all of them are OK ... + */ + for (i = 0; i < chunk; i++) { + ii = chunk-i-1; + wait_on_buffer(bh[ii]); + if (!buffer_uptodate(bh[ii])) + goto read_error; + } + +retry_write: + for (i = 0; i < chunk; i++) + mark_buffer_dirty_lowprio(bh[i]); + + ll_rw_block(WRITE, chunk, bh); + run_task_queue(&tq_disk); + + for (i = 0; i < chunk; i++) { + ii = chunk-i-1; + wait_on_buffer(bh[ii]); + + if (spare && disk_faulty(spare)) { + for (k = 0; k < chunk; k++) + brelse(bh[k]); + printk(" \n "); + err = -EIO; + goto out; + } + + if (!buffer_uptodate(bh[ii])) { + curr_bsize = device_bsize(read_disk); + if (curr_bsize != blocksize) { + printk(KERN_INFO + "md%d: blocksize changed during write\n", + mdidx(mddev)); + for (k = 0; k < chunk; k++) + if (bh[k]) { + if (buffer_lowprio(bh[k])) + mark_buffer_clean(bh[k]); + brelse(bh[k]); + } + goto retry_read; + } + printk(" BAD WRITE %8d>\n", j); + /* + * Ouch, write error, retry or bail out. + */ + if (max_write_errors) { + max_write_errors--; + printk ( KERN_WARNING "md%d: write error while reconstructing, at block %u(%d).\n", mdidx(mddev), j, blocksize); + goto retry_write; + } + printk ( KERN_ALERT + "too many write errors, stopping reconstruction.\n"); + for (k = 0; k < chunk; k++) + if (bh[k]) { + if (buffer_lowprio(bh[k])) + mark_buffer_clean(bh[k]); + brelse(bh[k]); + } + err = -EIO; + goto out; + } } /* - * FIXME: put this status bar thing into /proc + * This is the normal 'everything went OK' case + * do a 'free-behind' logic, we sure dont need + * this buffer if it was the only user. */ - if (!(j%(max_blocks/100))) { - if (!(percent%10)) - printk (" %03d%% done.\n",percent); - else - printk ("."); - percent++; + for (i = 0; i < chunk; i++) + cache_drop_behind(bh[i]); + + + if (md_signal_pending(current)) { + /* + * got a signal, exit. + */ + mddev->curr_resync = 0; + printk("md_do_sync() got signal ... exiting\n"); + md_flush_signals(); + err = -EINTR; + goto out; } + + /* + * this loop exits only if either when we are slower than + * the 'hard' speed limit, or the system was IO-idle for + * a jiffy. + * the system might be non-idle CPU-wise, but we only care + * about not overloading the IO subsystem. (things like an + * e2fsck being done on the RAID array should execute fast) + */ +repeat: + if (md_need_resched(current)) + schedule(); + + if ((blocksize/1024)*j/((jiffies-starttime)/HZ + 1) + 1 + > sysctl_speed_limit) { + current->priority = 1; + + if (!is_mddev_idle(mddev)) { + current->state = TASK_INTERRUPTIBLE; + md_schedule_timeout(HZ/2); + if (!md_signal_pending(current)) + goto repeat; + } + } else + current->priority = 40; } fsync_dev(read_disk); - printk("md: %s: sync done.\n", kdevname(read_disk)); - mddev->busy--; - return 0; + printk(KERN_INFO "md: md%d: sync done.\n",mdidx(mddev)); + err = 0; + /* + * this also signals 'finished resyncing' to md_stop + */ +out: + up(&mddev->resync_sem); +out_nolock: + free_pages((unsigned long)bh, RA_ORDER); + mddev->curr_resync = 0; + wake_up(&resync_wait); + return err; + +read_error: + /* + * set_blocksize() might change the blocksize. This + * should not happen often, but it happens when eg. + * someone mounts a filesystem that has non-1k + * blocksize. set_blocksize() doesnt touch our + * buffer, but to avoid aliasing problems we change + * our internal blocksize too and retry the read. + */ + curr_bsize = device_bsize(read_disk); + if (curr_bsize != blocksize) { + printk(KERN_INFO "md%d: blocksize changed during read\n", + mdidx(mddev)); + for (k = 0; k < chunk; k++) + if (bh[k]) { + if (buffer_lowprio(bh[k])) + mark_buffer_clean(bh[k]); + brelse(bh[k]); + } + goto retry_read; + } + + /* + * It's a real read problem. We retry and bail out + * only if it's excessive. + */ + if (max_read_errors) { + max_read_errors--; + printk ( KERN_WARNING "md%d: read error while reconstructing, at block %u(%d).\n", mdidx(mddev), j, blocksize); + for (k = 0; k < chunk; k++) + if (bh[k]) { + if (buffer_lowprio(bh[k])) + mark_buffer_clean(bh[k]); + brelse(bh[k]); + } + goto retry_read; + } + printk ( KERN_ALERT "too many read errors, stopping reconstruction.\n"); + for (k = 0; k < chunk; k++) + if (bh[k]) { + if (buffer_lowprio(bh[k])) + mark_buffer_clean(bh[k]); + brelse(bh[k]); + } + err = -EIO; + goto out; } +#undef MAX_NR_BLOCKS + /* - * This is a kernel thread which: syncs a spare disk with the active array + * This is a kernel thread which syncs a spare disk with the active array * * the amount of foolproofing might seem to be a tad excessive, but an * early (not so error-safe) version of raid1syncd synced the first 0.5 gigs * of my root partition with the first 0.5 gigs of my /home partition ... so * i'm a bit nervous ;) */ -void mdsyncd (void *data) +void md_do_recovery (void *data) { - int i; - struct md_dev *mddev; - md_superblock_t *sb; - md_descriptor_t *spare; + int err; + mddev_t *mddev; + mdp_super_t *sb; + mdp_disk_t *spare; unsigned long flags; + struct md_list_head *tmp; - for (i = 0, mddev = md_dev; i < MAX_MD_DEV; i++, mddev++) { + printk(KERN_INFO "md: recovery thread got woken up ...\n"); +restart: + ITERATE_MDDEV(mddev,tmp) { if ((sb = mddev->sb) == NULL) continue; + if (mddev->recovery_running) + continue; if (sb->active_disks == sb->raid_disks) continue; - if (!sb->spare_disks) + if (!sb->spare_disks) { + printk(KERN_ERR "md%d: no spare disk to reconstruct array! -- continuing in degraded mode\n", mdidx(mddev)); continue; + } + /* + * now here we get the spare and resync it. + */ if ((spare = get_spare(mddev)) == NULL) continue; - if (!mddev->pers->mark_spare) + printk(KERN_INFO "md%d: resyncing spare disk %s to replace failed disk\n", mdidx(mddev), partition_name(MKDEV(spare->major,spare->minor))); + if (!mddev->pers->diskop) continue; - if (mddev->pers->mark_spare(mddev, spare, SPARE_WRITE)) - continue; - if (md_do_sync(mddev) || (spare->state & (1 << MD_FAULTY_DEVICE))) { - mddev->pers->mark_spare(mddev, spare, SPARE_INACTIVE); + if (mddev->pers->diskop(mddev, &spare, DISKOP_SPARE_WRITE)) continue; + down(&mddev->recovery_sem); + mddev->recovery_running = 1; + err = md_do_sync(mddev, spare); + if (err == -EIO) { + printk(KERN_INFO "md%d: spare disk %s failed, skipping to next spare.\n", mdidx(mddev), partition_name(MKDEV(spare->major,spare->minor))); + if (!disk_faulty(spare)) { + mddev->pers->diskop(mddev,&spare,DISKOP_SPARE_INACTIVE); + mark_disk_faulty(spare); + mark_disk_nonsync(spare); + mark_disk_inactive(spare); + sb->spare_disks--; + sb->working_disks--; + sb->failed_disks++; + } + } else + if (disk_faulty(spare)) + mddev->pers->diskop(mddev, &spare, + DISKOP_SPARE_INACTIVE); + if (err == -EINTR) { + /* + * Recovery got interrupted ... + * signal back that we have finished using the array. + */ + mddev->pers->diskop(mddev, &spare, + DISKOP_SPARE_INACTIVE); + up(&mddev->recovery_sem); + /* + * we keep 'recovery_running == 1', so we will not + * start a reconstruction next time around ... + * the stop code will set it to 0 explicitly. + */ + goto restart; + } else { + mddev->recovery_running = 0; + up(&mddev->recovery_sem); } save_flags(flags); cli(); - mddev->pers->mark_spare(mddev, spare, SPARE_ACTIVE); - spare->state |= (1 << MD_SYNC_DEVICE); - spare->state |= (1 << MD_ACTIVE_DEVICE); - sb->spare_disks--; - sb->active_disks++; - mddev->sb_dirty = 1; - md_update_sb(mddev - md_dev); + if (!disk_faulty(spare)) { + /* + * the SPARE_ACTIVE diskop possibly changes the + * pointer too + */ + mddev->pers->diskop(mddev, &spare, DISKOP_SPARE_ACTIVE); + mark_disk_sync(spare); + mark_disk_active(spare); + sb->active_disks++; + sb->spare_disks--; + } restore_flags(flags); + mddev->sb_dirty = 1; + md_update_sb(mddev); + goto restart; } + printk(KERN_INFO "md: recovery thread finished ...\n"); } +int md_notify_reboot(struct notifier_block *this, + unsigned long code, void *x) +{ + struct md_list_head *tmp; + mddev_t *mddev; + + if ((code == MD_SYS_DOWN) || (code == MD_SYS_HALT) + || (code == MD_SYS_POWER_OFF)) { + + printk(KERN_INFO "stopping all md devices.\n"); + + ITERATE_MDDEV(mddev,tmp) + do_md_stop (mddev, 1); + /* + * certain more exotic SCSI devices are known to be + * volatile wrt too early system reboots. While the + * right place to handle this issue is the given + * driver, we do want to have a safe RAID driver ... + */ + md_mdelay(1000*1); + } + return NOTIFY_DONE; +} + +struct notifier_block md_notifier = { + md_notify_reboot, + NULL, + 0 +}; + +md__initfunc(void raid_setup(char *str, int *ints)) +{ + char tmpline[100]; + int len, pos, nr, i; + + len = strlen(str) + 1; + nr = 0; + pos = 0; + + for (i = 0; i < len; i++) { + char c = str[i]; + + if (c == ',' || !c) { + tmpline[pos] = 0; + if (!strcmp(tmpline,"noautodetect")) + raid_setup_args.noautodetect = 1; + nr++; + pos = 0; + continue; + } + tmpline[pos] = c; + pos++; + } + raid_setup_args.set = 1; + return; +} + #ifdef CONFIG_MD_BOOT struct { int set; int ints[100]; char str[100]; -} md_setup_args __initdata = { +} md_setup_args md__initdata = { 0,{0},{0} }; /* called from init/main.c */ -__initfunc(void md_setup(char *str,int *ints)) +md__initfunc(void md_setup(char *str,int *ints)) { int i; for(i=0;i<=ints[0];i++) { @@ -1228,21 +3793,24 @@ return; } -__initfunc(void do_md_setup(char *str,int *ints)) +md__initfunc(void do_md_setup(char *str,int *ints)) { - int minor, pers, factor, fault; +#if 0 + int minor, pers, chunk_size, fault; kdev_t dev; int i=1; + printk("i plan to phase this out --mingo\n"); + if(ints[0] < 4) { - printk ("md: Too few Arguments (%d).\n", ints[0]); + printk (KERN_WARNING "md: Too few Arguments (%d).\n", ints[0]); return; } minor=ints[i++]; - if (minor >= MAX_MD_DEV) { - printk ("md: Minor device number too high.\n"); + if ((unsigned int)minor >= MAX_MD_DEVS) { + printk (KERN_WARNING "md: Minor device number too high.\n"); return; } @@ -1252,18 +3820,20 @@ case -1: #ifdef CONFIG_MD_LINEAR pers = LINEAR; - printk ("md: Setting up md%d as linear device.\n",minor); + printk (KERN_INFO "md: Setting up md%d as linear device.\n", + minor); #else - printk ("md: Linear mode not configured." + printk (KERN_WARNING "md: Linear mode not configured." "Recompile the kernel with linear mode enabled!\n"); #endif break; case 0: pers = STRIPED; #ifdef CONFIG_MD_STRIPED - printk ("md: Setting up md%d as a striped device.\n",minor); + printk (KERN_INFO "md: Setting up md%d as a striped device.\n", + minor); #else - printk ("md: Striped mode not configured." + printk (KERN_WARNING "md: Striped mode not configured." "Recompile the kernel with striped mode enabled!\n"); #endif break; @@ -1278,79 +3848,145 @@ break; */ default: - printk ("md: Unknown or not supported raid level %d.\n", ints[--i]); + printk (KERN_WARNING "md: Unknown or not supported raid level %d.\n", ints[--i]); return; } - if(pers) { + if (pers) { - factor=ints[i++]; /* Chunksize */ - fault =ints[i++]; /* Faultlevel */ + chunk_size = ints[i++]; /* Chunksize */ + fault = ints[i++]; /* Faultlevel */ - pers=pers | factor | (fault << FAULT_SHIFT); + pers = pers | chunk_size | (fault << FAULT_SHIFT); - while( str && (dev = name_to_kdev_t(str))) { - do_md_add (minor, dev); - if((str = strchr (str, ',')) != NULL) - str++; - } + while( str && (dev = name_to_kdev_t(str))) { + do_md_add (minor, dev); + if((str = strchr (str, ',')) != NULL) + str++; + } - do_md_run (minor, pers); - printk ("md: Loading md%d.\n",minor); + do_md_run (minor, pers); + printk (KERN_INFO "md: Loading md%d.\n",minor); } - +#endif } #endif +void hsm_init (void); +void translucent_init (void); void linear_init (void); void raid0_init (void); void raid1_init (void); void raid5_init (void); -__initfunc(int md_init (void)) +md__initfunc(int md_init (void)) { - printk ("md driver %d.%d.%d MAX_MD_DEV=%d, MAX_REAL=%d\n", - MD_MAJOR_VERSION, MD_MINOR_VERSION, MD_PATCHLEVEL_VERSION, - MAX_MD_DEV, MAX_REAL); - - if (register_blkdev (MD_MAJOR, "md", &md_fops)) - { - printk ("Unable to get major %d for md\n", MD_MAJOR); - return (-1); - } - - blk_dev[MD_MAJOR].request_fn=DEVICE_REQUEST; - blk_dev[MD_MAJOR].current_request=NULL; - read_ahead[MD_MAJOR]=INT_MAX; - memset(md_dev, 0, MAX_MD_DEV * sizeof (struct md_dev)); - md_gendisk.next=gendisk_head; - - gendisk_head=&md_gendisk; - -#if SUPPORT_RECONSTRUCTION - if ((md_sync_thread = md_register_thread(mdsyncd, NULL)) == NULL) - printk("md: bug: md_sync_thread == NULL\n"); -#endif /* SUPPORT_RECONSTRUCTION */ + static char * name = "mdrecoveryd"; + + printk (KERN_INFO "md driver %d.%d.%d MAX_MD_DEVS=%d, MAX_REAL=%d\n", + MD_MAJOR_VERSION, MD_MINOR_VERSION, + MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MAX_REAL); + + if (register_blkdev (MD_MAJOR, "md", &md_fops)) + { + printk (KERN_ALERT "Unable to get major %d for md\n", MD_MAJOR); + return (-1); + } + + blk_dev[MD_MAJOR].request_fn = DEVICE_REQUEST; + blk_dev[MD_MAJOR].current_request = NULL; + read_ahead[MD_MAJOR] = INT_MAX; + md_gendisk.next = gendisk_head; + + gendisk_head = &md_gendisk; + + md_recovery_thread = md_register_thread(md_do_recovery, NULL, name); + if (!md_recovery_thread) + printk(KERN_ALERT "bug: couldn't allocate md_recovery_thread\n"); + md_register_reboot_notifier(&md_notifier); + md_register_sysctl(); + +#ifdef CONFIG_MD_HSM + hsm_init (); +#endif +#ifdef CONFIG_MD_TRANSLUCENT + translucent_init (); +#endif #ifdef CONFIG_MD_LINEAR - linear_init (); + linear_init (); #endif #ifdef CONFIG_MD_STRIPED - raid0_init (); + raid0_init (); #endif #ifdef CONFIG_MD_MIRRORING - raid1_init (); + raid1_init (); #endif #ifdef CONFIG_MD_RAID5 - raid5_init (); + raid5_init (); +#endif +#if defined(CONFIG_MD_RAID5) || defined(CONFIG_MD_RAID5_MODULE) + /* + * pick a XOR routine, runtime. + */ + calibrate_xor_block(); #endif - return (0); + + return (0); } #ifdef CONFIG_MD_BOOT -__initfunc(void md_setup_drive(void)) +md__initfunc(void md_setup_drive(void)) { if(md_setup_args.set) do_md_setup(md_setup_args.str, md_setup_args.ints); } #endif + +MD_EXPORT_SYMBOL(md_size); +MD_EXPORT_SYMBOL(register_md_personality); +MD_EXPORT_SYMBOL(unregister_md_personality); +MD_EXPORT_SYMBOL(partition_name); +MD_EXPORT_SYMBOL(md_error); +MD_EXPORT_SYMBOL(md_recover_arrays); +MD_EXPORT_SYMBOL(md_register_thread); +MD_EXPORT_SYMBOL(md_unregister_thread); +MD_EXPORT_SYMBOL(md_update_sb); +MD_EXPORT_SYMBOL(md_map); +MD_EXPORT_SYMBOL(md_wakeup_thread); +MD_EXPORT_SYMBOL(md_do_sync); +MD_EXPORT_SYMBOL(md_print_devices); +MD_EXPORT_SYMBOL(find_rdev_nr); +MD_EXPORT_SYMBOL(md_check_ordering); +MD_EXPORT_SYMBOL(md_interrupt_thread); +MD_EXPORT_SYMBOL(mddev_map); + +#ifdef CONFIG_PROC_FS +static struct proc_dir_entry proc_md = { + PROC_MD, 6, "mdstat", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations, +}; +#endif + +static void md_geninit (struct gendisk *gdisk) +{ + int i; + + for(i = 0; i < MAX_MD_DEVS; i++) { + md_blocksizes[i] = 1024; + md_maxreadahead[i] = MD_READAHEAD; + md_gendisk.part[i].start_sect = -1; /* avoid partition check */ + md_gendisk.part[i].nr_sects = 0; + } + + printk("md.c: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t)); + + blksize_size[MD_MAJOR] = md_blocksizes; + md_set_global_readahead(md_maxreadahead); + +#ifdef CONFIG_PROC_FS + proc_register(&proc_root, &proc_md); +#endif +} + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/nbd.c linux.ac/drivers/block/nbd.c --- linux.vanilla/drivers/block/nbd.c Wed Mar 24 10:55:15 1999 +++ linux.ac/drivers/block/nbd.c Mon Jun 21 13:13:11 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/raid0.c linux.ac/drivers/block/raid0.c --- linux.vanilla/drivers/block/raid0.c Sun Nov 8 15:07:37 1998 +++ linux.ac/drivers/block/raid0.c Mon Jul 19 03:26:58 1999 @@ -1,4 +1,3 @@ - /* raid0.c : Multiple Devices driver for Linux Copyright (C) 1994-96 Marc ZYNGIER @@ -18,146 +17,201 @@ */ #include -#include -#include -#include +#include #define MAJOR_NR MD_MAJOR #define MD_DRIVER #define MD_PERSONALITY -static int create_strip_zones (int minor, struct md_dev *mddev) +static int create_strip_zones (mddev_t *mddev) { - int i, j, c=0; - int current_offset=0; - struct real_dev *smallest_by_zone; - struct raid0_data *data=(struct raid0_data *) mddev->private; - - data->nr_strip_zones=1; - - for (i=1; inb_dev; i++) - { - for (j=0; jdevices[i].size==mddev->devices[j].size) - { - c=1; - break; - } - - if (!c) - data->nr_strip_zones++; - - c=0; - } - - if ((data->strip_zone=vmalloc(sizeof(struct strip_zone)*data->nr_strip_zones)) == NULL) - return 1; - - data->smallest=NULL; - - for (i=0; inr_strip_zones; i++) - { - data->strip_zone[i].dev_offset=current_offset; - smallest_by_zone=NULL; - c=0; - - for (j=0; jnb_dev; j++) - if (mddev->devices[j].size>current_offset) - { - data->strip_zone[i].dev[c++]=mddev->devices+j; - if (!smallest_by_zone || - smallest_by_zone->size > mddev->devices[j].size) - smallest_by_zone=mddev->devices+j; - } - - data->strip_zone[i].nb_dev=c; - data->strip_zone[i].size=(smallest_by_zone->size-current_offset)*c; - - if (!data->smallest || - data->smallest->size > data->strip_zone[i].size) - data->smallest=data->strip_zone+i; - - data->strip_zone[i].zone_offset=i ? (data->strip_zone[i-1].zone_offset+ - data->strip_zone[i-1].size) : 0; - current_offset=smallest_by_zone->size; - } - return 0; + int i, c, j, j1, j2; + int current_offset, curr_zone_offset; + raid0_conf_t *conf = mddev_to_conf(mddev); + mdk_rdev_t *smallest, *rdev1, *rdev2, *rdev; + + /* + * The number of 'same size groups' + */ + conf->nr_strip_zones = 0; + + ITERATE_RDEV_ORDERED(mddev,rdev1,j1) { + printk("raid0: looking at %s\n", partition_name(rdev1->dev)); + c = 0; + ITERATE_RDEV_ORDERED(mddev,rdev2,j2) { + printk("raid0: comparing %s(%d) with %s(%d)\n", partition_name(rdev1->dev), rdev1->size, partition_name(rdev2->dev), rdev2->size); + if (rdev2 == rdev1) { + printk("raid0: END\n"); + break; + } + if (rdev2->size == rdev1->size) + { + /* + * Not unique, dont count it as a new + * group + */ + printk("raid0: EQUAL\n"); + c = 1; + break; + } + printk("raid0: NOT EQUAL\n"); + } + if (!c) { + printk("raid0: ==> UNIQUE\n"); + conf->nr_strip_zones++; + printk("raid0: %d zones\n", conf->nr_strip_zones); + } + } + printk("raid0: FINAL %d zones\n", conf->nr_strip_zones); + + conf->strip_zone = vmalloc(sizeof(struct strip_zone)* + conf->nr_strip_zones); + if (!conf->strip_zone) + return 1; + + + conf->smallest = NULL; + current_offset = 0; + curr_zone_offset = 0; + + for (i = 0; i < conf->nr_strip_zones; i++) + { + struct strip_zone *zone = conf->strip_zone + i; + + printk("zone %d\n", i); + zone->dev_offset = current_offset; + smallest = NULL; + c = 0; + + ITERATE_RDEV_ORDERED(mddev,rdev,j) { + + printk(" checking %s ...", partition_name(rdev->dev)); + if (rdev->size > current_offset) + { + printk(" contained as device %d\n", c); + zone->dev[c] = rdev; + c++; + if (!smallest || (rdev->size size)) { + smallest = rdev; + printk(" (%d) is smallest!.\n", rdev->size); + } + } else + printk(" nope.\n"); + } + + zone->nb_dev = c; + zone->size = (smallest->size - current_offset) * c; + printk(" zone->nb_dev: %d, size: %d\n",zone->nb_dev,zone->size); + + if (!conf->smallest || (zone->size < conf->smallest->size)) + conf->smallest = zone; + + zone->zone_offset = curr_zone_offset; + curr_zone_offset += zone->size; + + current_offset = smallest->size; + printk("current zone offset: %d\n", current_offset); + } + printk("done.\n"); + return 0; } -static int raid0_run (int minor, struct md_dev *mddev) +static int raid0_run (mddev_t *mddev) { - int cur=0, i=0, size, zone0_size, nb_zone; - struct raid0_data *data; - - MOD_INC_USE_COUNT; + int cur=0, i=0, size, zone0_size, nb_zone; + raid0_conf_t *conf; - if ((mddev->private=vmalloc (sizeof (struct raid0_data))) == NULL) return 1; - data=(struct raid0_data *) mddev->private; - - if (create_strip_zones (minor, mddev)) - { - vfree(data); - return 1; - } - - nb_zone=data->nr_zones= - md_size[minor]/data->smallest->size + - (md_size[minor]%data->smallest->size ? 1 : 0); - - printk ("raid0 : Allocating %ld bytes for hash.\n",(long)sizeof(struct raid0_hash)*nb_zone); - if ((data->hash_table=vmalloc (sizeof (struct raid0_hash)*nb_zone)) == NULL) - { - vfree(data->strip_zone); - vfree(data); - return 1; - } - size=data->strip_zone[cur].size; - - i=0; - while (curnr_strip_zones) - { - data->hash_table[i].zone0=data->strip_zone+cur; - - if (size>=data->smallest->size)/* If we completely fill the slot */ - { - data->hash_table[i++].zone1=NULL; - size-=data->smallest->size; - - if (!size) - { - if (++cur==data->nr_strip_zones) continue; - size=data->strip_zone[cur].size; - } - - continue; - } - - if (++cur==data->nr_strip_zones) /* Last dev, set unit1 as NULL */ - { - data->hash_table[i].zone1=NULL; - continue; - } - - zone0_size=size; /* Here, we use a 2nd dev to fill the slot */ - size=data->strip_zone[cur].size; - data->hash_table[i++].zone1=data->strip_zone+cur; - size-=(data->smallest->size - zone0_size); - } + MOD_INC_USE_COUNT; - return (0); + conf = vmalloc(sizeof (raid0_conf_t)); + if (!conf) + goto out; + mddev->private = (void *)conf; + + if (md_check_ordering(mddev)) { + printk("raid0: disks are not ordered, aborting!\n"); + goto out_free_conf; + } + + if (create_strip_zones (mddev)) + goto out_free_conf; + + printk("raid0 : md_size is %d blocks.\n", md_size[mdidx(mddev)]); + printk("raid0 : conf->smallest->size is %d blocks.\n", conf->smallest->size); + nb_zone = md_size[mdidx(mddev)]/conf->smallest->size + + (md_size[mdidx(mddev)] % conf->smallest->size ? 1 : 0); + printk("raid0 : nb_zone is %d.\n", nb_zone); + conf->nr_zones = nb_zone; + + printk("raid0 : Allocating %d bytes for hash.\n", + sizeof(struct raid0_hash)*nb_zone); + + conf->hash_table = vmalloc (sizeof (struct raid0_hash)*nb_zone); + if (!conf->hash_table) + goto out_free_zone_conf; + size = conf->strip_zone[cur].size; + + i = 0; + while (cur < conf->nr_strip_zones) { + conf->hash_table[i].zone0 = conf->strip_zone + cur; + + /* + * If we completely fill the slot + */ + if (size >= conf->smallest->size) { + conf->hash_table[i++].zone1 = NULL; + size -= conf->smallest->size; + + if (!size) { + if (++cur == conf->nr_strip_zones) + continue; + size = conf->strip_zone[cur].size; + } + continue; + } + if (++cur == conf->nr_strip_zones) { + /* + * Last dev, set unit1 as NULL + */ + conf->hash_table[i].zone1=NULL; + continue; + } + + /* + * Here we use a 2nd dev to fill the slot + */ + zone0_size = size; + size = conf->strip_zone[cur].size; + conf->hash_table[i++].zone1 = conf->strip_zone + cur; + size -= (conf->smallest->size - zone0_size); + } + return 0; + +out_free_zone_conf: + vfree(conf->strip_zone); + conf->strip_zone = NULL; + +out_free_conf: + vfree(conf); + mddev->private = NULL; +out: + MOD_DEC_USE_COUNT; + return 1; } - -static int raid0_stop (int minor, struct md_dev *mddev) +static int raid0_stop (mddev_t *mddev) { - struct raid0_data *data=(struct raid0_data *) mddev->private; + raid0_conf_t *conf = mddev_to_conf(mddev); - vfree (data->hash_table); - vfree (data->strip_zone); - vfree (data); + vfree (conf->hash_table); + conf->hash_table = NULL; + vfree (conf->strip_zone); + conf->strip_zone = NULL; + vfree (conf); + mddev->private = NULL; - MOD_DEC_USE_COUNT; - return 0; + MOD_DEC_USE_COUNT; + return 0; } /* @@ -167,129 +221,135 @@ * Of course, those facts may not be valid anymore (and surely won't...) * Hey guys, there's some work out there ;-) */ -static int raid0_map (struct md_dev *mddev, kdev_t *rdev, +static int raid0_map (mddev_t *mddev, kdev_t dev, kdev_t *rdev, unsigned long *rsector, unsigned long size) { - struct raid0_data *data=(struct raid0_data *) mddev->private; - static struct raid0_hash *hash; - struct strip_zone *zone; - struct real_dev *tmp_dev; - int blk_in_chunk, factor, chunk, chunk_size; - long block, rblock; - - factor=FACTOR(mddev); - chunk_size=(1UL << FACTOR_SHIFT(factor)); - block=*rsector >> 1; - hash=data->hash_table+(block/data->smallest->size); - - /* Sanity check */ - if ((chunk_size*2)<(*rsector % (chunk_size*2))+size) - { - printk ("raid0_convert : can't convert block across chunks or bigger than %dk %ld %ld\n", chunk_size, *rsector, size); - return (-1); - } - - if (block >= (hash->zone0->size + - hash->zone0->zone_offset)) - { - if (!hash->zone1) - { - printk ("raid0_convert : hash->zone1==NULL for block %ld\n", block); - return (-1); - } - - zone=hash->zone1; - } - else - zone=hash->zone0; + raid0_conf_t *conf = mddev_to_conf(mddev); + struct raid0_hash *hash; + struct strip_zone *zone; + mdk_rdev_t *tmp_dev; + int blk_in_chunk, chunksize_bits, chunk, chunk_size; + long block, rblock; + + chunk_size = mddev->param.chunk_size >> 10; + chunksize_bits = ffz(~chunk_size); + block = *rsector >> 1; + hash = conf->hash_table + block / conf->smallest->size; + + /* Sanity check */ + if ((chunk_size * 2) < (*rsector % (chunk_size * 2)) + size) + goto bad_map; + + if (!hash) + goto bad_hash; + + if (!hash->zone0) + goto bad_zone0; + + if (block >= (hash->zone0->size + hash->zone0->zone_offset)) { + if (!hash->zone1) + goto bad_zone1; + zone = hash->zone1; + } else + zone = hash->zone0; - blk_in_chunk=block & (chunk_size -1); - chunk=(block - zone->zone_offset) / (zone->nb_dev<dev[(block >> FACTOR_SHIFT(factor)) % zone->nb_dev]; - rblock=(chunk << FACTOR_SHIFT(factor)) + blk_in_chunk + zone->dev_offset; + blk_in_chunk = block & (chunk_size -1); + chunk = (block - zone->zone_offset) / (zone->nb_dev << chunksize_bits); + tmp_dev = zone->dev[(block >> chunksize_bits) % zone->nb_dev]; + rblock = (chunk << chunksize_bits) + blk_in_chunk + zone->dev_offset; - *rdev=tmp_dev->dev; - *rsector=rblock<<1; + *rdev = tmp_dev->dev; + *rsector = rblock << 1; - return (0); + return 0; + +bad_map: + printk ("raid0_map bug: can't convert block across chunks or bigger than %dk %ld %ld\n", chunk_size, *rsector, size); + return -1; +bad_hash: + printk("raid0_map bug: hash==NULL for block %ld\n", block); + return -1; +bad_zone0: + printk ("raid0_map bug: hash->zone0==NULL for block %ld\n", block); + return -1; +bad_zone1: + printk ("raid0_map bug: hash->zone1==NULL for block %ld\n", block); + return -1; } -static int raid0_status (char *page, int minor, struct md_dev *mddev) +static int raid0_status (char *page, mddev_t *mddev) { - int sz=0; + int sz = 0; #undef MD_DEBUG #ifdef MD_DEBUG - int j, k; - struct raid0_data *data=(struct raid0_data *) mddev->private; + int j, k; + raid0_conf_t *conf = mddev_to_conf(mddev); - sz+=sprintf (page+sz, " "); - for (j=0; jnr_zones; j++) - { - sz+=sprintf (page+sz, "[z%d", - data->hash_table[j].zone0-data->strip_zone); - if (data->hash_table[j].zone1) - sz+=sprintf (page+sz, "/z%d] ", - data->hash_table[j].zone1-data->strip_zone); - else - sz+=sprintf (page+sz, "] "); - } + sz += sprintf(page + sz, " "); + for (j = 0; j < conf->nr_zones; j++) { + sz += sprintf(page + sz, "[z%d", + conf->hash_table[j].zone0 - conf->strip_zone); + if (conf->hash_table[j].zone1) + sz += sprintf(page+sz, "/z%d] ", + conf->hash_table[j].zone1 - conf->strip_zone); + else + sz += sprintf(page+sz, "] "); + } - sz+=sprintf (page+sz, "\n"); + sz += sprintf(page + sz, "\n"); - for (j=0; jnr_strip_zones; j++) - { - sz+=sprintf (page+sz, " z%d=[", j); - for (k=0; kstrip_zone[j].nb_dev; k++) - sz+=sprintf (page+sz, "%s/", - partition_name(data->strip_zone[j].dev[k]->dev)); - sz--; - sz+=sprintf (page+sz, "] zo=%d do=%d s=%d\n", - data->strip_zone[j].zone_offset, - data->strip_zone[j].dev_offset, - data->strip_zone[j].size); - } + for (j = 0; j < conf->nr_strip_zones; j++) { + sz += sprintf(page + sz, " z%d=[", j); + for (k = 0; k < conf->strip_zone[j].nb_dev; k++) + sz += sprintf (page+sz, "%s/", partition_name( + conf->strip_zone[j].dev[k]->dev)); + sz--; + sz += sprintf (page+sz, "] zo=%d do=%d s=%d\n", + conf->strip_zone[j].zone_offset, + conf->strip_zone[j].dev_offset, + conf->strip_zone[j].size); + } #endif - sz+=sprintf (page+sz, " %dk chunks", 1<param.chunk_size/1024); + return sz; } - -static struct md_personality raid0_personality= +static mdk_personality_t raid0_personality= { - "raid0", - raid0_map, - NULL, /* no special make_request */ - NULL, /* no special end_request */ - raid0_run, - raid0_stop, - raid0_status, - NULL, /* no ioctls */ - 0, - NULL, /* no error_handler */ - NULL, /* hot_add_disk */ - NULL, /* hot_remove_disk */ - NULL /* mark_spare */ + "raid0", + raid0_map, + NULL, /* no special make_request */ + NULL, /* no special end_request */ + raid0_run, + raid0_stop, + raid0_status, + NULL, /* no ioctls */ + 0, + NULL, /* no error_handler */ + NULL, /* no diskop */ + NULL, /* no stop resync */ + NULL /* no restart resync */ }; - #ifndef MODULE void raid0_init (void) { - register_md_personality (RAID0, &raid0_personality); + register_md_personality (RAID0, &raid0_personality); } #else int init_module (void) { - return (register_md_personality (RAID0, &raid0_personality)); + return (register_md_personality (RAID0, &raid0_personality)); } void cleanup_module (void) { - unregister_md_personality (RAID0); + unregister_md_personality (RAID0); } #endif + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/raid1.c linux.ac/drivers/block/raid1.c --- linux.vanilla/drivers/block/raid1.c Tue Dec 22 23:19:36 1998 +++ linux.ac/drivers/block/raid1.c Mon Jul 19 03:26:58 1999 @@ -1,6 +1,6 @@ -/************************************************************************ +/* * raid1.c : Multiple Devices driver for Linux - * Copyright (C) 1996 Ingo Molnar, Miguel de Icaza, Gadi Oxman + * Copyright (C) 1996, 1997, 1998 Ingo Molnar, Miguel de Icaza, Gadi Oxman * * RAID-1 management functions. * @@ -15,50 +15,52 @@ */ #include -#include #include -#include -#include -#include +#include #include #define MAJOR_NR MD_MAJOR #define MD_DRIVER #define MD_PERSONALITY -/* - * The following can be used to debug the driver - */ -/*#define RAID1_DEBUG*/ -#ifdef RAID1_DEBUG -#define PRINTK(x) do { printk x; } while (0); -#else -#define PRINTK(x) do { ; } while (0); -#endif +#define MAX_LINEAR_SECTORS 128 #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define MIN(a,b) ((a) < (b) ? (a) : (b)) -static struct md_personality raid1_personality; -static struct md_thread *raid1_thread = NULL; +static mdk_personality_t raid1_personality; struct buffer_head *raid1_retry_list = NULL; -static int __raid1_map (struct md_dev *mddev, kdev_t *rdev, +static void * raid1_kmalloc (int size) +{ + void * ptr; + /* + * now we are rather fault tolerant than nice, but + * there are a couple of places in the RAID code where we + * simply can not afford to fail an allocation because + * there is no failure return path (eg. make_request()) + */ + while (!(ptr = kmalloc (sizeof (raid1_conf_t), GFP_KERNEL))) + printk ("raid1: out of memory, retrying...\n"); + + memset(ptr, 0, size); + return ptr; +} + +static int __raid1_map (mddev_t *mddev, kdev_t *rdev, unsigned long *rsector, unsigned long size) { - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; - int i, n = raid_conf->raid_disks; + raid1_conf_t *conf = mddev_to_conf(mddev); + int i, disks = MD_SB_DISKS; /* * Later we do read balancing on the read side * now we use the first available disk. */ - PRINTK(("raid1_map().\n")); - - for (i=0; imirrors[i].operational) { - *rdev = raid_conf->mirrors[i].dev; + for (i = 0; i < disks; i++) { + if (conf->mirrors[i].operational) { + *rdev = conf->mirrors[i].dev; return (0); } } @@ -67,29 +69,29 @@ return (-1); } -static int raid1_map (struct md_dev *mddev, kdev_t *rdev, +static int raid1_map (mddev_t *mddev, kdev_t dev, kdev_t *rdev, unsigned long *rsector, unsigned long size) { return 0; } -void raid1_reschedule_retry (struct buffer_head *bh) +static void raid1_reschedule_retry (struct buffer_head *bh) { struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_dev_id); - - PRINTK(("raid1_reschedule_retry().\n")); + mddev_t *mddev = r1_bh->mddev; + raid1_conf_t *conf = mddev_to_conf(mddev); r1_bh->next_retry = raid1_retry_list; raid1_retry_list = bh; - md_wakeup_thread(raid1_thread); + md_wakeup_thread(conf->thread); } /* - * raid1_end_buffer_io() is called when we have finished servicing a mirrored + * raid1_end_bh_io() is called when we have finished servicing a mirrored * operation and are ready to return a success/failure code to the buffer * cache layer. */ -static inline void raid1_end_buffer_io(struct raid1_bh *r1_bh, int uptodate) +static void raid1_end_bh_io (struct raid1_bh *r1_bh, int uptodate) { struct buffer_head *bh = r1_bh->master_bh; @@ -97,8 +99,6 @@ kfree(r1_bh); } -int raid1_one_error=0; - void raid1_end_request (struct buffer_head *bh, int uptodate) { struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_dev_id); @@ -106,12 +106,7 @@ save_flags(flags); cli(); - PRINTK(("raid1_end_request().\n")); - if (raid1_one_error) { - raid1_one_error=0; - uptodate=0; - } /* * this branch is our 'one mirror IO has finished' event handler: */ @@ -136,15 +131,11 @@ */ if ( (r1_bh->cmd == READ) || (r1_bh->cmd == READA) ) { - - PRINTK(("raid1_end_request(), read branch.\n")); - /* * we have only one buffer_head on the read side */ if (uptodate) { - PRINTK(("raid1_end_request(), read branch, uptodate.\n")); - raid1_end_buffer_io(r1_bh, uptodate); + raid1_end_bh_io(r1_bh, uptodate); restore_flags(flags); return; } @@ -152,67 +143,56 @@ * oops, read error: */ printk(KERN_ERR "raid1: %s: rescheduling block %lu\n", - kdevname(bh->b_dev), bh->b_blocknr); - raid1_reschedule_retry (bh); + partition_name(bh->b_dev), bh->b_blocknr); + raid1_reschedule_retry(bh); restore_flags(flags); return; } /* - * WRITE or WRITEA. - */ - PRINTK(("raid1_end_request(), write branch.\n")); - - /* + * WRITE: + * * Let's see if all mirrored write operations have finished - * already [we have irqs off, so we can decrease]: + * already. */ - if (!--r1_bh->remaining) { - struct md_dev *mddev = r1_bh->mddev; - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; - int i, n = raid_conf->raid_disks; + if (atomic_dec_and_test(&r1_bh->remaining)) { + int i, disks = MD_SB_DISKS; - PRINTK(("raid1_end_request(), remaining == 0.\n")); + for ( i = 0; i < disks; i++) + if (r1_bh->mirror_bh[i]) + kfree(r1_bh->mirror_bh[i]); - for ( i=0; imirror_bh[i]) kfree(r1_bh->mirror_bh[i]); - - raid1_end_buffer_io(r1_bh, test_bit(BH_Uptodate, &r1_bh->state)); + raid1_end_bh_io(r1_bh, test_bit(BH_Uptodate, &r1_bh->state)); } - else PRINTK(("raid1_end_request(), remaining == %u.\n", r1_bh->remaining)); restore_flags(flags); } -/* This routine checks if the undelying device is an md device and in that - * case it maps the blocks before putting the request on the queue +/* + * This routine checks if the undelying device is an md device + * and in that case it maps the blocks before putting the + * request on the queue */ -static inline void -map_and_make_request (int rw, struct buffer_head *bh) +static void map_and_make_request (int rw, struct buffer_head *bh) { if (MAJOR (bh->b_rdev) == MD_MAJOR) - md_map (MINOR (bh->b_rdev), &bh->b_rdev, &bh->b_rsector, bh->b_size >> 9); + md_map (bh->b_rdev, &bh->b_rdev, + &bh->b_rsector, bh->b_size >> 9); clear_bit(BH_Lock, &bh->b_state); make_request (MAJOR (bh->b_rdev), rw, bh); } -static int -raid1_make_request (struct md_dev *mddev, int rw, struct buffer_head * bh) +static int raid1_make_request (mddev_t *mddev, int rw, + struct buffer_head * bh) { - - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; + raid1_conf_t *conf = mddev_to_conf(mddev); struct buffer_head *mirror_bh[MD_SB_DISKS], *bh_req; struct raid1_bh * r1_bh; - int n = raid_conf->raid_disks, i, sum_bhs = 0, switch_disks = 0, sectors; + int disks = MD_SB_DISKS; + int i, sum_bhs = 0, switch_disks = 0, sectors, lowprio = 0; struct mirror_info *mirror; - PRINTK(("raid1_make_request().\n")); - - while (!( /* FIXME: now we are rather fault tolerant than nice */ - r1_bh = kmalloc (sizeof (struct raid1_bh), GFP_KERNEL) - ) ) - printk ("raid1_make_request(#1): out of memory\n"); - memset (r1_bh, 0, sizeof (struct raid1_bh)); + r1_bh = raid1_kmalloc (sizeof (struct raid1_bh)); /* * make_request() can abort the operation when READA or WRITEA are being @@ -223,43 +203,65 @@ if (rw == READA) rw = READ; if (rw == WRITEA) rw = WRITE; - if (rw == WRITE || rw == WRITEA) - mark_buffer_clean(bh); /* Too early ? */ + if (rw == WRITE) { + /* + * Too early ? + */ + mark_buffer_clean(bh); + /* + * not too early. we _first_ clean the bh, then we start + * the IO, then when the IO has finished, we unlock the + * bh and mark it uptodate. This way we do not miss the + * case when the bh got dirty again during the IO. + */ + } + + /* + * special flag for 'lowprio' reconstruction requests ... + */ + if (buffer_lowprio(bh)) + lowprio = 1; /* - * i think the read and write branch should be separated completely, since we want - * to do read balancing on the read side for example. Comments? :) --mingo + * i think the read and write branch should be separated completely, + * since we want to do read balancing on the read side for example. + * Comments? :) --mingo */ r1_bh->master_bh=bh; r1_bh->mddev=mddev; r1_bh->cmd = rw; - if (rw==READ || rw==READA) { - int last_used = raid_conf->last_used; - PRINTK(("raid1_make_request(), read branch.\n")); - mirror = raid_conf->mirrors + last_used; + if (rw==READ) { + int last_used = conf->last_used; + + /* + * read balancing logic: + */ + mirror = conf->mirrors + last_used; bh->b_rdev = mirror->dev; sectors = bh->b_size >> 9; - if (bh->b_blocknr * sectors == raid_conf->next_sect) { - raid_conf->sect_count += sectors; - if (raid_conf->sect_count >= mirror->sect_limit) + + if (bh->b_blocknr * sectors == conf->next_sect) { + conf->sect_count += sectors; + if (conf->sect_count >= mirror->sect_limit) switch_disks = 1; } else switch_disks = 1; - raid_conf->next_sect = (bh->b_blocknr + 1) * sectors; - if (switch_disks) { - PRINTK(("read-balancing: switching %d -> %d (%d sectors)\n", last_used, mirror->next, raid_conf->sect_count)); - raid_conf->sect_count = 0; - last_used = raid_conf->last_used = mirror->next; + conf->next_sect = (bh->b_blocknr + 1) * sectors; + /* + * Do not switch disks if full resync is in progress ... + */ + if (switch_disks && !conf->resync_mirrors) { + conf->sect_count = 0; + last_used = conf->last_used = mirror->next; /* - * Do not switch to write-only disks ... resyncing - * is in progress + * Do not switch to write-only disks ... + * reconstruction is in progress */ - while (raid_conf->mirrors[last_used].write_only) - raid_conf->last_used = raid_conf->mirrors[last_used].next; + while (conf->mirrors[last_used].write_only) + conf->last_used = conf->mirrors[last_used].next; } - PRINTK (("raid1 read queue: %d %d\n", MAJOR (bh->b_rdev), MINOR (bh->b_rdev))); bh_req = &r1_bh->bh_req; memcpy(bh_req, bh, sizeof(*bh)); bh_req->b_end_io = raid1_end_request; @@ -269,13 +271,12 @@ } /* - * WRITE or WRITEA. + * WRITE: */ - PRINTK(("raid1_make_request(n=%d), write branch.\n",n)); - for (i = 0; i < n; i++) { + for (i = 0; i < disks; i++) { - if (!raid_conf->mirrors [i].operational) { + if (!conf->mirrors[i].operational) { /* * the r1_bh->mirror_bh[i] pointer remains NULL */ @@ -283,85 +284,91 @@ continue; } + /* + * special case for reconstruction ... + */ + if (lowprio && (i == conf->last_used)) { + mirror_bh[i] = NULL; + continue; + } + + /* + * We should use a private pool (size depending on NR_REQUEST), + * to avoid writes filling up the memory with bhs + * + * Such pools are much faster than kmalloc anyways (so we waste + * almost nothing by not using the master bh when writing and + * win alot of cleanness) but for now we are cool enough. --mingo + * + * It's safe to sleep here, buffer heads cannot be used in a shared + * manner in the write branch. Look how we lock the buffer at the + * beginning of this function to grok the difference ;) + */ + mirror_bh[i] = raid1_kmalloc(sizeof(struct buffer_head)); + /* + * prepare mirrored bh (fields ordered for max mem throughput): + */ + mirror_bh[i]->b_blocknr = bh->b_blocknr; + mirror_bh[i]->b_dev = bh->b_dev; + mirror_bh[i]->b_rdev = conf->mirrors[i].dev; + mirror_bh[i]->b_rsector = bh->b_rsector; + mirror_bh[i]->b_state = (1<b_state |= (1<b_count = 1; + mirror_bh[i]->b_size = bh->b_size; + mirror_bh[i]->b_data = bh->b_data; + mirror_bh[i]->b_list = BUF_LOCKED; + mirror_bh[i]->b_end_io = raid1_end_request; + mirror_bh[i]->b_dev_id = r1_bh; + + r1_bh->mirror_bh[i] = mirror_bh[i]; + sum_bhs++; + } + + md_atomic_set(&r1_bh->remaining, sum_bhs); + /* - * We should use a private pool (size depending on NR_REQUEST), - * to avoid writes filling up the memory with bhs - * - * Such pools are much faster than kmalloc anyways (so we waste almost - * nothing by not using the master bh when writing and win alot of cleanness) - * - * but for now we are cool enough. --mingo - * - * It's safe to sleep here, buffer heads cannot be used in a shared - * manner in the write branch. Look how we lock the buffer at the beginning - * of this function to grok the difference ;) - */ - while (!( /* FIXME: now we are rather fault tolerant than nice */ - mirror_bh[i] = kmalloc (sizeof (struct buffer_head), GFP_KERNEL) - ) ) - printk ("raid1_make_request(#2): out of memory\n"); - memset (mirror_bh[i], 0, sizeof (struct buffer_head)); - - /* - * prepare mirrored bh (fields ordered for max mem throughput): - */ - mirror_bh [i]->b_blocknr = bh->b_blocknr; - mirror_bh [i]->b_dev = bh->b_dev; - mirror_bh [i]->b_rdev = raid_conf->mirrors [i].dev; - mirror_bh [i]->b_rsector = bh->b_rsector; - mirror_bh [i]->b_state = (1<b_count = 1; - mirror_bh [i]->b_size = bh->b_size; - mirror_bh [i]->b_data = bh->b_data; - mirror_bh [i]->b_list = BUF_LOCKED; - mirror_bh [i]->b_end_io = raid1_end_request; - mirror_bh [i]->b_dev_id = r1_bh; - - r1_bh->mirror_bh[i] = mirror_bh[i]; - sum_bhs++; - } - - r1_bh->remaining = sum_bhs; - - PRINTK(("raid1_make_request(), write branch, sum_bhs=%d.\n",sum_bhs)); - - /* - * We have to be a bit careful about the semaphore above, thats why we - * start the requests separately. Since kmalloc() could fail, sleep and - * make_request() can sleep too, this is the safer solution. Imagine, - * end_request decreasing the semaphore before we could have set it up ... - * We could play tricks with the semaphore (presetting it and correcting - * at the end if sum_bhs is not 'n' but we have to do end_request by hand - * if all requests finish until we had a chance to set up the semaphore - * correctly ... lots of races). - */ - for (i = 0; i < n; i++) - if (mirror_bh [i] != NULL) - map_and_make_request (rw, mirror_bh [i]); + * We have to be a bit careful about the semaphore above, thats + * why we start the requests separately. Since kmalloc() could + * fail, sleep and make_request() can sleep too, this is the + * safer solution. Imagine, end_request decreasing the semaphore + * before we could have set it up ... We could play tricks with + * the semaphore (presetting it and correcting at the end if + * sum_bhs is not 'n' but we have to do end_request by hand if + * all requests finish until we had a chance to set up the + * semaphore correctly ... lots of races). + */ + for (i = 0; i < disks; i++) + if (mirror_bh[i]) + map_and_make_request(rw, mirror_bh[i]); return (0); } -static int raid1_status (char *page, int minor, struct md_dev *mddev) +static int raid1_status (char *page, mddev_t *mddev) { - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; + raid1_conf_t *conf = mddev_to_conf(mddev); int sz = 0, i; - sz += sprintf (page+sz, " [%d/%d] [", raid_conf->raid_disks, raid_conf->working_disks); - for (i = 0; i < raid_conf->raid_disks; i++) - sz += sprintf (page+sz, "%s", raid_conf->mirrors [i].operational ? "U" : "_"); + sz += sprintf (page+sz, " [%d/%d] [", conf->raid_disks, + conf->working_disks); + for (i = 0; i < conf->raid_disks; i++) + sz += sprintf (page+sz, "%s", + conf->mirrors[i].operational ? "U" : "_"); sz += sprintf (page+sz, "]"); return sz; } -static void raid1_fix_links (struct raid1_data *raid_conf, int failed_index) +static void unlink_disk (raid1_conf_t *conf, int target) { - int disks = raid_conf->raid_disks; - int j; + int disks = MD_SB_DISKS; + int i; - for (j = 0; j < disks; j++) - if (raid_conf->mirrors [j].next == failed_index) - raid_conf->mirrors [j].next = raid_conf->mirrors [failed_index].next; + for (i = 0; i < disks; i++) + if (conf->mirrors[i].next == target) + conf->mirrors[i].next = conf->mirrors[target].next; } #define LAST_DISK KERN_ALERT \ @@ -380,48 +387,53 @@ #define ALREADY_SYNCING KERN_INFO \ "raid1: syncing already in progress.\n" -static int raid1_error (struct md_dev *mddev, kdev_t dev) +static void mark_disk_bad (mddev_t *mddev, int failed) { - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; - struct mirror_info *mirror; - md_superblock_t *sb = mddev->sb; - int disks = raid_conf->raid_disks; - int i; + raid1_conf_t *conf = mddev_to_conf(mddev); + struct mirror_info *mirror = conf->mirrors+failed; + mdp_super_t *sb = mddev->sb; + + mirror->operational = 0; + unlink_disk(conf, failed); + mark_disk_faulty(sb->disks+mirror->number); + mark_disk_nonsync(sb->disks+mirror->number); + mark_disk_inactive(sb->disks+mirror->number); + sb->active_disks--; + sb->working_disks--; + sb->failed_disks++; + mddev->sb_dirty = 1; + md_wakeup_thread(conf->thread); + conf->working_disks--; + printk (DISK_FAILED, partition_name (mirror->dev), + conf->working_disks); +} - PRINTK(("raid1_error called\n")); +static int raid1_error (mddev_t *mddev, kdev_t dev) +{ + raid1_conf_t *conf = mddev_to_conf(mddev); + struct mirror_info * mirrors = conf->mirrors; + int disks = MD_SB_DISKS; + int i; - if (raid_conf->working_disks == 1) { + if (conf->working_disks == 1) { /* * Uh oh, we can do nothing if this is our last disk, but * first check if this is a queued request for a device * which has just failed. */ - for (i = 0, mirror = raid_conf->mirrors; i < disks; - i++, mirror++) - if (mirror->dev == dev && !mirror->operational) + for (i = 0; i < disks; i++) { + if (mirrors[i].dev==dev && !mirrors[i].operational) return 0; + } printk (LAST_DISK); } else { - /* Mark disk as unusable */ - for (i = 0, mirror = raid_conf->mirrors; i < disks; - i++, mirror++) { - if (mirror->dev == dev && mirror->operational){ - mirror->operational = 0; - raid1_fix_links (raid_conf, i); - sb->disks[mirror->number].state |= - (1 << MD_FAULTY_DEVICE); - sb->disks[mirror->number].state &= - ~(1 << MD_SYNC_DEVICE); - sb->disks[mirror->number].state &= - ~(1 << MD_ACTIVE_DEVICE); - sb->active_disks--; - sb->working_disks--; - sb->failed_disks++; - mddev->sb_dirty = 1; - md_wakeup_thread(raid1_thread); - raid_conf->working_disks--; - printk (DISK_FAILED, kdevname (dev), - raid_conf->working_disks); + /* + * Mark disk as unusable + */ + for (i = 0; i < disks; i++) { + if (mirrors[i].dev==dev && mirrors[i].operational) { + mark_disk_bad (mddev, i); + break; } } } @@ -434,219 +446,396 @@ #undef START_SYNCING /* - * This is the personality-specific hot-addition routine + * Insert the spare disk into the drive-ring */ +static void link_disk(raid1_conf_t *conf, struct mirror_info *mirror) +{ + int j, next; + int disks = MD_SB_DISKS; + struct mirror_info *p = conf->mirrors; -#define NO_SUPERBLOCK KERN_ERR \ -"raid1: cannot hot-add disk to the array with no RAID superblock\n" + for (j = 0; j < disks; j++, p++) + if (p->operational && !p->write_only) { + next = p->next; + p->next = mirror->raid_disk; + mirror->next = next; + return; + } -#define WRONG_LEVEL KERN_ERR \ -"raid1: hot-add: level of disk is not RAID-1\n" + printk("raid1: bug: no read-operational devices\n"); +} -#define HOT_ADD_SUCCEEDED KERN_INFO \ -"raid1: device %s hot-added\n" +static void print_raid1_conf (raid1_conf_t *conf) +{ + int i; + struct mirror_info *tmp; + + printk("RAID1 conf printout:\n"); + if (!conf) { + printk("(conf==NULL)\n"); + return; + } + printk(" --- wd:%d rd:%d nd:%d\n", conf->working_disks, + conf->raid_disks, conf->nr_disks); + + for (i = 0; i < MD_SB_DISKS; i++) { + tmp = conf->mirrors + i; + printk(" disk %d, s:%d, o:%d, n:%d rd:%d us:%d dev:%s\n", + i, tmp->spare,tmp->operational, + tmp->number,tmp->raid_disk,tmp->used_slot, + partition_name(tmp->dev)); + } +} -static int raid1_hot_add_disk (struct md_dev *mddev, kdev_t dev) +static int raid1_diskop(mddev_t *mddev, mdp_disk_t **d, int state) { + int err = 0; + int i, failed_disk=-1, spare_disk=-1, removed_disk=-1, added_disk=-1; + raid1_conf_t *conf = mddev->private; + struct mirror_info *tmp, *sdisk, *fdisk, *rdisk, *adisk; unsigned long flags; - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; - struct mirror_info *mirror; - md_superblock_t *sb = mddev->sb; - struct real_dev * realdev; - int n; + mdp_super_t *sb = mddev->sb; + mdp_disk_t *failed_desc, *spare_desc, *added_desc; + + save_flags(flags); + cli(); + print_raid1_conf(conf); /* - * The device has its superblock already read and it was found - * to be consistent for generic RAID usage. Now we check whether - * it's usable for RAID-1 hot addition. + * find the disk ... */ + switch (state) { - n = mddev->nb_dev++; - realdev = &mddev->devices[n]; - if (!realdev->sb) { - printk (NO_SUPERBLOCK); - return -EINVAL; - } - if (realdev->sb->level != 1) { - printk (WRONG_LEVEL); - return -EINVAL; + case DISKOP_SPARE_ACTIVE: + + /* + * Find the failed disk within the RAID1 configuration ... + * (this can only be in the first conf->working_disks part) + */ + for (i = 0; i < conf->raid_disks; i++) { + tmp = conf->mirrors + i; + if ((!tmp->operational && !tmp->spare) || + !tmp->used_slot) { + failed_disk = i; + break; + } + } + /* + * When we activate a spare disk we _must_ have a disk in + * the lower (active) part of the array to replace. + */ + if ((failed_disk == -1) || (failed_disk >= conf->raid_disks)) { + MD_BUG(); + err = 1; + goto abort; + } + /* fall through */ + + case DISKOP_SPARE_WRITE: + case DISKOP_SPARE_INACTIVE: + + /* + * Find the spare disk ... (can only be in the 'high' + * area of the array) + */ + for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { + tmp = conf->mirrors + i; + if (tmp->spare && tmp->number == (*d)->number) { + spare_disk = i; + break; + } + } + if (spare_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; + + case DISKOP_HOT_REMOVE_DISK: + + for (i = 0; i < MD_SB_DISKS; i++) { + tmp = conf->mirrors + i; + if (tmp->used_slot && (tmp->number == (*d)->number)) { + if (tmp->operational) { + err = -EBUSY; + goto abort; + } + removed_disk = i; + break; + } + } + if (removed_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; + + case DISKOP_HOT_ADD_DISK: + + for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { + tmp = conf->mirrors + i; + if (!tmp->used_slot) { + added_disk = i; + break; + } + } + if (added_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; } - /* FIXME: are there other things left we could sanity-check? */ + switch (state) { /* - * We have to disable interrupts, as our RAID-1 state is used - * from irq handlers as well. + * Switch the spare disk to write-only mode: */ - save_flags(flags); - cli(); + case DISKOP_SPARE_WRITE: + sdisk = conf->mirrors + spare_disk; + sdisk->operational = 1; + sdisk->write_only = 1; + break; + /* + * Deactivate a spare disk: + */ + case DISKOP_SPARE_INACTIVE: + sdisk = conf->mirrors + spare_disk; + sdisk->operational = 0; + sdisk->write_only = 0; + break; + /* + * Activate (mark read-write) the (now sync) spare disk, + * which means we switch it's 'raid position' (->raid_disk) + * with the failed disk. (only the first 'conf->nr_disks' + * slots are used for 'real' disks and we must preserve this + * property) + */ + case DISKOP_SPARE_ACTIVE: - raid_conf->raid_disks++; - mirror = raid_conf->mirrors+n; + sdisk = conf->mirrors + spare_disk; + fdisk = conf->mirrors + failed_disk; - mirror->number=n; - mirror->raid_disk=n; - mirror->dev=dev; - mirror->next=0; /* FIXME */ - mirror->sect_limit=128; - - mirror->operational=0; - mirror->spare=1; - mirror->write_only=0; - - sb->disks[n].state |= (1 << MD_FAULTY_DEVICE); - sb->disks[n].state &= ~(1 << MD_SYNC_DEVICE); - sb->disks[n].state &= ~(1 << MD_ACTIVE_DEVICE); - sb->nr_disks++; - sb->spare_disks++; + spare_desc = &sb->disks[sdisk->number]; + failed_desc = &sb->disks[fdisk->number]; - restore_flags(flags); + if (spare_desc != *d) { + MD_BUG(); + err = 1; + goto abort; + } - md_update_sb(MINOR(dev)); + if (spare_desc->raid_disk != sdisk->raid_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + if (sdisk->raid_disk != spare_disk) { + MD_BUG(); + err = 1; + goto abort; + } - printk (HOT_ADD_SUCCEEDED, kdevname(realdev->dev)); + if (failed_desc->raid_disk != fdisk->raid_disk) { + MD_BUG(); + err = 1; + goto abort; + } - return 0; -} + if (fdisk->raid_disk != failed_disk) { + MD_BUG(); + err = 1; + goto abort; + } -#undef NO_SUPERBLOCK -#undef WRONG_LEVEL -#undef HOT_ADD_SUCCEEDED + /* + * do the switch finally + */ + xchg_values(*spare_desc, *failed_desc); + xchg_values(*fdisk, *sdisk); -/* - * Insert the spare disk into the drive-ring - */ -static void add_ring(struct raid1_data *raid_conf, struct mirror_info *mirror) -{ - int j, next; - struct mirror_info *p = raid_conf->mirrors; + /* + * (careful, 'failed' and 'spare' are switched from now on) + * + * we want to preserve linear numbering and we want to + * give the proper raid_disk number to the now activated + * disk. (this means we switch back these values) + */ + + xchg_values(spare_desc->raid_disk, failed_desc->raid_disk); + xchg_values(sdisk->raid_disk, fdisk->raid_disk); + xchg_values(spare_desc->number, failed_desc->number); + xchg_values(sdisk->number, fdisk->number); - for (j = 0; j < raid_conf->raid_disks; j++, p++) - if (p->operational && !p->write_only) { - next = p->next; - p->next = mirror->raid_disk; - mirror->next = next; - return; - } - printk("raid1: bug: no read-operational devices\n"); -} + *d = failed_desc; -static int raid1_mark_spare(struct md_dev *mddev, md_descriptor_t *spare, - int state) -{ - int i = 0, failed_disk = -1; - struct raid1_data *raid_conf = mddev->private; - struct mirror_info *mirror = raid_conf->mirrors; - md_descriptor_t *descriptor; - unsigned long flags; + if (sdisk->dev == MKDEV(0,0)) + sdisk->used_slot = 0; + /* + * this really activates the spare. + */ + fdisk->spare = 0; + fdisk->write_only = 0; + link_disk(conf, fdisk); - for (i = 0; i < MD_SB_DISKS; i++, mirror++) { - if (mirror->spare && mirror->number == spare->number) - goto found; - } - return 1; -found: - for (i = 0, mirror = raid_conf->mirrors; i < raid_conf->raid_disks; - i++, mirror++) - if (!mirror->operational) - failed_disk = i; + /* + * if we activate a spare, we definitely replace a + * non-operational disk slot in the 'low' area of + * the disk array. + */ - save_flags(flags); - cli(); - switch (state) { - case SPARE_WRITE: - mirror->operational = 1; - mirror->write_only = 1; - raid_conf->raid_disks = MAX(raid_conf->raid_disks, - mirror->raid_disk + 1); - break; - case SPARE_INACTIVE: - mirror->operational = 0; - mirror->write_only = 0; - break; - case SPARE_ACTIVE: - mirror->spare = 0; - mirror->write_only = 0; - raid_conf->working_disks++; - add_ring(raid_conf, mirror); - - if (failed_disk != -1) { - descriptor = &mddev->sb->disks[raid_conf->mirrors[failed_disk].number]; - i = spare->raid_disk; - spare->raid_disk = descriptor->raid_disk; - descriptor->raid_disk = i; - } - break; - default: - printk("raid1_mark_spare: bug: state == %d\n", state); - restore_flags(flags); - return 1; + conf->working_disks++; + + break; + + case DISKOP_HOT_REMOVE_DISK: + rdisk = conf->mirrors + removed_disk; + + if (rdisk->spare && (removed_disk < conf->raid_disks)) { + MD_BUG(); + err = 1; + goto abort; + } + rdisk->dev = MKDEV(0,0); + rdisk->used_slot = 0; + conf->nr_disks--; + break; + + case DISKOP_HOT_ADD_DISK: + adisk = conf->mirrors + added_disk; + added_desc = *d; + + if (added_disk != added_desc->number) { + MD_BUG(); + err = 1; + goto abort; + } + + adisk->number = added_desc->number; + adisk->raid_disk = added_desc->raid_disk; + adisk->dev = MKDEV(added_desc->major,added_desc->minor); + + adisk->operational = 0; + adisk->write_only = 0; + adisk->spare = 1; + adisk->used_slot = 1; + conf->nr_disks++; + + break; + + default: + MD_BUG(); + err = 1; + goto abort; } +abort: restore_flags(flags); - return 0; + print_raid1_conf(conf); + return err; } + +#define IO_ERROR KERN_ALERT \ +"raid1: %s: unrecoverable I/O read error for block %lu\n" + +#define REDIRECT_SECTOR KERN_ERR \ +"raid1: %s: redirecting sector %lu to another mirror\n" + /* * This is a kernel thread which: * * 1. Retries failed read operations on working mirrors. * 2. Updates the raid superblock when problems encounter. */ -void raid1d (void *data) +static void raid1d (void *data) { struct buffer_head *bh; kdev_t dev; unsigned long flags; - struct raid1_bh * r1_bh; - struct md_dev *mddev; + struct raid1_bh *r1_bh; + mddev_t *mddev; - PRINTK(("raid1d() active\n")); - save_flags(flags); - cli(); while (raid1_retry_list) { + save_flags(flags); + cli(); bh = raid1_retry_list; r1_bh = (struct raid1_bh *)(bh->b_dev_id); raid1_retry_list = r1_bh->next_retry; restore_flags(flags); - mddev = md_dev + MINOR(bh->b_dev); + mddev = kdev_to_mddev(bh->b_dev); if (mddev->sb_dirty) { - printk("dirty sb detected, updating.\n"); + printk(KERN_INFO "dirty sb detected, updating.\n"); mddev->sb_dirty = 0; - md_update_sb(MINOR(bh->b_dev)); + md_update_sb(mddev); } dev = bh->b_rdev; - __raid1_map (md_dev + MINOR(bh->b_dev), &bh->b_rdev, &bh->b_rsector, bh->b_size >> 9); + __raid1_map (mddev, &bh->b_rdev, &bh->b_rsector, + bh->b_size >> 9); if (bh->b_rdev == dev) { - printk (KERN_ALERT - "raid1: %s: unrecoverable I/O read error for block %lu\n", - kdevname(bh->b_dev), bh->b_blocknr); - raid1_end_buffer_io(r1_bh, 0); + printk (IO_ERROR, partition_name(bh->b_dev), bh->b_blocknr); + raid1_end_bh_io(r1_bh, 0); } else { - printk (KERN_ERR "raid1: %s: redirecting sector %lu to another mirror\n", - kdevname(bh->b_dev), bh->b_blocknr); + printk (REDIRECT_SECTOR, + partition_name(bh->b_dev), bh->b_blocknr); map_and_make_request (r1_bh->cmd, bh); } - cli(); } - restore_flags(flags); } +#undef IO_ERROR +#undef REDIRECT_SECTOR + +/* + * Private kernel thread to reconstruct mirrors after an unclean + * shutdown. + */ +static void raid1syncd (void *data) +{ + raid1_conf_t *conf = data; + mddev_t *mddev = conf->mddev; + + if (!conf->resync_mirrors) + return; + if (conf->resync_mirrors == 2) + return; + down(&mddev->recovery_sem); + if (md_do_sync(mddev, NULL)) { + up(&mddev->recovery_sem); + return; + } + /* + * Only if everything went Ok. + */ + conf->resync_mirrors = 0; + up(&mddev->recovery_sem); +} + /* * This will catch the scenario in which one of the mirrors was * mounted as a normal device rather than as a part of a raid set. + * + * check_consistency is very personality-dependent, eg. RAID5 cannot + * do this check, it uses another method. */ -static int __check_consistency (struct md_dev *mddev, int row) +static int __check_consistency (mddev_t *mddev, int row) { - struct raid1_data *raid_conf = mddev->private; + raid1_conf_t *conf = mddev_to_conf(mddev); + int disks = MD_SB_DISKS; kdev_t dev; struct buffer_head *bh = NULL; int i, rc = 0; char *buffer = NULL; - for (i = 0; i < raid_conf->raid_disks; i++) { - if (!raid_conf->mirrors[i].operational) + for (i = 0; i < disks; i++) { + printk("(checking disk %d)\n",i); + if (!conf->mirrors[i].operational) continue; - dev = raid_conf->mirrors[i].dev; + printk("(really checking disk %d)\n",i); + dev = conf->mirrors[i].dev; set_blocksize(dev, 4096); if ((bh = bread(dev, row / 4, 4096)) == NULL) break; @@ -675,163 +864,342 @@ return rc; } -static int check_consistency (struct md_dev *mddev) +static int check_consistency (mddev_t *mddev) { - int size = mddev->sb->size; - int row; + if (__check_consistency(mddev, 0)) +/* + * we do not do this currently, as it's perfectly possible to + * have an inconsistent array when it's freshly created. Only + * newly written data has to be consistent. + */ + return 0; - for (row = 0; row < size; row += size / 8) - if (__check_consistency(mddev, row)) - return 1; return 0; } -static int raid1_run (int minor, struct md_dev *mddev) +#define INVALID_LEVEL KERN_WARNING \ +"raid1: md%d: raid level not set to mirroring (%d)\n" + +#define NO_SB KERN_ERR \ +"raid1: disabled mirror %s (couldn't access raid superblock)\n" + +#define ERRORS KERN_ERR \ +"raid1: disabled mirror %s (errors detected)\n" + +#define NOT_IN_SYNC KERN_ERR \ +"raid1: disabled mirror %s (not in sync)\n" + +#define INCONSISTENT KERN_ERR \ +"raid1: disabled mirror %s (inconsistent descriptor)\n" + +#define ALREADY_RUNNING KERN_ERR \ +"raid1: disabled mirror %s (mirror %d already operational)\n" + +#define OPERATIONAL KERN_INFO \ +"raid1: device %s operational as mirror %d\n" + +#define MEM_ERROR KERN_ERR \ +"raid1: couldn't allocate memory for md%d\n" + +#define SPARE KERN_INFO \ +"raid1: spare disk %s\n" + +#define NONE_OPERATIONAL KERN_ERR \ +"raid1: no operational mirrors for md%d\n" + +#define RUNNING_CKRAID KERN_ERR \ +"raid1: detected mirror differences -- running resync\n" + +#define ARRAY_IS_ACTIVE KERN_INFO \ +"raid1: raid set md%d active with %d out of %d mirrors\n" + +#define THREAD_ERROR KERN_ERR \ +"raid1: couldn't allocate thread for md%d\n" + +#define START_RESYNC KERN_WARNING \ +"raid1: raid set md%d not clean; reconstructing mirrors\n" + +static int raid1_run (mddev_t *mddev) { - struct raid1_data *raid_conf; - int i, j, raid_disk; - md_superblock_t *sb = mddev->sb; - md_descriptor_t *descriptor; - struct real_dev *realdev; + raid1_conf_t *conf; + int i, j, disk_idx; + struct mirror_info *disk; + mdp_super_t *sb = mddev->sb; + mdp_disk_t *descriptor; + mdk_rdev_t *rdev; + struct md_list_head *tmp; + int start_recovery = 0; MOD_INC_USE_COUNT; if (sb->level != 1) { - printk("raid1: %s: raid level not set to mirroring (%d)\n", - kdevname(MKDEV(MD_MAJOR, minor)), sb->level); - MOD_DEC_USE_COUNT; - return -EIO; - } - /**** - * copy the now verified devices into our private RAID1 bookkeeping - * area. [whatever we allocate in raid1_run(), should be freed in - * raid1_stop()] - */ - - while (!( /* FIXME: now we are rather fault tolerant than nice */ - mddev->private = kmalloc (sizeof (struct raid1_data), GFP_KERNEL) - ) ) - printk ("raid1_run(): out of memory\n"); - raid_conf = mddev->private; - memset(raid_conf, 0, sizeof(*raid_conf)); - - PRINTK(("raid1_run(%d) called.\n", minor)); - - for (i = 0; i < mddev->nb_dev; i++) { - realdev = &mddev->devices[i]; - if (!realdev->sb) { - printk(KERN_ERR "raid1: disabled mirror %s (couldn't access raid superblock)\n", kdevname(realdev->dev)); + printk(INVALID_LEVEL, mdidx(mddev), sb->level); + goto out; + } + /* + * copy the already verified devices into our private RAID1 + * bookkeeping area. [whatever we allocate in raid1_run(), + * should be freed in raid1_stop()] + */ + + conf = raid1_kmalloc(sizeof(raid1_conf_t)); + mddev->private = conf; + if (!conf) { + printk(MEM_ERROR, mdidx(mddev)); + goto out; + } + + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->faulty) { + printk(ERRORS, partition_name(rdev->dev)); + } else { + if (!rdev->sb) { + MD_BUG(); + continue; + } + } + if (rdev->desc_nr == -1) { + MD_BUG(); continue; } - - /* - * This is important -- we are using the descriptor on - * the disk only to get a pointer to the descriptor on - * the main superblock, which might be more recent. - */ - descriptor = &sb->disks[realdev->sb->descriptor.number]; - if (descriptor->state & (1 << MD_FAULTY_DEVICE)) { - printk(KERN_ERR "raid1: disabled mirror %s (errors detected)\n", kdevname(realdev->dev)); + descriptor = &sb->disks[rdev->desc_nr]; + disk_idx = descriptor->raid_disk; + disk = conf->mirrors + disk_idx; + + if (disk_faulty(descriptor)) { + disk->number = descriptor->number; + disk->raid_disk = disk_idx; + disk->dev = rdev->dev; + disk->sect_limit = MAX_LINEAR_SECTORS; + disk->operational = 0; + disk->write_only = 0; + disk->spare = 0; + disk->used_slot = 1; continue; } - if (descriptor->state & (1 << MD_ACTIVE_DEVICE)) { - if (!(descriptor->state & (1 << MD_SYNC_DEVICE))) { - printk(KERN_ERR "raid1: disabled mirror %s (not in sync)\n", kdevname(realdev->dev)); + if (disk_active(descriptor)) { + if (!disk_sync(descriptor)) { + printk(NOT_IN_SYNC, + partition_name(rdev->dev)); continue; } - raid_disk = descriptor->raid_disk; - if (descriptor->number > sb->nr_disks || raid_disk > sb->raid_disks) { - printk(KERN_ERR "raid1: disabled mirror %s (inconsistent descriptor)\n", kdevname(realdev->dev)); + if ((descriptor->number > MD_SB_DISKS) || + (disk_idx > sb->raid_disks)) { + + printk(INCONSISTENT, + partition_name(rdev->dev)); continue; } - if (raid_conf->mirrors[raid_disk].operational) { - printk(KERN_ERR "raid1: disabled mirror %s (mirror %d already operational)\n", kdevname(realdev->dev), raid_disk); + if (disk->operational) { + printk(ALREADY_RUNNING, + partition_name(rdev->dev), + disk_idx); continue; } - printk(KERN_INFO "raid1: device %s operational as mirror %d\n", kdevname(realdev->dev), raid_disk); - raid_conf->mirrors[raid_disk].number = descriptor->number; - raid_conf->mirrors[raid_disk].raid_disk = raid_disk; - raid_conf->mirrors[raid_disk].dev = mddev->devices [i].dev; - raid_conf->mirrors[raid_disk].operational = 1; - raid_conf->mirrors[raid_disk].sect_limit = 128; - raid_conf->working_disks++; + printk(OPERATIONAL, partition_name(rdev->dev), + disk_idx); + disk->number = descriptor->number; + disk->raid_disk = disk_idx; + disk->dev = rdev->dev; + disk->sect_limit = MAX_LINEAR_SECTORS; + disk->operational = 1; + disk->write_only = 0; + disk->spare = 0; + disk->used_slot = 1; + conf->working_disks++; } else { /* * Must be a spare disk .. */ - printk(KERN_INFO "raid1: spare disk %s\n", kdevname(realdev->dev)); - raid_disk = descriptor->raid_disk; - raid_conf->mirrors[raid_disk].number = descriptor->number; - raid_conf->mirrors[raid_disk].raid_disk = raid_disk; - raid_conf->mirrors[raid_disk].dev = mddev->devices [i].dev; - raid_conf->mirrors[raid_disk].sect_limit = 128; - - raid_conf->mirrors[raid_disk].operational = 0; - raid_conf->mirrors[raid_disk].write_only = 0; - raid_conf->mirrors[raid_disk].spare = 1; - } - } - if (!raid_conf->working_disks) { - printk(KERN_ERR "raid1: no operational mirrors for %s\n", kdevname(MKDEV(MD_MAJOR, minor))); - kfree(raid_conf); - mddev->private = NULL; - MOD_DEC_USE_COUNT; - return -EIO; - } - - raid_conf->raid_disks = sb->raid_disks; - raid_conf->mddev = mddev; - - for (j = 0; !raid_conf->mirrors[j].operational; j++); - raid_conf->last_used = j; - for (i = raid_conf->raid_disks - 1; i >= 0; i--) { - if (raid_conf->mirrors[i].operational) { - PRINTK(("raid_conf->mirrors[%d].next == %d\n", i, j)); - raid_conf->mirrors[i].next = j; + printk(SPARE, partition_name(rdev->dev)); + disk->number = descriptor->number; + disk->raid_disk = disk_idx; + disk->dev = rdev->dev; + disk->sect_limit = MAX_LINEAR_SECTORS; + disk->operational = 0; + disk->write_only = 0; + disk->spare = 1; + disk->used_slot = 1; + } + } + if (!conf->working_disks) { + printk(NONE_OPERATIONAL, mdidx(mddev)); + goto out_free_conf; + } + + conf->raid_disks = sb->raid_disks; + conf->nr_disks = sb->nr_disks; + conf->mddev = mddev; + + for (i = 0; i < MD_SB_DISKS; i++) { + + descriptor = sb->disks+i; + disk_idx = descriptor->raid_disk; + disk = conf->mirrors + disk_idx; + + if (disk_faulty(descriptor) && (disk_idx < conf->raid_disks) && + !disk->used_slot) { + + disk->number = descriptor->number; + disk->raid_disk = disk_idx; + disk->dev = MKDEV(0,0); + + disk->operational = 0; + disk->write_only = 0; + disk->spare = 0; + disk->used_slot = 1; + } + } + + /* + * find the first working one and use it as a starting point + * to read balancing. + */ + for (j = 0; !conf->mirrors[j].operational; j++) + /* nothing */; + conf->last_used = j; + + /* + * initialize the 'working disks' list. + */ + for (i = conf->raid_disks - 1; i >= 0; i--) { + if (conf->mirrors[i].operational) { + conf->mirrors[i].next = j; j = i; } } - if (check_consistency(mddev)) { - printk(KERN_ERR "raid1: detected mirror differences -- run ckraid\n"); - sb->state |= 1 << MD_SB_ERRORS; - kfree(raid_conf); - mddev->private = NULL; - MOD_DEC_USE_COUNT; - return -EIO; + if (conf->working_disks != sb->raid_disks) { + printk(KERN_ALERT "raid1: md%d, not all disks are operational -- trying to recover array\n", mdidx(mddev)); + start_recovery = 1; } + if (!start_recovery && (sb->state & (1 << MD_SB_CLEAN))) { + /* + * we do sanity checks even if the device says + * it's clean ... + */ + if (check_consistency(mddev)) { + printk(RUNNING_CKRAID); + sb->state &= ~(1 << MD_SB_CLEAN); + } + } + + { + const char * name = "raid1d"; + + conf->thread = md_register_thread(raid1d, conf, name); + if (!conf->thread) { + printk(THREAD_ERROR, mdidx(mddev)); + goto out_free_conf; + } + } + + if (!start_recovery && !(sb->state & (1 << MD_SB_CLEAN))) { + const char * name = "raid1syncd"; + + conf->resync_thread = md_register_thread(raid1syncd, conf,name); + if (!conf->resync_thread) { + printk(THREAD_ERROR, mdidx(mddev)); + goto out_free_conf; + } + + printk(START_RESYNC, mdidx(mddev)); + conf->resync_mirrors = 1; + md_wakeup_thread(conf->resync_thread); + } + /* * Regenerate the "device is in sync with the raid set" bit for * each device. */ - for (i = 0; i < sb->nr_disks ; i++) { - sb->disks[i].state &= ~(1 << MD_SYNC_DEVICE); + for (i = 0; i < MD_SB_DISKS; i++) { + mark_disk_nonsync(sb->disks+i); for (j = 0; j < sb->raid_disks; j++) { - if (!raid_conf->mirrors[j].operational) + if (!conf->mirrors[j].operational) continue; - if (sb->disks[i].number == raid_conf->mirrors[j].number) - sb->disks[i].state |= 1 << MD_SYNC_DEVICE; + if (sb->disks[i].number == conf->mirrors[j].number) + mark_disk_sync(sb->disks+i); } } - sb->active_disks = raid_conf->working_disks; + sb->active_disks = conf->working_disks; - printk("raid1: raid set %s active with %d out of %d mirrors\n", kdevname(MKDEV(MD_MAJOR, minor)), sb->active_disks, sb->raid_disks); - /* Ok, everything is just fine now */ - return (0); + if (start_recovery) + md_recover_arrays(); + + + printk(ARRAY_IS_ACTIVE, mdidx(mddev), sb->active_disks, sb->raid_disks); + /* + * Ok, everything is just fine now + */ + return 0; + +out_free_conf: + kfree(conf); + mddev->private = NULL; +out: + MOD_DEC_USE_COUNT; + return -EIO; +} + +#undef INVALID_LEVEL +#undef NO_SB +#undef ERRORS +#undef NOT_IN_SYNC +#undef INCONSISTENT +#undef ALREADY_RUNNING +#undef OPERATIONAL +#undef SPARE +#undef NONE_OPERATIONAL +#undef RUNNING_CKRAID +#undef ARRAY_IS_ACTIVE + +static int raid1_stop_resync (mddev_t *mddev) +{ + raid1_conf_t *conf = mddev_to_conf(mddev); + + if (conf->resync_thread) { + if (conf->resync_mirrors) { + conf->resync_mirrors = 2; + md_interrupt_thread(conf->resync_thread); + printk(KERN_INFO "raid1: mirror resync was not fully finished, restarting next time.\n"); + return 1; + } + return 0; + } + return 0; +} + +static int raid1_restart_resync (mddev_t *mddev) +{ + raid1_conf_t *conf = mddev_to_conf(mddev); + + if (conf->resync_mirrors) { + if (!conf->resync_thread) { + MD_BUG(); + return 0; + } + conf->resync_mirrors = 1; + md_wakeup_thread(conf->resync_thread); + return 1; + } + return 0; } -static int raid1_stop (int minor, struct md_dev *mddev) +static int raid1_stop (mddev_t *mddev) { - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; + raid1_conf_t *conf = mddev_to_conf(mddev); - kfree (raid_conf); + md_unregister_thread(conf->thread); + if (conf->resync_thread) + md_unregister_thread(conf->resync_thread); + kfree(conf); mddev->private = NULL; MOD_DEC_USE_COUNT; return 0; } -static struct md_personality raid1_personality= +static mdk_personality_t raid1_personality= { "raid1", raid1_map, @@ -843,15 +1211,13 @@ NULL, /* no ioctls */ 0, raid1_error, - raid1_hot_add_disk, - /* raid1_hot_remove_drive */ NULL, - raid1_mark_spare + raid1_diskop, + raid1_stop_resync, + raid1_restart_resync }; int raid1_init (void) { - if ((raid1_thread = md_register_thread(raid1d, NULL)) == NULL) - return -EBUSY; return register_md_personality (RAID1, &raid1_personality); } @@ -863,7 +1229,6 @@ void cleanup_module (void) { - md_unregister_thread (raid1_thread); unregister_md_personality (RAID1); } #endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/raid5.c linux.ac/drivers/block/raid5.c --- linux.vanilla/drivers/block/raid5.c Sun Nov 8 15:07:37 1998 +++ linux.ac/drivers/block/raid5.c Mon Jul 19 03:26:58 1999 @@ -1,4 +1,4 @@ -/***************************************************************************** +/* * raid5.c : Multiple Devices driver for Linux * Copyright (C) 1996, 1997 Ingo Molnar, Miguel de Icaza, Gadi Oxman * @@ -14,16 +14,15 @@ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #include #include -#include -#include +#include #include #include -#include -static struct md_personality raid5_personality; +static mdk_personality_t raid5_personality; /* * Stripe cache @@ -33,7 +32,7 @@ #define HASH_PAGES_ORDER 0 #define NR_HASH (HASH_PAGES * PAGE_SIZE / sizeof(struct stripe_head *)) #define HASH_MASK (NR_HASH - 1) -#define stripe_hash(raid_conf, sect, size) ((raid_conf)->stripe_hashtbl[((sect) / (size >> 9)) & HASH_MASK]) +#define stripe_hash(conf, sect, size) ((conf)->stripe_hashtbl[((sect) / (size >> 9)) & HASH_MASK]) /* * The following can be used to debug the driver @@ -46,6 +45,8 @@ #define PRINTK(x) do { ; } while (0) #endif +static void print_raid5_conf (raid5_conf_t *conf); + static inline int stripe_locked(struct stripe_head *sh) { return test_bit(STRIPE_LOCKED, &sh->state); @@ -61,32 +62,32 @@ */ static inline void lock_stripe(struct stripe_head *sh) { - struct raid5_data *raid_conf = sh->raid_conf; - if (!test_and_set_bit(STRIPE_LOCKED, &sh->state)) { + raid5_conf_t *conf = sh->raid_conf; + if (!md_test_and_set_bit(STRIPE_LOCKED, &sh->state)) { PRINTK(("locking stripe %lu\n", sh->sector)); - raid_conf->nr_locked_stripes++; + conf->nr_locked_stripes++; } } static inline void unlock_stripe(struct stripe_head *sh) { - struct raid5_data *raid_conf = sh->raid_conf; - if (test_and_clear_bit(STRIPE_LOCKED, &sh->state)) { + raid5_conf_t *conf = sh->raid_conf; + if (md_test_and_clear_bit(STRIPE_LOCKED, &sh->state)) { PRINTK(("unlocking stripe %lu\n", sh->sector)); - raid_conf->nr_locked_stripes--; + conf->nr_locked_stripes--; wake_up(&sh->wait); } } static inline void finish_stripe(struct stripe_head *sh) { - struct raid5_data *raid_conf = sh->raid_conf; + raid5_conf_t *conf = sh->raid_conf; unlock_stripe(sh); sh->cmd = STRIPE_NONE; sh->phase = PHASE_COMPLETE; - raid_conf->nr_pending_stripes--; - raid_conf->nr_cached_stripes++; - wake_up(&raid_conf->wait_for_stripe); + conf->nr_pending_stripes--; + conf->nr_cached_stripes++; + wake_up(&conf->wait_for_stripe); } void __wait_on_stripe(struct stripe_head *sh) @@ -114,7 +115,7 @@ __wait_on_stripe(sh); } -static inline void remove_hash(struct raid5_data *raid_conf, struct stripe_head *sh) +static inline void remove_hash(raid5_conf_t *conf, struct stripe_head *sh) { PRINTK(("remove_hash(), stripe %lu\n", sh->sector)); @@ -123,21 +124,22 @@ sh->hash_next->hash_pprev = sh->hash_pprev; *sh->hash_pprev = sh->hash_next; sh->hash_pprev = NULL; - raid_conf->nr_hashed_stripes--; + conf->nr_hashed_stripes--; } } -static inline void insert_hash(struct raid5_data *raid_conf, struct stripe_head *sh) +static inline void insert_hash(raid5_conf_t *conf, struct stripe_head *sh) { - struct stripe_head **shp = &stripe_hash(raid_conf, sh->sector, sh->size); + struct stripe_head **shp = &stripe_hash(conf, sh->sector, sh->size); - PRINTK(("insert_hash(), stripe %lu, nr_hashed_stripes %d\n", sh->sector, raid_conf->nr_hashed_stripes)); + PRINTK(("insert_hash(), stripe %lu, nr_hashed_stripes %d\n", + sh->sector, conf->nr_hashed_stripes)); if ((sh->hash_next = *shp) != NULL) (*shp)->hash_pprev = &sh->hash_next; *shp = sh; sh->hash_pprev = shp; - raid_conf->nr_hashed_stripes++; + conf->nr_hashed_stripes++; } static struct buffer_head *get_free_buffer(struct stripe_head *sh, int b_size) @@ -145,13 +147,15 @@ struct buffer_head *bh; unsigned long flags; - save_flags(flags); - cli(); - if ((bh = sh->buffer_pool) == NULL) - return NULL; + md_spin_lock_irqsave(&sh->stripe_lock, flags); + bh = sh->buffer_pool; + if (!bh) + goto out_unlock; sh->buffer_pool = bh->b_next; bh->b_size = b_size; - restore_flags(flags); +out_unlock: + md_spin_unlock_irqrestore(&sh->stripe_lock, flags); + return bh; } @@ -160,12 +164,14 @@ struct buffer_head *bh; unsigned long flags; - save_flags(flags); - cli(); - if ((bh = sh->bh_pool) == NULL) - return NULL; + md_spin_lock_irqsave(&sh->stripe_lock, flags); + bh = sh->bh_pool; + if (!bh) + goto out_unlock; sh->bh_pool = bh->b_next; - restore_flags(flags); +out_unlock: + md_spin_unlock_irqrestore(&sh->stripe_lock, flags); + return bh; } @@ -173,54 +179,52 @@ { unsigned long flags; - save_flags(flags); - cli(); + md_spin_lock_irqsave(&sh->stripe_lock, flags); bh->b_next = sh->buffer_pool; sh->buffer_pool = bh; - restore_flags(flags); + md_spin_unlock_irqrestore(&sh->stripe_lock, flags); } static void put_free_bh(struct stripe_head *sh, struct buffer_head *bh) { unsigned long flags; - save_flags(flags); - cli(); + md_spin_lock_irqsave(&sh->stripe_lock, flags); bh->b_next = sh->bh_pool; sh->bh_pool = bh; - restore_flags(flags); + md_spin_unlock_irqrestore(&sh->stripe_lock, flags); } -static struct stripe_head *get_free_stripe(struct raid5_data *raid_conf) +static struct stripe_head *get_free_stripe(raid5_conf_t *conf) { struct stripe_head *sh; unsigned long flags; save_flags(flags); cli(); - if ((sh = raid_conf->free_sh_list) == NULL) { + if ((sh = conf->free_sh_list) == NULL) { restore_flags(flags); return NULL; } - raid_conf->free_sh_list = sh->free_next; - raid_conf->nr_free_sh--; - if (!raid_conf->nr_free_sh && raid_conf->free_sh_list) + conf->free_sh_list = sh->free_next; + conf->nr_free_sh--; + if (!conf->nr_free_sh && conf->free_sh_list) printk ("raid5: bug: free_sh_list != NULL, nr_free_sh == 0\n"); restore_flags(flags); - if (sh->hash_pprev || sh->nr_pending || sh->count) + if (sh->hash_pprev || md_atomic_read(&sh->nr_pending) || sh->count) printk("get_free_stripe(): bug\n"); return sh; } -static void put_free_stripe(struct raid5_data *raid_conf, struct stripe_head *sh) +static void put_free_stripe(raid5_conf_t *conf, struct stripe_head *sh) { unsigned long flags; save_flags(flags); cli(); - sh->free_next = raid_conf->free_sh_list; - raid_conf->free_sh_list = sh; - raid_conf->nr_free_sh++; + sh->free_next = conf->free_sh_list; + conf->free_sh_list = sh; + conf->nr_free_sh++; restore_flags(flags); } @@ -324,8 +328,8 @@ static void kfree_stripe(struct stripe_head *sh) { - struct raid5_data *raid_conf = sh->raid_conf; - int disks = raid_conf->raid_disks, j; + raid5_conf_t *conf = sh->raid_conf; + int disks = conf->raid_disks, j; PRINTK(("kfree_stripe called, stripe %lu\n", sh->sector)); if (sh->phase != PHASE_COMPLETE || stripe_locked(sh) || sh->count) { @@ -338,19 +342,19 @@ if (sh->bh_new[j] || sh->bh_copy[j]) printk("raid5: bug: sector %lu, new %p, copy %p\n", sh->sector, sh->bh_new[j], sh->bh_copy[j]); } - remove_hash(raid_conf, sh); - put_free_stripe(raid_conf, sh); + remove_hash(conf, sh); + put_free_stripe(conf, sh); } -static int shrink_stripe_cache(struct raid5_data *raid_conf, int nr) +static int shrink_stripe_cache(raid5_conf_t *conf, int nr) { struct stripe_head *sh; int i, count = 0; - PRINTK(("shrink_stripe_cache called, %d/%d, clock %d\n", nr, raid_conf->nr_hashed_stripes, raid_conf->clock)); + PRINTK(("shrink_stripe_cache called, %d/%d, clock %d\n", nr, conf->nr_hashed_stripes, conf->clock)); for (i = 0; i < NR_HASH; i++) { repeat: - sh = raid_conf->stripe_hashtbl[(i + raid_conf->clock) & HASH_MASK]; + sh = conf->stripe_hashtbl[(i + conf->clock) & HASH_MASK]; for (; sh; sh = sh->hash_next) { if (sh->phase != PHASE_COMPLETE) continue; @@ -360,30 +364,30 @@ continue; kfree_stripe(sh); if (++count == nr) { - PRINTK(("shrink completed, nr_hashed_stripes %d\n", raid_conf->nr_hashed_stripes)); - raid_conf->clock = (i + raid_conf->clock) & HASH_MASK; + PRINTK(("shrink completed, nr_hashed_stripes %d\n", conf->nr_hashed_stripes)); + conf->clock = (i + conf->clock) & HASH_MASK; return nr; } goto repeat; } } - PRINTK(("shrink completed, nr_hashed_stripes %d\n", raid_conf->nr_hashed_stripes)); + PRINTK(("shrink completed, nr_hashed_stripes %d\n", conf->nr_hashed_stripes)); return count; } -static struct stripe_head *find_stripe(struct raid5_data *raid_conf, unsigned long sector, int size) +static struct stripe_head *find_stripe(raid5_conf_t *conf, unsigned long sector, int size) { struct stripe_head *sh; - if (raid_conf->buffer_size != size) { - PRINTK(("switching size, %d --> %d\n", raid_conf->buffer_size, size)); - shrink_stripe_cache(raid_conf, raid_conf->max_nr_stripes); - raid_conf->buffer_size = size; + if (conf->buffer_size != size) { + PRINTK(("switching size, %d --> %d\n", conf->buffer_size, size)); + shrink_stripe_cache(conf, conf->max_nr_stripes); + conf->buffer_size = size; } PRINTK(("find_stripe, sector %lu\n", sector)); - for (sh = stripe_hash(raid_conf, sector, size); sh; sh = sh->hash_next) - if (sh->sector == sector && sh->raid_conf == raid_conf) { + for (sh = stripe_hash(conf, sector, size); sh; sh = sh->hash_next) + if (sh->sector == sector && sh->raid_conf == conf) { if (sh->size == size) { PRINTK(("found stripe %lu\n", sector)); return sh; @@ -397,7 +401,7 @@ return NULL; } -static int grow_stripes(struct raid5_data *raid_conf, int num, int priority) +static int grow_stripes(raid5_conf_t *conf, int num, int priority) { struct stripe_head *sh; @@ -405,62 +409,64 @@ if ((sh = kmalloc(sizeof(struct stripe_head), priority)) == NULL) return 1; memset(sh, 0, sizeof(*sh)); - if (grow_buffers(sh, 2 * raid_conf->raid_disks, PAGE_SIZE, priority)) { - shrink_buffers(sh, 2 * raid_conf->raid_disks); + sh->stripe_lock = MD_SPIN_LOCK_UNLOCKED; + + if (grow_buffers(sh, 2 * conf->raid_disks, PAGE_SIZE, priority)) { + shrink_buffers(sh, 2 * conf->raid_disks); kfree(sh); return 1; } - if (grow_bh(sh, raid_conf->raid_disks, priority)) { - shrink_buffers(sh, 2 * raid_conf->raid_disks); - shrink_bh(sh, raid_conf->raid_disks); + if (grow_bh(sh, conf->raid_disks, priority)) { + shrink_buffers(sh, 2 * conf->raid_disks); + shrink_bh(sh, conf->raid_disks); kfree(sh); return 1; } - put_free_stripe(raid_conf, sh); - raid_conf->nr_stripes++; + put_free_stripe(conf, sh); + conf->nr_stripes++; } return 0; } -static void shrink_stripes(struct raid5_data *raid_conf, int num) +static void shrink_stripes(raid5_conf_t *conf, int num) { struct stripe_head *sh; while (num--) { - sh = get_free_stripe(raid_conf); + sh = get_free_stripe(conf); if (!sh) break; - shrink_buffers(sh, raid_conf->raid_disks * 2); - shrink_bh(sh, raid_conf->raid_disks); + shrink_buffers(sh, conf->raid_disks * 2); + shrink_bh(sh, conf->raid_disks); kfree(sh); - raid_conf->nr_stripes--; + conf->nr_stripes--; } } -static struct stripe_head *kmalloc_stripe(struct raid5_data *raid_conf, unsigned long sector, int size) +static struct stripe_head *kmalloc_stripe(raid5_conf_t *conf, unsigned long sector, int size) { struct stripe_head *sh = NULL, *tmp; struct buffer_head *buffer_pool, *bh_pool; PRINTK(("kmalloc_stripe called\n")); - while ((sh = get_free_stripe(raid_conf)) == NULL) { - shrink_stripe_cache(raid_conf, raid_conf->max_nr_stripes / 8); - if ((sh = get_free_stripe(raid_conf)) != NULL) + while ((sh = get_free_stripe(conf)) == NULL) { + shrink_stripe_cache(conf, conf->max_nr_stripes / 8); + if ((sh = get_free_stripe(conf)) != NULL) break; - if (!raid_conf->nr_pending_stripes) + if (!conf->nr_pending_stripes) printk("raid5: bug: nr_free_sh == 0, nr_pending_stripes == 0\n"); - md_wakeup_thread(raid_conf->thread); + md_wakeup_thread(conf->thread); PRINTK(("waiting for some stripes to complete\n")); - sleep_on(&raid_conf->wait_for_stripe); + sleep_on(&conf->wait_for_stripe); } /* * The above might have slept, so perhaps another process * already created the stripe for us.. */ - if ((tmp = find_stripe(raid_conf, sector, size)) != NULL) { - put_free_stripe(raid_conf, sh); + if ((tmp = find_stripe(conf, sector, size)) != NULL) { + put_free_stripe(conf, sh); wait_on_stripe(tmp); return tmp; } @@ -472,25 +478,25 @@ sh->bh_pool = bh_pool; sh->phase = PHASE_COMPLETE; sh->cmd = STRIPE_NONE; - sh->raid_conf = raid_conf; + sh->raid_conf = conf; sh->sector = sector; sh->size = size; - raid_conf->nr_cached_stripes++; - insert_hash(raid_conf, sh); + conf->nr_cached_stripes++; + insert_hash(conf, sh); } else printk("raid5: bug: kmalloc_stripe() == NULL\n"); return sh; } -static struct stripe_head *get_stripe(struct raid5_data *raid_conf, unsigned long sector, int size) +static struct stripe_head *get_stripe(raid5_conf_t *conf, unsigned long sector, int size) { struct stripe_head *sh; PRINTK(("get_stripe, sector %lu\n", sector)); - sh = find_stripe(raid_conf, sector, size); + sh = find_stripe(conf, sector, size); if (sh) wait_on_stripe(sh); else - sh = kmalloc_stripe(raid_conf, sector, size); + sh = kmalloc_stripe(conf, sector, size); return sh; } @@ -523,7 +529,7 @@ bh->b_end_io(bh, uptodate); if (!uptodate) printk(KERN_ALERT "raid5: %s: unrecoverable I/O error for " - "block %lu\n", kdevname(bh->b_dev), bh->b_blocknr); + "block %lu\n", partition_name(bh->b_dev), bh->b_blocknr); } static inline void raid5_mark_buffer_uptodate (struct buffer_head *bh, int uptodate) @@ -537,36 +543,35 @@ static void raid5_end_request (struct buffer_head * bh, int uptodate) { struct stripe_head *sh = bh->b_dev_id; - struct raid5_data *raid_conf = sh->raid_conf; - int disks = raid_conf->raid_disks, i; + raid5_conf_t *conf = sh->raid_conf; + int disks = conf->raid_disks, i; unsigned long flags; PRINTK(("end_request %lu, nr_pending %d\n", sh->sector, sh->nr_pending)); - save_flags(flags); - cli(); + md_spin_lock_irqsave(&sh->stripe_lock, flags); raid5_mark_buffer_uptodate(bh, uptodate); - --sh->nr_pending; - if (!sh->nr_pending) { - md_wakeup_thread(raid_conf->thread); - atomic_inc(&raid_conf->nr_handle); + if (atomic_dec_and_test(&sh->nr_pending)) { + md_wakeup_thread(conf->thread); + atomic_inc(&conf->nr_handle); } - if (!uptodate) + if (!uptodate) { md_error(bh->b_dev, bh->b_rdev); - if (raid_conf->failed_disks) { + } + if (conf->failed_disks) { for (i = 0; i < disks; i++) { - if (raid_conf->disks[i].operational) + if (conf->disks[i].operational) continue; if (bh != sh->bh_old[i] && bh != sh->bh_req[i] && bh != sh->bh_copy[i]) continue; - if (bh->b_rdev != raid_conf->disks[i].dev) + if (bh->b_rdev != conf->disks[i].dev) continue; set_bit(STRIPE_ERROR, &sh->state); } } - restore_flags(flags); + md_spin_unlock_irqrestore(&sh->stripe_lock, flags); } -static int raid5_map (struct md_dev *mddev, kdev_t *rdev, +static int raid5_map (mddev_t *mddev, kdev_t dev, kdev_t *rdev, unsigned long *rsector, unsigned long size) { /* No complex mapping used: the core of the work is done in the @@ -577,11 +582,10 @@ static void raid5_build_block (struct stripe_head *sh, struct buffer_head *bh, int i) { - struct raid5_data *raid_conf = sh->raid_conf; - struct md_dev *mddev = raid_conf->mddev; - int minor = (int) (mddev - md_dev); + raid5_conf_t *conf = sh->raid_conf; + mddev_t *mddev = conf->mddev; char *b_data; - kdev_t dev = MKDEV(MD_MAJOR, minor); + kdev_t dev = mddev_to_kdev(mddev); int block = sh->sector / (sh->size >> 9); b_data = ((volatile struct buffer_head *) bh)->b_data; @@ -589,7 +593,7 @@ init_buffer(bh, dev, block, raid5_end_request, sh); ((volatile struct buffer_head *) bh)->b_data = b_data; - bh->b_rdev = raid_conf->disks[i].dev; + bh->b_rdev = conf->disks[i].dev; bh->b_rsector = sh->sector; bh->b_state = (1 << BH_Req); @@ -597,33 +601,62 @@ bh->b_list = BUF_LOCKED; } -static int raid5_error (struct md_dev *mddev, kdev_t dev) +static int raid5_error (mddev_t *mddev, kdev_t dev) { - struct raid5_data *raid_conf = (struct raid5_data *) mddev->private; - md_superblock_t *sb = mddev->sb; + raid5_conf_t *conf = (raid5_conf_t *) mddev->private; + mdp_super_t *sb = mddev->sb; struct disk_info *disk; int i; PRINTK(("raid5_error called\n")); - raid_conf->resync_parity = 0; - for (i = 0, disk = raid_conf->disks; i < raid_conf->raid_disks; i++, disk++) + conf->resync_parity = 0; + for (i = 0, disk = conf->disks; i < conf->raid_disks; i++, disk++) { if (disk->dev == dev && disk->operational) { disk->operational = 0; - sb->disks[disk->number].state |= (1 << MD_FAULTY_DEVICE); - sb->disks[disk->number].state &= ~(1 << MD_SYNC_DEVICE); - sb->disks[disk->number].state &= ~(1 << MD_ACTIVE_DEVICE); + mark_disk_faulty(sb->disks+disk->number); + mark_disk_nonsync(sb->disks+disk->number); + mark_disk_inactive(sb->disks+disk->number); sb->active_disks--; sb->working_disks--; sb->failed_disks++; mddev->sb_dirty = 1; - raid_conf->working_disks--; - raid_conf->failed_disks++; - md_wakeup_thread(raid_conf->thread); + conf->working_disks--; + conf->failed_disks++; + md_wakeup_thread(conf->thread); printk (KERN_ALERT - "RAID5: Disk failure on %s, disabling device." - "Operation continuing on %d devices\n", - kdevname (dev), raid_conf->working_disks); + "raid5: Disk failure on %s, disabling device." + " Operation continuing on %d devices\n", + partition_name (dev), conf->working_disks); + return -EIO; } + } + /* + * handle errors in spares (during reconstruction) + */ + if (conf->spare) { + disk = conf->spare; + if (disk->dev == dev) { + printk (KERN_ALERT + "raid5: Disk failure on spare %s\n", + partition_name (dev)); + if (!conf->spare->operational) { + MD_BUG(); + return -EIO; + } + disk->operational = 0; + disk->write_only = 0; + conf->spare = NULL; + mark_disk_faulty(sb->disks+disk->number); + mark_disk_nonsync(sb->disks+disk->number); + mark_disk_inactive(sb->disks+disk->number); + sb->spare_disks--; + sb->working_disks--; + sb->failed_disks++; + + return -EIO; + } + } + MD_BUG(); return 0; } @@ -634,12 +667,12 @@ static inline unsigned long raid5_compute_sector (int r_sector, unsigned int raid_disks, unsigned int data_disks, unsigned int * dd_idx, unsigned int * pd_idx, - struct raid5_data *raid_conf) + raid5_conf_t *conf) { unsigned int stripe; int chunk_number, chunk_offset; unsigned long new_sector; - int sectors_per_chunk = raid_conf->chunk_size >> 9; + int sectors_per_chunk = conf->chunk_size >> 9; /* First compute the information on this sector */ @@ -662,9 +695,9 @@ /* * Select the parity disk based on the user selected algorithm. */ - if (raid_conf->level == 4) + if (conf->level == 4) *pd_idx = data_disks; - else switch (raid_conf->algorithm) { + else switch (conf->algorithm) { case ALGORITHM_LEFT_ASYMMETRIC: *pd_idx = data_disks - stripe % raid_disks; if (*dd_idx >= *pd_idx) @@ -684,7 +717,7 @@ *dd_idx = (*pd_idx + 1 + *dd_idx) % raid_disks; break; default: - printk ("raid5: unsupported algorithm %d\n", raid_conf->algorithm); + printk ("raid5: unsupported algorithm %d\n", conf->algorithm); } /* @@ -705,16 +738,16 @@ static unsigned long compute_blocknr(struct stripe_head *sh, int i) { - struct raid5_data *raid_conf = sh->raid_conf; - int raid_disks = raid_conf->raid_disks, data_disks = raid_disks - 1; + raid5_conf_t *conf = sh->raid_conf; + int raid_disks = conf->raid_disks, data_disks = raid_disks - 1; unsigned long new_sector = sh->sector, check; - int sectors_per_chunk = raid_conf->chunk_size >> 9; + int sectors_per_chunk = conf->chunk_size >> 9; unsigned long stripe = new_sector / sectors_per_chunk; int chunk_offset = new_sector % sectors_per_chunk; int chunk_number, dummy1, dummy2, dd_idx = i; unsigned long r_sector, blocknr; - switch (raid_conf->algorithm) { + switch (conf->algorithm) { case ALGORITHM_LEFT_ASYMMETRIC: case ALGORITHM_RIGHT_ASYMMETRIC: if (i > sh->pd_idx) @@ -727,14 +760,14 @@ i -= (sh->pd_idx + 1); break; default: - printk ("raid5: unsupported algorithm %d\n", raid_conf->algorithm); + printk ("raid5: unsupported algorithm %d\n", conf->algorithm); } chunk_number = stripe * data_disks + i; r_sector = chunk_number * sectors_per_chunk + chunk_offset; blocknr = r_sector / (sh->size >> 9); - check = raid5_compute_sector (r_sector, raid_disks, data_disks, &dummy1, &dummy2, raid_conf); + check = raid5_compute_sector (r_sector, raid_disks, data_disks, &dummy1, &dummy2, conf); if (check != sh->sector || dummy1 != dd_idx || dummy2 != sh->pd_idx) { printk("compute_blocknr: map not correct\n"); return 0; @@ -742,36 +775,11 @@ return blocknr; } -#ifdef HAVE_ARCH_XORBLOCK -static void xor_block(struct buffer_head *dest, struct buffer_head *source) -{ - __xor_block((char *) dest->b_data, (char *) source->b_data, dest->b_size); -} -#else -static void xor_block(struct buffer_head *dest, struct buffer_head *source) -{ - long lines = dest->b_size / (sizeof (long)) / 8, i; - long *destp = (long *) dest->b_data, *sourcep = (long *) source->b_data; - - for (i = lines; i > 0; i--) { - *(destp + 0) ^= *(sourcep + 0); - *(destp + 1) ^= *(sourcep + 1); - *(destp + 2) ^= *(sourcep + 2); - *(destp + 3) ^= *(sourcep + 3); - *(destp + 4) ^= *(sourcep + 4); - *(destp + 5) ^= *(sourcep + 5); - *(destp + 6) ^= *(sourcep + 6); - *(destp + 7) ^= *(sourcep + 7); - destp += 8; - sourcep += 8; - } -} -#endif - static void compute_block(struct stripe_head *sh, int dd_idx) { - struct raid5_data *raid_conf = sh->raid_conf; - int i, disks = raid_conf->raid_disks; + raid5_conf_t *conf = sh->raid_conf; + int i, count, disks = conf->raid_disks; + struct buffer_head *bh_ptr[MAX_XOR_BLOCKS]; PRINTK(("compute_block, stripe %lu, idx %d\n", sh->sector, dd_idx)); @@ -780,69 +788,100 @@ raid5_build_block(sh, sh->bh_old[dd_idx], dd_idx); memset(sh->bh_old[dd_idx]->b_data, 0, sh->size); + bh_ptr[0] = sh->bh_old[dd_idx]; + count = 1; for (i = 0; i < disks; i++) { if (i == dd_idx) continue; if (sh->bh_old[i]) { - xor_block(sh->bh_old[dd_idx], sh->bh_old[i]); - continue; - } else + bh_ptr[count++] = sh->bh_old[i]; + } else { printk("compute_block() %d, stripe %lu, %d not present\n", dd_idx, sh->sector, i); + } + if (count == MAX_XOR_BLOCKS) { + xor_block(count, &bh_ptr[0]); + count = 1; + } + } + if(count != 1) { + xor_block(count, &bh_ptr[0]); } raid5_mark_buffer_uptodate(sh->bh_old[dd_idx], 1); } static void compute_parity(struct stripe_head *sh, int method) { - struct raid5_data *raid_conf = sh->raid_conf; - int i, pd_idx = sh->pd_idx, disks = raid_conf->raid_disks; + raid5_conf_t *conf = sh->raid_conf; + int i, pd_idx = sh->pd_idx, disks = conf->raid_disks, lowprio, count; + struct buffer_head *bh_ptr[MAX_XOR_BLOCKS]; PRINTK(("compute_parity, stripe %lu, method %d\n", sh->sector, method)); + lowprio = 1; for (i = 0; i < disks; i++) { if (i == pd_idx || !sh->bh_new[i]) continue; if (!sh->bh_copy[i]) sh->bh_copy[i] = raid5_kmalloc_buffer(sh, sh->size); raid5_build_block(sh, sh->bh_copy[i], i); + if (!buffer_lowprio(sh->bh_new[i])) + lowprio = 0; + else + mark_buffer_lowprio(sh->bh_copy[i]); mark_buffer_clean(sh->bh_new[i]); memcpy(sh->bh_copy[i]->b_data, sh->bh_new[i]->b_data, sh->size); } if (sh->bh_copy[pd_idx] == NULL) sh->bh_copy[pd_idx] = raid5_kmalloc_buffer(sh, sh->size); raid5_build_block(sh, sh->bh_copy[pd_idx], sh->pd_idx); + if (lowprio) + mark_buffer_lowprio(sh->bh_copy[pd_idx]); if (method == RECONSTRUCT_WRITE) { memset(sh->bh_copy[pd_idx]->b_data, 0, sh->size); + bh_ptr[0] = sh->bh_copy[pd_idx]; + count = 1; for (i = 0; i < disks; i++) { if (i == sh->pd_idx) continue; if (sh->bh_new[i]) { - xor_block(sh->bh_copy[pd_idx], sh->bh_copy[i]); - continue; + bh_ptr[count++] = sh->bh_copy[i]; + } else if (sh->bh_old[i]) { + bh_ptr[count++] = sh->bh_old[i]; } - if (sh->bh_old[i]) { - xor_block(sh->bh_copy[pd_idx], sh->bh_old[i]); - continue; + if (count == MAX_XOR_BLOCKS) { + xor_block(count, &bh_ptr[0]); + count = 1; } } + if (count != 1) { + xor_block(count, &bh_ptr[0]); + } } else if (method == READ_MODIFY_WRITE) { memcpy(sh->bh_copy[pd_idx]->b_data, sh->bh_old[pd_idx]->b_data, sh->size); + bh_ptr[0] = sh->bh_copy[pd_idx]; + count = 1; for (i = 0; i < disks; i++) { if (i == sh->pd_idx) continue; if (sh->bh_new[i] && sh->bh_old[i]) { - xor_block(sh->bh_copy[pd_idx], sh->bh_copy[i]); - xor_block(sh->bh_copy[pd_idx], sh->bh_old[i]); - continue; + bh_ptr[count++] = sh->bh_copy[i]; + bh_ptr[count++] = sh->bh_old[i]; + } + if (count >= (MAX_XOR_BLOCKS - 1)) { + xor_block(count, &bh_ptr[0]); + count = 1; } } + if (count != 1) { + xor_block(count, &bh_ptr[0]); + } } raid5_mark_buffer_uptodate(sh->bh_copy[pd_idx], 1); } static void add_stripe_bh (struct stripe_head *sh, struct buffer_head *bh, int dd_idx, int rw) { - struct raid5_data *raid_conf = sh->raid_conf; + raid5_conf_t *conf = sh->raid_conf; struct buffer_head *bh_req; if (sh->bh_new[dd_idx]) { @@ -860,19 +899,22 @@ if (sh->phase == PHASE_COMPLETE && sh->cmd == STRIPE_NONE) { sh->phase = PHASE_BEGIN; sh->cmd = (rw == READ) ? STRIPE_READ : STRIPE_WRITE; - raid_conf->nr_pending_stripes++; - atomic_inc(&raid_conf->nr_handle); + conf->nr_pending_stripes++; + atomic_inc(&conf->nr_handle); } sh->bh_new[dd_idx] = bh; sh->bh_req[dd_idx] = bh_req; sh->cmd_new[dd_idx] = rw; sh->new[dd_idx] = 1; + + if (buffer_lowprio(bh)) + mark_buffer_lowprio(bh_req); } static void complete_stripe(struct stripe_head *sh) { - struct raid5_data *raid_conf = sh->raid_conf; - int disks = raid_conf->raid_disks; + raid5_conf_t *conf = sh->raid_conf; + int disks = conf->raid_disks; int i, new = 0; PRINTK(("complete_stripe %lu\n", sh->sector)); @@ -909,6 +951,22 @@ } } + +static int is_stripe_lowprio(struct stripe_head *sh, int disks) +{ + int i, lowprio = 1; + + for (i = 0; i < disks; i++) { + if (sh->bh_new[i]) + if (!buffer_lowprio(sh->bh_new[i])) + lowprio = 0; + if (sh->bh_old[i]) + if (!buffer_lowprio(sh->bh_old[i])) + lowprio = 0; + } + return lowprio; +} + /* * handle_stripe() is our main logic routine. Note that: * @@ -919,28 +977,27 @@ * 2. We should be careful to set sh->nr_pending whenever we sleep, * to prevent re-entry of handle_stripe() for the same sh. * - * 3. raid_conf->failed_disks and disk->operational can be changed + * 3. conf->failed_disks and disk->operational can be changed * from an interrupt. This complicates things a bit, but it allows * us to stop issuing requests for a failed drive as soon as possible. */ static void handle_stripe(struct stripe_head *sh) { - struct raid5_data *raid_conf = sh->raid_conf; - struct md_dev *mddev = raid_conf->mddev; - int minor = (int) (mddev - md_dev); + raid5_conf_t *conf = sh->raid_conf; + mddev_t *mddev = conf->mddev; struct buffer_head *bh; - int disks = raid_conf->raid_disks; - int i, nr = 0, nr_read = 0, nr_write = 0; + int disks = conf->raid_disks; + int i, nr = 0, nr_read = 0, nr_write = 0, lowprio; int nr_cache = 0, nr_cache_other = 0, nr_cache_overwrite = 0, parity = 0; int nr_failed_other = 0, nr_failed_overwrite = 0, parity_failed = 0; int reading = 0, nr_writing = 0; int method1 = INT_MAX, method2 = INT_MAX; int block; unsigned long flags; - int operational[MD_SB_DISKS], failed_disks = raid_conf->failed_disks; + int operational[MD_SB_DISKS], failed_disks = conf->failed_disks; PRINTK(("handle_stripe(), stripe %lu\n", sh->sector)); - if (sh->nr_pending) { + if (md_atomic_read(&sh->nr_pending)) { printk("handle_stripe(), stripe %lu, io still pending\n", sh->sector); return; } @@ -949,9 +1006,9 @@ return; } - atomic_dec(&raid_conf->nr_handle); + atomic_dec(&conf->nr_handle); - if (test_and_clear_bit(STRIPE_ERROR, &sh->state)) { + if (md_test_and_clear_bit(STRIPE_ERROR, &sh->state)) { printk("raid5: restarting stripe %lu\n", sh->sector); sh->phase = PHASE_BEGIN; } @@ -969,11 +1026,11 @@ save_flags(flags); cli(); for (i = 0; i < disks; i++) { - operational[i] = raid_conf->disks[i].operational; - if (i == sh->pd_idx && raid_conf->resync_parity) + operational[i] = conf->disks[i].operational; + if (i == sh->pd_idx && conf->resync_parity) operational[i] = 0; } - failed_disks = raid_conf->failed_disks; + failed_disks = conf->failed_disks; restore_flags(flags); if (failed_disks > 1) { @@ -1017,7 +1074,7 @@ } if (nr_write && nr_read) - printk("raid5: bug, nr_write == %d, nr_read == %d, sh->cmd == %d\n", nr_write, nr_read, sh->cmd); + printk("raid5: bug, nr_write ==`%d, nr_read == %d, sh->cmd == %d\n", nr_write, nr_read, sh->cmd); if (nr_write) { /* @@ -1030,7 +1087,7 @@ if (sh->bh_new[i]) continue; block = (int) compute_blocknr(sh, i); - bh = find_buffer(MKDEV(MD_MAJOR, minor), block, sh->size); + bh = find_buffer(mddev_to_kdev(mddev), block, sh->size); if (bh && bh->b_count == 0 && buffer_dirty(bh) && !buffer_locked(bh)) { PRINTK(("Whee.. sector %lu, index %d (%d) found in the buffer cache!\n", sh->sector, i, block)); add_stripe_bh(sh, bh, i, WRITE); @@ -1064,21 +1121,22 @@ if (!method1 || !method2) { lock_stripe(sh); - sh->nr_pending++; + lowprio = is_stripe_lowprio(sh, disks); + atomic_inc(&sh->nr_pending); sh->phase = PHASE_WRITE; compute_parity(sh, method1 <= method2 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE); for (i = 0; i < disks; i++) { - if (!operational[i] && !raid_conf->spare && !raid_conf->resync_parity) + if (!operational[i] && !conf->spare && !conf->resync_parity) continue; if (i == sh->pd_idx || sh->bh_new[i]) nr_writing++; } - sh->nr_pending = nr_writing; - PRINTK(("handle_stripe() %lu, writing back %d\n", sh->sector, sh->nr_pending)); + md_atomic_set(&sh->nr_pending, nr_writing); + PRINTK(("handle_stripe() %lu, writing back %d\n", sh->sector, md_atomic_read(&sh->nr_pending))); for (i = 0; i < disks; i++) { - if (!operational[i] && !raid_conf->spare && !raid_conf->resync_parity) + if (!operational[i] && !conf->spare && !conf->resync_parity) continue; bh = sh->bh_copy[i]; if (i != sh->pd_idx && ((bh == NULL) ^ (sh->bh_new[i] == NULL))) @@ -1089,18 +1147,30 @@ bh->b_state |= (1<b_state); - if (!operational[i] && !raid_conf->resync_parity) { - bh->b_rdev = raid_conf->spare->dev; - make_request(MAJOR(raid_conf->spare->dev), WRITE, bh); - } else - make_request(MAJOR(raid_conf->disks[i].dev), WRITE, bh); + if (!operational[i] && !conf->resync_parity) { + bh->b_rdev = conf->spare->dev; + make_request(MAJOR(conf->spare->dev), WRITE, bh); + } else { +#if 0 + make_request(MAJOR(conf->disks[i].dev), WRITE, bh); +#else + if (!lowprio || (i==sh->pd_idx)) + make_request(MAJOR(conf->disks[i].dev), WRITE, bh); + else { + mark_buffer_clean(bh); + raid5_end_request(bh,1); + sh->new[i] = 0; + } +#endif + } } } return; } lock_stripe(sh); - sh->nr_pending++; + lowprio = is_stripe_lowprio(sh, disks); + atomic_inc(&sh->nr_pending); if (method1 < method2) { sh->write_method = RECONSTRUCT_WRITE; for (i = 0; i < disks; i++) { @@ -1110,6 +1180,8 @@ continue; sh->bh_old[i] = raid5_kmalloc_buffer(sh, sh->size); raid5_build_block(sh, sh->bh_old[i], i); + if (lowprio) + mark_buffer_lowprio(sh->bh_old[i]); reading++; } } else { @@ -1121,19 +1193,21 @@ continue; sh->bh_old[i] = raid5_kmalloc_buffer(sh, sh->size); raid5_build_block(sh, sh->bh_old[i], i); + if (lowprio) + mark_buffer_lowprio(sh->bh_old[i]); reading++; } } sh->phase = PHASE_READ_OLD; - sh->nr_pending = reading; - PRINTK(("handle_stripe() %lu, reading %d old buffers\n", sh->sector, sh->nr_pending)); + md_atomic_set(&sh->nr_pending, reading); + PRINTK(("handle_stripe() %lu, reading %d old buffers\n", sh->sector, md_atomic_read(&sh->nr_pending))); for (i = 0; i < disks; i++) { if (!sh->bh_old[i]) continue; if (buffer_uptodate(sh->bh_old[i])) continue; clear_bit(BH_Lock, &sh->bh_old[i]->b_state); - make_request(MAJOR(raid_conf->disks[i].dev), READ, sh->bh_old[i]); + make_request(MAJOR(conf->disks[i].dev), READ, sh->bh_old[i]); } } else { /* @@ -1141,7 +1215,8 @@ */ method1 = nr_read - nr_cache_overwrite; lock_stripe(sh); - sh->nr_pending++; + lowprio = is_stripe_lowprio(sh,disks); + atomic_inc(&sh->nr_pending); PRINTK(("handle_stripe(), sector %lu, nr_read %d, nr_cache %d, method1 %d\n", sh->sector, nr_read, nr_cache, method1)); if (!method1 || (method1 == 1 && nr_cache == disks - 1)) { @@ -1149,18 +1224,22 @@ for (i = 0; i < disks; i++) { if (!sh->bh_new[i]) continue; - if (!sh->bh_old[i]) + if (!sh->bh_old[i]) { compute_block(sh, i); + if (lowprio) + mark_buffer_lowprio + (sh->bh_old[i]); + } memcpy(sh->bh_new[i]->b_data, sh->bh_old[i]->b_data, sh->size); } - sh->nr_pending--; + atomic_dec(&sh->nr_pending); complete_stripe(sh); return; } if (nr_failed_overwrite) { sh->phase = PHASE_READ_OLD; - sh->nr_pending = (disks - 1) - nr_cache; - PRINTK(("handle_stripe() %lu, phase READ_OLD, pending %d\n", sh->sector, sh->nr_pending)); + md_atomic_set(&sh->nr_pending, (disks - 1) - nr_cache); + PRINTK(("handle_stripe() %lu, phase READ_OLD, pending %d\n", sh->sector, md_atomic_read(&sh->nr_pending))); for (i = 0; i < disks; i++) { if (sh->bh_old[i]) continue; @@ -1168,13 +1247,16 @@ continue; sh->bh_old[i] = raid5_kmalloc_buffer(sh, sh->size); raid5_build_block(sh, sh->bh_old[i], i); + if (lowprio) + mark_buffer_lowprio(sh->bh_old[i]); clear_bit(BH_Lock, &sh->bh_old[i]->b_state); - make_request(MAJOR(raid_conf->disks[i].dev), READ, sh->bh_old[i]); + make_request(MAJOR(conf->disks[i].dev), READ, sh->bh_old[i]); } } else { sh->phase = PHASE_READ; - sh->nr_pending = nr_read - nr_cache_overwrite; - PRINTK(("handle_stripe() %lu, phase READ, pending %d\n", sh->sector, sh->nr_pending)); + md_atomic_set(&sh->nr_pending, + nr_read - nr_cache_overwrite); + PRINTK(("handle_stripe() %lu, phase READ, pending %d\n", sh->sector, md_atomic_read(&sh->nr_pending))); for (i = 0; i < disks; i++) { if (!sh->bh_new[i]) continue; @@ -1182,16 +1264,16 @@ memcpy(sh->bh_new[i]->b_data, sh->bh_old[i]->b_data, sh->size); continue; } - make_request(MAJOR(raid_conf->disks[i].dev), READ, sh->bh_req[i]); + make_request(MAJOR(conf->disks[i].dev), READ, sh->bh_req[i]); } } } } -static int raid5_make_request (struct md_dev *mddev, int rw, struct buffer_head * bh) +static int raid5_make_request (mddev_t *mddev, int rw, struct buffer_head * bh) { - struct raid5_data *raid_conf = (struct raid5_data *) mddev->private; - const unsigned int raid_disks = raid_conf->raid_disks; + raid5_conf_t *conf = (raid5_conf_t *) mddev->private; + const unsigned int raid_disks = conf->raid_disks; const unsigned int data_disks = raid_disks - 1; unsigned int dd_idx, pd_idx; unsigned long new_sector; @@ -1202,15 +1284,15 @@ if (rw == WRITEA) rw = WRITE; new_sector = raid5_compute_sector(bh->b_rsector, raid_disks, data_disks, - &dd_idx, &pd_idx, raid_conf); + &dd_idx, &pd_idx, conf); PRINTK(("raid5_make_request, sector %lu\n", new_sector)); repeat: - sh = get_stripe(raid_conf, new_sector, bh->b_size); + sh = get_stripe(conf, new_sector, bh->b_size); if ((rw == READ && sh->cmd == STRIPE_WRITE) || (rw == WRITE && sh->cmd == STRIPE_READ)) { PRINTK(("raid5: lock contention, rw == %d, sh->cmd == %d\n", rw, sh->cmd)); lock_stripe(sh); - if (!sh->nr_pending) + if (!md_atomic_read(&sh->nr_pending)) handle_stripe(sh); goto repeat; } @@ -1221,24 +1303,24 @@ printk("raid5: bug: stripe->bh_new[%d], sector %lu exists\n", dd_idx, sh->sector); printk("raid5: bh %p, bh_new %p\n", bh, sh->bh_new[dd_idx]); lock_stripe(sh); - md_wakeup_thread(raid_conf->thread); + md_wakeup_thread(conf->thread); wait_on_stripe(sh); goto repeat; } add_stripe_bh(sh, bh, dd_idx, rw); - md_wakeup_thread(raid_conf->thread); + md_wakeup_thread(conf->thread); return 0; } static void unplug_devices(struct stripe_head *sh) { #if 0 - struct raid5_data *raid_conf = sh->raid_conf; + raid5_conf_t *conf = sh->raid_conf; int i; - for (i = 0; i < raid_conf->raid_disks; i++) - unplug_device(blk_dev + MAJOR(raid_conf->disks[i].dev)); + for (i = 0; i < conf->raid_disks; i++) + unplug_device(blk_dev + MAJOR(conf->disks[i].dev)); #endif } @@ -1252,8 +1334,8 @@ static void raid5d (void *data) { struct stripe_head *sh; - struct raid5_data *raid_conf = data; - struct md_dev *mddev = raid_conf->mddev; + raid5_conf_t *conf = data; + mddev_t *mddev = conf->mddev; int i, handled = 0, unplug = 0; unsigned long flags; @@ -1261,47 +1343,47 @@ if (mddev->sb_dirty) { mddev->sb_dirty = 0; - md_update_sb((int) (mddev - md_dev)); + md_update_sb(mddev); } for (i = 0; i < NR_HASH; i++) { repeat: - sh = raid_conf->stripe_hashtbl[i]; + sh = conf->stripe_hashtbl[i]; for (; sh; sh = sh->hash_next) { - if (sh->raid_conf != raid_conf) + if (sh->raid_conf != conf) continue; if (sh->phase == PHASE_COMPLETE) continue; - if (sh->nr_pending) + if (md_atomic_read(&sh->nr_pending)) continue; - if (sh->sector == raid_conf->next_sector) { - raid_conf->sector_count += (sh->size >> 9); - if (raid_conf->sector_count >= 128) + if (sh->sector == conf->next_sector) { + conf->sector_count += (sh->size >> 9); + if (conf->sector_count >= 128) unplug = 1; } else unplug = 1; if (unplug) { - PRINTK(("unplugging devices, sector == %lu, count == %d\n", sh->sector, raid_conf->sector_count)); + PRINTK(("unplugging devices, sector == %lu, count == %d\n", sh->sector, conf->sector_count)); unplug_devices(sh); unplug = 0; - raid_conf->sector_count = 0; + conf->sector_count = 0; } - raid_conf->next_sector = sh->sector + (sh->size >> 9); + conf->next_sector = sh->sector + (sh->size >> 9); handled++; handle_stripe(sh); goto repeat; } } - if (raid_conf) { - PRINTK(("%d stripes handled, nr_handle %d\n", handled, atomic_read(&raid_conf->nr_handle))); + if (conf) { + PRINTK(("%d stripes handled, nr_handle %d\n", handled, md_atomic_read(&conf->nr_handle))); save_flags(flags); cli(); - if (!atomic_read(&raid_conf->nr_handle)) - clear_bit(THREAD_WAKEUP, &raid_conf->thread->flags); + if (!md_atomic_read(&conf->nr_handle)) + clear_bit(THREAD_WAKEUP, &conf->thread->flags); + restore_flags(flags); } PRINTK(("--- raid5d inactive\n")); } -#if SUPPORT_RECONSTRUCTION /* * Private kernel thread for parity reconstruction after an unclean * shutdown. Reconstruction on spare drives in case of a failed drive @@ -1309,44 +1391,64 @@ */ static void raid5syncd (void *data) { - struct raid5_data *raid_conf = data; - struct md_dev *mddev = raid_conf->mddev; + raid5_conf_t *conf = data; + mddev_t *mddev = conf->mddev; - if (!raid_conf->resync_parity) + if (!conf->resync_parity) + return; + if (conf->resync_parity == 2) + return; + down(&mddev->recovery_sem); + if (md_do_sync(mddev,NULL)) { + up(&mddev->recovery_sem); + printk("raid5: resync aborted!\n"); return; - md_do_sync(mddev); - raid_conf->resync_parity = 0; + } + conf->resync_parity = 0; + up(&mddev->recovery_sem); + printk("raid5: resync finished.\n"); } -#endif /* SUPPORT_RECONSTRUCTION */ -static int __check_consistency (struct md_dev *mddev, int row) +static int __check_consistency (mddev_t *mddev, int row) { - struct raid5_data *raid_conf = mddev->private; + raid5_conf_t *conf = mddev->private; kdev_t dev; struct buffer_head *bh[MD_SB_DISKS], tmp; - int i, rc = 0, nr = 0; + int i, rc = 0, nr = 0, count; + struct buffer_head *bh_ptr[MAX_XOR_BLOCKS]; - if (raid_conf->working_disks != raid_conf->raid_disks) + if (conf->working_disks != conf->raid_disks) return 0; tmp.b_size = 4096; if ((tmp.b_data = (char *) get_free_page(GFP_KERNEL)) == NULL) return 0; + md_clear_page((unsigned long)tmp.b_data); memset(bh, 0, MD_SB_DISKS * sizeof(struct buffer_head *)); - for (i = 0; i < raid_conf->raid_disks; i++) { - dev = raid_conf->disks[i].dev; + for (i = 0; i < conf->raid_disks; i++) { + dev = conf->disks[i].dev; set_blocksize(dev, 4096); if ((bh[i] = bread(dev, row / 4, 4096)) == NULL) break; nr++; } - if (nr == raid_conf->raid_disks) { - for (i = 1; i < nr; i++) - xor_block(&tmp, bh[i]); + if (nr == conf->raid_disks) { + bh_ptr[0] = &tmp; + count = 1; + for (i = 1; i < nr; i++) { + bh_ptr[count++] = bh[i]; + if (count == MAX_XOR_BLOCKS) { + xor_block(count, &bh_ptr[0]); + count = 1; + } + } + if (count != 1) { + xor_block(count, &bh_ptr[0]); + } if (memcmp(tmp.b_data, bh[0]->b_data, 4096)) rc = 1; } - for (i = 0; i < raid_conf->raid_disks; i++) { - dev = raid_conf->disks[i].dev; + for (i = 0; i < conf->raid_disks; i++) { + dev = conf->disks[i].dev; if (bh[i]) { bforget(bh[i]); bh[i] = NULL; @@ -1358,285 +1460,607 @@ return rc; } -static int check_consistency (struct md_dev *mddev) +static int check_consistency (mddev_t *mddev) { - int size = mddev->sb->size; - int row; + if (__check_consistency(mddev, 0)) +/* + * We are not checking this currently, as it's legitimate to have + * an inconsistent array, at creation time. + */ + return 0; - for (row = 0; row < size; row += size / 8) - if (__check_consistency(mddev, row)) - return 1; return 0; } -static int raid5_run (int minor, struct md_dev *mddev) +static int raid5_run (mddev_t *mddev) { - struct raid5_data *raid_conf; + raid5_conf_t *conf; int i, j, raid_disk, memory; - md_superblock_t *sb = mddev->sb; - md_descriptor_t *descriptor; - struct real_dev *realdev; + mdp_super_t *sb = mddev->sb; + mdp_disk_t *desc; + mdk_rdev_t *rdev; + struct disk_info *disk; + struct md_list_head *tmp; + int start_recovery = 0; MOD_INC_USE_COUNT; if (sb->level != 5 && sb->level != 4) { - printk("raid5: %s: raid level not set to 4/5 (%d)\n", kdevname(MKDEV(MD_MAJOR, minor)), sb->level); + printk("raid5: md%d: raid level not set to 4/5 (%d)\n", mdidx(mddev), sb->level); MOD_DEC_USE_COUNT; return -EIO; } - mddev->private = kmalloc (sizeof (struct raid5_data), GFP_KERNEL); - if ((raid_conf = mddev->private) == NULL) + mddev->private = kmalloc (sizeof (raid5_conf_t), GFP_KERNEL); + if ((conf = mddev->private) == NULL) goto abort; - memset (raid_conf, 0, sizeof (*raid_conf)); - raid_conf->mddev = mddev; + memset (conf, 0, sizeof (*conf)); + conf->mddev = mddev; - if ((raid_conf->stripe_hashtbl = (struct stripe_head **) __get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER)) == NULL) + if ((conf->stripe_hashtbl = (struct stripe_head **) md__get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER)) == NULL) goto abort; - memset(raid_conf->stripe_hashtbl, 0, HASH_PAGES * PAGE_SIZE); + memset(conf->stripe_hashtbl, 0, HASH_PAGES * PAGE_SIZE); - init_waitqueue(&raid_conf->wait_for_stripe); - PRINTK(("raid5_run(%d) called.\n", minor)); - - for (i = 0; i < mddev->nb_dev; i++) { - realdev = &mddev->devices[i]; - if (!realdev->sb) { - printk(KERN_ERR "raid5: disabled device %s (couldn't access raid superblock)\n", kdevname(realdev->dev)); - continue; - } + init_waitqueue(&conf->wait_for_stripe); + PRINTK(("raid5_run(md%d) called.\n", mdidx(mddev))); + ITERATE_RDEV(mddev,rdev,tmp) { /* * This is important -- we are using the descriptor on * the disk only to get a pointer to the descriptor on * the main superblock, which might be more recent. */ - descriptor = &sb->disks[realdev->sb->descriptor.number]; - if (descriptor->state & (1 << MD_FAULTY_DEVICE)) { - printk(KERN_ERR "raid5: disabled device %s (errors detected)\n", kdevname(realdev->dev)); + desc = sb->disks + rdev->desc_nr; + raid_disk = desc->raid_disk; + disk = conf->disks + raid_disk; + + if (disk_faulty(desc)) { + printk(KERN_ERR "raid5: disabled device %s (errors detected)\n", partition_name(rdev->dev)); + if (!rdev->faulty) { + MD_BUG(); + goto abort; + } + disk->number = desc->number; + disk->raid_disk = raid_disk; + disk->dev = rdev->dev; + + disk->operational = 0; + disk->write_only = 0; + disk->spare = 0; + disk->used_slot = 1; continue; } - if (descriptor->state & (1 << MD_ACTIVE_DEVICE)) { - if (!(descriptor->state & (1 << MD_SYNC_DEVICE))) { - printk(KERN_ERR "raid5: disabled device %s (not in sync)\n", kdevname(realdev->dev)); - continue; + if (disk_active(desc)) { + if (!disk_sync(desc)) { + printk(KERN_ERR "raid5: disabled device %s (not in sync)\n", partition_name(rdev->dev)); + MD_BUG(); + goto abort; } - raid_disk = descriptor->raid_disk; - if (descriptor->number > sb->nr_disks || raid_disk > sb->raid_disks) { - printk(KERN_ERR "raid5: disabled device %s (inconsistent descriptor)\n", kdevname(realdev->dev)); + if (raid_disk > sb->raid_disks) { + printk(KERN_ERR "raid5: disabled device %s (inconsistent descriptor)\n", partition_name(rdev->dev)); continue; } - if (raid_conf->disks[raid_disk].operational) { - printk(KERN_ERR "raid5: disabled device %s (device %d already operational)\n", kdevname(realdev->dev), raid_disk); + if (disk->operational) { + printk(KERN_ERR "raid5: disabled device %s (device %d already operational)\n", partition_name(rdev->dev), raid_disk); continue; } - printk(KERN_INFO "raid5: device %s operational as raid disk %d\n", kdevname(realdev->dev), raid_disk); + printk(KERN_INFO "raid5: device %s operational as raid disk %d\n", partition_name(rdev->dev), raid_disk); - raid_conf->disks[raid_disk].number = descriptor->number; - raid_conf->disks[raid_disk].raid_disk = raid_disk; - raid_conf->disks[raid_disk].dev = mddev->devices[i].dev; - raid_conf->disks[raid_disk].operational = 1; + disk->number = desc->number; + disk->raid_disk = raid_disk; + disk->dev = rdev->dev; + disk->operational = 1; + disk->used_slot = 1; - raid_conf->working_disks++; + conf->working_disks++; } else { /* * Must be a spare disk .. */ - printk(KERN_INFO "raid5: spare disk %s\n", kdevname(realdev->dev)); - raid_disk = descriptor->raid_disk; - raid_conf->disks[raid_disk].number = descriptor->number; - raid_conf->disks[raid_disk].raid_disk = raid_disk; - raid_conf->disks[raid_disk].dev = mddev->devices [i].dev; - - raid_conf->disks[raid_disk].operational = 0; - raid_conf->disks[raid_disk].write_only = 0; - raid_conf->disks[raid_disk].spare = 1; - } - } - raid_conf->raid_disks = sb->raid_disks; - raid_conf->failed_disks = raid_conf->raid_disks - raid_conf->working_disks; - raid_conf->mddev = mddev; - raid_conf->chunk_size = sb->chunk_size; - raid_conf->level = sb->level; - raid_conf->algorithm = sb->parity_algorithm; - raid_conf->max_nr_stripes = NR_STRIPES; + printk(KERN_INFO "raid5: spare disk %s\n", partition_name(rdev->dev)); + disk->number = desc->number; + disk->raid_disk = raid_disk; + disk->dev = rdev->dev; - if (raid_conf->working_disks != sb->raid_disks && sb->state != (1 << MD_SB_CLEAN)) { - printk(KERN_ALERT "raid5: raid set %s not clean and not all disks are operational -- run ckraid\n", kdevname(MKDEV(MD_MAJOR, minor))); - goto abort; + disk->operational = 0; + disk->write_only = 0; + disk->spare = 1; + disk->used_slot = 1; + } } - if (!raid_conf->chunk_size || raid_conf->chunk_size % 4) { - printk(KERN_ERR "raid5: invalid chunk size %d for %s\n", raid_conf->chunk_size, kdevname(MKDEV(MD_MAJOR, minor))); + + for (i = 0; i < MD_SB_DISKS; i++) { + desc = sb->disks + i; + raid_disk = desc->raid_disk; + disk = conf->disks + raid_disk; + + if (disk_faulty(desc) && (raid_disk < sb->raid_disks) && + !conf->disks[raid_disk].used_slot) { + + disk->number = desc->number; + disk->raid_disk = raid_disk; + disk->dev = MKDEV(0,0); + + disk->operational = 0; + disk->write_only = 0; + disk->spare = 0; + disk->used_slot = 1; + } + } + + conf->raid_disks = sb->raid_disks; + /* + * 0 for a fully functional array, 1 for a degraded array. + */ + conf->failed_disks = conf->raid_disks - conf->working_disks; + conf->mddev = mddev; + conf->chunk_size = sb->chunk_size; + conf->level = sb->level; + conf->algorithm = sb->layout; + conf->max_nr_stripes = NR_STRIPES; + +#if 0 + for (i = 0; i < conf->raid_disks; i++) { + if (!conf->disks[i].used_slot) { + MD_BUG(); + goto abort; + } + } +#endif + if (!conf->chunk_size || conf->chunk_size % 4) { + printk(KERN_ERR "raid5: invalid chunk size %d for md%d\n", conf->chunk_size, mdidx(mddev)); goto abort; } - if (raid_conf->algorithm > ALGORITHM_RIGHT_SYMMETRIC) { - printk(KERN_ERR "raid5: unsupported parity algorithm %d for %s\n", raid_conf->algorithm, kdevname(MKDEV(MD_MAJOR, minor))); + if (conf->algorithm > ALGORITHM_RIGHT_SYMMETRIC) { + printk(KERN_ERR "raid5: unsupported parity algorithm %d for md%d\n", conf->algorithm, mdidx(mddev)); goto abort; } - if (raid_conf->failed_disks > 1) { - printk(KERN_ERR "raid5: not enough operational devices for %s (%d/%d failed)\n", kdevname(MKDEV(MD_MAJOR, minor)), raid_conf->failed_disks, raid_conf->raid_disks); + if (conf->failed_disks > 1) { + printk(KERN_ERR "raid5: not enough operational devices for md%d (%d/%d failed)\n", mdidx(mddev), conf->failed_disks, conf->raid_disks); goto abort; } - if ((sb->state & (1 << MD_SB_CLEAN)) && check_consistency(mddev)) { - printk(KERN_ERR "raid5: detected raid-5 xor inconsistenty -- run ckraid\n"); - sb->state |= 1 << MD_SB_ERRORS; - goto abort; + if (conf->working_disks != sb->raid_disks) { + printk(KERN_ALERT "raid5: md%d, not all disks are operational -- trying to recover array\n", mdidx(mddev)); + start_recovery = 1; } - if ((raid_conf->thread = md_register_thread(raid5d, raid_conf)) == NULL) { - printk(KERN_ERR "raid5: couldn't allocate thread for %s\n", kdevname(MKDEV(MD_MAJOR, minor))); - goto abort; + if (!start_recovery && (sb->state & (1 << MD_SB_CLEAN)) && + check_consistency(mddev)) { + printk(KERN_ERR "raid5: detected raid-5 superblock xor inconsistency -- running resync\n"); + sb->state &= ~(1 << MD_SB_CLEAN); } -#if SUPPORT_RECONSTRUCTION - if ((raid_conf->resync_thread = md_register_thread(raid5syncd, raid_conf)) == NULL) { - printk(KERN_ERR "raid5: couldn't allocate thread for %s\n", kdevname(MKDEV(MD_MAJOR, minor))); - goto abort; + { + const char * name = "raid5d"; + + conf->thread = md_register_thread(raid5d, conf, name); + if (!conf->thread) { + printk(KERN_ERR "raid5: couldn't allocate thread for md%d\n", mdidx(mddev)); + goto abort; + } } -#endif /* SUPPORT_RECONSTRUCTION */ - memory = raid_conf->max_nr_stripes * (sizeof(struct stripe_head) + - raid_conf->raid_disks * (sizeof(struct buffer_head) + + memory = conf->max_nr_stripes * (sizeof(struct stripe_head) + + conf->raid_disks * (sizeof(struct buffer_head) + 2 * (sizeof(struct buffer_head) + PAGE_SIZE))) / 1024; - if (grow_stripes(raid_conf, raid_conf->max_nr_stripes, GFP_KERNEL)) { + if (grow_stripes(conf, conf->max_nr_stripes, GFP_KERNEL)) { printk(KERN_ERR "raid5: couldn't allocate %dkB for buffers\n", memory); - shrink_stripes(raid_conf, raid_conf->max_nr_stripes); + shrink_stripes(conf, conf->max_nr_stripes); goto abort; } else - printk(KERN_INFO "raid5: allocated %dkB for %s\n", memory, kdevname(MKDEV(MD_MAJOR, minor))); + printk(KERN_INFO "raid5: allocated %dkB for md%d\n", memory, mdidx(mddev)); /* * Regenerate the "device is in sync with the raid set" bit for * each device. */ - for (i = 0; i < sb->nr_disks ; i++) { - sb->disks[i].state &= ~(1 << MD_SYNC_DEVICE); + for (i = 0; i < MD_SB_DISKS ; i++) { + mark_disk_nonsync(sb->disks + i); for (j = 0; j < sb->raid_disks; j++) { - if (!raid_conf->disks[j].operational) + if (!conf->disks[j].operational) continue; - if (sb->disks[i].number == raid_conf->disks[j].number) - sb->disks[i].state |= 1 << MD_SYNC_DEVICE; + if (sb->disks[i].number == conf->disks[j].number) + mark_disk_sync(sb->disks + i); } } - sb->active_disks = raid_conf->working_disks; + sb->active_disks = conf->working_disks; if (sb->active_disks == sb->raid_disks) - printk("raid5: raid level %d set %s active with %d out of %d devices, algorithm %d\n", raid_conf->level, kdevname(MKDEV(MD_MAJOR, minor)), sb->active_disks, sb->raid_disks, raid_conf->algorithm); + printk("raid5: raid level %d set md%d active with %d out of %d devices, algorithm %d\n", conf->level, mdidx(mddev), sb->active_disks, sb->raid_disks, conf->algorithm); else - printk(KERN_ALERT "raid5: raid level %d set %s active with %d out of %d devices, algorithm %d\n", raid_conf->level, kdevname(MKDEV(MD_MAJOR, minor)), sb->active_disks, sb->raid_disks, raid_conf->algorithm); + printk(KERN_ALERT "raid5: raid level %d set md%d active with %d out of %d devices, algorithm %d\n", conf->level, mdidx(mddev), sb->active_disks, sb->raid_disks, conf->algorithm); + + if (!start_recovery && ((sb->state & (1 << MD_SB_CLEAN))==0)) { + const char * name = "raid5syncd"; + + conf->resync_thread = md_register_thread(raid5syncd, conf,name); + if (!conf->resync_thread) { + printk(KERN_ERR "raid5: couldn't allocate thread for md%d\n", mdidx(mddev)); + goto abort; + } - if ((sb->state & (1 << MD_SB_CLEAN)) == 0) { - printk("raid5: raid set %s not clean; re-constructing parity\n", kdevname(MKDEV(MD_MAJOR, minor))); - raid_conf->resync_parity = 1; -#if SUPPORT_RECONSTRUCTION - md_wakeup_thread(raid_conf->resync_thread); -#endif /* SUPPORT_RECONSTRUCTION */ + printk("raid5: raid set md%d not clean; reconstructing parity\n", mdidx(mddev)); + conf->resync_parity = 1; + md_wakeup_thread(conf->resync_thread); } + print_raid5_conf(conf); + if (start_recovery) + md_recover_arrays(); + print_raid5_conf(conf); + /* Ok, everything is just fine now */ return (0); abort: - if (raid_conf) { - if (raid_conf->stripe_hashtbl) - free_pages((unsigned long) raid_conf->stripe_hashtbl, HASH_PAGES_ORDER); - kfree(raid_conf); + if (conf) { + print_raid5_conf(conf); + if (conf->stripe_hashtbl) + free_pages((unsigned long) conf->stripe_hashtbl, + HASH_PAGES_ORDER); + kfree(conf); } mddev->private = NULL; - printk(KERN_ALERT "raid5: failed to run raid set %s\n", kdevname(MKDEV(MD_MAJOR, minor))); + printk(KERN_ALERT "raid5: failed to run raid set md%d\n", mdidx(mddev)); MOD_DEC_USE_COUNT; return -EIO; } -static int raid5_stop (int minor, struct md_dev *mddev) +static int raid5_stop_resync (mddev_t *mddev) +{ + raid5_conf_t *conf = mddev_to_conf(mddev); + mdk_thread_t *thread = conf->resync_thread; + + if (thread) { + if (conf->resync_parity) { + conf->resync_parity = 2; + md_interrupt_thread(thread); + printk(KERN_INFO "raid5: parity resync was not fully finished, restarting next time.\n"); + return 1; + } + return 0; + } + return 0; +} + +static int raid5_restart_resync (mddev_t *mddev) { - struct raid5_data *raid_conf = (struct raid5_data *) mddev->private; + raid5_conf_t *conf = mddev_to_conf(mddev); - shrink_stripe_cache(raid_conf, raid_conf->max_nr_stripes); - shrink_stripes(raid_conf, raid_conf->max_nr_stripes); - md_unregister_thread(raid_conf->thread); -#if SUPPORT_RECONSTRUCTION - md_unregister_thread(raid_conf->resync_thread); -#endif /* SUPPORT_RECONSTRUCTION */ - free_pages((unsigned long) raid_conf->stripe_hashtbl, HASH_PAGES_ORDER); - kfree(raid_conf); + if (conf->resync_parity) { + if (!conf->resync_thread) { + MD_BUG(); + return 0; + } + printk("raid5: waking up raid5resync.\n"); + conf->resync_parity = 1; + md_wakeup_thread(conf->resync_thread); + return 1; + } else + printk("raid5: no restart-resync needed.\n"); + return 0; +} + + +static int raid5_stop (mddev_t *mddev) +{ + raid5_conf_t *conf = (raid5_conf_t *) mddev->private; + + shrink_stripe_cache(conf, conf->max_nr_stripes); + shrink_stripes(conf, conf->max_nr_stripes); + md_unregister_thread(conf->thread); + if (conf->resync_thread) + md_unregister_thread(conf->resync_thread); + free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); + kfree(conf); mddev->private = NULL; MOD_DEC_USE_COUNT; return 0; } -static int raid5_status (char *page, int minor, struct md_dev *mddev) +static int raid5_status (char *page, mddev_t *mddev) { - struct raid5_data *raid_conf = (struct raid5_data *) mddev->private; - md_superblock_t *sb = mddev->sb; + raid5_conf_t *conf = (raid5_conf_t *) mddev->private; + mdp_super_t *sb = mddev->sb; int sz = 0, i; - sz += sprintf (page+sz, " level %d, %dk chunk, algorithm %d", sb->level, sb->chunk_size >> 10, sb->parity_algorithm); - sz += sprintf (page+sz, " [%d/%d] [", raid_conf->raid_disks, raid_conf->working_disks); - for (i = 0; i < raid_conf->raid_disks; i++) - sz += sprintf (page+sz, "%s", raid_conf->disks[i].operational ? "U" : "_"); + sz += sprintf (page+sz, " level %d, %dk chunk, algorithm %d", sb->level, sb->chunk_size >> 10, sb->layout); + sz += sprintf (page+sz, " [%d/%d] [", conf->raid_disks, conf->working_disks); + for (i = 0; i < conf->raid_disks; i++) + sz += sprintf (page+sz, "%s", conf->disks[i].operational ? "U" : "_"); sz += sprintf (page+sz, "]"); return sz; } -static int raid5_mark_spare(struct md_dev *mddev, md_descriptor_t *spare, int state) +static void print_raid5_conf (raid5_conf_t *conf) +{ + int i; + struct disk_info *tmp; + + printk("RAID5 conf printout:\n"); + if (!conf) { + printk("(conf==NULL)\n"); + return; + } + printk(" --- rd:%d wd:%d fd:%d\n", conf->raid_disks, + conf->working_disks, conf->failed_disks); + + for (i = 0; i < MD_SB_DISKS; i++) { + tmp = conf->disks + i; + printk(" disk %d, s:%d, o:%d, n:%d rd:%d us:%d dev:%s\n", + i, tmp->spare,tmp->operational, + tmp->number,tmp->raid_disk,tmp->used_slot, + partition_name(tmp->dev)); + } +} + +static int raid5_diskop(mddev_t *mddev, mdp_disk_t **d, int state) { - int i = 0, failed_disk = -1; - struct raid5_data *raid_conf = mddev->private; - struct disk_info *disk = raid_conf->disks; + int err = 0; + int i, failed_disk=-1, spare_disk=-1, removed_disk=-1, added_disk=-1; + raid5_conf_t *conf = mddev->private; + struct disk_info *tmp, *sdisk, *fdisk, *rdisk, *adisk; unsigned long flags; - md_superblock_t *sb = mddev->sb; - md_descriptor_t *descriptor; + mdp_super_t *sb = mddev->sb; + mdp_disk_t *failed_desc, *spare_desc, *added_desc; - for (i = 0; i < MD_SB_DISKS; i++, disk++) { - if (disk->spare && disk->number == spare->number) - goto found; - } - return 1; -found: - for (i = 0, disk = raid_conf->disks; i < raid_conf->raid_disks; i++, disk++) - if (!disk->operational) - failed_disk = i; - if (failed_disk == -1) - return 1; save_flags(flags); cli(); + + print_raid5_conf(conf); + /* + * find the disk ... + */ switch (state) { - case SPARE_WRITE: - disk->operational = 1; - disk->write_only = 1; - raid_conf->spare = disk; - break; - case SPARE_INACTIVE: - disk->operational = 0; - disk->write_only = 0; - raid_conf->spare = NULL; - break; - case SPARE_ACTIVE: - disk->spare = 0; - disk->write_only = 0; - descriptor = &sb->disks[raid_conf->disks[failed_disk].number]; - i = spare->raid_disk; - disk->raid_disk = spare->raid_disk = descriptor->raid_disk; - if (disk->raid_disk != failed_disk) - printk("raid5: disk->raid_disk != failed_disk"); - descriptor->raid_disk = i; - - raid_conf->spare = NULL; - raid_conf->working_disks++; - raid_conf->failed_disks--; - raid_conf->disks[failed_disk] = *disk; - break; - default: - printk("raid5_mark_spare: bug: state == %d\n", state); - restore_flags(flags); - return 1; + case DISKOP_SPARE_ACTIVE: + + /* + * Find the failed disk within the RAID5 configuration ... + * (this can only be in the first conf->raid_disks part) + */ + for (i = 0; i < conf->raid_disks; i++) { + tmp = conf->disks + i; + if ((!tmp->operational && !tmp->spare) || + !tmp->used_slot) { + failed_disk = i; + break; + } + } + /* + * When we activate a spare disk we _must_ have a disk in + * the lower (active) part of the array to replace. + */ + if ((failed_disk == -1) || (failed_disk >= conf->raid_disks)) { + MD_BUG(); + err = 1; + goto abort; + } + /* fall through */ + + case DISKOP_SPARE_WRITE: + case DISKOP_SPARE_INACTIVE: + + /* + * Find the spare disk ... (can only be in the 'high' + * area of the array) + */ + for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { + tmp = conf->disks + i; + if (tmp->spare && tmp->number == (*d)->number) { + spare_disk = i; + break; + } + } + if (spare_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; + + case DISKOP_HOT_REMOVE_DISK: + + for (i = 0; i < MD_SB_DISKS; i++) { + tmp = conf->disks + i; + if (tmp->used_slot && (tmp->number == (*d)->number)) { + if (tmp->operational) { + err = -EBUSY; + goto abort; + } + removed_disk = i; + break; + } + } + if (removed_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; + + case DISKOP_HOT_ADD_DISK: + + for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { + tmp = conf->disks + i; + if (!tmp->used_slot) { + added_disk = i; + break; + } + } + if (added_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; + } + + switch (state) { + /* + * Switch the spare disk to write-only mode: + */ + case DISKOP_SPARE_WRITE: + if (conf->spare) { + MD_BUG(); + err = 1; + goto abort; + } + sdisk = conf->disks + spare_disk; + sdisk->operational = 1; + sdisk->write_only = 1; + conf->spare = sdisk; + break; + /* + * Deactivate a spare disk: + */ + case DISKOP_SPARE_INACTIVE: + sdisk = conf->disks + spare_disk; + sdisk->operational = 0; + sdisk->write_only = 0; + /* + * Was the spare being resynced? + */ + if (conf->spare == sdisk) + conf->spare = NULL; + break; + /* + * Activate (mark read-write) the (now sync) spare disk, + * which means we switch it's 'raid position' (->raid_disk) + * with the failed disk. (only the first 'conf->raid_disks' + * slots are used for 'real' disks and we must preserve this + * property) + */ + case DISKOP_SPARE_ACTIVE: + if (!conf->spare) { + MD_BUG(); + err = 1; + goto abort; + } + sdisk = conf->disks + spare_disk; + fdisk = conf->disks + failed_disk; + + spare_desc = &sb->disks[sdisk->number]; + failed_desc = &sb->disks[fdisk->number]; + + if (spare_desc != *d) { + MD_BUG(); + err = 1; + goto abort; + } + + if (spare_desc->raid_disk != sdisk->raid_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + if (sdisk->raid_disk != spare_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + if (failed_desc->raid_disk != fdisk->raid_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + if (fdisk->raid_disk != failed_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + /* + * do the switch finally + */ + xchg_values(*spare_desc, *failed_desc); + xchg_values(*fdisk, *sdisk); + + /* + * (careful, 'failed' and 'spare' are switched from now on) + * + * we want to preserve linear numbering and we want to + * give the proper raid_disk number to the now activated + * disk. (this means we switch back these values) + */ + + xchg_values(spare_desc->raid_disk, failed_desc->raid_disk); + xchg_values(sdisk->raid_disk, fdisk->raid_disk); + xchg_values(spare_desc->number, failed_desc->number); + xchg_values(sdisk->number, fdisk->number); + + *d = failed_desc; + + if (sdisk->dev == MKDEV(0,0)) + sdisk->used_slot = 0; + + /* + * this really activates the spare. + */ + fdisk->spare = 0; + fdisk->write_only = 0; + + /* + * if we activate a spare, we definitely replace a + * non-operational disk slot in the 'low' area of + * the disk array. + */ + conf->failed_disks--; + conf->working_disks++; + conf->spare = NULL; + + break; + + case DISKOP_HOT_REMOVE_DISK: + rdisk = conf->disks + removed_disk; + + if (rdisk->spare && (removed_disk < conf->raid_disks)) { + MD_BUG(); + err = 1; + goto abort; + } + rdisk->dev = MKDEV(0,0); + rdisk->used_slot = 0; + + break; + + case DISKOP_HOT_ADD_DISK: + adisk = conf->disks + added_disk; + added_desc = *d; + + if (added_disk != added_desc->number) { + MD_BUG(); + err = 1; + goto abort; + } + + adisk->number = added_desc->number; + adisk->raid_disk = added_desc->raid_disk; + adisk->dev = MKDEV(added_desc->major,added_desc->minor); + + adisk->operational = 0; + adisk->write_only = 0; + adisk->spare = 1; + adisk->used_slot = 1; + + + break; + + default: + MD_BUG(); + err = 1; + goto abort; } +abort: restore_flags(flags); - return 0; + print_raid5_conf(conf); + return err; } -static struct md_personality raid5_personality= +static mdk_personality_t raid5_personality= { "raid5", raid5_map, @@ -1648,14 +2072,19 @@ NULL, /* no ioctls */ 0, raid5_error, - /* raid5_hot_add_disk, */ NULL, - /* raid1_hot_remove_drive */ NULL, - raid5_mark_spare + raid5_diskop, + raid5_stop_resync, + raid5_restart_resync }; int raid5_init (void) { - return register_md_personality (RAID5, &raid5_personality); + int err; + + err = register_md_personality (RAID5, &raid5_personality); + if (err) + return err; + return 0; } #ifdef MODULE diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/rd.c linux.ac/drivers/block/rd.c --- linux.vanilla/drivers/block/rd.c Thu May 27 22:11:53 1999 +++ linux.ac/drivers/block/rd.c Thu Jul 8 06:14:11 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.ac/drivers/block/smart1,2.h --- linux.vanilla/drivers/block/smart1,2.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/block/smart1,2.h Mon Jul 5 05:11:43 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/block/translucent.c linux.ac/drivers/block/translucent.c --- linux.vanilla/drivers/block/translucent.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/block/translucent.c Mon Jul 19 03:26:58 1999 @@ -0,0 +1,136 @@ +/* + translucent.c : Translucent RAID driver for Linux + Copyright (C) 1998 Ingo Molnar + + Translucent mode management functions. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + You should have received a copy of the GNU General Public License + (for example /usr/src/linux/COPYING); if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include + +#include +#include + +#include + +#define MAJOR_NR MD_MAJOR +#define MD_DRIVER +#define MD_PERSONALITY + +static int translucent_run (mddev_t *mddev) +{ + translucent_conf_t *conf; + mdk_rdev_t *rdev; + int i; + + MOD_INC_USE_COUNT; + + conf = kmalloc (sizeof (*conf), GFP_KERNEL); + if (!conf) + goto out; + mddev->private = conf; + + if (mddev->nb_dev != 2) { + printk("translucent: this mode needs 2 disks, aborting!\n"); + goto out; + } + + if (md_check_ordering(mddev)) { + printk("translucent: disks are not ordered, aborting!\n"); + goto out; + } + + ITERATE_RDEV_ORDERED(mddev,rdev,i) { + dev_info_t *disk = conf->disks + i; + + disk->dev = rdev->dev; + disk->size = rdev->size; + } + + return 0; + +out: + if (conf) + kfree(conf); + + MOD_DEC_USE_COUNT; + return 1; +} + +static int translucent_stop (mddev_t *mddev) +{ + translucent_conf_t *conf = mddev_to_conf(mddev); + + kfree(conf); + + MOD_DEC_USE_COUNT; + + return 0; +} + + +static int translucent_map (mddev_t *mddev, kdev_t dev, kdev_t *rdev, + unsigned long *rsector, unsigned long size) +{ + translucent_conf_t *conf = mddev_to_conf(mddev); + + *rdev = conf->disks[0].dev; + + return 0; +} + +static int translucent_status (char *page, mddev_t *mddev) +{ + int sz = 0; + + sz += sprintf(page+sz, " %d%% full", 10); + return sz; +} + + +static mdk_personality_t translucent_personality= +{ + "translucent", + translucent_map, + NULL, + NULL, + translucent_run, + translucent_stop, + translucent_status, + NULL, + 0, + NULL, + NULL, + NULL, + NULL +}; + +#ifndef MODULE + +md__initfunc(void translucent_init (void)) +{ + register_md_personality (TRANSLUCENT, &translucent_personality); +} + +#else + +int init_module (void) +{ + return (register_md_personality (TRANSLUCENT, &translucent_personality)); +} + +void cleanup_module (void) +{ + unregister_md_personality (TRANSLUCENT); +} + +#endif + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/xor.c linux.ac/drivers/block/xor.c --- linux.vanilla/drivers/block/xor.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/block/xor.c Mon Jul 19 03:26:58 1999 @@ -0,0 +1,1479 @@ +/* + * xor.c : Multiple Devices driver for Linux + * + * Copyright (C) 1996, 1997, 1998, 1999 Ingo Molnar, Matti Aarnio, Jakub Jelinek + * + * + * optimized RAID-5 checksumming functions. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * You should have received a copy of the GNU General Public License + * (for example /usr/src/linux/COPYING); if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#ifdef __sparc_v9__ +#include +#include +#include +#endif + +/* + * we use the 'XOR function template' to register multiple xor + * functions runtime. The kernel measures their speed upon bootup + * and decides which one to use. (compile-time registration is + * not enough as certain CPU features like MMX can only be detected + * runtime) + * + * this architecture makes it pretty easy to add new routines + * that are faster on certain CPUs, without killing other CPU's + * 'native' routine. Although the current routines are belived + * to be the physically fastest ones on all CPUs tested, but + * feel free to prove me wrong and add yet another routine =B-) + * --mingo + */ + +#define MAX_XOR_BLOCKS 5 + +#define XOR_ARGS (unsigned int count, struct buffer_head **bh_ptr) + +typedef void (*xor_block_t) XOR_ARGS; +xor_block_t xor_block = NULL; + +#ifndef __sparc_v9__ + +struct xor_block_template; + +struct xor_block_template { + char * name; + xor_block_t xor_block; + int speed; + struct xor_block_template * next; +}; + +struct xor_block_template * xor_functions = NULL; + +#define XORBLOCK_TEMPLATE(x) \ +static void xor_block_##x XOR_ARGS; \ +static struct xor_block_template t_xor_block_##x = \ + { #x, xor_block_##x, 0, NULL }; \ +static void xor_block_##x XOR_ARGS + +#ifdef __i386__ + +#ifdef CONFIG_X86_XMM +/* + * Cache avoiding checksumming functions utilizing KNI instructions + * Copyright (C) 1999 Zach Brown (with obvious credit due Ingo) + */ + +XORBLOCK_TEMPLATE(pIII_kni) +{ + char xmm_save[16*4]; + int cr0; + int lines = (bh_ptr[0]->b_size>>8); + + __asm__ __volatile__ ( + "movl %%cr0,%0 ;\n\t" + "clts ;\n\t" + "movups %%xmm0,(%1) ;\n\t" + "movups %%xmm1,0x10(%1) ;\n\t" + "movups %%xmm2,0x20(%1) ;\n\t" + "movups %%xmm3,0x30(%1) ;\n\t" + : "=r" (cr0) + : "r" (xmm_save) + : "memory" ); + +#define OFFS(x) "8*("#x"*2)" +#define PF0(x) \ + " prefetcht0 "OFFS(x)"(%1) ;\n" +#define LD(x,y) \ + " movaps "OFFS(x)"(%1), %%xmm"#y" ;\n" +#define ST(x,y) \ + " movaps %%xmm"#y", "OFFS(x)"(%1) ;\n" +#define PF1(x) \ + " prefetchnta "OFFS(x)"(%2) ;\n" +#define PF2(x) \ + " prefetchnta "OFFS(x)"(%3) ;\n" +#define PF3(x) \ + " prefetchnta "OFFS(x)"(%4) ;\n" +#define PF4(x) \ + " prefetchnta "OFFS(x)"(%5) ;\n" +#define PF5(x) \ + " prefetchnta "OFFS(x)"(%6) ;\n" +#define XO1(x,y) \ + " xorps "OFFS(x)"(%2), %%xmm"#y" ;\n" +#define XO2(x,y) \ + " xorps "OFFS(x)"(%3), %%xmm"#y" ;\n" +#define XO3(x,y) \ + " xorps "OFFS(x)"(%4), %%xmm"#y" ;\n" +#define XO4(x,y) \ + " xorps "OFFS(x)"(%5), %%xmm"#y" ;\n" +#define XO5(x,y) \ + " xorps "OFFS(x)"(%6), %%xmm"#y" ;\n" + + switch(count) { + case 2: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + LD(i,0) \ + LD(i+1,1) \ + PF1(i) \ + PF1(i+2) \ + LD(i+2,2) \ + LD(i+3,3) \ + PF0(i+4) \ + PF0(i+6) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + ST(i,0) \ + ST(i+1,1) \ + ST(i+2,2) \ + ST(i+3,3) \ + + + PF0(0) + PF0(2) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $256, %1 ;\n" + " addl $256, %2 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data) + : "memory" ); + break; + case 3: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + PF1(i) \ + PF1(i+2) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + PF2(i) \ + PF2(i+2) \ + PF0(i+4) \ + PF0(i+6) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + XO2(i,0) \ + XO2(i+1,1) \ + XO2(i+2,2) \ + XO2(i+3,3) \ + ST(i,0) \ + ST(i+1,1) \ + ST(i+2,2) \ + ST(i+3,3) \ + + + PF0(0) + PF0(2) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $256, %1 ;\n" + " addl $256, %2 ;\n" + " addl $256, %3 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data) + : "memory" ); + break; + case 4: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + PF1(i) \ + PF1(i+2) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + PF2(i) \ + PF2(i+2) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + PF3(i) \ + PF3(i+2) \ + PF0(i+4) \ + PF0(i+6) \ + XO2(i,0) \ + XO2(i+1,1) \ + XO2(i+2,2) \ + XO2(i+3,3) \ + XO3(i,0) \ + XO3(i+1,1) \ + XO3(i+2,2) \ + XO3(i+3,3) \ + ST(i,0) \ + ST(i+1,1) \ + ST(i+2,2) \ + ST(i+3,3) \ + + + PF0(0) + PF0(2) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $256, %1 ;\n" + " addl $256, %2 ;\n" + " addl $256, %3 ;\n" + " addl $256, %4 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data), + "r" (bh_ptr[3]->b_data) + : "memory" ); + break; + case 5: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + PF1(i) \ + PF1(i+2) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + PF2(i) \ + PF2(i+2) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + PF3(i) \ + PF3(i+2) \ + XO2(i,0) \ + XO2(i+1,1) \ + XO2(i+2,2) \ + XO2(i+3,3) \ + PF4(i) \ + PF4(i+2) \ + PF0(i+4) \ + PF0(i+6) \ + XO3(i,0) \ + XO3(i+1,1) \ + XO3(i+2,2) \ + XO3(i+3,3) \ + XO4(i,0) \ + XO4(i+1,1) \ + XO4(i+2,2) \ + XO4(i+3,3) \ + ST(i,0) \ + ST(i+1,1) \ + ST(i+2,2) \ + ST(i+3,3) \ + + + PF0(0) + PF0(2) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $256, %1 ;\n" + " addl $256, %2 ;\n" + " addl $256, %3 ;\n" + " addl $256, %4 ;\n" + " addl $256, %5 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data), + "r" (bh_ptr[3]->b_data), + "r" (bh_ptr[4]->b_data) + : "memory"); + break; + } + + __asm__ __volatile__ ( + "sfence ;\n\t" + "movups (%1),%%xmm0 ;\n\t" + "movups 0x10(%1),%%xmm1 ;\n\t" + "movups 0x20(%1),%%xmm2 ;\n\t" + "movups 0x30(%1),%%xmm3 ;\n\t" + "movl %0,%%cr0 ;\n\t" + : + : "r" (cr0), "r" (xmm_save) + : "memory" ); +} + +#undef OFFS +#undef LD +#undef ST +#undef PF0 +#undef PF1 +#undef PF2 +#undef PF3 +#undef PF4 +#undef PF5 +#undef XO1 +#undef XO2 +#undef XO3 +#undef XO4 +#undef XO5 +#undef BLOCK + +#endif /* CONFIG_X86_XMM */ + +/* + * high-speed RAID5 checksumming functions utilizing MMX instructions + * Copyright (C) 1998 Ingo Molnar + */ +XORBLOCK_TEMPLATE(pII_mmx) +{ + char fpu_save[108]; + int lines = (bh_ptr[0]->b_size>>7); + + if (!(current->flags & PF_USEDFPU)) + __asm__ __volatile__ ( " clts;\n"); + + __asm__ __volatile__ ( " fsave %0; fwait\n"::"m"(fpu_save[0]) ); + +#define LD(x,y) \ + " movq 8*("#x")(%1), %%mm"#y" ;\n" +#define ST(x,y) \ + " movq %%mm"#y", 8*("#x")(%1) ;\n" +#define XO1(x,y) \ + " pxor 8*("#x")(%2), %%mm"#y" ;\n" +#define XO2(x,y) \ + " pxor 8*("#x")(%3), %%mm"#y" ;\n" +#define XO3(x,y) \ + " pxor 8*("#x")(%4), %%mm"#y" ;\n" +#define XO4(x,y) \ + " pxor 8*("#x")(%5), %%mm"#y" ;\n" + + switch(count) { + case 2: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + XO1(i,0) \ + ST(i,0) \ + XO1(i+1,1) \ + ST(i+1,1) \ + XO1(i+2,2) \ + ST(i+2,2) \ + XO1(i+3,3) \ + ST(i+3,3) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $128, %1 ;\n" + " addl $128, %2 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data) + : "memory"); + break; + case 3: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + XO2(i,0) \ + ST(i,0) \ + XO2(i+1,1) \ + ST(i+1,1) \ + XO2(i+2,2) \ + ST(i+2,2) \ + XO2(i+3,3) \ + ST(i+3,3) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $128, %1 ;\n" + " addl $128, %2 ;\n" + " addl $128, %3 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data) + : "memory"); + break; + case 4: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + XO2(i,0) \ + XO2(i+1,1) \ + XO2(i+2,2) \ + XO2(i+3,3) \ + XO3(i,0) \ + ST(i,0) \ + XO3(i+1,1) \ + ST(i+1,1) \ + XO3(i+2,2) \ + ST(i+2,2) \ + XO3(i+3,3) \ + ST(i+3,3) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $128, %1 ;\n" + " addl $128, %2 ;\n" + " addl $128, %3 ;\n" + " addl $128, %4 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data), + "r" (bh_ptr[3]->b_data) + : "memory"); + break; + case 5: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + XO2(i,0) \ + XO2(i+1,1) \ + XO2(i+2,2) \ + XO2(i+3,3) \ + XO3(i,0) \ + XO3(i+1,1) \ + XO3(i+2,2) \ + XO3(i+3,3) \ + XO4(i,0) \ + ST(i,0) \ + XO4(i+1,1) \ + ST(i+1,1) \ + XO4(i+2,2) \ + ST(i+2,2) \ + XO4(i+3,3) \ + ST(i+3,3) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $128, %1 ;\n" + " addl $128, %2 ;\n" + " addl $128, %3 ;\n" + " addl $128, %4 ;\n" + " addl $128, %5 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data), + "r" (bh_ptr[3]->b_data), + "r" (bh_ptr[4]->b_data) + : "memory"); + break; + } + + __asm__ __volatile__ ( " frstor %0;\n"::"m"(fpu_save[0]) ); + + if (!(current->flags & PF_USEDFPU)) + stts(); +} + +#undef LD +#undef XO1 +#undef XO2 +#undef XO3 +#undef XO4 +#undef ST +#undef BLOCK + +XORBLOCK_TEMPLATE(p5_mmx) +{ + char fpu_save[108]; + int lines = (bh_ptr[0]->b_size>>6); + + if (!(current->flags & PF_USEDFPU)) + __asm__ __volatile__ ( " clts;\n"); + + __asm__ __volatile__ ( " fsave %0; fwait\n"::"m"(fpu_save[0]) ); + + switch(count) { + case 2: + __asm__ __volatile__ ( + + " .align 32,0x90 ;\n" + " 1: ;\n" + " movq (%1), %%mm0 ;\n" + " movq 8(%1), %%mm1 ;\n" + " pxor (%2), %%mm0 ;\n" + " movq 16(%1), %%mm2 ;\n" + " movq %%mm0, (%1) ;\n" + " pxor 8(%2), %%mm1 ;\n" + " movq 24(%1), %%mm3 ;\n" + " movq %%mm1, 8(%1) ;\n" + " pxor 16(%2), %%mm2 ;\n" + " movq 32(%1), %%mm4 ;\n" + " movq %%mm2, 16(%1) ;\n" + " pxor 24(%2), %%mm3 ;\n" + " movq 40(%1), %%mm5 ;\n" + " movq %%mm3, 24(%1) ;\n" + " pxor 32(%2), %%mm4 ;\n" + " movq 48(%1), %%mm6 ;\n" + " movq %%mm4, 32(%1) ;\n" + " pxor 40(%2), %%mm5 ;\n" + " movq 56(%1), %%mm7 ;\n" + " movq %%mm5, 40(%1) ;\n" + " pxor 48(%2), %%mm6 ;\n" + " pxor 56(%2), %%mm7 ;\n" + " movq %%mm6, 48(%1) ;\n" + " movq %%mm7, 56(%1) ;\n" + + " addl $64, %1 ;\n" + " addl $64, %2 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data) + : "memory" ); + break; + case 3: + __asm__ __volatile__ ( + + " .align 32,0x90 ;\n" + " 1: ;\n" + " movq (%1), %%mm0 ;\n" + " movq 8(%1), %%mm1 ;\n" + " pxor (%2), %%mm0 ;\n" + " movq 16(%1), %%mm2 ;\n" + " pxor 8(%2), %%mm1 ;\n" + " pxor (%3), %%mm0 ;\n" + " pxor 16(%2), %%mm2 ;\n" + " movq %%mm0, (%1) ;\n" + " pxor 8(%3), %%mm1 ;\n" + " pxor 16(%3), %%mm2 ;\n" + " movq 24(%1), %%mm3 ;\n" + " movq %%mm1, 8(%1) ;\n" + " movq 32(%1), %%mm4 ;\n" + " movq 40(%1), %%mm5 ;\n" + " pxor 24(%2), %%mm3 ;\n" + " movq %%mm2, 16(%1) ;\n" + " pxor 32(%2), %%mm4 ;\n" + " pxor 24(%3), %%mm3 ;\n" + " pxor 40(%2), %%mm5 ;\n" + " movq %%mm3, 24(%1) ;\n" + " pxor 32(%3), %%mm4 ;\n" + " pxor 40(%3), %%mm5 ;\n" + " movq 48(%1), %%mm6 ;\n" + " movq %%mm4, 32(%1) ;\n" + " movq 56(%1), %%mm7 ;\n" + " pxor 48(%2), %%mm6 ;\n" + " movq %%mm5, 40(%1) ;\n" + " pxor 56(%2), %%mm7 ;\n" + " pxor 48(%3), %%mm6 ;\n" + " pxor 56(%3), %%mm7 ;\n" + " movq %%mm6, 48(%1) ;\n" + " movq %%mm7, 56(%1) ;\n" + + " addl $64, %1 ;\n" + " addl $64, %2 ;\n" + " addl $64, %3 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data) + : "memory" ); + break; + case 4: + __asm__ __volatile__ ( + + " .align 32,0x90 ;\n" + " 1: ;\n" + " movq (%1), %%mm0 ;\n" + " movq 8(%1), %%mm1 ;\n" + " pxor (%2), %%mm0 ;\n" + " movq 16(%1), %%mm2 ;\n" + " pxor 8(%2), %%mm1 ;\n" + " pxor (%3), %%mm0 ;\n" + " pxor 16(%2), %%mm2 ;\n" + " pxor 8(%3), %%mm1 ;\n" + " pxor (%4), %%mm0 ;\n" + " movq 24(%1), %%mm3 ;\n" + " pxor 16(%3), %%mm2 ;\n" + " pxor 8(%4), %%mm1 ;\n" + " movq %%mm0, (%1) ;\n" + " movq 32(%1), %%mm4 ;\n" + " pxor 24(%2), %%mm3 ;\n" + " pxor 16(%4), %%mm2 ;\n" + " movq %%mm1, 8(%1) ;\n" + " movq 40(%1), %%mm5 ;\n" + " pxor 32(%2), %%mm4 ;\n" + " pxor 24(%3), %%mm3 ;\n" + " movq %%mm2, 16(%1) ;\n" + " pxor 40(%2), %%mm5 ;\n" + " pxor 32(%3), %%mm4 ;\n" + " pxor 24(%4), %%mm3 ;\n" + " movq %%mm3, 24(%1) ;\n" + " movq 56(%1), %%mm7 ;\n" + " movq 48(%1), %%mm6 ;\n" + " pxor 40(%3), %%mm5 ;\n" + " pxor 32(%4), %%mm4 ;\n" + " pxor 48(%2), %%mm6 ;\n" + " movq %%mm4, 32(%1) ;\n" + " pxor 56(%2), %%mm7 ;\n" + " pxor 40(%4), %%mm5 ;\n" + " pxor 48(%3), %%mm6 ;\n" + " pxor 56(%3), %%mm7 ;\n" + " movq %%mm5, 40(%1) ;\n" + " pxor 48(%4), %%mm6 ;\n" + " pxor 56(%4), %%mm7 ;\n" + " movq %%mm6, 48(%1) ;\n" + " movq %%mm7, 56(%1) ;\n" + + " addl $64, %1 ;\n" + " addl $64, %2 ;\n" + " addl $64, %3 ;\n" + " addl $64, %4 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data), + "r" (bh_ptr[3]->b_data) + : "memory" ); + break; + case 5: + __asm__ __volatile__ ( + + " .align 32,0x90 ;\n" + " 1: ;\n" + " movq (%1), %%mm0 ;\n" + " movq 8(%1), %%mm1 ;\n" + " pxor (%2), %%mm0 ;\n" + " pxor 8(%2), %%mm1 ;\n" + " movq 16(%1), %%mm2 ;\n" + " pxor (%3), %%mm0 ;\n" + " pxor 8(%3), %%mm1 ;\n" + " pxor 16(%2), %%mm2 ;\n" + " pxor (%4), %%mm0 ;\n" + " pxor 8(%4), %%mm1 ;\n" + " pxor 16(%3), %%mm2 ;\n" + " movq 24(%1), %%mm3 ;\n" + " pxor (%5), %%mm0 ;\n" + " pxor 8(%5), %%mm1 ;\n" + " movq %%mm0, (%1) ;\n" + " pxor 16(%4), %%mm2 ;\n" + " pxor 24(%2), %%mm3 ;\n" + " movq %%mm1, 8(%1) ;\n" + " pxor 16(%5), %%mm2 ;\n" + " pxor 24(%3), %%mm3 ;\n" + " movq 32(%1), %%mm4 ;\n" + " movq %%mm2, 16(%1) ;\n" + " pxor 24(%4), %%mm3 ;\n" + " pxor 32(%2), %%mm4 ;\n" + " movq 40(%1), %%mm5 ;\n" + " pxor 24(%5), %%mm3 ;\n" + " pxor 32(%3), %%mm4 ;\n" + " pxor 40(%2), %%mm5 ;\n" + " movq %%mm3, 24(%1) ;\n" + " pxor 32(%4), %%mm4 ;\n" + " pxor 40(%3), %%mm5 ;\n" + " movq 48(%1), %%mm6 ;\n" + " movq 56(%1), %%mm7 ;\n" + " pxor 32(%5), %%mm4 ;\n" + " pxor 40(%4), %%mm5 ;\n" + " pxor 48(%2), %%mm6 ;\n" + " pxor 56(%2), %%mm7 ;\n" + " movq %%mm4, 32(%1) ;\n" + " pxor 48(%3), %%mm6 ;\n" + " pxor 56(%3), %%mm7 ;\n" + " pxor 40(%5), %%mm5 ;\n" + " pxor 48(%4), %%mm6 ;\n" + " pxor 56(%4), %%mm7 ;\n" + " movq %%mm5, 40(%1) ;\n" + " pxor 48(%5), %%mm6 ;\n" + " pxor 56(%5), %%mm7 ;\n" + " movq %%mm6, 48(%1) ;\n" + " movq %%mm7, 56(%1) ;\n" + + " addl $64, %1 ;\n" + " addl $64, %2 ;\n" + " addl $64, %3 ;\n" + " addl $64, %4 ;\n" + " addl $64, %5 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data), + "r" (bh_ptr[3]->b_data), + "r" (bh_ptr[4]->b_data) + : "memory" ); + break; + } + + __asm__ __volatile__ ( " frstor %0;\n"::"m"(fpu_save[0]) ); + + if (!(current->flags & PF_USEDFPU)) + stts(); +} +#endif /* __i386__ */ +#endif /* !__sparc_v9__ */ + +#ifdef __sparc_v9__ +/* + * High speed xor_block operation for RAID4/5 utilizing the + * UltraSparc Visual Instruction Set. + * + * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz) + * + * Requirements: + * !(((long)destp | (long)sourcep) & (64 - 1)) && + * !(len & 127) && len >= 256 + * + * It is done in pure assembly, as otherwise gcc makes it + * a non-leaf function, which is not what we want. + * Also, we don't measure the speeds as on other architectures, + * as the measuring routine does not take into account cold caches + * and the fact that xor_block_VIS bypasses the caches. + * xor_block_32regs might be 5% faster if caches are hot and things + * just right, but I think it is better not to pollute the caches. + * Actually, if I'd just fight for speed for hot caches, I could + * write a hybrid VIS/integer routine, which would do always two + * 64B blocks in VIS and two in IEUs, but I really care more about + * caches. + */ +extern void *VISenter(void); +extern void xor_block_VIS SRCDEST; + +void __xor_block_VIS(void) +{ +__asm__ (" + .globl xor_block_VIS +xor_block_VIS: + ldx [%%o1 + %0], %%o1 + ldx [%%o0 + %1], %%o2 + ldx [%%o0 + %0], %%o0 + rd %%fprs, %%o5 + andcc %%o5, %2, %%g0 + be,pt %%icc, 297f + sethi %%hi(%5), %%g1 + jmpl %%g1 + %%lo(%5), %%g7 + add %%g7, 8, %%g7 +297: wr %%g0, %4, %%fprs + wr %%g0, %3, %%asi + membar #LoadStore|#StoreLoad|#StoreStore + sub %%o2, 128, %%o2 + ldda [%%o0] %3, %%f0 + ldda [%%o1] %3, %%f16 +1: ldda [%%o0 + 64] %%asi, %%f32 + fxor %%f0, %%f16, %%f16 + fxor %%f2, %%f18, %%f18 + fxor %%f4, %%f20, %%f20 + fxor %%f6, %%f22, %%f22 + fxor %%f8, %%f24, %%f24 + fxor %%f10, %%f26, %%f26 + fxor %%f12, %%f28, %%f28 + fxor %%f14, %%f30, %%f30 + stda %%f16, [%%o0] %3 + ldda [%%o1 + 64] %%asi, %%f48 + ldda [%%o0 + 128] %%asi, %%f0 + fxor %%f32, %%f48, %%f48 + fxor %%f34, %%f50, %%f50 + add %%o0, 128, %%o0 + fxor %%f36, %%f52, %%f52 + add %%o1, 128, %%o1 + fxor %%f38, %%f54, %%f54 + subcc %%o2, 128, %%o2 + fxor %%f40, %%f56, %%f56 + fxor %%f42, %%f58, %%f58 + fxor %%f44, %%f60, %%f60 + fxor %%f46, %%f62, %%f62 + stda %%f48, [%%o0 - 64] %%asi + bne,pt %%xcc, 1b + ldda [%%o1] %3, %%f16 + ldda [%%o0 + 64] %%asi, %%f32 + fxor %%f0, %%f16, %%f16 + fxor %%f2, %%f18, %%f18 + fxor %%f4, %%f20, %%f20 + fxor %%f6, %%f22, %%f22 + fxor %%f8, %%f24, %%f24 + fxor %%f10, %%f26, %%f26 + fxor %%f12, %%f28, %%f28 + fxor %%f14, %%f30, %%f30 + stda %%f16, [%%o0] %3 + ldda [%%o1 + 64] %%asi, %%f48 + membar #Sync + fxor %%f32, %%f48, %%f48 + fxor %%f34, %%f50, %%f50 + fxor %%f36, %%f52, %%f52 + fxor %%f38, %%f54, %%f54 + fxor %%f40, %%f56, %%f56 + fxor %%f42, %%f58, %%f58 + fxor %%f44, %%f60, %%f60 + fxor %%f46, %%f62, %%f62 + stda %%f48, [%%o0 + 64] %%asi + membar #Sync|#StoreStore|#StoreLoad + retl + wr %%g0, 0, %%fprs + " : : + "i" (&((struct buffer_head *)0)->b_data), + "i" (&((struct buffer_head *)0)->b_size), + "i" (FPRS_FEF|FPRS_DU), "i" (ASI_BLK_P), + "i" (FPRS_FEF), "i" (VISenter)); +} +#endif /* __sparc_v9__ */ + +#if defined(__sparc__) && !defined(__sparc_v9__) +/* + * High speed xor_block operation for RAID4/5 utilizing the + * ldd/std SPARC instructions. + * + * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz) + * + */ + +XORBLOCK_TEMPLATE(SPARC) +{ + int size = dest->b_size; + int lines = size / (sizeof (long)) / 8, i; + long *destp = (long *) dest->b_data; + long *sourcep = (long *) source->b_data; + + for (i = lines; i > 0; i--) { + __asm__ __volatile__(" + ldd [%0 + 0x00], %%g2 + ldd [%0 + 0x08], %%g4 + ldd [%0 + 0x10], %%o0 + ldd [%0 + 0x18], %%o2 + ldd [%1 + 0x00], %%o4 + ldd [%1 + 0x08], %%l0 + ldd [%1 + 0x10], %%l2 + ldd [%1 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + std %%g2, [%0 + 0x00] + std %%g4, [%0 + 0x08] + std %%o0, [%0 + 0x10] + std %%o2, [%0 + 0x18] + " : : "r" (destp), "r" (sourcep) : "g2", "g3", "g4", "g5", "o0", + "o1", "o2", "o3", "o4", "o5", "l0", "l1", "l2", "l3", "l4", "l5"); + + destp += 8; + sourcep += 8; + } +} +#endif /* __sparc_v[78]__ */ + +#ifndef __sparc_v9__ + +/* + * this one works reasonably on any x86 CPU + * (send me an assembly version for inclusion if you can make it faster) + * + * this one is just as fast as written in pure assembly on x86. + * the reason for this separate version is that the + * fast open-coded xor routine "32reg" produces suboptimal code + * on x86, due to lack of registers. + */ +XORBLOCK_TEMPLATE(8regs) +{ + int len = bh_ptr[0]->b_size; + long *destp = (long *) bh_ptr[0]->b_data; + long *source1, *source2, *source3, *source4; + long lines = len / (sizeof (long)) / 8, i; + + switch(count) { + case 2: + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + *(destp + 0) ^= *(source1 + 0); + *(destp + 1) ^= *(source1 + 1); + *(destp + 2) ^= *(source1 + 2); + *(destp + 3) ^= *(source1 + 3); + *(destp + 4) ^= *(source1 + 4); + *(destp + 5) ^= *(source1 + 5); + *(destp + 6) ^= *(source1 + 6); + *(destp + 7) ^= *(source1 + 7); + source1 += 8; + destp += 8; + } + break; + case 3: + source2 = (long *) bh_ptr[2]->b_data; + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + *(destp + 0) ^= *(source1 + 0); + *(destp + 0) ^= *(source2 + 0); + *(destp + 1) ^= *(source1 + 1); + *(destp + 1) ^= *(source2 + 1); + *(destp + 2) ^= *(source1 + 2); + *(destp + 2) ^= *(source2 + 2); + *(destp + 3) ^= *(source1 + 3); + *(destp + 3) ^= *(source2 + 3); + *(destp + 4) ^= *(source1 + 4); + *(destp + 4) ^= *(source2 + 4); + *(destp + 5) ^= *(source1 + 5); + *(destp + 5) ^= *(source2 + 5); + *(destp + 6) ^= *(source1 + 6); + *(destp + 6) ^= *(source2 + 6); + *(destp + 7) ^= *(source1 + 7); + *(destp + 7) ^= *(source2 + 7); + source1 += 8; + source2 += 8; + destp += 8; + } + break; + case 4: + source3 = (long *) bh_ptr[3]->b_data; + source2 = (long *) bh_ptr[2]->b_data; + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + *(destp + 0) ^= *(source1 + 0); + *(destp + 0) ^= *(source2 + 0); + *(destp + 0) ^= *(source3 + 0); + *(destp + 1) ^= *(source1 + 1); + *(destp + 1) ^= *(source2 + 1); + *(destp + 1) ^= *(source3 + 1); + *(destp + 2) ^= *(source1 + 2); + *(destp + 2) ^= *(source2 + 2); + *(destp + 2) ^= *(source3 + 2); + *(destp + 3) ^= *(source1 + 3); + *(destp + 3) ^= *(source2 + 3); + *(destp + 3) ^= *(source3 + 3); + *(destp + 4) ^= *(source1 + 4); + *(destp + 4) ^= *(source2 + 4); + *(destp + 4) ^= *(source3 + 4); + *(destp + 5) ^= *(source1 + 5); + *(destp + 5) ^= *(source2 + 5); + *(destp + 5) ^= *(source3 + 5); + *(destp + 6) ^= *(source1 + 6); + *(destp + 6) ^= *(source2 + 6); + *(destp + 6) ^= *(source3 + 6); + *(destp + 7) ^= *(source1 + 7); + *(destp + 7) ^= *(source2 + 7); + *(destp + 7) ^= *(source3 + 7); + source1 += 8; + source2 += 8; + source3 += 8; + destp += 8; + } + break; + case 5: + source4 = (long *) bh_ptr[4]->b_data; + source3 = (long *) bh_ptr[3]->b_data; + source2 = (long *) bh_ptr[2]->b_data; + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + *(destp + 0) ^= *(source1 + 0); + *(destp + 0) ^= *(source2 + 0); + *(destp + 0) ^= *(source3 + 0); + *(destp + 0) ^= *(source4 + 0); + *(destp + 1) ^= *(source1 + 1); + *(destp + 1) ^= *(source2 + 1); + *(destp + 1) ^= *(source3 + 1); + *(destp + 1) ^= *(source4 + 1); + *(destp + 2) ^= *(source1 + 2); + *(destp + 2) ^= *(source2 + 2); + *(destp + 2) ^= *(source3 + 2); + *(destp + 2) ^= *(source4 + 2); + *(destp + 3) ^= *(source1 + 3); + *(destp + 3) ^= *(source2 + 3); + *(destp + 3) ^= *(source3 + 3); + *(destp + 3) ^= *(source4 + 3); + *(destp + 4) ^= *(source1 + 4); + *(destp + 4) ^= *(source2 + 4); + *(destp + 4) ^= *(source3 + 4); + *(destp + 4) ^= *(source4 + 4); + *(destp + 5) ^= *(source1 + 5); + *(destp + 5) ^= *(source2 + 5); + *(destp + 5) ^= *(source3 + 5); + *(destp + 5) ^= *(source4 + 5); + *(destp + 6) ^= *(source1 + 6); + *(destp + 6) ^= *(source2 + 6); + *(destp + 6) ^= *(source3 + 6); + *(destp + 6) ^= *(source4 + 6); + *(destp + 7) ^= *(source1 + 7); + *(destp + 7) ^= *(source2 + 7); + *(destp + 7) ^= *(source3 + 7); + *(destp + 7) ^= *(source4 + 7); + source1 += 8; + source2 += 8; + source3 += 8; + source4 += 8; + destp += 8; + } + break; + } +} + +/* + * platform independent RAID5 checksum calculation, this should + * be very fast on any platform that has a decent amount of + * registers. (32 or more) + */ +XORBLOCK_TEMPLATE(32regs) +{ + int size = bh_ptr[0]->b_size; + int lines = size / (sizeof (long)) / 8, i; + long *destp = (long *) bh_ptr[0]->b_data; + long *source1, *source2, *source3, *source4; + + /* LOTS of registers available... + We do explicite loop-unrolling here for code which + favours RISC machines. In fact this is almoast direct + RISC assembly on Alpha and SPARC :-) */ + + + switch(count) { + case 2: + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + register long d0, d1, d2, d3, d4, d5, d6, d7; + d0 = destp[0]; /* Pull the stuff into registers */ + d1 = destp[1]; /* ... in bursts, if possible. */ + d2 = destp[2]; + d3 = destp[3]; + d4 = destp[4]; + d5 = destp[5]; + d6 = destp[6]; + d7 = destp[7]; + d0 ^= source1[0]; + d1 ^= source1[1]; + d2 ^= source1[2]; + d3 ^= source1[3]; + d4 ^= source1[4]; + d5 ^= source1[5]; + d6 ^= source1[6]; + d7 ^= source1[7]; + destp[0] = d0; /* Store the result (in burts) */ + destp[1] = d1; + destp[2] = d2; + destp[3] = d3; + destp[4] = d4; /* Store the result (in burts) */ + destp[5] = d5; + destp[6] = d6; + destp[7] = d7; + source1 += 8; + destp += 8; + } + break; + case 3: + source2 = (long *) bh_ptr[2]->b_data; + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + register long d0, d1, d2, d3, d4, d5, d6, d7; + d0 = destp[0]; /* Pull the stuff into registers */ + d1 = destp[1]; /* ... in bursts, if possible. */ + d2 = destp[2]; + d3 = destp[3]; + d4 = destp[4]; + d5 = destp[5]; + d6 = destp[6]; + d7 = destp[7]; + d0 ^= source1[0]; + d1 ^= source1[1]; + d2 ^= source1[2]; + d3 ^= source1[3]; + d4 ^= source1[4]; + d5 ^= source1[5]; + d6 ^= source1[6]; + d7 ^= source1[7]; + d0 ^= source2[0]; + d1 ^= source2[1]; + d2 ^= source2[2]; + d3 ^= source2[3]; + d4 ^= source2[4]; + d5 ^= source2[5]; + d6 ^= source2[6]; + d7 ^= source2[7]; + destp[0] = d0; /* Store the result (in burts) */ + destp[1] = d1; + destp[2] = d2; + destp[3] = d3; + destp[4] = d4; /* Store the result (in burts) */ + destp[5] = d5; + destp[6] = d6; + destp[7] = d7; + source1 += 8; + source2 += 8; + destp += 8; + } + break; + case 4: + source3 = (long *) bh_ptr[3]->b_data; + source2 = (long *) bh_ptr[2]->b_data; + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + register long d0, d1, d2, d3, d4, d5, d6, d7; + d0 = destp[0]; /* Pull the stuff into registers */ + d1 = destp[1]; /* ... in bursts, if possible. */ + d2 = destp[2]; + d3 = destp[3]; + d4 = destp[4]; + d5 = destp[5]; + d6 = destp[6]; + d7 = destp[7]; + d0 ^= source1[0]; + d1 ^= source1[1]; + d2 ^= source1[2]; + d3 ^= source1[3]; + d4 ^= source1[4]; + d5 ^= source1[5]; + d6 ^= source1[6]; + d7 ^= source1[7]; + d0 ^= source2[0]; + d1 ^= source2[1]; + d2 ^= source2[2]; + d3 ^= source2[3]; + d4 ^= source2[4]; + d5 ^= source2[5]; + d6 ^= source2[6]; + d7 ^= source2[7]; + d0 ^= source3[0]; + d1 ^= source3[1]; + d2 ^= source3[2]; + d3 ^= source3[3]; + d4 ^= source3[4]; + d5 ^= source3[5]; + d6 ^= source3[6]; + d7 ^= source3[7]; + destp[0] = d0; /* Store the result (in burts) */ + destp[1] = d1; + destp[2] = d2; + destp[3] = d3; + destp[4] = d4; /* Store the result (in burts) */ + destp[5] = d5; + destp[6] = d6; + destp[7] = d7; + source1 += 8; + source2 += 8; + source3 += 8; + destp += 8; + } + break; + case 5: + source4 = (long *) bh_ptr[4]->b_data; + source3 = (long *) bh_ptr[3]->b_data; + source2 = (long *) bh_ptr[2]->b_data; + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + register long d0, d1, d2, d3, d4, d5, d6, d7; + d0 = destp[0]; /* Pull the stuff into registers */ + d1 = destp[1]; /* ... in bursts, if possible. */ + d2 = destp[2]; + d3 = destp[3]; + d4 = destp[4]; + d5 = destp[5]; + d6 = destp[6]; + d7 = destp[7]; + d0 ^= source1[0]; + d1 ^= source1[1]; + d2 ^= source1[2]; + d3 ^= source1[3]; + d4 ^= source1[4]; + d5 ^= source1[5]; + d6 ^= source1[6]; + d7 ^= source1[7]; + d0 ^= source2[0]; + d1 ^= source2[1]; + d2 ^= source2[2]; + d3 ^= source2[3]; + d4 ^= source2[4]; + d5 ^= source2[5]; + d6 ^= source2[6]; + d7 ^= source2[7]; + d0 ^= source3[0]; + d1 ^= source3[1]; + d2 ^= source3[2]; + d3 ^= source3[3]; + d4 ^= source3[4]; + d5 ^= source3[5]; + d6 ^= source3[6]; + d7 ^= source3[7]; + d0 ^= source4[0]; + d1 ^= source4[1]; + d2 ^= source4[2]; + d3 ^= source4[3]; + d4 ^= source4[4]; + d5 ^= source4[5]; + d6 ^= source4[6]; + d7 ^= source4[7]; + destp[0] = d0; /* Store the result (in burts) */ + destp[1] = d1; + destp[2] = d2; + destp[3] = d3; + destp[4] = d4; /* Store the result (in burts) */ + destp[5] = d5; + destp[6] = d6; + destp[7] = d7; + source1 += 8; + source2 += 8; + source3 += 8; + source4 += 8; + destp += 8; + } + break; + } +} + +/* + * (the -6*32 shift factor colors the cache) + */ +#define SIZE (PAGE_SIZE-6*32) + +static void xor_speed ( struct xor_block_template * func, + struct buffer_head *b1, struct buffer_head *b2) +{ + int speed; + unsigned long now; + int i, count, max; + struct buffer_head *bh_ptr[6]; + + func->next = xor_functions; + xor_functions = func; + bh_ptr[0] = b1; + bh_ptr[1] = b2; + + /* + * count the number of XORs done during a whole jiffy. + * calculate the speed of checksumming from this. + * (we use a 2-page allocation to have guaranteed + * color L1-cache layout) + */ + max = 0; + for (i = 0; i < 5; i++) { + now = jiffies; + count = 0; + while (jiffies == now) { + mb(); + func->xor_block(2,bh_ptr); + mb(); + count++; + mb(); + } + if (count > max) + max = count; + } + + speed = max * (HZ*SIZE/1024); + func->speed = speed; + + printk( " %-10s: %5d.%03d MB/sec\n", func->name, + speed / 1000, speed % 1000); +} + +static inline void pick_fastest_function(void) +{ + struct xor_block_template *f, *fastest; + + fastest = xor_functions; + for (f = fastest; f; f = f->next) { + if (f->speed > fastest->speed) + fastest = f; + } +#ifdef CONFIG_X86_XMM + if (boot_cpu_data.mmu_cr4_features & X86_CR4_OSXMMEXCPT) { + fastest = &t_xor_block_pIII_kni; + } +#endif + xor_block = fastest->xor_block; + printk( "using fastest function: %s (%d.%03d MB/sec)\n", fastest->name, + fastest->speed / 1000, fastest->speed % 1000); +} + + +void calibrate_xor_block(void) +{ + struct buffer_head b1, b2; + + memset(&b1,0,sizeof(b1)); + b2 = b1; + + b1.b_data = (char *) md__get_free_pages(GFP_KERNEL,2); + if (!b1.b_data) { + pick_fastest_function(); + return; + } + b2.b_data = b1.b_data + 2*PAGE_SIZE + SIZE; + + b1.b_size = SIZE; + + printk(KERN_INFO "raid5: measuring checksumming speed\n"); + + sti(); /* should be safe */ + +#if defined(__sparc__) && !defined(__sparc_v9__) + printk(KERN_INFO "raid5: using high-speed SPARC checksum routine\n"); + xor_speed(&t_xor_block_SPARC,&b1,&b2); +#endif + +#ifdef CONFIG_X86_XMM + if (boot_cpu_data.mmu_cr4_features & X86_CR4_OSXMMEXCPT) { + printk(KERN_INFO + "raid5: KNI detected, trying cache-avoiding KNI checksum routine\n"); + /* we force the use of the KNI xor block because it + can write around l2. we may also be able + to load into the l1 only depending on how + the cpu deals with a load to a line that is + being prefetched. + */ + xor_speed(&t_xor_block_pIII_kni,&b1,&b2); + } +#endif /* CONFIG_X86_XMM */ + +#ifdef __i386__ + + if (md_cpu_has_mmx()) { + printk(KERN_INFO + "raid5: MMX detected, trying high-speed MMX checksum routines\n"); + xor_speed(&t_xor_block_pII_mmx,&b1,&b2); + xor_speed(&t_xor_block_p5_mmx,&b1,&b2); + } + +#endif /* __i386__ */ + + + xor_speed(&t_xor_block_8regs,&b1,&b2); + xor_speed(&t_xor_block_32regs,&b1,&b2); + + free_pages((unsigned long)b1.b_data,2); + pick_fastest_function(); +} + +#else /* __sparc_v9__ */ + +void calibrate_xor_block(void) +{ + printk(KERN_INFO "raid5: using high-speed VIS checksum routine\n"); + xor_block = xor_block_VIS; +} + +#endif /* __sparc_v9__ */ + +MD_EXPORT_SYMBOL(xor_block); + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/cdrom/cdrom.c linux.ac/drivers/cdrom/cdrom.c --- linux.vanilla/drivers/cdrom/cdrom.c Thu May 27 22:11:53 1999 +++ linux.ac/drivers/cdrom/cdrom.c Mon Jul 19 03:29:53 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.ac/drivers/char/Config.in --- linux.vanilla/drivers/char/Config.in Thu May 27 22:11:53 1999 +++ linux.ac/drivers/char/Config.in Fri Jul 2 23:14:12 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 @@ -145,6 +148,11 @@ 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 if [ "$CONFIG_RADIO_TYPHOON" != "n" ]; then @@ -159,6 +167,9 @@ if [ "$CONFIG_RADIO_ZOLTRIX" = "y" ]; then hex ' ZOLTRIX I/O port (0x20c or 0x30c)' CONFIG_RADIO_ZOLTRIX_PORT 20c fi + dep_tristate 'Zoran ZR36057/36060 support' CONFIG_VIDEO_ZORAN $CONFIG_VIDEO_DEV + dep_tristate ' Include support for Iomega Buz' CONFIG_VIDEO_BUZ $CONFIG_VIDEO_ZORAN + #dep_tristate ' Include support for LML33' CONFIG_VIDEO_LML33 $CONFIG_VIDEO_ZORAN fi endmenu @@ -173,6 +184,8 @@ endmenu tristate 'Double Talk PC internal speech card support' CONFIG_DTLK + +tristate 'Mappable DMA driver for 3D graphics cards' CONFIG_DMARAM mainmenu_option next_comment comment 'Ftape, the floppy tape device driver' diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/Makefile linux.ac/drivers/char/Makefile --- linux.vanilla/drivers/char/Makefile Thu May 27 22:11:53 1999 +++ linux.ac/drivers/char/Makefile Fri Jul 2 19:31:24 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 @@ -278,6 +294,14 @@ endif endif +ifeq ($(CONFIG_DMARAM),y) +L_OBJS += dmaram.o +else + ifeq ($(CONFIG_DMARAM),m) + M_OBJS += dmaram.o + endif +endif + ifeq ($(CONFIG_RTC),y) L_OBJS += rtc.o endif @@ -346,6 +370,30 @@ endif endif +ifeq ($(CONFIG_VIDEO_ZORAN),y) +L_OBJS += buz.o +else + ifeq ($(CONFIG_VIDEO_LML33),m) + M_OBJS += buz.o + endif +endif + +ifeq ($(CONFIG_VIDEO_LML33),y) +L_OBJS += bt856.o bt819.o +else + ifeq ($(CONFIG_VIDEO_LML33),m) + M_OBJS += bt856.o bt819.o + endif +endif + +ifeq ($(CONFIG_VIDEO_BUZ),y) +L_OBJS += saa7111.o saa7185.o +else + ifeq ($(CONFIG_VIDEO_BUZ),m) + M_OBJS += saa7111.o saa7185.o + endif +endif + ifeq ($(CONFIG_VIDEO_PMS),y) L_OBJS += pms.o else @@ -362,6 +410,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 +533,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.ac/drivers/char/bttv.c --- linux.vanilla/drivers/char/bttv.c Tue Jun 15 16:49:48 1999 +++ linux.ac/drivers/char/bttv.c Mon Jul 19 03:50:23 1999 @@ -81,8 +81,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 +110,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 +129,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 +217,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 +235,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 +570,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 +854,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 +912,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 +921,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 +985,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 +1022,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 +1038,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 +1068,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 +1081,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 +1193,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 +1218,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 +1328,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 +1522,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 +1709,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 +2317,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 +3159,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 +3214,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 +3379,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 +3435,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 +3453,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 +3550,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 +3568,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 +3592,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 +3871,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.ac/drivers/char/bttv.h --- linux.vanilla/drivers/char/bttv.h Tue Jun 15 16:49:48 1999 +++ linux.ac/drivers/char/bttv.h Mon Jul 19 05:19:20 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/buz.c linux.ac/drivers/char/buz.c --- linux.vanilla/drivers/char/buz.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/char/buz.c Mon Jul 19 03:45:43 1999 @@ -0,0 +1,3481 @@ +#define MAX_KMALLOC_MEM (512*1024) +/* + buz - Iomega Buz driver version 1.0 + + Copyright (C) 1999 Rainer Johanni + + based on + + buz.0.0.3 Copyright (C) 1998 Dave Perks + + and + + bttv - Bt848 frame grabber driver + + Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include "buz.h" +#include +#include + +#define IRQ_MASK ( ZR36057_ISR_GIRQ0 | /* ZR36057_ISR_GIRQ1 | ZR36057_ISR_CodRepIRQ | */ ZR36057_ISR_JPEGRepIRQ ) +#define GPIO_MASK 0xdf + +/* + + BUZ + + GPIO0 = 1, take board out of reset + GPIO1 = 1, take JPEG codec out of sleep mode + GPIO3 = 1, deassert FRAME# to 36060 + + + GIRQ0 signals a vertical sync of the video signal + GIRQ1 signals that ZR36060's DATERR# line is asserted. + + SAA7111A + + In their infinite wisdom, the Iomega engineers decided to + use the same input line for composite and S-Video Color, + although there are two entries not connected at all! + Through this ingenious strike, it is not possible to + keep two running video sources connected at the same time + to Composite and S-VHS input! + + mode 0 - N/C + mode 1 - S-Video Y + mode 2 - noise or something I don't know + mode 3 - Composite and S-Video C + mode 4 - N/C + mode 5 - S-Video (gain C independently selectable of gain Y) + mode 6 - N/C + mode 7 - S-Video (gain C adapted to gain Y) + */ + +#define MAJOR_VERSION 1 /* driver major version */ +#define MINOR_VERSION 0 /* driver minor version */ + +#define BUZ_NAME "Iomega BUZ V-1.0" /* name of the driver */ + +#define DEBUG(x) /* Debug driver */ +#define IDEBUG(x) /* Debug interrupt handler */ +#define IOCTL_DEBUG(x) + + +/* The parameters for this driver */ + +/* + The video mem address of the video card. + The driver has a little database for some videocards + to determine it from there. If your video card is not in there + you have either to give it to the driver as a parameter + or set in in a VIDIOCSFBUF ioctl + */ + +static unsigned long vidmem = 0; /* Video memory base address */ + +/* Special purposes only: */ + +static int triton = 0; /* 0=no, 1=yes */ +static int natoma = 0; /* 0=no, 1=yes */ + +/* + Number and size of grab buffers for Video 4 Linux + The vast majority of applications should not need more than 2, + the very popular BTTV driver actually does ONLY have 2. + Time sensitive applications might need more, the maximum + is VIDEO_MAX_FRAME (defined in ). + + The size is set so that the maximum possible request + can be satisfied. Decrease it, if bigphys_area alloc'd + memory is low. If you don't have the bigphys_area patch, + set it to 128 KB. Will you allow only to grab small + images with V4L, but that's better than nothing. + + v4l_bufsize has to be given in KB ! + + */ + +static int v4l_nbufs = 2; +static int v4l_bufsize = 128; /* Everybody should be able to work with this setting */ + +/* + Default input and video norm at startup of the driver. + */ + +static int default_input = 0; /* 0=Composite, 1=S-VHS */ +static int default_norm = 0; /* 0=PAL, 1=NTSC */ + +MODULE_PARM(vidmem, "i"); +MODULE_PARM(triton, "i"); +MODULE_PARM(natoma, "i"); +MODULE_PARM(v4l_nbufs, "i"); +MODULE_PARM(v4l_bufsize, "i"); +MODULE_PARM(default_input, "i"); +MODULE_PARM(default_norm, "i"); + +/* Anybody who uses more than four? */ +#define BUZ_MAX 4 + +static int zoran_num; /* number of Buzs in use */ +static struct zoran zoran[BUZ_MAX]; + +/* forward references */ + +static void v4l_fbuffer_free(struct zoran *zr); +static void jpg_fbuffer_free(struct zoran *zr); +static void zoran_feed_stat_com(struct zoran *zr); + + + +/* + * Allocate the V4L grab buffers + * + * These have to be pysically contiguous. + * If v4l_bufsize <= MAX_KMALLOC_MEM we use kmalloc + */ + +static int v4l_fbuffer_alloc(struct zoran *zr) +{ + int i, off; + unsigned char *mem; + + for (i = 0; i < v4l_nbufs; i++) { + if (zr->v4l_gbuf[i].fbuffer) + printk(KERN_WARNING "%s: v4l_fbuffer_alloc: buffer %d allready allocated ?\n", zr->name, i); + + if (v4l_bufsize <= MAX_KMALLOC_MEM) { + /* Use kmalloc */ + + mem = (unsigned char *) kmalloc(v4l_bufsize, GFP_KERNEL); + if (mem == 0) { + printk(KERN_ERR "%s: kmalloc for V4L bufs failed\n", zr->name); + v4l_fbuffer_free(zr); + return -ENOBUFS; + } + zr->v4l_gbuf[i].fbuffer = mem; + zr->v4l_gbuf[i].fbuffer_phys = virt_to_phys(mem); + zr->v4l_gbuf[i].fbuffer_bus = virt_to_bus(mem); + for (off = 0; off < v4l_bufsize; off += PAGE_SIZE) + mem_map_reserve(MAP_NR(mem + off)); + DEBUG(printk(BUZ_INFO ": V4L frame %d mem 0x%x (bus: 0x%x=%d)\n", i, mem, virt_to_bus(mem), virt_to_bus(mem))); + } else { + return -ENOBUFS; + } + } + + return 0; +} + +/* free the V4L grab buffers */ +static void v4l_fbuffer_free(struct zoran *zr) +{ + int i, off; + unsigned char *mem; + + for (i = 0; i < v4l_nbufs; i++) { + if (!zr->v4l_gbuf[i].fbuffer) + continue; + + mem = zr->v4l_gbuf[i].fbuffer; + for (off = 0; off < v4l_bufsize; off += PAGE_SIZE) + mem_map_unreserve(MAP_NR(mem + off)); + kfree((void *) zr->v4l_gbuf[i].fbuffer); + zr->v4l_gbuf[i].fbuffer = NULL; + } +} + +/* + * Allocate the MJPEG grab buffers. + * + * If the requested buffer size is smaller than MAX_KMALLOC_MEM, + * kmalloc is used to request a physically contiguous area, + * else we allocate the memory in framgents with get_free_page. + * + * If a Natoma chipset is present and this is a revision 1 zr36057, + * each MJPEG buffer needs to be physically contiguous. + * (RJ: This statement is from Dave Perks' original driver, + * I could never check it because I have a zr36067) + * The driver cares about this because it reduces the buffer + * size to MAX_KMALLOC_MEM in that case (which forces contiguous allocation). + * + * RJ: The contents grab buffers needs never be accessed in the driver. + * Therefore there is no need to allocate them with vmalloc in order + * to get a contiguous virtual memory space. + * I don't understand why many other drivers first allocate them with + * vmalloc (which uses internally also get_free_page, but delivers you + * virtual addresses) and then again have to make a lot of efforts + * to get the physical address. + * + */ + +static int jpg_fbuffer_alloc(struct zoran *zr) +{ + int i, j, off, alloc_contig; + unsigned long mem; + + /* Decide if we should alloc contiguous or fragmented memory */ + /* This has to be identical in jpg_fbuffer_alloc and jpg_fbuffer_free */ + + alloc_contig = (zr->jpg_bufsize < MAX_KMALLOC_MEM); + + for (i = 0; i < zr->jpg_nbufs; i++) { + if (zr->jpg_gbuf[i].frag_tab) + printk(KERN_WARNING "%s: jpg_fbuffer_alloc: buffer %d allready allocated ???\n", zr->name, i); + + /* Allocate fragment table for this buffer */ + + mem = get_free_page(GFP_KERNEL); + if (mem == 0) { + printk(KERN_ERR "%s: jpg_fbuffer_alloc: get_free_page (frag_tab) failed for buffer %d\n", zr->name, i); + jpg_fbuffer_free(zr); + return -ENOBUFS; + } + memset((void *) mem, 0, PAGE_SIZE); + zr->jpg_gbuf[i].frag_tab = (u32 *) mem; + zr->jpg_gbuf[i].frag_tab_bus = virt_to_bus((void *) mem); + + if (alloc_contig) { + mem = (unsigned long) kmalloc(zr->jpg_bufsize, GFP_KERNEL); + if (mem == 0) { + jpg_fbuffer_free(zr); + return -ENOBUFS; + } + zr->jpg_gbuf[i].frag_tab[0] = virt_to_bus((void *) mem); + zr->jpg_gbuf[i].frag_tab[1] = ((zr->jpg_bufsize / 4) << 1) | 1; + for (off = 0; off < zr->jpg_bufsize; off += PAGE_SIZE) + mem_map_reserve(MAP_NR(mem + off)); + } else { + /* jpg_bufsize is alreay page aligned */ + for (j = 0; j < zr->jpg_bufsize / PAGE_SIZE; j++) { + mem = get_free_page(GFP_KERNEL); + if (mem == 0) { + jpg_fbuffer_free(zr); + return -ENOBUFS; + } + zr->jpg_gbuf[i].frag_tab[2 * j] = virt_to_bus((void *) mem); + zr->jpg_gbuf[i].frag_tab[2 * j + 1] = (PAGE_SIZE / 4) << 1; + mem_map_reserve(MAP_NR(mem)); + } + + zr->jpg_gbuf[i].frag_tab[2 * j - 1] |= 1; + } + } + + DEBUG(printk("jpg_fbuffer_alloc: %d KB allocated\n", + (zr->jpg_nbufs * zr->jpg_bufsize) >> 10)); + zr->jpg_buffers_allocated = 1; + return 0; +} + +/* free the MJPEG grab buffers */ +static void jpg_fbuffer_free(struct zoran *zr) +{ + int i, j, off, alloc_contig; + unsigned char *mem; + + /* Decide if we should alloc contiguous or fragmented memory */ + /* This has to be identical in jpg_fbuffer_alloc and jpg_fbuffer_free */ + + alloc_contig = (zr->jpg_bufsize < MAX_KMALLOC_MEM); + + for (i = 0; i < zr->jpg_nbufs; i++) { + if (!zr->jpg_gbuf[i].frag_tab) + continue; + + if (alloc_contig) { + if (zr->jpg_gbuf[i].frag_tab[0]) { + mem = (unsigned char *) bus_to_virt(zr->jpg_gbuf[i].frag_tab[0]); + for (off = 0; off < zr->jpg_bufsize; off += PAGE_SIZE) + mem_map_unreserve(MAP_NR(mem + off)); + kfree((void *) mem); + zr->jpg_gbuf[i].frag_tab[0] = 0; + zr->jpg_gbuf[i].frag_tab[1] = 0; + } + } else { + for (j = 0; j < zr->jpg_bufsize / PAGE_SIZE; j++) { + if (!zr->jpg_gbuf[i].frag_tab[2 * j]) + break; + mem_map_unreserve(MAP_NR(bus_to_virt(zr->jpg_gbuf[i].frag_tab[2 * j]))); + free_page((unsigned long) bus_to_virt(zr->jpg_gbuf[i].frag_tab[2 * j])); + zr->jpg_gbuf[i].frag_tab[2 * j] = 0; + zr->jpg_gbuf[i].frag_tab[2 * j + 1] = 0; + } + } + + free_page((unsigned long) zr->jpg_gbuf[i].frag_tab); + zr->jpg_gbuf[i].frag_tab = NULL; + } + zr->jpg_buffers_allocated = 0; +} + + +/* ----------------------------------------------------------------------- */ + +/* I2C functions */ + +#define I2C_DELAY 10 + + +/* software I2C functions */ + +static void i2c_setlines(struct i2c_bus *bus, int ctrl, int data) +{ + struct zoran *zr = (struct zoran *) bus->data; + btwrite((data << 1) | ctrl, ZR36057_I2CBR); + btread(ZR36057_I2CBR); + udelay(I2C_DELAY); +} + +static int i2c_getdataline(struct i2c_bus *bus) +{ + struct zoran *zr = (struct zoran *) bus->data; + return (btread(ZR36057_I2CBR) >> 1) & 1; +} + +void attach_inform(struct i2c_bus *bus, int id) +{ + DEBUG(struct zoran *zr = (struct zoran *) bus->data); + DEBUG(printk(BUZ_DEBUG "-%u: i2c attach %02x\n", zr->id, id)); +} + +void detach_inform(struct i2c_bus *bus, int id) +{ + DEBUG(struct zoran *zr = (struct zoran *) bus->data); + DEBUG(printk(BUZ_DEBUG "-%u: i2c detach %02x\n", zr->id, id)); +} + +static struct i2c_bus zoran_i2c_bus_template = +{ + "zr36057", + I2C_BUSID_BT848, + NULL, + + SPIN_LOCK_UNLOCKED, + + attach_inform, + detach_inform, + + i2c_setlines, + i2c_getdataline, + NULL, + NULL, +}; + + +/* ----------------------------------------------------------------------- */ + +static void GPIO(struct zoran *zr, unsigned bit, unsigned value) +{ + u32 reg; + u32 mask; + + mask = 1 << (24 + bit); + reg = btread(ZR36057_GPPGCR1) & ~mask; + if (value) { + reg |= mask; + } + btwrite(reg, ZR36057_GPPGCR1); + /* Stop any PCI posting on the GPIO bus */ + btread(ZR36057_I2CBR); +} + + +/* + * Set the registers for the size we have specified. Don't bother + * trying to understand this without the ZR36057 manual in front of + * you [AC]. + * + * PS: The manual is free for download in .pdf format from + * www.zoran.com - nicely done those folks. + */ + +struct tvnorm { + u16 Wt, Wa, Ht, Ha, HStart, VStart; +}; + +static struct tvnorm tvnorms[] = +{ + /* PAL-BDGHI */ + {864, 720, 625, 576, 31, 16}, + /* NTSC */ + {858, 720, 525, 480, 21, 8}, +}; +#define TVNORMS (sizeof(tvnorms) / sizeof(tvnorm)) + +static int format2bpp(int format) +{ + int bpp; + + /* Determine the number of bytes per pixel for the video format requested */ + + switch (format) { + + case VIDEO_PALETTE_YUV422: + bpp = 2; + break; + + case VIDEO_PALETTE_RGB555: + bpp = 2; + break; + + case VIDEO_PALETTE_RGB565: + bpp = 2; + break; + + case VIDEO_PALETTE_RGB24: + bpp = 3; + break; + + case VIDEO_PALETTE_RGB32: + bpp = 4; + break; + + default: + bpp = 0; + } + + return bpp; +} + +/* + * set geometry + */ +static void zr36057_set_vfe(struct zoran *zr, int video_width, int video_height, + unsigned int video_format) +{ + struct tvnorm *tvn; + unsigned HStart, HEnd, VStart, VEnd; + unsigned DispMode; + unsigned VidWinWid, VidWinHt; + unsigned hcrop1, hcrop2, vcrop1, vcrop2; + unsigned Wa, We, Ha, He; + unsigned X, Y, HorDcm, VerDcm; + u32 reg; + unsigned mask_line_size; + + if (zr->params.norm < 0 || zr->params.norm > 1) { + printk(KERN_ERR "%s: set_vfe: video_norm = %d not valid\n", zr->name, zr->params.norm); + return; + } + if (video_width < BUZ_MIN_WIDTH || video_height < BUZ_MIN_HEIGHT) { + printk(KERN_ERR "%s: set_vfe: w=%d h=%d not valid\n", zr->name, video_width, video_height); + return; + } + tvn = &tvnorms[zr->params.norm]; + + Wa = tvn->Wa; + Ha = tvn->Ha; + + /* if window has more than half of active height, + switch on interlacing - we want the full information */ + + zr->video_interlace = (video_height > Ha / 2); + +/**** zr36057 ****/ + + /* horizontal */ + VidWinWid = video_width; + X = (VidWinWid * 64 + tvn->Wa - 1) / tvn->Wa; + We = (VidWinWid * 64) / X; + HorDcm = 64 - X; + hcrop1 = 2 * ((tvn->Wa - We) / 4); + hcrop2 = tvn->Wa - We - hcrop1; + HStart = tvn->HStart | 1; + HEnd = HStart + tvn->Wa - 1; + HStart += hcrop1; + HEnd -= hcrop2; + reg = ((HStart & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HStart) + | ((HEnd & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HEnd); + reg |= ZR36057_VFEHCR_HSPol; + btwrite(reg, ZR36057_VFEHCR); + + /* Vertical */ + DispMode = !zr->video_interlace; + VidWinHt = DispMode ? video_height : video_height / 2; + Y = (VidWinHt * 64 * 2 + tvn->Ha - 1) / tvn->Ha; + He = (VidWinHt * 64) / Y; + VerDcm = 64 - Y; + vcrop1 = (tvn->Ha / 2 - He) / 2; + vcrop2 = tvn->Ha / 2 - He - vcrop1; + VStart = tvn->VStart; + VEnd = VStart + tvn->Ha / 2 - 1; + VStart += vcrop1; + VEnd -= vcrop2; + reg = ((VStart & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VStart) + | ((VEnd & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VEnd); + reg |= ZR36057_VFEVCR_VSPol; + btwrite(reg, ZR36057_VFEVCR); + + /* scaler and pixel format */ + reg = 0 // ZR36057_VFESPFR_ExtFl /* Trying to live without ExtFl */ + | (HorDcm << ZR36057_VFESPFR_HorDcm) + | (VerDcm << ZR36057_VFESPFR_VerDcm) + | (DispMode << ZR36057_VFESPFR_DispMode) + | ZR36057_VFESPFR_LittleEndian; + /* RJ: I don't know, why the following has to be the opposite + of the corresponding ZR36060 setting, but only this way + we get the correct colors when uncompressing to the screen */ + reg |= ZR36057_VFESPFR_VCLKPol; + /* RJ: Don't know if that is needed for NTSC also */ + reg |= ZR36057_VFESPFR_TopField; + switch (video_format) { + + case VIDEO_PALETTE_YUV422: + reg |= ZR36057_VFESPFR_YUV422; + break; + + case VIDEO_PALETTE_RGB555: + reg |= ZR36057_VFESPFR_RGB555 | ZR36057_VFESPFR_ErrDif; + break; + + case VIDEO_PALETTE_RGB565: + reg |= ZR36057_VFESPFR_RGB565 | ZR36057_VFESPFR_ErrDif; + break; + + case VIDEO_PALETTE_RGB24: + reg |= ZR36057_VFESPFR_RGB888 | ZR36057_VFESPFR_Pack24; + break; + + case VIDEO_PALETTE_RGB32: + reg |= ZR36057_VFESPFR_RGB888; + break; + + default: + printk(KERN_INFO "%s: Unknown color_fmt=%x\n", zr->name, video_format); + return; + + } + if (HorDcm >= 48) { + reg |= 3 << ZR36057_VFESPFR_HFilter; /* 5 tap filter */ + } else if (HorDcm >= 32) { + reg |= 2 << ZR36057_VFESPFR_HFilter; /* 4 tap filter */ + } else if (HorDcm >= 16) { + reg |= 1 << ZR36057_VFESPFR_HFilter; /* 3 tap filter */ + } + btwrite(reg, ZR36057_VFESPFR); + + /* display configuration */ + + reg = (16 << ZR36057_VDCR_MinPix) + | (VidWinHt << ZR36057_VDCR_VidWinHt) + | (VidWinWid << ZR36057_VDCR_VidWinWid); + if (triton) + reg &= ~ZR36057_VDCR_Triton; + else + reg |= ZR36057_VDCR_Triton; + btwrite(reg, ZR36057_VDCR); + + /* Write overlay clipping mask data, but don't enable overlay clipping */ + /* RJ: since this makes only sense on the screen, we use + zr->window.width instead of video_width */ + + mask_line_size = (BUZ_MAX_WIDTH + 31) / 32; + reg = virt_to_bus(zr->overlay_mask); + btwrite(reg, ZR36057_MMTR); + reg = virt_to_bus(zr->overlay_mask + mask_line_size); + btwrite(reg, ZR36057_MMBR); + reg = mask_line_size - (zr->window.width + 31) / 32; + if (DispMode == 0) + reg += mask_line_size; + reg <<= ZR36057_OCR_MaskStride; + btwrite(reg, ZR36057_OCR); + +} + +/* + * Switch overlay on or off + */ + +static void zr36057_overlay(struct zoran *zr, int on) +{ + int fmt, bpp; + u32 reg; + + if (on) { + /* do the necessary settings ... */ + + btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR); /* switch it off first */ + + switch (zr->buffer.depth) { + case 15: + fmt = VIDEO_PALETTE_RGB555; + bpp = 2; + break; + case 16: + fmt = VIDEO_PALETTE_RGB565; + bpp = 2; + break; + case 24: + fmt = VIDEO_PALETTE_RGB24; + bpp = 3; + break; + case 32: + fmt = VIDEO_PALETTE_RGB32; + bpp = 4; + break; + default: + fmt = 0; + bpp = 0; + } + + zr36057_set_vfe(zr, zr->window.width, zr->window.height, fmt); + + /* Start and length of each line MUST be 4-byte aligned. + This should be allready checked before the call to this routine. + All error messages are internal driver checking only! */ + + /* video display top and bottom registers */ + + reg = (u32) zr->buffer.base + + zr->window.x * bpp + + zr->window.y * zr->buffer.bytesperline; + btwrite(reg, ZR36057_VDTR); + if (reg & 3) + printk(KERN_ERR "%s: zr36057_overlay: video_address not aligned\n", zr->name); + if (zr->video_interlace) + reg += zr->buffer.bytesperline; + btwrite(reg, ZR36057_VDBR); + + /* video stride, status, and frame grab register */ + + reg = zr->buffer.bytesperline - zr->window.width * bpp; + if (zr->video_interlace) + reg += zr->buffer.bytesperline; + if (reg & 3) + printk(KERN_ERR "%s: zr36057_overlay: video_stride not aligned\n", zr->name); + reg = (reg << ZR36057_VSSFGR_DispStride); + reg |= ZR36057_VSSFGR_VidOvf; /* clear overflow status */ + btwrite(reg, ZR36057_VSSFGR); + + /* Set overlay clipping */ + + if (zr->window.clipcount) + btor(ZR36057_OCR_OvlEnable, ZR36057_OCR); + + /* ... and switch it on */ + + btor(ZR36057_VDCR_VidEn, ZR36057_VDCR); + } else { + /* Switch it off */ + + btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR); + } +} + +/* + * The overlay mask has one bit for each pixel on a scan line, + * and the maximum window size is BUZ_MAX_WIDTH * BUZ_MAX_HEIGHT pixels. + */ +static void write_overlay_mask(struct zoran *zr, struct video_clip *vp, int count) +{ + unsigned mask_line_size = (BUZ_MAX_WIDTH + 31) / 32; + u32 *mask; + int x, y, width, height; + unsigned i, j, k; + u32 reg; + + /* fill mask with one bits */ + memset(zr->overlay_mask, ~0, mask_line_size * 4 * BUZ_MAX_HEIGHT); + reg = 0; + + for (i = 0; i < count; ++i) { + /* pick up local copy of clip */ + x = vp[i].x; + y = vp[i].y; + width = vp[i].width; + height = vp[i].height; + + /* trim clips that extend beyond the window */ + if (x < 0) { + width += x; + x = 0; + } + if (y < 0) { + height += y; + y = 0; + } + if (x + width > zr->window.width) { + width = zr->window.width - x; + } + if (y + height > zr->window.height) { + height = zr->window.height - y; + } + /* ignore degenerate clips */ + if (height <= 0) { + continue; + } + if (width <= 0) { + continue; + } + /* apply clip for each scan line */ + for (j = 0; j < height; ++j) { + /* reset bit for each pixel */ + /* this can be optimized later if need be */ + mask = zr->overlay_mask + (y + j) * mask_line_size; + for (k = 0; k < width; ++k) { + mask[(x + k) / 32] &= ~((u32) 1 << (x + k) % 32); + } + } + } +} + +/* Enable/Disable uncompressed memory grabbing of the 36057 */ + +static void zr36057_set_memgrab(struct zoran *zr, int mode) +{ + if (mode) { + if (btread(ZR36057_VSSFGR) & (ZR36057_VSSFGR_SnapShot | ZR36057_VSSFGR_FrameGrab)) + printk(KERN_WARNING "%s: zr36057_set_memgrab_on with SnapShot or FrameGrab on ???\n", zr->name); + + /* switch on VSync interrupts */ + + btwrite(IRQ_MASK, ZR36057_ISR); // Clear Interrupts + + btor(ZR36057_ICR_GIRQ0, ZR36057_ICR); + + /* enable SnapShot */ + + btor(ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR); + + /* Set zr36057 video front end and enable video */ + +#ifdef XAWTV_HACK + zr36057_set_vfe(zr, zr->gwidth > 720 ? 720 : zr->gwidth, zr->gheight, zr->gformat); +#else + zr36057_set_vfe(zr, zr->gwidth, zr->gheight, zr->gformat); +#endif + + zr->v4l_memgrab_active = 1; + } else { + zr->v4l_memgrab_active = 0; + + /* switch off VSync interrupts */ + + btand(~ZR36057_ICR_GIRQ0, ZR36057_ICR); + + /* reenable grabbing to screen if it was running */ + + if (zr->v4l_overlay_active) { + zr36057_overlay(zr, 1); + } else { + btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR); + btand(~ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR); + } + } +} + +static int wait_grab_pending(struct zoran *zr) +{ + unsigned long flags; + + /* wait until all pending grabs are finished */ + + if (!zr->v4l_memgrab_active) + return 0; + + while (zr->v4l_pend_tail != zr->v4l_pend_head) { + interruptible_sleep_on(&zr->v4l_capq); + if (signal_pending(current)) + return -ERESTARTSYS; + } + + spin_lock_irqsave(&zr->lock, flags); + zr36057_set_memgrab(zr, 0); + spin_unlock_irqrestore(&zr->lock, flags); + + return 0; +} + +/* + * V4L Buffer grabbing + */ + +static int v4l_grab(struct zoran *zr, struct video_mmap *mp) +{ + unsigned long flags; + int res, bpp; + + /* + * There is a long list of limitations to what is allowed to be grabbed + * We don't output error messages her, since some programs (e.g. xawtv) + * just try several settings to find out what is valid or not. + */ + + /* No grabbing outside the buffer range! */ + + if (mp->frame >= v4l_nbufs || mp->frame < 0) + return -EINVAL; + + /* Check size and format of the grab wanted */ + + if (mp->height < BUZ_MIN_HEIGHT || mp->width < BUZ_MIN_WIDTH) + return -EINVAL; + if (mp->height > BUZ_MAX_HEIGHT || mp->width > BUZ_MAX_WIDTH) + return -EINVAL; + + bpp = format2bpp(mp->format); + if (bpp == 0) + return -EINVAL; + + /* Check against available buffer size */ + + if (mp->height * mp->width * bpp > v4l_bufsize) + return -EINVAL; + + /* The video front end needs 4-byte alinged line sizes */ + + if ((bpp == 2 && (mp->width & 1)) || (bpp == 3 && (mp->width & 3))) + return -EINVAL; + + /* + * To minimize the time spent in the IRQ routine, we avoid setting up + * the video front end there. + * If this grab has different parameters from a running streaming capture + * we stop the streaming capture and start it over again. + */ + + if (zr->v4l_memgrab_active && + (zr->gwidth != mp->width || zr->gheight != mp->height || zr->gformat != mp->format)) { + res = wait_grab_pending(zr); + if (res) + return res; + } + zr->gwidth = mp->width; + zr->gheight = mp->height; + zr->gformat = mp->format; + zr->gbpl = bpp * zr->gwidth; + + + spin_lock_irqsave(&zr->lock, flags); + + /* make sure a grab isn't going on currently with this buffer */ + + switch (zr->v4l_gbuf[mp->frame].state) { + + default: + case BUZ_STATE_PEND: + res = -EBUSY; /* what are you doing? */ + break; + + case BUZ_STATE_USER: + case BUZ_STATE_DONE: + /* since there is at least one unused buffer there's room for at least one more pend[] entry */ + zr->v4l_pend[zr->v4l_pend_head++ & V4L_MASK_FRAME] = mp->frame; + zr->v4l_gbuf[mp->frame].state = BUZ_STATE_PEND; + res = 0; + break; + + } + + /* put the 36057 into frame grabbing mode */ + + if (!res && !zr->v4l_memgrab_active) + zr36057_set_memgrab(zr, 1); + + spin_unlock_irqrestore(&zr->lock, flags); + + return res; +} + +/* + * Sync on a V4L buffer + */ + +static int v4l_sync(struct zoran *zr, int frame) +{ + unsigned long flags; + + + /* check passed-in frame number */ + if (frame >= v4l_nbufs || frame < 0) { + printk(KERN_ERR "%s: v4l_sync: frame %d is invalid\n", zr->name, frame); + return -EINVAL; + } + /* Check if is buffer was queued at all */ + + if (zr->v4l_gbuf[frame].state == BUZ_STATE_USER) { +// printk(KERN_ERR "%s: v4l_sync: Trying to sync on a buffer which was not queued?\n", zr->name); + return -EINVAL; + } + /* wait on this buffer to get ready */ + + while (zr->v4l_gbuf[frame].state == BUZ_STATE_PEND) { + interruptible_sleep_on(&zr->v4l_capq); + if (signal_pending(current)) + return -ERESTARTSYS; + } + + /* buffer should now be in BUZ_STATE_DONE */ + + if (zr->v4l_gbuf[frame].state != BUZ_STATE_DONE) + printk(KERN_ERR "%s: v4l_sync - internal error\n", zr->name); + + /* Check if streaming capture has finished */ + + spin_lock_irqsave(&zr->lock, flags); + + if (zr->v4l_pend_tail == zr->v4l_pend_head) + zr36057_set_memgrab(zr, 0); + + spin_unlock_irqrestore(&zr->lock, flags); + + return 0; +} +/***************************************************************************** + * * + * Set up the Buz-specific MJPEG part * + * * + *****************************************************************************/ + +/* + * Wait til post office is no longer busy + */ + +static int post_office_wait(struct zoran *zr) +{ + u32 por; + u32 ct=0; + + while (((por = btread(ZR36057_POR)) & (ZR36057_POR_POPen | ZR36057_POR_POTime)) == ZR36057_POR_POPen) { + ct++; + if(ct>100000) + { + printk(KERN_ERR "%s: timeout on post office.\n", zr->name); + return -1; + } + /* wait for something to happen */ + } + if ((por & ZR36057_POR_POPen) != 0) { + printk(KERN_WARNING "%s: pop pending %08x\n", zr->name, por); + return -1; + } +#if 0 + /* The LML 33 gets this bit wrong */ + + if ((por & (ZR36057_POR_POTime | ZR36057_POR_POPen)) != 0) { + printk(KERN_WARNING "%s: pop timeout %08x\n", zr->name, por); + return -1; + } +#endif + return 0; +} + +static int post_office_write(struct zoran *zr, unsigned guest, unsigned reg, unsigned value) +{ + u32 por; + + post_office_wait(zr); + por = ZR36057_POR_PODir | ZR36057_POR_POTime | ((guest & 7) << 20) | ((reg & 7) << 16) | (value & 0xFF); + btwrite(por, ZR36057_POR); + return post_office_wait(zr); +} + +static int post_office_read(struct zoran *zr, unsigned guest, unsigned reg) +{ + u32 por; + + post_office_wait(zr); + por = ZR36057_POR_POTime | ((guest & 7) << 20) | ((reg & 7) << 16); + btwrite(por, ZR36057_POR); + if (post_office_wait(zr) < 0) { + return -1; + } + return btread(ZR36057_POR) & 0xFF; +} + +static int zr36060_write_8(struct zoran *zr, unsigned reg, unsigned val) +{ + if (post_office_wait(zr) + || post_office_write(zr, 0, 1, reg >> 8) + || post_office_write(zr, 0, 2, reg)) { + return -1; + } + return post_office_write(zr, 0, 3, val); +} + +static int zr36060_write_16(struct zoran *zr, unsigned reg, unsigned val) +{ + if (zr36060_write_8(zr, reg + 0, val >> 8)) { + return -1; + } + return zr36060_write_8(zr, reg + 1, val >> 0); +} + +static int zr36060_write_24(struct zoran *zr, unsigned reg, unsigned val) +{ + if (zr36060_write_8(zr, reg + 0, val >> 16)) { + return -1; + } + return zr36060_write_16(zr, reg + 1, val >> 0); +} + +static int zr36060_write_32(struct zoran *zr, unsigned reg, unsigned val) +{ + if (zr36060_write_16(zr, reg + 0, val >> 16)) { + return -1; + } + return zr36060_write_16(zr, reg + 2, val >> 0); +} + +static u32 zr36060_read_8(struct zoran *zr, unsigned reg) +{ + if (post_office_wait(zr) + || post_office_write(zr, 0, 1, reg >> 8) + || post_office_write(zr, 0, 2, reg)) { + return -1; + } + return post_office_read(zr, 0, 3) & 0xFF; +} + +static int zr36060_reset(struct zoran *zr) +{ + return post_office_write(zr, 3, 0, 0); +} + +static void zr36060_sleep(struct zoran *zr, int sleep) +{ + GPIO(zr, 1, !sleep); +} + + +static void zr36060_set_jpg(struct zoran *zr, enum zoran_codec_mode mode) +{ + struct tvnorm *tvn; + u32 reg; + int size; + + reg = (1 << 0) /* CodeMstr */ + |(0 << 2) /* CFIS=0 */ + |(0 << 6) /* Endian=0 */ + |(0 << 7); /* Code16=0 */ + zr36060_write_8(zr, 0x002, reg); + + switch (mode) { + + case BUZ_MODE_MOTION_DECOMPRESS: + case BUZ_MODE_STILL_DECOMPRESS: + reg = 0x00; /* Codec mode = decompression */ + break; + + case BUZ_MODE_MOTION_COMPRESS: + case BUZ_MODE_STILL_COMPRESS: + default: + reg = 0xa4; /* Codec mode = compression with variable scale factor */ + break; + + } + zr36060_write_8(zr, 0x003, reg); + + reg = 0x00; /* reserved, mbz */ + zr36060_write_8(zr, 0x004, reg); + + reg = 0xff; /* 510 bits/block */ + zr36060_write_8(zr, 0x005, reg); + + /* JPEG markers */ + reg = (zr->params.jpeg_markers) & 0x38; /* DRI, DQT, DHT */ + if (zr->params.COM_len) + reg |= JPEG_MARKER_COM; + if (zr->params.APP_len) + reg |= JPEG_MARKER_APP; + zr36060_write_8(zr, 0x006, reg); + + reg = (0 << 3) /* DATERR=0 */ + |(0 << 2) /* END=0 */ + |(0 << 1) /* EOI=0 */ + |(0 << 0); /* EOAV=0 */ + zr36060_write_8(zr, 0x007, reg); + + /* code volume */ + + /* Target field size in pixels: */ + tvn = &tvnorms[zr->params.norm]; + size = (tvn->Ha / 2) * (tvn->Wa) / (zr->params.HorDcm) / (zr->params.VerDcm); + + /* Target compressed field size in bits: */ + size = size * 16; /* uncompressed size in bits */ + size = size * zr->params.quality / 400; /* quality = 100 is a compression ratio 1:4 */ + + /* Lower limit (arbitrary, 1 KB) */ + if (size < 8192) + size = 8192; + + /* Upper limit: 7/8 of the code buffers */ + if (size * zr->params.field_per_buff > zr->jpg_bufsize * 7) + size = zr->jpg_bufsize * 7 / zr->params.field_per_buff; + + reg = size; + zr36060_write_32(zr, 0x009, reg); + + /* how do we set initial SF as a function of quality parameter? */ + reg = 0x0100; /* SF=1.0 */ + zr36060_write_16(zr, 0x011, reg); + + reg = 0x00ffffff; /* AF=max */ + zr36060_write_24(zr, 0x013, reg); + + reg = 0x0000; /* test */ + zr36060_write_16(zr, 0x024, reg); +} + +static void zr36060_set_video(struct zoran *zr, enum zoran_codec_mode mode) +{ + struct tvnorm *tvn; + u32 reg; + + reg = (0 << 7) /* Video8=0 */ + |(0 << 6) /* Range=0 */ + |(0 << 3) /* FlDet=0 */ + |(1 << 2) /* FlVedge=1 */ + |(0 << 1) /* FlExt=0 */ + |(0 << 0); /* SyncMstr=0 */ + + /* According to ZR36067 documentation, FlDet should correspond + to the odd_even flag of the ZR36067 */ + if (zr->params.odd_even) + reg |= (1 << 3); + + if (mode != BUZ_MODE_STILL_DECOMPRESS) { + /* limit pixels to range 16..235 as per CCIR-601 */ + reg |= (1 << 6); /* Range=1 */ + } + zr36060_write_8(zr, 0x030, reg); + + reg = (0 << 7) /* VCLKPol=0 */ + |(0 << 6) /* PValPol=0 */ + |(1 << 5) /* PoePol=1 */ + |(0 << 4) /* SImgPol=0 */ + |(0 << 3) /* BLPol=0 */ + |(0 << 2) /* FlPol=0 */ + |(0 << 1) /* HSPol=0, sync on falling edge */ + |(1 << 0); /* VSPol=1 */ + zr36060_write_8(zr, 0x031, reg); + + switch (zr->params.HorDcm) { + default: + case 1: + reg = (0 << 0); + break; /* HScale = 0 */ + + case 2: + reg = (1 << 0); + break; /* HScale = 1 */ + + case 4: + reg = (2 << 0); + break; /* HScale = 2 */ + } + if (zr->params.VerDcm == 2) + reg |= (1 << 2); + zr36060_write_8(zr, 0x032, reg); + + reg = 0x80; /* BackY */ + zr36060_write_8(zr, 0x033, reg); + + reg = 0xe0; /* BackU */ + zr36060_write_8(zr, 0x034, reg); + + reg = 0xe0; /* BackV */ + zr36060_write_8(zr, 0x035, reg); + + /* sync generator */ + + tvn = &tvnorms[zr->params.norm]; + + reg = tvn->Ht - 1; /* Vtotal */ + zr36060_write_16(zr, 0x036, reg); + + reg = tvn->Wt - 1; /* Htotal */ + zr36060_write_16(zr, 0x038, reg); + + reg = 6 - 1; /* VsyncSize */ + zr36060_write_8(zr, 0x03a, reg); + + reg = 100 - 1; /* HsyncSize */ + zr36060_write_8(zr, 0x03b, reg); + + reg = tvn->VStart - 1; /* BVstart */ + zr36060_write_8(zr, 0x03c, reg); + + reg += tvn->Ha / 2; /* BVend */ + zr36060_write_16(zr, 0x03e, reg); + + reg = tvn->HStart - 1; /* BHstart */ + zr36060_write_8(zr, 0x03d, reg); + + reg += tvn->Wa; /* BHend */ + zr36060_write_16(zr, 0x040, reg); + + /* active area */ + reg = zr->params.img_y + tvn->VStart; /* Vstart */ + zr36060_write_16(zr, 0x042, reg); + + reg += zr->params.img_height; /* Vend */ + zr36060_write_16(zr, 0x044, reg); + + reg = zr->params.img_x + tvn->HStart; /* Hstart */ + zr36060_write_16(zr, 0x046, reg); + + reg += zr->params.img_width; /* Hend */ + zr36060_write_16(zr, 0x048, reg); + + /* subimage area */ + reg = zr->params.img_y + tvn->VStart; /* SVstart */ + zr36060_write_16(zr, 0x04a, reg); + + reg += zr->params.img_height; /* SVend */ + zr36060_write_16(zr, 0x04c, reg); + + reg = zr->params.img_x + tvn->HStart; /* SHstart */ + zr36060_write_16(zr, 0x04e, reg); + + reg += zr->params.img_width; /* SHend */ + zr36060_write_16(zr, 0x050, reg); +} + +static void zr36060_set_jpg_SOF(struct zoran *zr) +{ + u32 reg; + + + reg = 0xffc0; /* SOF marker */ + zr36060_write_16(zr, 0x060, reg); + + reg = 17; /* SOF length */ + zr36060_write_16(zr, 0x062, reg); + + reg = 8; /* precision 8 bits */ + zr36060_write_8(zr, 0x064, reg); + + reg = zr->params.img_height / zr->params.VerDcm; /* image height */ + zr36060_write_16(zr, 0x065, reg); + + reg = zr->params.img_width / zr->params.HorDcm; /* image width */ + zr36060_write_16(zr, 0x067, reg); + + reg = 3; /* 3 color components */ + zr36060_write_8(zr, 0x069, reg); + + reg = 0x002100; /* Y component */ + zr36060_write_24(zr, 0x06a, reg); + + reg = 0x011101; /* U component */ + zr36060_write_24(zr, 0x06d, reg); + + reg = 0x021101; /* V component */ + zr36060_write_24(zr, 0x070, reg); +} + +static void zr36060_set_jpg_SOS(struct zoran *zr) +{ + u32 reg; + + + reg = 0xffda; /* SOS marker */ + zr36060_write_16(zr, 0x07a, reg); + + reg = 12; /* SOS length */ + zr36060_write_16(zr, 0x07c, reg); + + reg = 3; /* 3 color components */ + zr36060_write_8(zr, 0x07e, reg); + + reg = 0x0000; /* Y component */ + zr36060_write_16(zr, 0x07f, reg); + + reg = 0x0111; /* U component */ + zr36060_write_16(zr, 0x081, reg); + + reg = 0x0211; /* V component */ + zr36060_write_16(zr, 0x083, reg); + + reg = 0x003f00; /* Start, end spectral scans */ + zr36060_write_24(zr, 0x085, reg); +} + +static void zr36060_set_jpg_DRI(struct zoran *zr) +{ + u32 reg; + + + reg = 0xffdd; /* DRI marker */ + zr36060_write_16(zr, 0x0c0, reg); + + reg = 4; /* DRI length */ + zr36060_write_16(zr, 0x0c2, reg); + + reg = 8; /* length in MCUs */ + zr36060_write_16(zr, 0x0c4, reg); +} + +static void zr36060_set_jpg_DQT(struct zoran *zr) +{ + unsigned i; + unsigned adr; + static const u8 dqt[] = + { + 0xff, 0xdb, /* DHT marker */ + 0x00, 0x84, /* DHT length */ + 0x00, /* table ID 0 */ + 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, + 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, + 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, + 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, + 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44, + 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, + 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, + 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63, + 0x01, /* table ID 1 */ + 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, + 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63 + }; + + /* write fixed quantitization tables */ + adr = 0x0cc; + for (i = 0; i < sizeof(dqt); ++i) { + zr36060_write_8(zr, adr++, dqt[i]); + } +} + +static void zr36060_set_jpg_DHT(struct zoran *zr) +{ + unsigned i; + unsigned adr; + static const u8 dht[] = + { + 0xff, 0xc4, /* DHT marker */ + 0x01, 0xa2, /* DHT length */ + 0x00, /* table class 0, ID 0 */ + 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, /* # codes of length 1..8 */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* # codes of length 8..16 */ + 0x00, /* values for codes of length 2 */ + 0x01, 0x02, 0x03, 0x04, 0x05, /* values for codes of length 3 */ + 0x06, /* values for codes of length 4 */ + 0x07, /* values for codes of length 5 */ + 0x08, /* values for codes of length 6 */ + 0x09, /* values for codes of length 7 */ + 0x0a, /* values for codes of length 8 */ + 0x0b, /* values for codes of length 9 */ + 0x01, /* table class 0, ID 1 */ + 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* # codes of length 1..8 */ + 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, /* # codes of length 9..16 */ + 0x00, 0x01, 0x02, /* values for codes of length 2 */ + 0x03, /* values for codes of length 3 */ + 0x04, /* values for codes of length 4 */ + 0x05, /* values for codes of length 5 */ + 0x06, /* values for codes of length 6 */ + 0x07, /* values for codes of length 7 */ + 0x08, /* values for codes of length 8 */ + 0x09, /* values for codes of length 9 */ + 0x0a, /* values for codes of length 10 */ + 0x0b, /* values for codes of length 11 */ + 0x10, + 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, + 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, + 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, + 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, + 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, + 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, + 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, + 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, + 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, + 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, + 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, + 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, + 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, + 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, + 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, + 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, + 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, + 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, + 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, + 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, + 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, + 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, + 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, + 0xf6, 0xf7, 0xf8, 0xf9, 0xfa + }; + + /* write fixed Huffman tables */ + adr = 0x1d4; + for (i = 0; i < sizeof(dht); ++i) { + zr36060_write_8(zr, adr++, dht[i]); + } +} + +static void zr36060_set_jpg_APP(struct zoran *zr) +{ + unsigned adr; + int len, i; + u32 reg; + + + len = zr->params.APP_len; + if (len < 0) + len = 0; + if (len > 60) + len = 60; + + i = zr->params.APPn; + if (i < 0) + i = 0; + if (i > 15) + i = 15; + + reg = 0xffe0 + i; /* APPn marker */ + zr36060_write_16(zr, 0x380, reg); + + reg = len + 2; /* APPn len */ + zr36060_write_16(zr, 0x382, reg); + + /* write APPn data */ + adr = 0x384; + for (i = 0; i < 60; i++) { + zr36060_write_8(zr, adr++, (i < len ? zr->params.APP_data[i] : 0)); + } +} + +static void zr36060_set_jpg_COM(struct zoran *zr) +{ + unsigned adr; + int len, i; + u32 reg; + + + len = zr->params.COM_len; + if (len < 0) + len = 0; + if (len > 60) + len = 60; + + reg = 0xfffe; /* COM marker */ + zr36060_write_16(zr, 0x3c0, reg); + + reg = len + 2; /* COM len */ + zr36060_write_16(zr, 0x3c2, reg); + + /* write COM data */ + adr = 0x3c4; + for (i = 0; i < 60; i++) { + zr36060_write_8(zr, adr++, (i < len ? zr->params.COM_data[i] : 0)); + } +} + +static void zr36060_set_cap(struct zoran *zr, enum zoran_codec_mode mode) +{ + unsigned i; + u32 reg; + + zr36060_reset(zr); + mdelay(10); + + reg = (0 << 7) /* Load=0 */ + |(1 << 0); /* SynRst=1 */ + zr36060_write_8(zr, 0x000, reg); + + zr36060_set_jpg(zr, mode); + zr36060_set_video(zr, mode); + zr36060_set_jpg_SOF(zr); + zr36060_set_jpg_SOS(zr); + zr36060_set_jpg_DRI(zr); + zr36060_set_jpg_DQT(zr); + zr36060_set_jpg_DHT(zr); + zr36060_set_jpg_APP(zr); + zr36060_set_jpg_COM(zr); + + reg = (1 << 7) /* Load=1 */ + |(0 << 0); /* SynRst=0 */ + zr36060_write_8(zr, 0x000, reg); + + /* wait for codec to unbusy */ + for (i = 0; i < 1000; ++i) { + reg = zr36060_read_8(zr, 0x001); + if ((reg & (1 << 7)) == 0) { + DEBUG(printk(KERN_DEBUG "060: loaded, loops=%u\n", i)); + return; + } + udelay(1000); + } + printk(KERN_INFO "060: stuck busy, statux=%02x\n", reg); +} + +static void zr36057_set_jpg(struct zoran *zr, enum zoran_codec_mode mode) +{ + struct tvnorm *tvn; + u32 reg; + int i; + + tvn = &tvnorms[zr->params.norm]; + + /* assert P_Reset */ + btwrite(0, ZR36057_JPC); + + /* re-initialize DMA ring stuff */ + zr->jpg_que_head = 0; + zr->jpg_dma_head = 0; + zr->jpg_dma_tail = 0; + zr->jpg_que_tail = 0; + zr->jpg_seq_num = 0; + for (i = 0; i < BUZ_NUM_STAT_COM; ++i) { + zr->stat_com[i] = 1; /* mark as unavailable to zr36057 */ + } + for (i = 0; i < zr->jpg_nbufs; i++) { + zr->jpg_gbuf[i].state = BUZ_STATE_USER; /* nothing going on */ + } + + /* MJPEG compression mode */ + switch (mode) { + + case BUZ_MODE_MOTION_COMPRESS: + default: + reg = ZR36057_JMC_MJPGCmpMode; + break; + + case BUZ_MODE_MOTION_DECOMPRESS: + reg = ZR36057_JMC_MJPGExpMode; + reg |= ZR36057_JMC_SyncMstr; + /* RJ: The following is experimental - improves the output to screen */ + if (zr->params.VFIFO_FB) + reg |= ZR36057_JMC_VFIFO_FB; + break; + + case BUZ_MODE_STILL_COMPRESS: + reg = ZR36057_JMC_JPGCmpMode; + break; + + case BUZ_MODE_STILL_DECOMPRESS: + reg = ZR36057_JMC_JPGExpMode; + break; + + } + reg |= ZR36057_JMC_JPG; + if (zr->params.field_per_buff == 1) + reg |= ZR36057_JMC_Fld_per_buff; + btwrite(reg, ZR36057_JMC); + + /* vertical */ + btor(ZR36057_VFEVCR_VSPol, ZR36057_VFEVCR); + reg = (6 << ZR36057_VSP_VsyncSize) | (tvn->Ht << ZR36057_VSP_FrmTot); + btwrite(reg, ZR36057_VSP); + reg = ((zr->params.img_y + tvn->VStart) << ZR36057_FVAP_NAY) + | (zr->params.img_height << ZR36057_FVAP_PAY); + btwrite(reg, ZR36057_FVAP); + + /* horizontal */ + btor(ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR); + reg = ((tvn->Wt - 100) << ZR36057_HSP_HsyncStart) | (tvn->Wt << ZR36057_HSP_LineTot); + btwrite(reg, ZR36057_HSP); + reg = ((zr->params.img_x + tvn->HStart) << ZR36057_FHAP_NAX) + | (zr->params.img_width << ZR36057_FHAP_PAX); + btwrite(reg, ZR36057_FHAP); + + /* field process parameters */ + if (zr->params.odd_even) + reg = ZR36057_FPP_Odd_Even; + else + reg = 0; + btwrite(reg, ZR36057_FPP); + + /* Set proper VCLK Polarity, else colors will be wrong during playback */ + btor(ZR36057_VFESPFR_VCLKPol, ZR36057_VFESPFR); + + /* code base address and FIFO threshold */ + reg = virt_to_bus(zr->stat_com); + btwrite(reg, ZR36057_JCBA); + reg = 0x50; + btwrite(reg, ZR36057_JCFT); + + /* JPEG codec guest ID */ + reg = (1 << ZR36057_JCGI_JPEGuestID) | (0 << ZR36057_JCGI_JPEGuestReg); + btwrite(reg, ZR36057_JCGI); + + /* Code transfer guest ID */ + reg = (0 << ZR36057_MCTCR_CodGuestID) | (3 << ZR36057_MCTCR_CodGuestReg); + reg |= ZR36057_MCTCR_CFlush; + btwrite(reg, ZR36057_MCTCR); + + /* deassert P_Reset */ + btwrite(ZR36057_JPC_P_Reset, ZR36057_JPC); +} + +static void zr36057_enable_jpg(struct zoran *zr, enum zoran_codec_mode mode) +{ + static int zero = 0; + static int one = 1; + + switch (mode) { + + case BUZ_MODE_MOTION_COMPRESS: + zr36060_set_cap(zr, mode); + zr36057_set_jpg(zr, mode); + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_ENABLE_OUTPUT, &one); + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER, ENCODER_SET_INPUT, &zero); + + /* deassert P_Reset, assert Code transfer enable */ + btwrite(IRQ_MASK, ZR36057_ISR); + btand(~ZR36057_MCTCR_CFlush, ZR36057_MCTCR); + break; + + case BUZ_MODE_MOTION_DECOMPRESS: + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_ENABLE_OUTPUT, &zero); + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER, ENCODER_SET_INPUT, &one); + zr36060_set_cap(zr, mode); + zr36057_set_jpg(zr, mode); + + /* deassert P_Reset, assert Code transfer enable */ + btwrite(IRQ_MASK, ZR36057_ISR); + btand(~ZR36057_MCTCR_CFlush, ZR36057_MCTCR); + break; + + case BUZ_MODE_IDLE: + default: + /* shut down processing */ + btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR); + btwrite(ZR36057_JPC_P_Reset, ZR36057_JPC); + btand(~ZR36057_JMC_VFIFO_FB, ZR36057_JMC); + btand(~ZR36057_JMC_SyncMstr, ZR36057_JMC); + btand(~ZR36057_JMC_Go_en, ZR36057_JMC); + btwrite(0, ZR36057_ISR); + zr36060_reset(zr); + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_ENABLE_OUTPUT, &one); + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER, ENCODER_SET_INPUT, &zero); + break; + + } + zr->codec_mode = mode; +} + +/* + * Queue a MJPEG buffer for capture/playback + */ + +static int jpg_qbuf(struct zoran *zr, int frame, enum zoran_codec_mode mode) +{ + unsigned long flags; + int res; + + /* Check if buffers are allocated */ + + if (!zr->jpg_buffers_allocated) { + printk(KERN_ERR "%s: jpg_qbuf: buffers not yet allocated\n", zr->name); + return -ENOMEM; + } + /* Does the user want to stop streaming? */ + + if (frame < 0) { + if (zr->codec_mode == mode) { + zr36057_enable_jpg(zr, BUZ_MODE_IDLE); + return 0; + } else { + printk(KERN_ERR "%s: jpg_qbuf - stop streaming but not in streaming mode\n", zr->name); + return -EINVAL; + } + } + /* No grabbing outside the buffer range! */ + + if (frame >= zr->jpg_nbufs) { + printk(KERN_ERR "%s: jpg_qbuf: buffer %d out of range\n", zr->name, frame); + return -EINVAL; + } + /* what is the codec mode right now? */ + + if (zr->codec_mode == BUZ_MODE_IDLE) { + /* Ok load up the zr36060 and go */ + zr36057_enable_jpg(zr, mode); + } else if (zr->codec_mode != mode) { + /* wrong codec mode active - invalid */ + printk(KERN_ERR "%s: jpg_qbuf - codec in wrong mode\n", zr->name); + return -EINVAL; + } + spin_lock_irqsave(&zr->lock, flags); + + /* make sure a grab isn't going on currently with this buffer */ + + switch (zr->jpg_gbuf[frame].state) { + + default: + case BUZ_STATE_DMA: + case BUZ_STATE_PEND: + case BUZ_STATE_DONE: + res = -EBUSY; /* what are you doing? */ + break; + + case BUZ_STATE_USER: + /* since there is at least one unused buffer there's room for at least one more pend[] entry */ + zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] = frame; + zr->jpg_gbuf[frame].state = BUZ_STATE_PEND; + zoran_feed_stat_com(zr); + res = 0; + break; + + } + + spin_unlock_irqrestore(&zr->lock, flags); + + /* Start the zr36060 when the first frame is queued */ + if (zr->jpg_que_head == 1) { + btor(ZR36057_JMC_Go_en, ZR36057_JMC); + btwrite(ZR36057_JPC_P_Reset | ZR36057_JPC_CodTrnsEn | ZR36057_JPC_Active, ZR36057_JPC); + } + return res; +} + +/* + * Sync on a MJPEG buffer + */ + +static int jpg_sync(struct zoran *zr, struct zoran_sync *bs) +{ + unsigned long flags; + int frame; + + if (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS && + zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) { + return -EINVAL; + } + while (zr->jpg_que_tail == zr->jpg_dma_tail) { + interruptible_sleep_on(&zr->jpg_capq); + if (signal_pending(current)) + return -ERESTARTSYS; + } + + spin_lock_irqsave(&zr->lock, flags); + + frame = zr->jpg_pend[zr->jpg_que_tail++ & BUZ_MASK_FRAME]; + + /* buffer should now be in BUZ_STATE_DONE */ + + if (zr->jpg_gbuf[frame].state != BUZ_STATE_DONE) + printk(KERN_ERR "%s: jpg_sync - internal error\n", zr->name); + + *bs = zr->jpg_gbuf[frame].bs; + zr->jpg_gbuf[frame].state = BUZ_STATE_USER; + + spin_unlock_irqrestore(&zr->lock, flags); + + return 0; +} + +/* when this is called the spinlock must be held */ +static void zoran_feed_stat_com(struct zoran *zr) +{ + /* move frames from pending queue to DMA */ + + int frame, i, max_stat_com; + + max_stat_com = (zr->params.TmpDcm == 1) ? BUZ_NUM_STAT_COM : (BUZ_NUM_STAT_COM >> 1); + + while ((zr->jpg_dma_head - zr->jpg_dma_tail) < max_stat_com + && zr->jpg_dma_head != zr->jpg_que_head) { + + frame = zr->jpg_pend[zr->jpg_dma_head & BUZ_MASK_FRAME]; + if (zr->params.TmpDcm == 1) { + /* fill 1 stat_com entry */ + i = zr->jpg_dma_head & BUZ_MASK_STAT_COM; + zr->stat_com[i] = zr->jpg_gbuf[frame].frag_tab_bus; + } else { + /* fill 2 stat_com entries */ + i = (zr->jpg_dma_head & 1) * 2; + zr->stat_com[i] = zr->jpg_gbuf[frame].frag_tab_bus; + zr->stat_com[i + 1] = zr->jpg_gbuf[frame].frag_tab_bus; + } + zr->jpg_gbuf[frame].state = BUZ_STATE_DMA; + zr->jpg_dma_head++; + + } +} + +/* when this is called the spinlock must be held */ +static void zoran_reap_stat_com(struct zoran *zr) +{ + /* move frames from DMA queue to done queue */ + + int i; + u32 stat_com; + unsigned int seq; + unsigned int dif; + int frame; + struct zoran_gbuffer *gbuf; + + /* In motion decompress we don't have a hardware frame counter, + we just count the interrupts here */ + + if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) + zr->jpg_seq_num++; + + while (zr->jpg_dma_tail != zr->jpg_dma_head) { + if (zr->params.TmpDcm == 1) + i = zr->jpg_dma_tail & BUZ_MASK_STAT_COM; + else + i = (zr->jpg_dma_tail & 1) * 2 + 1; + + stat_com = zr->stat_com[i]; + + if ((stat_com & 1) == 0) { + return; + } + frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME]; + gbuf = &zr->jpg_gbuf[frame]; + get_fast_time(&gbuf->bs.timestamp); + + if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { + gbuf->bs.length = (stat_com & 0x7fffff) >> 1; + + /* update sequence number with the help of the counter in stat_com */ + + seq = stat_com >> 24; + dif = (seq - zr->jpg_seq_num) & 0xff; + zr->jpg_seq_num += dif; + } else { + gbuf->bs.length = 0; + } + gbuf->bs.seq = zr->params.TmpDcm == 2 ? (zr->jpg_seq_num >> 1) : zr->jpg_seq_num; + gbuf->state = BUZ_STATE_DONE; + + zr->jpg_dma_tail++; + } +} + +static void zoran_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + u32 stat, astat; + int count; + struct zoran *zr; + unsigned long flags; + + zr = (struct zoran *) dev_id; + count = 0; + + spin_lock_irqsave(&zr->lock, flags); + while (1) { + /* get/clear interrupt status bits */ + stat = btread(ZR36057_ISR); + astat = stat & IRQ_MASK; + if (!astat) { + break; + } + btwrite(astat, ZR36057_ISR); + IDEBUG(printk(BUZ_DEBUG "-%u: astat %08x stat %08x\n", zr->id, astat, stat)); + +#if (IRQ_MASK & ZR36057_ISR_GIRQ0) + if (astat & ZR36057_ISR_GIRQ0) { + + /* Interrupts may still happen when zr->v4l_memgrab_active is switched off. + We simply ignore them */ + + if (zr->v4l_memgrab_active) { + +/* A lot more checks should be here ... */ + if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_SnapShot) == 0) + printk(KERN_WARNING "%s: BuzIRQ with SnapShot off ???\n", zr->name); + + if (zr->v4l_grab_frame != NO_GRAB_ACTIVE) { + /* There is a grab on a frame going on, check if it has finished */ + + if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_FrameGrab) == 0) { + /* it is finished, notify the user */ + + zr->v4l_gbuf[zr->v4l_grab_frame].state = BUZ_STATE_DONE; + zr->v4l_grab_frame = NO_GRAB_ACTIVE; + zr->v4l_grab_seq++; + zr->v4l_pend_tail++; + } + } + if (zr->v4l_grab_frame == NO_GRAB_ACTIVE) + wake_up_interruptible(&zr->v4l_capq); + + /* Check if there is another grab queued */ + + if (zr->v4l_grab_frame == NO_GRAB_ACTIVE && + zr->v4l_pend_tail != zr->v4l_pend_head) { + + int frame = zr->v4l_pend[zr->v4l_pend_tail & V4L_MASK_FRAME]; + u32 reg; + + zr->v4l_grab_frame = frame; + + /* Set zr36057 video front end and enable video */ + + /* Buffer address */ + + reg = zr->v4l_gbuf[frame].fbuffer_bus; + btwrite(reg, ZR36057_VDTR); + if (zr->video_interlace) + reg += zr->gbpl; + btwrite(reg, ZR36057_VDBR); + + /* video stride, status, and frame grab register */ + +#ifdef XAWTV_HACK + reg = (zr->gwidth > 720) ? ((zr->gwidth & ~3) - 720) * zr->gbpl / zr->gwidth : 0; +#else + reg = 0; +#endif + if (zr->video_interlace) + reg += zr->gbpl; + reg = (reg << ZR36057_VSSFGR_DispStride); + reg |= ZR36057_VSSFGR_VidOvf; + reg |= ZR36057_VSSFGR_SnapShot; + reg |= ZR36057_VSSFGR_FrameGrab; + btwrite(reg, ZR36057_VSSFGR); + + btor(ZR36057_VDCR_VidEn, ZR36057_VDCR); + } + } + } +#endif /* (IRQ_MASK & ZR36057_ISR_GIRQ0) */ + +#if (IRQ_MASK & ZR36057_ISR_GIRQ1) + if (astat & ZR36057_ISR_GIRQ1) { + unsigned csr = zr36060_read_8(zr, 0x001); + unsigned isr = zr36060_read_8(zr, 0x008); + + IDEBUG(printk(KERN_DEBUG "%s: ZR36057_ISR_GIRQ1 60_code=%02x 60_intr=%02x\n", + zr->name, csr, isr)); + + btand(~ZR36057_ICR_GIRQ1, ZR36057_ICR); + zoran_reap_stat_com(zr); + zoran_feed_stat_com(zr); + } +#endif /* (IRQ_MASK & ZR36057_ISR_GIRQ1) */ + +#if (IRQ_MASK & ZR36057_ISR_CodRepIRQ) + if (astat & ZR36057_ISR_CodRepIRQ) { + IDEBUG(printk(KERN_DEBUG "%s: ZR36057_ISR_CodRepIRQ\n", zr->name)); + btand(~ZR36057_ICR_CodRepIRQ, ZR36057_ICR); + } +#endif /* (IRQ_MASK & ZR36057_ISR_CodRepIRQ) */ + +#if (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ) + if ((astat & ZR36057_ISR_JPEGRepIRQ) && + (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || + zr->codec_mode == BUZ_MODE_MOTION_COMPRESS)) { + zoran_reap_stat_com(zr); + zoran_feed_stat_com(zr); + wake_up_interruptible(&zr->jpg_capq); + } +#endif /* (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ) */ + + count++; + if (count > 10) { + printk(KERN_WARNING "%s: irq loop %d\n", zr->name, count); + if (count > 20) { + btwrite(0, ZR36057_ICR); + printk(KERN_ERR "%s: IRQ lockup, cleared int mask\n", zr->name); + break; + } + } + } + spin_unlock_irqrestore(&zr->lock, flags); +} + +/* Check a zoran_params struct for correctness, insert default params */ + +static int zoran_check_params(struct zoran *zr, struct zoran_params *params) +{ + int err = 0, err0 = 0; + + /* insert constant params */ + + params->major_version = MAJOR_VERSION; + params->minor_version = MINOR_VERSION; + + /* Check input and norm */ + + if (params->input != 0 && params->input != 1) { + err++; + } + if (params->norm != VIDEO_MODE_PAL && params->norm != VIDEO_MODE_NTSC) { + err++; + } + /* Check decimation, set default values for decimation = 1, 2, 4 */ + + switch (params->decimation) { + case 1: + + params->HorDcm = 1; + params->VerDcm = 1; + params->TmpDcm = 1; + params->field_per_buff = 2; + + params->img_x = 0; + params->img_y = 0; + params->img_width = 720; + params->img_height = tvnorms[params->norm].Ha / 2; + break; + + case 2: + + params->HorDcm = 2; + params->VerDcm = 1; + params->TmpDcm = 2; + params->field_per_buff = 1; + + params->img_x = 8; + params->img_y = 0; + params->img_width = 704; + params->img_height = tvnorms[params->norm].Ha / 2; + break; + + case 4: + + params->HorDcm = 4; + params->VerDcm = 2; + params->TmpDcm = 2; + params->field_per_buff = 1; + + params->img_x = 8; + params->img_y = 0; + params->img_width = 704; + params->img_height = tvnorms[params->norm].Ha / 2; + break; + + case 0: + + /* We have to check the data the user has set */ + + if (params->HorDcm != 1 && params->HorDcm != 2 && params->HorDcm != 4) + err0++; + if (params->VerDcm != 1 && params->VerDcm != 2) + err0++; + if (params->TmpDcm != 1 && params->TmpDcm != 2) + err0++; + if (params->field_per_buff != 1 && params->field_per_buff != 2) + err0++; + + if (params->img_x < 0) + err0++; + if (params->img_y < 0) + err0++; + if (params->img_width < 0) + err0++; + if (params->img_height < 0) + err0++; + if (params->img_x + params->img_width > 720) + err0++; + if (params->img_y + params->img_height > tvnorms[params->norm].Ha / 2) + err0++; + if (params->img_width % (16 * params->HorDcm) != 0) + err0++; + if (params->img_height % (8 * params->VerDcm) != 0) + err0++; + + if (err0) { + err++; + } + break; + + default: + err++; + break; + } + + if (params->quality > 100) + params->quality = 100; + if (params->quality < 5) + params->quality = 5; + + if (params->APPn < 0) + params->APPn = 0; + if (params->APPn > 15) + params->APPn = 15; + if (params->APP_len < 0) + params->APP_len = 0; + if (params->APP_len > 60) + params->APP_len = 60; + if (params->COM_len < 0) + params->COM_len = 0; + if (params->COM_len > 60) + params->COM_len = 60; + + if (err) + return -EINVAL; + + return 0; + +} +static void zoran_open_init_params(struct zoran *zr) +{ + int i; + + /* Per default, map the V4L Buffers */ + + zr->map_mjpeg_buffers = 0; + + /* User must explicitly set a window */ + + zr->window_set = 0; + + zr->window.x = 0; + zr->window.y = 0; + zr->window.width = 0; + zr->window.height = 0; + zr->window.chromakey = 0; + zr->window.flags = 0; + zr->window.clips = NULL; + zr->window.clipcount = 0; + + zr->video_interlace = 0; + + zr->v4l_memgrab_active = 0; + zr->v4l_overlay_active = 0; + + zr->v4l_grab_frame = NO_GRAB_ACTIVE; + zr->v4l_grab_seq = 0; + + zr->gwidth = 0; + zr->gheight = 0; + zr->gformat = 0; + zr->gbpl = 0; + + /* DMA ring stuff for V4L */ + + zr->v4l_pend_tail = 0; + zr->v4l_pend_head = 0; + for (i = 0; i < v4l_nbufs; i++) { + zr->v4l_gbuf[i].state = BUZ_STATE_USER; /* nothing going on */ + } + + /* Set necessary params and call zoran_check_params to set the defaults */ + + zr->params.decimation = 1; + + zr->params.quality = 50; /* default compression factor 8 */ + zr->params.odd_even = 1; + + zr->params.APPn = 0; + zr->params.APP_len = 0; /* No APPn marker */ + for (i = 0; i < 60; i++) + zr->params.APP_data[i] = 0; + + zr->params.COM_len = 0; /* No COM marker */ + for (i = 0; i < 60; i++) + zr->params.COM_data[i] = 0; + + zr->params.VFIFO_FB = 0; + + memset(zr->params.reserved, 0, sizeof(zr->params.reserved)); + + zr->params.jpeg_markers = JPEG_MARKER_DHT | JPEG_MARKER_DQT; + + i = zoran_check_params(zr, &zr->params); + if (i) + printk(KERN_ERR "%s: zoran_open_init_params internal error\n", zr->name); +} + +/* + * Open a buz card. Right now the flags stuff is just playing + */ + +static int zoran_open(struct video_device *dev, int flags) +{ + struct zoran *zr = (struct zoran *) dev; + + DEBUG(printk(KERN_INFO ": zoran_open\n")); + + switch (flags) { + + case 0: + if (zr->user) + return -EBUSY; + zr->user++; + + if (v4l_fbuffer_alloc(zr) < 0) { + zr->user--; + return -ENOMEM; + } + /* default setup */ + + zoran_open_init_params(zr); + + zr36057_enable_jpg(zr, BUZ_MODE_IDLE); + + btwrite(IRQ_MASK, ZR36057_ISR); // Clears interrupts + + btor(ZR36057_ICR_IntPinEn, ZR36057_ICR); + + break; + + default: + return -EBUSY; + + } + MOD_INC_USE_COUNT; + return 0; +} + +static void zoran_close(struct video_device *dev) +{ + struct zoran *zr = (struct zoran *) dev; + + DEBUG(printk(KERN_INFO ": zoran_close\n")); + + /* disable interrupts */ + btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR); + + /* wake up sleeping beauties */ + wake_up_interruptible(&zr->v4l_capq); + wake_up_interruptible(&zr->jpg_capq); + + zr36057_enable_jpg(zr, BUZ_MODE_IDLE); + zr36057_set_memgrab(zr, 0); + if (zr->v4l_overlay_active) + zr36057_overlay(zr, 0); + + zr->user--; + + v4l_fbuffer_free(zr); + jpg_fbuffer_free(zr); + zr->jpg_nbufs = 0; + + MOD_DEC_USE_COUNT; + DEBUG(printk(KERN_INFO ": zoran_close done\n")); +} + + +static long zoran_read(struct video_device *dev, char *buf, unsigned long count, int nonblock) +{ + return -EINVAL; +} + +static long zoran_write(struct video_device *dev, const char *buf, unsigned long count, int nonblock) +{ + return -EINVAL; +} + +/* + * ioctl routine + */ + + +static int zoran_ioctl(struct video_device *dev, unsigned int cmd, void *arg) +{ + struct zoran *zr = (struct zoran *) dev; + + switch (cmd) { + + case VIDIOCGCAP: + { + struct video_capability b; + IOCTL_DEBUG(printk("buz ioctl VIDIOCGCAP\n")); + strncpy(b.name, zr->video_dev.name, sizeof(b.name)); + b.type = VID_TYPE_CAPTURE | + VID_TYPE_OVERLAY | + VID_TYPE_CLIPPING | + VID_TYPE_FRAMERAM | + VID_TYPE_SCALES; + /* theoretically we could also flag VID_TYPE_SUBCAPTURE + but this is not even implemented in the BTTV driver */ + + b.channels = 2; /* composite, svhs */ + b.audios = 0; + b.maxwidth = BUZ_MAX_WIDTH; + b.maxheight = BUZ_MAX_HEIGHT; + b.minwidth = BUZ_MIN_WIDTH; + b.minheight = BUZ_MIN_HEIGHT; + if (copy_to_user(arg, &b, sizeof(b))) { + return -EFAULT; + } + return 0; + } + + case VIDIOCGCHAN: + { + struct video_channel v; + + if (copy_from_user(&v, arg, sizeof(v))) { + return -EFAULT; + } + IOCTL_DEBUG(printk("buz ioctl VIDIOCGCHAN for channel %d\n", v.channel)); + switch (v.channel) { + case 0: + strcpy(v.name, "Composite"); + break; + case 1: + strcpy(v.name, "SVHS"); + break; + default: + return -EINVAL; + } + v.tuners = 0; + v.flags = 0; + v.type = VIDEO_TYPE_CAMERA; + v.norm = zr->params.norm; + if (copy_to_user(arg, &v, sizeof(v))) { + return -EFAULT; + } + return 0; + } + + /* RJ: the documentation at http://roadrunner.swansea.linux.org.uk/v4lapi.shtml says: + + * "The VIDIOCSCHAN ioctl takes an integer argument and switches the capture to this input." + * ^^^^^^^ + * The famos BTTV driver has it implemented with a struct video_channel argument + * and we follow it for compatibility reasons + * + * BTW: this is the only way the user can set the norm! + */ + + case VIDIOCSCHAN: + { + struct video_channel v; + int input; + int on, res; + + if (copy_from_user(&v, arg, sizeof(v))) { + return -EFAULT; + } + IOCTL_DEBUG(printk("buz ioctl VIDIOCSCHAN: channel=%d, norm=%d\n", v.channel, v.norm)); + switch (v.channel) { + case 0: + input = 3; + break; + case 1: + input = 7; + break; + default: + return -EINVAL; + } + + if (v.norm != VIDEO_MODE_PAL + && v.norm != VIDEO_MODE_NTSC) { + return -EINVAL; + } + zr->params.norm = v.norm; + zr->params.input = v.channel; + + /* We switch overlay off and on since a change in the norm + needs different VFE settings */ + + on = zr->v4l_overlay_active && !zr->v4l_memgrab_active; + if (on) + zr36057_overlay(zr, 0); + + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &input); + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &zr->params.norm); + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER, ENCODER_SET_NORM, &zr->params.norm); + + if (on) + zr36057_overlay(zr, 1); + + /* Make sure the changes come into effect */ + res = wait_grab_pending(zr); + if (res) + return res; + + return 0; + } + + case VIDIOCGTUNER: + case VIDIOCSTUNER: + return -EINVAL; + + case VIDIOCGPICT: + { + struct video_picture p = zr->picture; + + IOCTL_DEBUG(printk("buz ioctl VIDIOCGPICT\n")); + p.depth = zr->buffer.depth; + switch (zr->buffer.depth) { + case 15: + p.palette = VIDEO_PALETTE_RGB555; + break; + + case 16: + p.palette = VIDEO_PALETTE_RGB565; + break; + + case 24: + p.palette = VIDEO_PALETTE_RGB24; + break; + + case 32: + p.palette = VIDEO_PALETTE_RGB32; + break; + } + + if (copy_to_user(arg, &p, sizeof(p))) { + return -EFAULT; + } + return 0; + } + + case VIDIOCSPICT: + { + struct video_picture p; + + if (copy_from_user(&p, arg, sizeof(p))) { + return -EFAULT; + } + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &p); + IOCTL_DEBUG(printk("buz ioctl VIDIOCSPICT bri=%d hue=%d col=%d con=%d dep=%d pal=%d\n", + p.brightness, p.hue, p.colour, p.contrast, p.depth, p.palette)); + /* The depth and palette values have no meaning to us, + should we return -EINVAL if they don't fit ? */ + zr->picture = p; + return 0; + } + + case VIDIOCCAPTURE: + { + int v, res; + + if (copy_from_user(&v, arg, sizeof(v))) { + return -EFAULT; + } + IOCTL_DEBUG(printk("buz ioctl VIDIOCCAPTURE: %d\n", v)); + /* If there is nothing to do, return immediatly */ + + if ((v && zr->v4l_overlay_active) || (!v && !zr->v4l_overlay_active)) + return 0; + + if (v == 0) { + zr->v4l_overlay_active = 0; + if (!zr->v4l_memgrab_active) + zr36057_overlay(zr, 0); + /* When a grab is running, the video simply won't be switched on any more */ + } else { + if (!zr->buffer_set || !zr->window_set) { + return -EINVAL; + } + zr->v4l_overlay_active = 1; + if (!zr->v4l_memgrab_active) + zr36057_overlay(zr, 1); + /* When a grab is running, the video will be switched on when grab is finished */ + } + /* Make sure the changes come into effect */ + res = wait_grab_pending(zr); + if (res) + return res; + return 0; + } + + case VIDIOCGWIN: + { + IOCTL_DEBUG(printk("buz ioctl VIDIOCGWIN\n")); + if (copy_to_user(arg, &zr->window, sizeof(zr->window))) { + return -EFAULT; + } + return 0; + } + + case VIDIOCSWIN: + { + struct video_clip *vcp; + struct video_window vw; + int on, end, res; + + if (copy_from_user(&vw, arg, sizeof(vw))) { + return -EFAULT; + } + IOCTL_DEBUG(printk("buz ioctl VIDIOCSWIN: x=%d y=%d w=%d h=%d clipcount=%d\n", vw.x, vw.y, vw.width, vw.height, vw.clipcount)); + if (!zr->buffer_set) { + return -EINVAL; + } + /* + * The video front end needs 4-byte alinged line sizes, we correct that + * silently here if necessary + */ + + if (zr->buffer.depth == 15 || zr->buffer.depth == 16) { + end = (vw.x + vw.width) & ~1; /* round down */ + vw.x = (vw.x + 1) & ~1; /* round up */ + vw.width = end - vw.x; + } + if (zr->buffer.depth == 24) { + end = (vw.x + vw.width) & ~3; /* round down */ + vw.x = (vw.x + 3) & ~3; /* round up */ + vw.width = end - vw.x; + } +#if 0 + // At least xawtv seems to care about the following - just leave it away + /* + * Also corrected silently (as long as window fits at all): + * video not fitting the screen + */ +#if 0 + if (vw.x < 0 || vw.y < 0 || vw.x + vw.width > zr->buffer.width || + vw.y + vw.height > zr->buffer.height) { + printk(BUZ_ERR ": VIDIOCSWIN: window does not fit frame buffer: %dx%d+%d*%d\n", + vw.width, vw.height, vw.x, vw.y); + return -EINVAL; + } +#else + if (vw.x < 0) + vw.x = 0; + if (vw.y < 0) + vw.y = 0; + if (vw.x + vw.width > zr->buffer.width) + vw.width = zr->buffer.width - vw.x; + if (vw.y + vw.height > zr->buffer.height) + vw.height = zr->buffer.height - vw.y; +#endif +#endif + + /* Check for vaild parameters */ + if (vw.width < BUZ_MIN_WIDTH || vw.height < BUZ_MIN_HEIGHT || + vw.width > BUZ_MAX_WIDTH || vw.height > BUZ_MAX_HEIGHT) { + return -EINVAL; + } +#ifdef XAWTV_HACK + if (vw.width > 720) + vw.width = 720; +#endif + + zr->window.x = vw.x; + zr->window.y = vw.y; + zr->window.width = vw.width; + zr->window.height = vw.height; + zr->window.chromakey = 0; + zr->window.flags = 0; // RJ: Is this intended for interlace on/off ? + + zr->window.clips = NULL; + zr->window.clipcount = vw.clipcount; + + /* + * If an overlay is running, we have to switch it off + * and switch it on again in order to get the new settings in effect. + * + * We also want to avoid that the overlay mask is written + * when an overlay is running. + */ + + on = zr->v4l_overlay_active && !zr->v4l_memgrab_active; + if (on) + zr36057_overlay(zr, 0); + + /* + * Write the overlay mask if clips are wanted. + */ + if (vw.clipcount) { + vcp = vmalloc(sizeof(struct video_clip) * (vw.clipcount + 4)); + if (vcp == NULL) { + return -ENOMEM; + } + if (copy_from_user(vcp, vw.clips, sizeof(struct video_clip) * vw.clipcount)) { + vfree(vcp); + return -EFAULT; + } + write_overlay_mask(zr, vcp, vw.clipcount); + vfree(vcp); + } + if (on) + zr36057_overlay(zr, 1); + zr->window_set = 1; + + /* Make sure the changes come into effect */ + res = wait_grab_pending(zr); + if (res) + return res; + + return 0; + } + + case VIDIOCGFBUF: + { + IOCTL_DEBUG(printk("buz ioctl VIDIOCGFBUF\n")); + if (copy_to_user(arg, &zr->buffer, sizeof(zr->buffer))) { + return -EFAULT; + } + return 0; + } + + case VIDIOCSFBUF: + { + struct video_buffer v; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + + IOCTL_DEBUG(printk("buz ioctl VIDIOCSFBUF: base=0x%x w=%d h=%d depth=%d bpl=%d\n", (u32) v.base, v.width, v.height, v.depth, v.bytesperline)); + if (zr->v4l_overlay_active) { + /* Has the user gotten crazy ... ? */ + return -EINVAL; + } + if (v.depth != 15 + && v.depth != 16 + && v.depth != 24 + && v.depth != 32) { + return -EINVAL; + } + if (v.height <= 0 || v.width <= 0 || v.bytesperline <= 0) { + return -EINVAL; + } + if (v.bytesperline & 3) { + return -EINVAL; + } + if (v.base) { + zr->buffer.base = (void *) ((unsigned long) v.base & ~3); + } + zr->buffer.height = v.height; + zr->buffer.width = v.width; + zr->buffer.depth = v.depth; + zr->buffer.bytesperline = v.bytesperline; + + if (zr->buffer.base) + zr->buffer_set = 1; + zr->window_set = 0; /* The user should set new window parameters */ + return 0; + } + + /* RJ: what is VIDIOCKEY intended to do ??? */ + + case VIDIOCGFREQ: + case VIDIOCSFREQ: + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + return -EINVAL; + + case VIDIOCSYNC: + { + int v; + + if (copy_from_user(&v, arg, sizeof(v))) { + return -EFAULT; + } + IOCTL_DEBUG(printk("buz ioctl VIDIOCSYNC %d\n", v)); + return v4l_sync(zr, v); + } + + case VIDIOCMCAPTURE: + { + struct video_mmap vm; + + if (copy_from_user((void *) &vm, (void *) arg, sizeof(vm))) { + return -EFAULT; + } + IOCTL_DEBUG(printk("buz ioctl VIDIOCMCAPTURE frame=%d geom=%dx%d fmt=%d\n", + vm.frame, vm.height, vm.width, vm.format)); + return v4l_grab(zr, &vm); + } + + case VIDIOCGMBUF: + { + struct video_mbuf vm; + int i; + + IOCTL_DEBUG(printk("buz ioctl VIDIOCGMBUF\n")); + + vm.size = v4l_nbufs * v4l_bufsize; + vm.frames = v4l_nbufs; + for (i = 0; i < v4l_nbufs; i++) { + vm.offsets[i] = i * v4l_bufsize; + } + + /* The next mmap will map the V4L buffers */ + zr->map_mjpeg_buffers = 0; + + if (copy_to_user(arg, &vm, sizeof(vm))) { + return -EFAULT; + } + return 0; + } + + case VIDIOCGUNIT: + { + struct video_unit vu; + + IOCTL_DEBUG(printk("buz ioctl VIDIOCGUNIT\n")); + vu.video = zr->video_dev.minor; + vu.vbi = VIDEO_NO_UNIT; + vu.radio = VIDEO_NO_UNIT; + vu.audio = VIDEO_NO_UNIT; + vu.teletext = VIDEO_NO_UNIT; + if (copy_to_user(arg, &vu, sizeof(vu))) + return -EFAULT; + return 0; + } + + /* + * RJ: In principal we could support subcaptures for V4L grabbing. + * Not even the famous BTTV driver has them, however. + * If there should be a strong demand, one could consider + * to implement them. + */ + case VIDIOCGCAPTURE: + case VIDIOCSCAPTURE: + return -EINVAL; + + case BUZIOC_G_PARAMS: + { + IOCTL_DEBUG(printk("buz ioctl BUZIOC_G_PARAMS\n")); + if (copy_to_user(arg, &(zr->params), sizeof(zr->params))) + return -EFAULT; + return 0; + } + + case BUZIOC_S_PARAMS: + { + struct zoran_params bp; + int input, on; + + if (zr->codec_mode != BUZ_MODE_IDLE) { + return -EINVAL; + } + if (copy_from_user(&bp, arg, sizeof(bp))) { + return -EFAULT; + } + IOCTL_DEBUG(printk("buz ioctl BUZIOC_S_PARAMS\n")); + + /* Check the params first before overwriting our internal values */ + + if (zoran_check_params(zr, &bp)) + return -EINVAL; + + zr->params = bp; + + /* Make changes of input and norm go into effect immediatly */ + + /* We switch overlay off and on since a change in the norm + needs different VFE settings */ + + on = zr->v4l_overlay_active && !zr->v4l_memgrab_active; + if (on) + zr36057_overlay(zr, 0); + + input = zr->params.input == 0 ? 3 : 7; + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &input); + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &zr->params.norm); + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER, ENCODER_SET_NORM, &zr->params.norm); + + if (on) + zr36057_overlay(zr, 1); + + if (copy_to_user(arg, &bp, sizeof(bp))) { + return -EFAULT; + } + return 0; + } + + case BUZIOC_REQBUFS: + { + struct zoran_requestbuffers br; + + if (zr->jpg_buffers_allocated) { + return -EINVAL; + } + if (copy_from_user(&br, arg, sizeof(br))) { + return -EFAULT; + } + IOCTL_DEBUG(printk("buz ioctl BUZIOC_REQBUFS count = %lu size=%lu\n", + br.count, br.size)); + /* Enforce reasonable lower and upper limits */ + if (br.count < 4) + br.count = 4; /* Could be choosen smaller */ + if (br.count > BUZ_MAX_FRAME) + br.count = BUZ_MAX_FRAME; + br.size = PAGE_ALIGN(br.size); + if (br.size < 8192) + br.size = 8192; /* Arbitrary */ + /* br.size is limited by 1 page for the stat_com tables to a Maximum of 2 MB */ + if (br.size > (512 * 1024)) + br.size = (512 * 1024); /* 512 K should be enough */ + if (zr->need_contiguous && br.size > MAX_KMALLOC_MEM) + br.size = MAX_KMALLOC_MEM; + + zr->jpg_nbufs = br.count; + zr->jpg_bufsize = br.size; + + if (jpg_fbuffer_alloc(zr)) + return -ENOMEM; + + /* The next mmap will map the MJPEG buffers */ + zr->map_mjpeg_buffers = 1; + + if (copy_to_user(arg, &br, sizeof(br))) { + return -EFAULT; + } + return 0; + } + + case BUZIOC_QBUF_CAPT: + { + int nb; + + if (copy_from_user((void *) &nb, (void *) arg, sizeof(int))) { + return -EFAULT; + } + IOCTL_DEBUG(printk("buz ioctl BUZIOC_QBUF_CAPT %d\n", nb)); + return jpg_qbuf(zr, nb, BUZ_MODE_MOTION_COMPRESS); + } + + case BUZIOC_QBUF_PLAY: + { + int nb; + + if (copy_from_user((void *) &nb, (void *) arg, sizeof(int))) { + return -EFAULT; + } + IOCTL_DEBUG(printk("buz ioctl BUZIOC_QBUF_PLAY %d\n", nb)); + return jpg_qbuf(zr, nb, BUZ_MODE_MOTION_DECOMPRESS); + } + + case BUZIOC_SYNC: + { + struct zoran_sync bs; + int res; + + IOCTL_DEBUG(printk("buz ioctl BUZIOC_SYNC\n")); + res = jpg_sync(zr, &bs); + if (copy_to_user(arg, &bs, sizeof(bs))) { + return -EFAULT; + } + return res; + } + + case BUZIOC_G_STATUS: + { + struct zoran_status bs; + int norm, input, status; + unsigned long timeout; + + if (zr->codec_mode != BUZ_MODE_IDLE) { + return -EINVAL; + } + if (copy_from_user(&bs, arg, sizeof(bs))) { + return -EFAULT; + } + IOCTL_DEBUG(printk("buz ioctl BUZIOC_G_STATUS\n")); + switch (bs.input) { + case 0: + input = 3; + break; + case 1: + input = 7; + break; + default: + return -EINVAL; + } + + /* Set video norm to VIDEO_MODE_AUTO */ + + norm = VIDEO_MODE_AUTO; + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &input); + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &norm); + + /* sleep 1 second */ + + schedule_timeout(HZ); + + /* Get status of video decoder */ + + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_GET_STATUS, &status); + bs.signal = (status & DECODER_STATUS_GOOD) ? 1 : 0; + bs.norm = (status & DECODER_STATUS_NTSC) ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL; + bs.color = (status & DECODER_STATUS_COLOR) ? 1 : 0; + + /* restore previous input and norm */ + input = zr->params.input == 0 ? 3 : 7; + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &input); + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &zr->params.norm); + + if (copy_to_user(arg, &bs, sizeof(bs))) { + return -EFAULT; + } + return 0; + } + + default: + return -ENOIOCTLCMD; + + } + return 0; +} + + +/* + * This maps the buffers to user space. + * + * Depending on the state of zr->map_mjpeg_buffers + * the V4L or the MJPEG buffers are mapped + * + */ + +static int zoran_mmap(struct video_device *dev, const char *adr, unsigned long size) +{ + struct zoran *zr = (struct zoran *) dev; + unsigned long start = (unsigned long) adr; + unsigned long page, pos, todo, fraglen; + int i, j; + + if (zr->map_mjpeg_buffers) { + /* Map the MJPEG buffers */ + + if (!zr->jpg_buffers_allocated) { + return -ENOMEM; + } + if (size > zr->jpg_nbufs * zr->jpg_bufsize) { + return -EINVAL; + } + + for (i = 0; i < zr->jpg_nbufs; i++) { + for (j = 0; j < zr->jpg_bufsize / PAGE_SIZE; j++) { + fraglen = (zr->jpg_gbuf[i].frag_tab[2 * j + 1] & ~1) << 1; + todo = size; + if (todo > fraglen) + todo = fraglen; + pos = (unsigned long) zr->jpg_gbuf[i].frag_tab[2 * j]; + page = virt_to_phys(bus_to_virt(pos)); /* should just be pos on i386 */ + if (remap_page_range(start, page, todo, PAGE_SHARED)) { + printk(KERN_ERR "%s: zoran_mmap(V4L): remap_page_range failed\n", zr->name); + return -EAGAIN; + } + size -= todo; + start += todo; + if (size == 0) + break; + if (zr->jpg_gbuf[i].frag_tab[2 * j + 1] & 1) + break; /* was last fragment */ + } + if (size == 0) + break; + } + } else { + /* Map the V4L buffers */ + + if (size > v4l_nbufs * v4l_bufsize) { + return -EINVAL; + } + + for (i = 0; i < v4l_nbufs; i++) { + todo = size; + if (todo > v4l_bufsize) + todo = v4l_bufsize; + page = zr->v4l_gbuf[i].fbuffer_phys; + DEBUG(printk("V4L remap page range %d 0x%x %d to 0x%x\n", i, page, todo, start)); + if (remap_page_range(start, page, todo, PAGE_SHARED)) { + printk(KERN_ERR "%s: zoran_mmap(V4L): remap_page_range failed\n", zr->name); + return -EAGAIN; + } + size -= todo; + start += todo; + if (size == 0) + break; + } + } + return 0; +} + +static int zoran_init_done(struct video_device *dev) +{ + return 0; +} + +static struct video_device zoran_template = +{ + BUZ_NAME, + VID_TYPE_CAPTURE | VID_TYPE_OVERLAY | VID_TYPE_CLIPPING | VID_TYPE_FRAMERAM | + VID_TYPE_SCALES | VID_TYPE_SUBCAPTURE, + VID_HARDWARE_BT848, /* Not true, but the buz is not yet in the list */ + zoran_open, + zoran_close, + zoran_read, + zoran_write, + NULL, + zoran_ioctl, + zoran_mmap, + zoran_init_done, + NULL, + 0, + 0 +}; + +static int zr36057_init(int i) +{ + struct zoran *zr = &zoran[i]; + unsigned long mem; + unsigned mem_needed; + int j; + int rev; + + /* reset zr36057 */ + btwrite(0, ZR36057_SPGPPCR); + mdelay(10); + + /* default setup of all parameters which will persist beetween opens */ + + zr->user = 0; + + zr->map_mjpeg_buffers = 0; /* Map V4L buffers by default */ + + zr->jpg_nbufs = 0; + zr->jpg_bufsize = 0; + zr->jpg_buffers_allocated = 0; + + zr->buffer_set = 0; /* Flag if frame buffer has been set */ + zr->buffer.base = (void *) vidmem; + zr->buffer.width = 0; + zr->buffer.height = 0; + zr->buffer.depth = 0; + zr->buffer.bytesperline = 0; + + zr->params.norm = default_norm ? 1 : 0; /* Avoid nonsense settings from user */ + zr->params.input = default_input ? 1 : 0; /* Avoid nonsense settings from user */ + zr->video_interlace = 0; + + /* Should the following be reset at every open ? */ + + zr->picture.colour = 32768; + zr->picture.brightness = 32768; + zr->picture.hue = 32768; + zr->picture.contrast = 32768; + zr->picture.whiteness = 0; + zr->picture.depth = 0; + zr->picture.palette = 0; + + for (j = 0; j < VIDEO_MAX_FRAME; j++) { + zr->v4l_gbuf[i].fbuffer = 0; + zr->v4l_gbuf[i].fbuffer_phys = 0; + zr->v4l_gbuf[i].fbuffer_bus = 0; + } + + zr->stat_com = 0; + + /* default setup (will be repeated at every open) */ + + zoran_open_init_params(zr); + + /* allocate memory *before* doing anything to the hardware in case allocation fails */ + + /* STAT_COM table and overlay mask */ + + mem_needed = (BUZ_NUM_STAT_COM + ((BUZ_MAX_WIDTH + 31) / 32) * BUZ_MAX_HEIGHT) * 4; + mem = (unsigned long) kmalloc(mem_needed, GFP_KERNEL); + if (!mem) { + return -ENOMEM; + } + memset((void *) mem, 0, mem_needed); + + zr->stat_com = (u32 *) mem; + for (j = 0; j < BUZ_NUM_STAT_COM; j++) { + zr->stat_com[j] = 1; /* mark as unavailable to zr36057 */ + } + zr->overlay_mask = (u32 *) (mem + BUZ_NUM_STAT_COM * 4); + + /* Initialize zr->jpg_gbuf */ + + for (j = 0; j < BUZ_MAX_FRAME; j++) { + zr->jpg_gbuf[j].frag_tab = 0; + zr->jpg_gbuf[j].frag_tab_bus = 0; + zr->jpg_gbuf[j].state = BUZ_STATE_USER; + zr->jpg_gbuf[j].bs.frame = j; + } + + /* take zr36057 out of reset now */ + btwrite(ZR36057_SPGPPCR_SoftReset, ZR36057_SPGPPCR); + mdelay(10); + + /* stop all DMA processes */ + btwrite(ZR36057_MCTCR_CFlush, ZR36057_MCTCR); + btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR); + /* assert P_Reset */ + btwrite(0, ZR36057_JPC); + + switch(zr->board) + { + case BOARD_BUZ: + + /* set up GPIO direction */ + btwrite(ZR36057_SPGPPCR_SoftReset | 0, ZR36057_SPGPPCR); + + /* Set up guest bus timing - Guests 0..3 Tdur=12, Trec=3 */ + btwrite((GPIO_MASK << 24) | 0x8888, ZR36057_GPPGCR1); + mdelay(10); + + /* reset video decoder */ + + GPIO(zr, 0, 0); + mdelay(10); + GPIO(zr, 0, 1); + mdelay(10); + + /* reset JPEG codec */ + zr36060_sleep(zr, 0); + mdelay(10); + zr36060_reset(zr); + mdelay(10); + zr36060_sleep(zr, 1); + mdelay(10); + + /* display codec revision */ + if ((rev=zr36060_read_8(zr, 0x022)) == 0x33) { + printk(KERN_INFO "%s: Zoran ZR36060 (rev %d)\n", + zr->name, zr36060_read_8(zr, 0x023)); + } else { + printk(KERN_ERR "%s: Zoran ZR36060 not found (Rev=%d)\n", zr->name, rev); + kfree((void *) zr->stat_com); + return -1; + } + break; + + case BOARD_LML33: +// btwrite(btread(ZR36057_SPGPPCR)&~ZR36057_SPGPPCR_SoftReset , ZR36057_SPGPPCR); +// udelay(100); +// btwrite(btread(ZR36057_SPGPPCR)|ZR36057_SPGPPCR_SoftReset , ZR36057_SPGPPCR); +// udelay(1000); + + /* + * Set up the GPIO direction + */ + btwrite(btread(ZR36057_SPGPPCR_SoftReset)|0 , ZR36057_SPGPPCR); + /* Set up guest bus timing - Guests 0..2 Tdur=12, Trec=3 */ + btwrite(0xFF00F888, ZR36057_GPPGCR1); + mdelay(10); + GPIO(zr, 5, 0); /* Analog video bypass */ + udelay(3000); + GPIO(zr, 0, 0); /* Reset 819 */ + udelay(3000); + GPIO(zr, 0, 1); /* 819 back */ + udelay(3000); + /* reset JPEG codec */ + zr36060_sleep(zr, 0); + udelay(3000); + zr36060_reset(zr); + udelay(3000); + zr36060_sleep(zr, 1); + udelay(3000); + + /* display codec revision */ + if ((rev=zr36060_read_8(zr, 0x022)) == 0x33) { + printk(KERN_INFO "%s: Zoran ZR36060 (rev %d)\n", + zr->name, zr36060_read_8(zr, 0x023)); + } else { + printk(KERN_ERR "%s: Zoran ZR36060 not found (rev=%d)\n", zr->name, rev); +// kfree((void *) zr->stat_com); +// return -1; + } + break; + } + /* i2c */ + memcpy(&zr->i2c, &zoran_i2c_bus_template, sizeof(struct i2c_bus)); + sprintf(zr->i2c.name, "zoran%u%u", zr->id); + zr->i2c.data = zr; + if (i2c_register_bus(&zr->i2c) < 0) { + kfree((void *) zr->stat_com); + return -1; + } + /* + * Now add the template and register the device unit. + */ + memcpy(&zr->video_dev, &zoran_template, sizeof(zoran_template)); + sprintf(zr->video_dev.name, "zoran%u", zr->id); + if (video_register_device(&zr->video_dev, VFL_TYPE_GRABBER) < 0) { + i2c_unregister_bus(&zr->i2c); + kfree((void *) zr->stat_com); + return -1; + } + /* toggle JPEG codec sleep to sync PLL */ + zr36060_sleep(zr, 1); + mdelay(10); + zr36060_sleep(zr, 0); + mdelay(10); + + /* Enable bus-mastering */ + pci_set_master(zr->pci_dev); + + j = zr->params.input == 0 ? 3 : 7; + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_INPUT, &j); + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_NORM, &zr->params.norm); + i2c_control_device(&zr->i2c, I2C_DRIVERID_VIDEOENCODER, ENCODER_SET_NORM, &zr->params.norm); + + /* set individual interrupt enables (without GIRQ0) + but don't global enable until zoran_open() */ + + btwrite(IRQ_MASK & ~ZR36057_ISR_GIRQ0, ZR36057_ICR); + + if(request_irq(zr->pci_dev->irq, zoran_irq, + SA_SHIRQ | SA_INTERRUPT, zr->name, (void *) zr)<0) + { + printk(KERN_ERR "%s: Can't assign irq.\n", zr->name); + video_unregister_device(&zr->video_dev); + i2c_unregister_bus(&zr->i2c); + kfree((void *) zr->stat_com); + return -1; + } + zr->initialized = 1; + return 0; +} + + + +static void release_zoran(void) +{ + u8 command; + int i; + struct zoran *zr; + + for (i = 0; i < zoran_num; i++) { + zr = &zoran[i]; + + if (!zr->initialized) + continue; + + /* unregister i2c_bus */ + i2c_unregister_bus((&zr->i2c)); + + /* disable PCI bus-mastering */ + pci_read_config_byte(zr->pci_dev, PCI_COMMAND, &command); + command &= ~PCI_COMMAND_MASTER; + pci_write_config_byte(zr->pci_dev, PCI_COMMAND, command); + + /* put chip into reset */ + btwrite(0, ZR36057_SPGPPCR); + + free_irq(zr->pci_dev->irq, zr); + + /* unmap and free memory */ + + kfree((void *) zr->stat_com); + + iounmap(zr->zr36057_mem); + + video_unregister_device(&zr->video_dev); + } +} + +/* + * Scan for a Buz card (actually for the PCI controller ZR36057), + * request the irq and map the io memory + */ + +static int find_zr36057(void) +{ + unsigned char latency; + struct zoran *zr; + struct pci_dev *dev = NULL; + int result; + + zoran_num = 0; + + while (zoran_num < BUZ_MAX + && (dev = pci_find_device(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36057, dev)) != NULL) { + zr = &zoran[zoran_num]; + zr->pci_dev = dev; + zr->zr36057_mem = NULL; + zr->id = zoran_num; + sprintf(zr->name, "zoran%u", zr->id); + + spin_lock_init(&zr->lock); + + zr->zr36057_adr = zr->pci_dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK; + pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION, &zr->revision); + if (zr->revision < 2) { + printk(KERN_INFO "%s: Zoran ZR36057 (rev %d) irq: %d, memory: 0x%08x.\n", + zr->name, zr->revision, zr->pci_dev->irq, zr->zr36057_adr); + } else { + unsigned short ss_vendor_id, ss_id; + + pci_read_config_word(zr->pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor_id); + pci_read_config_word(zr->pci_dev, PCI_SUBSYSTEM_ID, &ss_id); + printk(KERN_INFO "%s: Zoran ZR36067 (rev %d) irq: %d, memory: 0x%08x\n", + zr->name, zr->revision, zr->pci_dev->irq, zr->zr36057_adr); + printk(KERN_INFO "%s: subsystem vendor=0x%04x id=0x%04x\n", + zr->name, ss_vendor_id, ss_id); + if(ss_vendor_id==0xFF10 && ss_id == 0xDE41) + { + zr->board = BOARD_LML33; + printk(KERN_INFO "%s: LML33 detected.\n", zr->name); + } + } + + zr->zr36057_mem = ioremap(zr->zr36057_adr, 0x1000); + + /* set PCI latency timer */ + pci_read_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, &latency); + if (latency != 48) { + printk(KERN_INFO "%s: Changing PCI latency from %d to 48.\n", zr->name, latency); + latency = 48; + pci_write_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, latency); + } + zoran_num++; + } + if (zoran_num == 0) + printk(KERN_INFO "zoran: no cards found.\n"); + + return zoran_num; +} + +#include "chipsets.h" + +static void handle_chipset(void) +{ + int index; + struct pci_dev *dev = NULL; + + for (index = 0; index < sizeof(black) / sizeof(black[0]); index++) { + if ((dev = pci_find_device(black[index].vendor, black[index].device, dev)) != NULL) { + printk(KERN_INFO ": Host bridge: %s, ", black[index].name); + switch (black[index].action) { + + case TRITON: + printk("enabling Triton support.\n"); + triton = 1; + break; + + case NATOMA: + printk("enabling Natoma workaround.\n"); + natoma = 1; + break; + } + } + } +} + +#ifdef MODULE +int init_module(void) +#else +int init_zoran_cards(struct video_init *unused) +#endif +{ + int i; + + + printk(KERN_INFO "Zoran driver 1.00 (c) 1999 Rainer Johanni, Dave Perks.\n"); + + /* Look for Buz cards */ + + if (find_zr36057() <= 0) { + return -EIO; + } + printk(KERN_INFO"zoran: %d zoran card(s) found\n", zoran_num); + + if (zoran_num == 0) + return -ENXIO; + + + /* check the parameters we have been given, adjust if necessary */ + + if (v4l_nbufs < 0) + v4l_nbufs = 0; + if (v4l_nbufs > VIDEO_MAX_FRAME) + v4l_nbufs = VIDEO_MAX_FRAME; + /* The user specfies the in KB, we want them in byte (and page aligned) */ + v4l_bufsize = PAGE_ALIGN(v4l_bufsize * 1024); + if (v4l_bufsize < 32768) + v4l_bufsize = 32768; + /* 2 MB is arbitrary but sufficient for the maximum possible images */ + if (v4l_bufsize > 2048 * 1024) + v4l_bufsize = 2048 * 1024; + + printk(KERN_INFO "zoran: using %d V4L buffers of size %d KB\n", v4l_nbufs, v4l_bufsize >> 10); + + /* Use parameter for vidmem or try to find a video card */ + + if (vidmem) { + printk(KERN_INFO "zoran: Using supplied video memory base address @ 0x%lx\n", vidmem); + } + + /* check if we have a Triton or Natome chipset */ + + handle_chipset(); + + /* take care of Natoma chipset and a revision 1 zr36057 */ + + for (i = 0; i < zoran_num; i++) { + if (natoma && zoran[i].revision <= 1) { + zoran[i].need_contiguous = 1; + printk(KERN_INFO "%s: ZR36057/Natome bug, max. buffer size is 128K\n", zoran[i].name); + } else { + zoran[i].need_contiguous = 0; + } + } + + /* initialize the Buzs */ + + /* We have to know which ones must be released if an error occurs */ + for (i = 0; i < zoran_num; i++) + zoran[i].initialized = 0; + + for (i = 0; i < zoran_num; i++) { + if (zr36057_init(i) < 0) { + release_zoran(); + return -EIO; + } + } + + return 0; +} + + + +#ifdef MODULE + +void cleanup_module(void) +{ + release_zoran(); +} + +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/buz.h linux.ac/drivers/char/buz.h --- linux.vanilla/drivers/char/buz.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/char/buz.h Thu Jul 1 23:20:12 1999 @@ -0,0 +1,319 @@ +/* + buz - Iomega Buz driver + + Copyright (C) 1999 Rainer Johanni + + based on + + buz.0.0.3 Copyright (C) 1998 Dave Perks + + and + + bttv - Bt848 frame grabber driver + Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _BUZ_H_ +#define _BUZ_H_ + +/* The Buz only supports a maximum width of 720, but some V4L + applications (e.g. xawtv are more happy with 768). + If XAWTV_HACK is defined, we try to fake a device with bigger width */ + +#define XAWTV_HACK + +#ifdef XAWTV_HACK +#define BUZ_MAX_WIDTH 768 /* never display more than 768 pixels */ +#else +#define BUZ_MAX_WIDTH 720 /* never display more than 720 pixels */ +#endif +#define BUZ_MAX_HEIGHT 576 /* never display more than 576 rows */ +#define BUZ_MIN_WIDTH 32 /* never display less than 32 pixels */ +#define BUZ_MIN_HEIGHT 24 /* never display less than 24 rows */ + +struct zoran_requestbuffers { + unsigned long count; /* Number of buffers for MJPEG grabbing */ + unsigned long size; /* Size PER BUFFER in bytes */ +}; + +struct zoran_sync { + unsigned long frame; /* number of buffer that has been free'd */ + unsigned long length; /* number of code bytes in buffer (capture only) */ + unsigned long seq; /* frame sequence number */ + struct timeval timestamp; /* timestamp */ +}; + +struct zoran_status { + int input; /* Input channel, has to be set prior to BUZIOC_G_STATUS */ + int signal; /* Returned: 1 if valid video signal detected */ + int norm; /* Returned: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */ + int color; /* Returned: 1 if color signal detected */ +}; + +struct zoran_params { + + /* The following parameters can only be queried */ + + int major_version; /* Major version number of driver */ + int minor_version; /* Minor version number of driver */ + + /* Main control parameters */ + + int input; /* Input channel: 0 = Composite, 1 = S-VHS */ + int norm; /* Norm: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */ + int decimation; /* decimation of captured video, + enlargement of video played back. + Valid values are 1, 2, 4 or 0. + 0 is a special value where the user + has full control over video scaling */ + + /* The following parameters only have to be set if decimation==0, + for other values of decimation they provide the data how the image is captured */ + + int HorDcm; /* Horizontal decimation: 1, 2 or 4 */ + int VerDcm; /* Vertical decimation: 1 or 2 */ + int TmpDcm; /* Temporal decimation: 1 or 2, + if TmpDcm==2 in capture every second frame is dropped, + in playback every frame is played twice */ + int field_per_buff; /* Number of fields per buffer: 1 or 2 */ + int img_x; /* start of image in x direction */ + int img_y; /* start of image in y direction */ + int img_width; /* image width BEFORE decimation, + must be a multiple of HorDcm*16 */ + int img_height; /* image height BEFORE decimation, + must be a multiple of VerDcm*8 */ + + /* --- End of parameters for decimation==0 only --- */ + + /* JPEG control parameters */ + + int quality; /* Measure for quality of compressed images. + Scales linearly with the size of the compressed images. + Must be beetween 0 and 100, 100 is a compression + ratio of 1:4 */ + + int odd_even; /* Which field should come first ??? */ + + int APPn; /* Number of APP segment to be written, must be 0..15 */ + int APP_len; /* Length of data in JPEG APPn segment */ + char APP_data[60]; /* Data in the JPEG APPn segment. */ + + int COM_len; /* Length of data in JPEG COM segment */ + char COM_data[60]; /* Data in JPEG COM segment */ + + unsigned long jpeg_markers; /* Which markers should go into the JPEG output. + Unless you exactly know what you do, leave them untouched. + Inluding less markers will make the resulting code + smaller, but there will be fewer aplications + which can read it. + The presence of the APP and COM marker is + influenced by APP0_len and COM_len ONLY! */ +#define JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */ +#define JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */ +#define JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ +#define JPEG_MARKER_COM (1<<6) /* Comment segment */ +#define JPEG_MARKER_APP (1<<7) /* App segment, driver will allways use APP0 */ + + int VFIFO_FB; /* Flag for enabling Video Fifo Feedback. + If this flag is turned on and JPEG decompressing + is going to the screen, the decompress process + is stopped every time the Video Fifo is full. + This enables a smooth decompress to the screen + but the video output signal will get scrambled */ + + /* Misc */ + + char reserved[312]; /* Makes 512 bytes for this structure */ +}; + +/* + Private IOCTL to set up for displaying MJPEG + */ +#define BUZIOC_G_PARAMS _IOR ('v', BASE_VIDIOCPRIVATE+0, struct zoran_params) +#define BUZIOC_S_PARAMS _IOWR('v', BASE_VIDIOCPRIVATE+1, struct zoran_params) +#define BUZIOC_REQBUFS _IOWR('v', BASE_VIDIOCPRIVATE+2, struct zoran_requestbuffers) +#define BUZIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOCPRIVATE+3, int) +#define BUZIOC_QBUF_PLAY _IOW ('v', BASE_VIDIOCPRIVATE+4, int) +#define BUZIOC_SYNC _IOR ('v', BASE_VIDIOCPRIVATE+5, struct zoran_sync) +#define BUZIOC_G_STATUS _IOWR('v', BASE_VIDIOCPRIVATE+6, struct zoran_status) + + +#ifdef __KERNEL__ + +#define BUZ_NUM_STAT_COM 4 +#define BUZ_MASK_STAT_COM 3 + +#define BUZ_MAX_FRAME 256 /* Must be a power of 2 */ +#define BUZ_MASK_FRAME 255 /* Must be BUZ_MAX_FRAME-1 */ + +#if VIDEO_MAX_FRAME <= 32 +#define V4L_MAX_FRAME 32 +#elif VIDEO_MAX_FRAME <= 64 +#define V4L_MAX_FRAME 64 +#else +#error "Too many video frame buffers to handle" +#endif +#define V4L_MASK_FRAME (V4L_MAX_FRAME - 1) + + +#include "zr36057.h" + +enum zoran_codec_mode { + BUZ_MODE_IDLE, /* nothing going on */ + BUZ_MODE_MOTION_COMPRESS, /* grabbing frames */ + BUZ_MODE_MOTION_DECOMPRESS, /* playing frames */ + BUZ_MODE_STILL_COMPRESS, /* still frame conversion */ + BUZ_MODE_STILL_DECOMPRESS /* still frame conversion */ +}; + +enum zoran_buffer_state { + BUZ_STATE_USER, /* buffer is owned by application */ + BUZ_STATE_PEND, /* buffer is queued in pend[] ready to feed to I/O */ + BUZ_STATE_DMA, /* buffer is queued in dma[] for I/O */ + BUZ_STATE_DONE /* buffer is ready to return to application */ +}; + +struct zoran_gbuffer { + u32 *frag_tab; /* addresses of frag table */ + u32 frag_tab_bus; /* same value cached to save time in ISR */ + enum zoran_buffer_state state; /* non-zero if corresponding buffer is in use in grab queue */ + struct zoran_sync bs; /* DONE: info to return to application */ +}; + +struct v4l_gbuffer { + char *fbuffer; /* virtual address of frame buffer */ + unsigned long fbuffer_phys; /* physical address of frame buffer */ + unsigned long fbuffer_bus; /* bus address of frame buffer */ + enum zoran_buffer_state state; /* state: unused/pending/done */ +}; + +struct zoran { + struct video_device video_dev; + struct i2c_bus i2c; + + int initialized; /* flag if zoran has been correctly initalized */ + int user; /* number of current users (0 or 1) */ + + unsigned short id; /* number of this device */ + char name[32]; /* name of this device */ + struct pci_dev *pci_dev; /* PCI device */ + unsigned char revision; /* revision of zr36057 */ + int board; /* Board type */ +#define BOARD_BUZ 0 +#define BOARD_LML33 1 + unsigned int zr36057_adr; /* bus address of IO mem returned by PCI BIOS */ + unsigned char *zr36057_mem; /* pointer to mapped IO memory */ + + int map_mjpeg_buffers; /* Flag which bufferset will map by next mmap() */ + + spinlock_t lock; /* Spinlock */ + + /* Video for Linux parameters */ + + struct video_picture picture; /* Current picture params */ + struct video_buffer buffer; /* Current buffer params */ + struct video_window window; /* Current window params */ + int buffer_set, window_set; /* Flags if the above structures are set */ + int video_interlace; /* Image on screen is interlaced */ + + u32 *overlay_mask; + + struct wait_queue *v4l_capq; /* wait here for grab to finish */ + + int v4l_overlay_active; /* Overlay grab is activated */ + int v4l_memgrab_active; /* Memory grab is activated */ + + int v4l_grab_frame; /* Frame number being currently grabbed */ +#define NO_GRAB_ACTIVE (-1) + int v4l_grab_seq; /* Number of frames grabbed */ + int gwidth; /* Width of current memory capture */ + int gheight; /* Height of current memory capture */ + int gformat; /* Format of ... */ + int gbpl; /* byte per line of ... */ + + /* V4L grab queue of frames pending */ + + unsigned v4l_pend_head; + unsigned v4l_pend_tail; + int v4l_pend[V4L_MAX_FRAME]; + + struct v4l_gbuffer v4l_gbuf[VIDEO_MAX_FRAME]; /* V4L buffers' info */ + + /* Buz MJPEG parameters */ + + unsigned long jpg_nbufs; /* Number of buffers */ + unsigned long jpg_bufsize; /* Size of mjpeg buffers in bytes */ + int jpg_buffers_allocated; /* Flag if buffers are allocated */ + int need_contiguous; /* Flag if contiguous buffers are needed */ + + enum zoran_codec_mode codec_mode; /* status of codec */ + struct zoran_params params; /* structure with a lot of things to play with */ + + struct wait_queue *jpg_capq; /* wait here for grab to finish */ + + /* grab queue counts/indices, mask with BUZ_MASK_STAT_COM before using as index */ + /* (dma_head - dma_tail) is number active in DMA, must be <= BUZ_NUM_STAT_COM */ + /* (value & BUZ_MASK_STAT_COM) corresponds to index in stat_com table */ + unsigned long jpg_que_head; /* Index where to put next buffer which is queued */ + unsigned long jpg_dma_head; /* Index of next buffer which goes into stat_com */ + unsigned long jpg_dma_tail; /* Index of last buffer in stat_com */ + unsigned long jpg_que_tail; /* Index of last buffer in queue */ + unsigned long jpg_seq_num; /* count of frames since grab/play started */ + + /* zr36057's code buffer table */ + u32 *stat_com; /* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */ + + /* (value & BUZ_MASK_FRAME) corresponds to index in pend[] queue */ + int jpg_pend[BUZ_MAX_FRAME]; + + /* array indexed by frame number */ + struct zoran_gbuffer jpg_gbuf[BUZ_MAX_FRAME]; /* MJPEG buffers' info */ +}; + +#endif + +/*The following should be done in more portable way. It depends on define + of _ALPHA_BUZ in the Makefile. */ + +#ifdef _ALPHA_BUZ +#define btwrite(dat,adr) writel((dat),(char *) (zr->zr36057_adr+(adr))) +#define btread(adr) readl(zr->zr36057_adr+(adr)) +#else +#define btwrite(dat,adr) writel((dat), (char *) (zr->zr36057_mem+(adr))) +#define btread(adr) readl(zr->zr36057_mem+(adr)) +#endif + +#define btand(dat,adr) btwrite((dat) & btread(adr), adr) +#define btor(dat,adr) btwrite((dat) | btread(adr), adr) +#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr) + +#define I2C_TSA5522 0xc2 +#define I2C_TDA9850 0xb6 +#define I2C_HAUPEE 0xa0 +#define I2C_STBEE 0xae +#define I2C_SAA7111 0x48 +#define I2C_SAA7185 0x88 + +#define TDA9850_CON1 0x04 +#define TDA9850_CON2 0x05 +#define TDA9850_CON3 0x06 +#define TDA9850_CON4 0x07 +#define TDA9850_ALI1 0x08 +#define TDA9850_ALI2 0x09 +#define TDA9850_ALI3 0x0a + +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/bw-qcam.c linux.ac/drivers/char/bw-qcam.c --- linux.vanilla/drivers/char/bw-qcam.c Mon Mar 29 10:25:55 1999 +++ linux.ac/drivers/char/bw-qcam.c Mon Jul 5 04:39:16 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.ac/drivers/char/c-qcam.c --- linux.vanilla/drivers/char/c-qcam.c Tue Dec 22 23:19:37 1998 +++ linux.ac/drivers/char/c-qcam.c Mon Jul 5 04:38:51 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/chipsets.h linux.ac/drivers/char/chipsets.h --- linux.vanilla/drivers/char/chipsets.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/char/chipsets.h Thu Jul 1 19:05:50 1999 @@ -0,0 +1,41 @@ +static const struct { + unsigned short vendor; + unsigned short device; + enum { + TRITON, + NATOMA + } action; + const char *name; +} black[] = { + + { + PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, TRITON, "82437" + }, + { + PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437VX, TRITON, "82437VX Triton II" + }, + { + PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439, TRITON, "82439HX Triton II" + }, + { + PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439TX, TRITON, "82439TX" + }, + { + PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, NATOMA, "82441FX Natoma" + }, + { + PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443LX_0, NATOMA, "440LX - 82443LX PAC Host" + }, + { + PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443LX_1, NATOMA, "440LX - 82443LX PAC AGP" + }, + { + PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_0, NATOMA, "440BX - 82443BX Host" + }, + { + PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_1, NATOMA, "440BX - 82443BX AGP" + }, + { + PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2, NATOMA, "440BX - 82443BX Host (no AGP)" + }, +}; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/cyclades.c linux.ac/drivers/char/cyclades.c --- linux.vanilla/drivers/char/cyclades.c Tue Jun 15 16:49:48 1999 +++ linux.ac/drivers/char/cyclades.c Wed Jun 30 00:15:32 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/dmaram.c linux.ac/drivers/char/dmaram.c --- linux.vanilla/drivers/char/dmaram.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/char/dmaram.c Mon Jul 19 03:45:43 1999 @@ -0,0 +1,235 @@ +/* + * A simple DMA memory driver for the Linux kernel. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#define MAX_DMARAM 32 + +#define DMA_MAJOR 125 + + +struct dmaram +{ + int buffsize; + void *raw_buf; + unsigned long raw_buf_phys; +}; + +struct dmaram *dma_dev[MAX_DMARAM]; + +static int dmaram_create(struct dmaram *dp) +{ + char *start_addr, *end_addr; + int size, sz, i; + if(dp->buffsize < PAGE_SIZE) + dp->buffsize = PAGE_SIZE; + dp->raw_buf = NULL; + start_addr = NULL; + + while (start_addr == NULL && dp->buffsize > PAGE_SIZE) { + for (sz = 0, size = PAGE_SIZE; size < dp->buffsize; sz++, size <<= 1); + { + dp->buffsize = PAGE_SIZE * (1 << sz); + start_addr = (char *) __get_free_pages(GFP_KERNEL, sz); + if (start_addr == NULL) + dp->buffsize /= 2; + } + } + if (start_addr == NULL) { + return -ENOMEM; + } else { + /* make some checks */ + end_addr = start_addr + dp->buffsize - 1; + } + dp->raw_buf = start_addr; + dp->raw_buf_phys = virt_to_bus(start_addr); + + for (i = MAP_NR(start_addr); i < MAP_NR(end_addr); i++) + set_bit(PG_reserved, &mem_map[i].flags);; + return 0; +} + +static void dmaram_destroy(struct dmaram *dp) +{ + int sz, size, i; + unsigned long start_addr, end_addr; + + if (dp->raw_buf == NULL) + return; + for (sz = 0, size = PAGE_SIZE; size < dp->buffsize; sz++, size <<= 1); + + start_addr = (unsigned long) dp->raw_buf; + end_addr = start_addr + dp->buffsize; + + for (i = MAP_NR(start_addr); i < MAP_NR(end_addr); i++) + clear_bit(PG_reserved, &mem_map[i].flags);; + + free_pages((unsigned long) dp->raw_buf, sz); + dp->raw_buf = NULL; +} + + +static int dma_open(struct inode *inode, struct file *file) +{ + void *ram; + int minor = MINOR(inode->i_rdev); + if(minor >= MAX_DMARAM) + return -ENXIO; + + /* + * The allocate may sleep - avoid races + */ + + ram = (struct dmaram *)kmalloc(sizeof(struct dmaram), GFP_KERNEL); + if(ram==NULL) + return -ENOMEM; + + if(dma_dev[minor] != NULL) + { + kfree(ram); + return -EBUSY; + } + + dma_dev[minor]=ram; + MOD_INC_USE_COUNT; + memset(dma_dev[minor], 0, sizeof(struct dmaram)); + return 0; +} + + +static int dma_release(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + struct dmaram *dp = dma_dev[minor]; + if(dp->raw_buf) + dmaram_destroy(dp); + kfree(dma_dev[minor]); + dma_dev[minor]=NULL; + MOD_DEC_USE_COUNT; + return 0; +} + +static long long dma_lseek(struct file *file, long long offset, int origin) +{ + return -ESPIPE; +} + +static int dma_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + struct dmaram *dp = dma_dev[MINOR(inode->i_rdev)]; + switch(cmd) + { + case DMAIOCSET: + { + long size; + if(dp->raw_buf) + return -EBUSY; + if(get_user(size, (long *)arg)) + return -EFAULT; + if(size < PAGE_SIZE || size%PAGE_SIZE) + return -EINVAL; + if(size > 32 * PAGE_SIZE) + size = 32 *PAGE_SIZE; + + dp->buffsize = size; + + return dmaram_create(dp); + } + + case DMAIOCGET: + { + struct dma_info dmi; + dmi.size = dp->buffsize; + dmi.phys = dp->raw_buf_phys; + if(copy_to_user((void *)arg, &dmi, sizeof(dmi))) + return -EFAULT; + return 0; + } + } + return -ENOTTY; +} + + +static int dma_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct dmaram *dp = dma_dev[MINOR(file->f_dentry->d_inode->i_rdev)]; + int size; + + if(dp->raw_buf == NULL) + return -EIO; + size = vma->vm_end - vma->vm_start; + if(size != dp->buffsize) + return -EINVAL; + if(remap_page_range(vma->vm_start, dp->raw_buf_phys, + size, vma->vm_page_prot)) + return -EAGAIN; + return 0; +} + +static ssize_t dma_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + return -EINVAL; +} + +static ssize_t dma_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +{ + return -EINVAL; +} + +static struct file_operations dma_fops= +{ + dma_lseek, + dma_read, + dma_write, + NULL, /* readdir */ + NULL, + dma_ioctl, + dma_mmap, + dma_open, + NULL, /* flush */ + dma_release +}; + +/* + * Initialise DMAram for Linux + */ + +int dmaram_init(void) +{ + printk(KERN_INFO "Linux DMA memory interface v0.02 (c) 1999 Red Hat Software\n"); + if(register_chrdev(DMA_MAJOR,"dmaram", &dma_fops)) + { + printk("dma_dev: unable to get major %d\n", DMA_MAJOR); + return -EIO; + } + return 0; +} + +#ifdef MODULE +int init_module(void) +{ + return dmaram_init(); +} + +void cleanup_module(void) +{ + unregister_chrdev(DMA_MAJOR, "dmaram"); +} + +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/dz.c linux.ac/drivers/char/dz.c --- linux.vanilla/drivers/char/dz.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/char/dz.c Mon Jul 19 03:45:43 1999 @@ -0,0 +1,1602 @@ +/* + * 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 +#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.ac/drivers/char/dz.h --- linux.vanilla/drivers/char/dz.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/char/dz.h Tue Jun 22 01:41:18 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/esp.c linux.ac/drivers/char/esp.c --- linux.vanilla/drivers/char/esp.c Sun Nov 8 15:10:12 1998 +++ linux.ac/drivers/char/esp.c Fri Jun 4 23:52:41 1999 @@ -2186,7 +2186,7 @@ if (signal_pending(current)) break; - if (timeout && ((orig_jiffies + timeout) < jiffies)) + if (timeout && time_before(orig_jiffies + timeout, jiffies)) break; serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/i2c.c linux.ac/drivers/char/i2c.c --- linux.vanilla/drivers/char/i2c.c Tue Jan 19 02:57:26 1999 +++ linux.ac/drivers/char/i2c.c Thu Jul 1 19:12:16 1999 @@ -40,6 +40,14 @@ extern int i2c_tuner_init(void); extern int msp3400c_init(void); #endif +#ifdef CONFIG_VIDEO_BUZ +extern int saa7111_init(void); +extern int saa7185_init(void); +#endif +#ifdef CONFIG_VIDEO_LML33 +extern int bt819_init(void); +extern int bt856_init(void); +#endif int i2c_init(void) { @@ -50,6 +58,14 @@ i2c_tuner_init(); msp3400c_init(); #endif +#ifdef CONFIG_VIDEO_BUZ + saa7111_init(); + saa7185_init(); +#endif +#ifdef CONFIG_VIDEO_LML33 + bt819_init(); + bt856_init(); +#endif return 0; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/isicom.c linux.ac/drivers/char/isicom.c --- linux.vanilla/drivers/char/isicom.c Thu May 27 22:11:53 1999 +++ linux.ac/drivers/char/isicom.c Thu Jul 8 01:47:43 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.ac/drivers/char/keyboard.c --- linux.vanilla/drivers/char/keyboard.c Wed Apr 28 19:14:26 1999 +++ linux.ac/drivers/char/keyboard.c Tue Jun 29 02:26:47 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/mem.c linux.ac/drivers/char/mem.c --- linux.vanilla/drivers/char/mem.c Thu May 27 22:11:53 1999 +++ linux.ac/drivers/char/mem.c Sun Jun 6 01:42:54 1999 @@ -250,11 +250,14 @@ count -= read; } - virtr = vread(buf, (char *)p, count); - if (virtr < 0) - return virtr; - *ppos += p + virtr; - return virtr + read; + if(count) { + if((virtr = vread(buf, (char *)p, count)) < 0) + return virtr; + read += virtr; + } + + *ppos += read; + return read; } /* diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/misc.c linux.ac/drivers/char/misc.c --- linux.vanilla/drivers/char/misc.c Mon Mar 29 10:25:55 1999 +++ linux.ac/drivers/char/misc.c Tue Jun 22 01:41:18 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.ac/drivers/char/pc_keyb.c --- linux.vanilla/drivers/char/pc_keyb.c Wed Apr 28 19:14:26 1999 +++ linux.ac/drivers/char/pc_keyb.c Tue Jun 29 02: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.ac/drivers/char/pc_keyb.h --- linux.vanilla/drivers/char/pc_keyb.h Tue Feb 23 14:21:33 1999 +++ linux.ac/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.ac/drivers/char/qpmouse.c --- linux.vanilla/drivers/char/qpmouse.c Sun Nov 8 15:10:12 1998 +++ linux.ac/drivers/char/qpmouse.c Tue Jun 29 02:26:47 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.ac/drivers/char/radio-cadet.c --- linux.vanilla/drivers/char/radio-cadet.c Tue Jun 15 16:49:48 1999 +++ linux.ac/drivers/char/radio-cadet.c Mon Jun 21 13:12:14 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;i + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#define DEBUG(x) /* Debug driver */ + +/* ----------------------------------------------------------------------- */ + +struct saa7111 { + struct i2c_bus *bus; + int addr; + unsigned char reg[32]; + + int norm; + int input; + int enable; + int bright; + int contrast; + int hue; + int sat; +}; + +#define I2C_SAA7111 0x48 + +#define I2C_DELAY 10 + +/* ----------------------------------------------------------------------- */ + +static int saa7111_write(struct saa7111 *dev, unsigned char subaddr, unsigned char data) +{ + int ack; + unsigned long flags; + + LOCK_I2C_BUS(dev->bus); + i2c_start(dev->bus); + i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY); + i2c_sendbyte(dev->bus, subaddr, I2C_DELAY); + ack = i2c_sendbyte(dev->bus, data, I2C_DELAY); + dev->reg[subaddr] = data; + i2c_stop(dev->bus); + UNLOCK_I2C_BUS(dev->bus); + return ack; +} + +static int saa7111_write_block(struct saa7111 *dev, unsigned const char *data, unsigned int len) +{ + int ack; + unsigned subaddr; + unsigned long flags; + + while (len > 1) { + LOCK_I2C_BUS(dev->bus); + i2c_start(dev->bus); + i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY); + ack = i2c_sendbyte(dev->bus, (subaddr = *data++), I2C_DELAY); + ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY); + len -= 2; + while (len > 1 && *data == ++subaddr) { + data++; + ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY); + len -= 2; + } + i2c_stop(dev->bus); + UNLOCK_I2C_BUS(dev->bus); + } + return ack; +} + +static int saa7111_read(struct saa7111 *dev, unsigned char subaddr) +{ + int data; + unsigned long flags; + + LOCK_I2C_BUS(dev->bus); + i2c_start(dev->bus); + i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY); + i2c_sendbyte(dev->bus, subaddr, I2C_DELAY); + i2c_start(dev->bus); + i2c_sendbyte(dev->bus, dev->addr | 1, I2C_DELAY); + data = i2c_readbyte(dev->bus, 1); + i2c_stop(dev->bus); + UNLOCK_I2C_BUS(dev->bus); + return data; +} + +/* ----------------------------------------------------------------------- */ + +static int saa7111_attach(struct i2c_device *device) +{ + int i; + struct saa7111 *decoder; + + static const unsigned char init[] = + { + 0x00, 0x00, /* 00 - ID byte */ + 0x01, 0x00, /* 01 - reserved */ + + /*front end */ + 0x02, 0xd0, /* 02 - FUSE=3, GUDL=2, MODE=0 */ + 0x03, 0x23, /* 03 - HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */ + 0x04, 0x00, /* 04 - GAI1=256 */ + 0x05, 0x00, /* 05 - GAI2=256 */ + + /* decoder */ + 0x06, 0xf6, /* 06 - HSB at 13(50Hz) / 17(60Hz) pixels after end of last line */ + 0x07, 0xdd, /* 07 - HSS at 113(50Hz) / 117(60Hz) pixels after end of last line */ + 0x08, 0xc8, /* 08 - AUFD=1, FSEL=1, EXFIL=0, VTRC=1, HPLL=0, VNOI=0 */ + 0x09, 0x01, /* 09 - BYPS=0, PREF=0, BPSS=0, VBLB=0, UPTCV=0, APER=1 */ + 0x0a, 0x80, /* 0a - BRIG=128 */ + 0x0b, 0x47, /* 0b - CONT=1.109 */ + 0x0c, 0x40, /* 0c - SATN=1.0 */ + 0x0d, 0x00, /* 0d - HUE=0 */ + 0x0e, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */ + 0x0f, 0x00, /* 0f - reserved */ + 0x10, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */ + 0x11, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1, OEYC=1, OEHV=1, VIPB=0, COLO=0 */ + 0x12, 0x00, /* 12 - output control 2 */ + 0x13, 0x00, /* 13 - output control 3 */ + 0x14, 0x00, /* 14 - reserved */ + 0x15, 0x00, /* 15 - VBI */ + 0x16, 0x00, /* 16 - VBI */ + 0x17, 0x00, /* 17 - VBI */ + }; + + device->data = decoder = kmalloc(sizeof(struct saa7111), GFP_KERNEL); + if (decoder == NULL) { + return -ENOMEM; + } + MOD_INC_USE_COUNT; + + memset(decoder, 0, sizeof(struct saa7111)); + strcpy(device->name, "saa7111"); + decoder->bus = device->bus; + decoder->addr = device->addr; + decoder->norm = VIDEO_MODE_NTSC; + decoder->input = 0; + decoder->enable = 1; + decoder->bright = 32768; + decoder->contrast = 32768; + decoder->hue = 32768; + decoder->sat = 32768; + + i = saa7111_write_block(decoder, init, sizeof(init)); + if (i < 0) { + printk(KERN_ERR "%s_attach: init status %d\n", device->name, i); + } else { + printk(KERN_INFO "%s_attach: chip version %x\n", device->name, saa7111_read(decoder, 0x00)); + } + return 0; +} + + +static int saa7111_detach(struct i2c_device *device) +{ + kfree(device->data); + MOD_DEC_USE_COUNT; + return 0; +} + +static int saa7111_command(struct i2c_device *device, unsigned int cmd, void *arg) +{ + struct saa7111 *decoder = device->data; + + switch (cmd) { + +#if defined(DECODER_DUMP) + case DECODER_DUMP: + { + int i; + + for (i = 0; i < 32; i += 16) { + int j; + + printk("KERN_DEBUG %s: %03x", device->name, i); + for (j = 0; j < 16; ++j) { + printk(" %02x", saa7111_read(decoder, i + j)); + } + printk("\n"); + } + } + break; +#endif /* defined(DECODER_DUMP) */ + + case DECODER_GET_CAPABILITIES: + { + struct video_decoder_capability *cap = arg; + + cap->flags + = VIDEO_DECODER_PAL + | VIDEO_DECODER_NTSC + | VIDEO_DECODER_AUTO + | VIDEO_DECODER_CCIR; + cap->inputs = 8; + cap->outputs = 1; + } + break; + + case DECODER_GET_STATUS: + { + int *iarg = arg; + int status; + int res; + + status = saa7111_read(decoder, 0x1f); + res = 0; + if ((status & (1 << 6)) == 0) { + res |= DECODER_STATUS_GOOD; + } + switch (decoder->norm) { + case VIDEO_MODE_NTSC: + res |= DECODER_STATUS_NTSC; + break; + case VIDEO_MODE_PAL: + res |= DECODER_STATUS_PAL; + break; + default: + case VIDEO_MODE_AUTO: + if ((status & (1 << 5)) != 0) { + res |= DECODER_STATUS_NTSC; + } else { + res |= DECODER_STATUS_PAL; + } + break; + } + if ((status & (1 << 0)) != 0) { + res |= DECODER_STATUS_COLOR; + } + *iarg = res; + } + break; + + case DECODER_SET_NORM: + { + int *iarg = arg; + + switch (*iarg) { + + case VIDEO_MODE_NTSC: + saa7111_write(decoder, 0x08, (decoder->reg[0x08] & 0x3f) | 0x40); + break; + + case VIDEO_MODE_PAL: + saa7111_write(decoder, 0x08, (decoder->reg[0x08] & 0x3f) | 0x00); + break; + + case VIDEO_MODE_AUTO: + saa7111_write(decoder, 0x08, (decoder->reg[0x08] & 0x3f) | 0x80); + break; + + default: + return -EINVAL; + + } + decoder->norm = *iarg; + } + break; + + case DECODER_SET_INPUT: + { + int *iarg = arg; + + if (*iarg < 0 || *iarg > 7) { + return -EINVAL; + } + if (decoder->input != *iarg) { + decoder->input = *iarg; + /* select mode */ + saa7111_write(decoder, 0x02, (decoder->reg[0x02] & 0xf8) | decoder->input); + /* bypass chrominance trap for modes 4..7 */ + saa7111_write(decoder, 0x09, (decoder->reg[0x09] & 0x7f) | ((decoder->input > 3) ? 0x80 : 0)); + } + } + break; + + case DECODER_SET_OUTPUT: + { + int *iarg = arg; + + /* not much choice of outputs */ + if (*iarg != 0) { + return -EINVAL; + } + } + break; + + case DECODER_ENABLE_OUTPUT: + { + int *iarg = arg; + int enable = (*iarg != 0); + + if (decoder->enable != enable) { + decoder->enable = enable; + +// RJ: If output should be disabled (for playing videos), we also need a open PLL. + // The input is set to 0 (where no input source is connected), although this + // is not necessary. + // + // If output should be enabled, we have to reverse the above. + + if (decoder->enable) { + saa7111_write(decoder, 0x02, (decoder->reg[0x02] & 0xf8) | decoder->input); + saa7111_write(decoder, 0x08, (decoder->reg[0x08] & 0xfb)); + saa7111_write(decoder, 0x11, (decoder->reg[0x11] & 0xf3) | 0x0c); + } else { + saa7111_write(decoder, 0x02, (decoder->reg[0x02] & 0xf8)); + saa7111_write(decoder, 0x08, (decoder->reg[0x08] & 0xfb) | 0x04); + saa7111_write(decoder, 0x11, (decoder->reg[0x11] & 0xf3)); + } + } + } + break; + + case DECODER_SET_PICTURE: + { + struct video_picture *pic = arg; + + if (decoder->bright != pic->brightness) { + /* We want 0 to 255 we get 0-65535 */ + decoder->bright = pic->brightness; + saa7111_write(decoder, 0x0a, decoder->bright >> 8); + } + if (decoder->contrast != pic->contrast) { + /* We want 0 to 127 we get 0-65535 */ + decoder->contrast = pic->contrast; + saa7111_write(decoder, 0x0b, decoder->contrast >> 9); + } + if (decoder->sat != pic->colour) { + /* We want 0 to 127 we get 0-65535 */ + decoder->sat = pic->colour; + saa7111_write(decoder, 0x0c, decoder->sat >> 9); + } + if (decoder->hue != pic->hue) { + /* We want -128 to 127 we get 0-65535 */ + decoder->hue = pic->hue; + saa7111_write(decoder, 0x0d, (decoder->hue - 32768) >> 8); + } + } + break; + + default: + return -EINVAL; + } + + return 0; +} + +/* ----------------------------------------------------------------------- */ + +struct i2c_driver i2c_driver_saa7111 = +{ + "saa7111", /* name */ + I2C_DRIVERID_VIDEODECODER, /* ID */ + I2C_SAA7111, I2C_SAA7111 + 1, + + saa7111_attach, + saa7111_detach, + saa7111_command +}; + +EXPORT_NO_SYMBOLS; + +#ifdef MODULE +int init_module(void) +#else +int saa7111_init(void) +#endif +{ + return i2c_register_driver(&i2c_driver_saa7111); +} + + + +#ifdef MODULE + +void cleanup_module(void) +{ + i2c_unregister_driver(&i2c_driver_saa7111); +} + +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/saa7185.c linux.ac/drivers/char/saa7185.c --- linux.vanilla/drivers/char/saa7185.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/char/saa7185.c Thu Jul 1 19:18:14 1999 @@ -0,0 +1,379 @@ +/* + saa7185 - Philips SAA7185B video encoder driver version 0.0.3 + + Copyright (C) 1998 Dave Perks + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#define DEBUG(x) x /* Debug driver */ + +/* ----------------------------------------------------------------------- */ + +struct saa7185 { + struct i2c_bus *bus; + int addr; + unsigned char reg[128]; + + int norm; + int enable; + int bright; + int contrast; + int hue; + int sat; +}; + +#define I2C_SAA7185 0x88 + +#define I2C_DELAY 10 + +/* ----------------------------------------------------------------------- */ + +static int saa7185_write(struct saa7185 *dev, unsigned char subaddr, unsigned char data) +{ + int ack; + unsigned long flags; + + LOCK_I2C_BUS(dev->bus); + + i2c_start(dev->bus); + i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY); + i2c_sendbyte(dev->bus, subaddr, I2C_DELAY); + ack = i2c_sendbyte(dev->bus, data, I2C_DELAY); + dev->reg[subaddr] = data; + i2c_stop(dev->bus); + UNLOCK_I2C_BUS(dev->bus); + return ack; +} + +static int saa7185_write_block(struct saa7185 *dev, unsigned const char *data, unsigned int len) +{ + int ack; + unsigned subaddr; + unsigned long flags; + + while (len > 1) { + LOCK_I2C_BUS(dev->bus); + i2c_start(dev->bus); + i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY); + ack = i2c_sendbyte(dev->bus, (subaddr = *data++), I2C_DELAY); + ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY); + len -= 2; + while (len > 1 && *data == ++subaddr) { + data++; + ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY); + len -= 2; + } + i2c_stop(dev->bus); + UNLOCK_I2C_BUS(dev->bus); + } + return ack; +} + +/* ----------------------------------------------------------------------- */ + +static const unsigned char init_common[] = +{ + 0x3a, 0x0f, /* CBENB=0, V656=0, VY2C=1, YUV2C=1, MY2C=1, MUV2C=1 */ + + 0x42, 0x6b, /* OVLY0=107 */ + 0x43, 0x00, /* OVLU0=0 white */ + 0x44, 0x00, /* OVLV0=0 */ + 0x45, 0x22, /* OVLY1=34 */ + 0x46, 0xac, /* OVLU1=172 yellow */ + 0x47, 0x0e, /* OVLV1=14 */ + 0x48, 0x03, /* OVLY2=3 */ + 0x49, 0x1d, /* OVLU2=29 cyan */ + 0x4a, 0xac, /* OVLV2=172 */ + 0x4b, 0xf0, /* OVLY3=240 */ + 0x4c, 0xc8, /* OVLU3=200 green */ + 0x4d, 0xb9, /* OVLV3=185 */ + 0x4e, 0xd4, /* OVLY4=212 */ + 0x4f, 0x38, /* OVLU4=56 magenta */ + 0x50, 0x47, /* OVLV4=71 */ + 0x51, 0xc1, /* OVLY5=193 */ + 0x52, 0xe3, /* OVLU5=227 red */ + 0x53, 0x54, /* OVLV5=84 */ + 0x54, 0xa3, /* OVLY6=163 */ + 0x55, 0x54, /* OVLU6=84 blue */ + 0x56, 0xf2, /* OVLV6=242 */ + 0x57, 0x90, /* OVLY7=144 */ + 0x58, 0x00, /* OVLU7=0 black */ + 0x59, 0x00, /* OVLV7=0 */ + + 0x5a, 0x00, /* CHPS=0 */ + 0x5b, 0x76, /* GAINU=118 */ + 0x5c, 0xa5, /* GAINV=165 */ + 0x5d, 0x3c, /* BLCKL=60 */ + 0x5e, 0x3a, /* BLNNL=58 */ + 0x5f, 0x3a, /* CCRS=0, BLNVB=58 */ + 0x60, 0x00, /* NULL */ + +/* 0x61 - 0x66 set according to norm */ + + 0x67, 0x00, /* 0 : caption 1st byte odd field */ + 0x68, 0x00, /* 0 : caption 2nd byte odd field */ + 0x69, 0x00, /* 0 : caption 1st byte even field */ + 0x6a, 0x00, /* 0 : caption 2nd byte even field */ + + 0x6b, 0x91, /* MODIN=2, PCREF=0, SCCLN=17 */ + 0x6c, 0x20, /* SRCV1=0, TRCV2=1, ORCV1=0, PRCV1=0, CBLF=0, ORCV2=0, PRCV2=0 */ + 0x6d, 0x00, /* SRCM1=0, CCEN=0 */ + + 0x6e, 0x0e, /* HTRIG=0x00e, approx. centered, at least for PAL */ + 0x6f, 0x00, /* HTRIG upper bits */ + 0x70, 0x20, /* PHRES=0, SBLN=1, VTRIG=0 */ + +/* The following should not be needed */ + + 0x71, 0x15, /* BMRQ=0x115 */ + 0x72, 0x90, /* EMRQ=0x690 */ + 0x73, 0x61, /* EMRQ=0x690, BMRQ=0x115 */ + 0x74, 0x00, /* NULL */ + 0x75, 0x00, /* NULL */ + 0x76, 0x00, /* NULL */ + 0x77, 0x15, /* BRCV=0x115 */ + 0x78, 0x90, /* ERCV=0x690 */ + 0x79, 0x61, /* ERCV=0x690, BRCV=0x115 */ + +/* Field length controls */ + + 0x7a, 0x70, /* FLC=0 */ + +/* The following should not be needed if SBLN = 1 */ + + 0x7b, 0x16, /* FAL=22 */ + 0x7c, 0x35, /* LAL=244 */ + 0x7d, 0x20, /* LAL=244, FAL=22 */ +}; + +static const unsigned char init_pal[] = +{ + 0x61, 0x1e, /* FISE=0, PAL=1, SCBW=1, RTCE=1, YGS=1, INPI=0, DOWN=0 */ + 0x62, 0xc8, /* DECTYP=1, BSTA=72 */ + 0x63, 0xcb, /* FSC0 */ + 0x64, 0x8a, /* FSC1 */ + 0x65, 0x09, /* FSC2 */ + 0x66, 0x2a, /* FSC3 */ +}; + +static const unsigned char init_ntsc[] = +{ + 0x61, 0x1d, /* FISE=1, PAL=0, SCBW=1, RTCE=1, YGS=1, INPI=0, DOWN=0 */ + 0x62, 0xe6, /* DECTYP=1, BSTA=102 */ + 0x63, 0x1f, /* FSC0 */ + 0x64, 0x7c, /* FSC1 */ + 0x65, 0xf0, /* FSC2 */ + 0x66, 0x21, /* FSC3 */ +}; + +static int saa7185_attach(struct i2c_device *device) +{ + int i; + struct saa7185 *encoder; + + device->data = encoder = kmalloc(sizeof(struct saa7185), GFP_KERNEL); + if (encoder == NULL) { + return -ENOMEM; + } + MOD_INC_USE_COUNT; + + memset(encoder, 0, sizeof(struct saa7185)); + strcpy(device->name, "saa7185"); + encoder->bus = device->bus; + encoder->addr = device->addr; + encoder->norm = VIDEO_MODE_NTSC; + encoder->enable = 1; + + i = saa7185_write_block(encoder, init_common, sizeof(init_common)); + if (i >= 0) { + i = saa7185_write_block(encoder, init_ntsc, sizeof(init_ntsc)); + } + if (i < 0) { + printk(KERN_ERR "%s_attach: init error %d\n", device->name, i); + } + return 0; +} + + +static int saa7185_detach(struct i2c_device *device) +{ + kfree(device->data); + MOD_DEC_USE_COUNT; + return 0; +} + +static int saa7185_command(struct i2c_device *device, unsigned int cmd, void *arg) +{ + struct saa7185 *encoder = device->data; + + switch (cmd) { + + case ENCODER_GET_CAPABILITIES: + { + struct video_encoder_capability *cap = arg; + + cap->flags + = VIDEO_ENCODER_PAL + | VIDEO_ENCODER_NTSC + | VIDEO_ENCODER_SECAM + | VIDEO_ENCODER_CCIR; + cap->inputs = 1; + cap->outputs = 1; + } + break; + + case ENCODER_SET_NORM: + { + int *iarg = arg; + + switch (*iarg) { + + case VIDEO_MODE_NTSC: + saa7185_write_block(encoder, init_ntsc, sizeof(init_ntsc)); + break; + + case VIDEO_MODE_PAL: + saa7185_write_block(encoder, init_pal, sizeof(init_pal)); + break; + + case VIDEO_MODE_SECAM: + default: + return -EINVAL; + + } + encoder->norm = *iarg; + } + break; + + case ENCODER_SET_INPUT: + { + int *iarg = arg; + +#if 0 + /* not much choice of inputs */ + if (*iarg != 0) { + return -EINVAL; + } +#else + /* RJ: *iarg = 0: input is from SA7111 + *iarg = 1: input is from ZR36060 */ + + switch (*iarg) { + + case 0: + /* Switch RTCE to 1 */ + saa7185_write(encoder, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08); + break; + + case 1: + /* Switch RTCE to 0 */ + saa7185_write(encoder, 0x61, (encoder->reg[0x61] & 0xf7) | 0x00); + break; + + default: + return -EINVAL; + + } +#endif + } + break; + + case ENCODER_SET_OUTPUT: + { + int *iarg = arg; + + /* not much choice of outputs */ + if (*iarg != 0) { + return -EINVAL; + } + } + break; + + case ENCODER_ENABLE_OUTPUT: + { + int *iarg = arg; + + encoder->enable = !!*iarg; + saa7185_write(encoder, 0x61, (encoder->reg[0x61] & 0xbf) | (encoder->enable ? 0x00 : 0x40)); + } + break; + + default: + return -EINVAL; + } + + return 0; +} + +/* ----------------------------------------------------------------------- */ + +struct i2c_driver i2c_driver_saa7185 = +{ + "saa7185", /* name */ + I2C_DRIVERID_VIDEOENCODER, /* ID */ + I2C_SAA7185, I2C_SAA7185 + 1, + + saa7185_attach, + saa7185_detach, + saa7185_command +}; + +EXPORT_NO_SYMBOLS; + +#ifdef MODULE +int init_module(void) +#else +int saa7185_init(void) +#endif +{ + return i2c_register_driver(&i2c_driver_saa7185); +} + + + +#ifdef MODULE + +void cleanup_module(void) +{ + i2c_unregister_driver(&i2c_driver_saa7185); +} + +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/serial.c linux.ac/drivers/char/serial.c --- linux.vanilla/drivers/char/serial.c Wed Mar 24 10:55:16 1999 +++ linux.ac/drivers/char/serial.c Wed Jun 30 00:50:36 1999 @@ -103,7 +103,8 @@ #define RS_STROBE_TIME (10*HZ) #define RS_ISR_PASS_LIMIT 256 -#define IRQ_T(info) ((info->flags & 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/sysrq.c linux.ac/drivers/char/sysrq.c --- linux.vanilla/drivers/char/sysrq.c Sun Nov 8 15:07:40 1998 +++ linux.ac/drivers/char/sysrq.c Mon Jun 7 00:10:10 1999 @@ -21,13 +21,12 @@ #include #include #include - -#include - #ifdef CONFIG_APM #include #endif +#include + extern void wakeup_bdflush(int); extern void reset_vc(unsigned int); extern int console_loglevel; @@ -85,7 +84,7 @@ #ifdef CONFIG_APM case 'o': /* O -- power off */ printk("Power off\n"); - apm_power_off(); + apm_power_off(1); break; #endif case 's': /* S -- emergency sync */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/videodev.c linux.ac/drivers/char/videodev.c --- linux.vanilla/drivers/char/videodev.c Tue Jun 15 16:49:48 1999 +++ linux.ac/drivers/char/videodev.c Thu Jul 1 19:13:11 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.ac/drivers/char/vino.c --- linux.vanilla/drivers/char/vino.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/char/vino.c Mon Jul 19 03:45:43 1999 @@ -0,0 +1,275 @@ +/* $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 "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.ac/drivers/char/vino.h --- linux.vanilla/drivers/char/vino.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/char/vino.h Tue Jun 22 01:41:18 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.ac/drivers/char/vt.c --- linux.vanilla/drivers/char/vt.c Tue Feb 23 14:21:33 1999 +++ linux.ac/drivers/char/vt.c Tue Jun 22 01:41:31 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/char/wdt.c linux.ac/drivers/char/wdt.c --- linux.vanilla/drivers/char/wdt.c Tue Jun 15 16:49:48 1999 +++ linux.ac/drivers/char/wdt.c Mon Jun 7 22:24:09 1999 @@ -51,27 +51,44 @@ static int wdt_is_open=0; /* - * You must set these - there is no sane way to probe for this board. - * You can use wdt=x,y to set these now. + * There is no sane way to probe for this board. + * You can use wdt=x,y,n to set these values + * or you can use 'insmod wdt io=x irq=y timeout=n' */ static int io=0x240; static int irq=11; +static int timeout=60; /* seconds */ -#define WD_TIMO (100*60) /* 1 minute */ +#ifdef MODULE + +EXPORT_NO_SYMBOLS; +MODULE_PARM(io, "i"); +MODULE_PARM_DESC(io, "I/O port for Watchdog WDT500/501 board"); +MODULE_PARM(irq, "i"); +MODULE_PARM_DESC(irq, "IRQ for Watchdog WDT500/501 board"); +MODULE_PARM(timeout, "i"); +MODULE_PARM_DESC(timeout, + "Timeout value for Watchdog WDT500/501 board (in seconds)"); + +#endif /* * Setup options */ -__initfunc(void wdt_setup(char *str, int *ints)) +void __init wdt_setup(char *str, int *ints) { if(ints[0]>0) { io=ints[1]; if(ints[0]>1) irq=ints[2]; + if(ints[0]>2) + timeout=ints[3]; } + + timeout *= 100; } /* @@ -168,7 +185,7 @@ /* Write a watchdog value */ inb_p(WDT_DC); wdt_ctr_mode(1,2); - wdt_ctr_load(1,WD_TIMO); /* Timeout */ + wdt_ctr_load(1,timeout); /* Timeout */ outb_p(0, WDT_DC); } @@ -260,7 +277,7 @@ wdt_ctr_mode(1,2); wdt_ctr_mode(2,0); wdt_ctr_load(0, 8948); /* count at 100Hz */ - wdt_ctr_load(1,WD_TIMO); /* Timeout 120 seconds */ + wdt_ctr_load(1,timeout); /* Timeout */ wdt_ctr_load(2,65535); outb_p(0, WDT_DC); /* Enable */ return 0; @@ -365,9 +382,9 @@ #endif -__initfunc(int wdt_init(void)) +int __init wdt_init(void) { - printk("WDT500/501-P driver 0.07 at %X (Interrupt %d)\n", io,irq); + printk("WDT500/501-P driver 0.08 at %X (Interrupt %d)\n", io,irq); if(request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p", NULL)) { printk("IRQ %d is not free.\n", irq); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/zr36057.h linux.ac/drivers/char/zr36057.h --- linux.vanilla/drivers/char/zr36057.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/char/zr36057.h Thu Jul 1 19:05:24 1999 @@ -0,0 +1,168 @@ +/* + zr36057.h - zr36057 register offsets + + Copyright (C) 1998 Dave Perks + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _ZR36057_H_ +#define _ZR36057_H_ + + +/* Zoran ZR36057 registers */ + +#define ZR36057_VFEHCR 0x000 /* Video Front End, Horizontal Configuration Register */ +#define ZR36057_VFEHCR_HSPol (1<<30) +#define ZR36057_VFEHCR_HStart 10 +#define ZR36057_VFEHCR_HEnd 0 +#define ZR36057_VFEHCR_Hmask 0x3ff + +#define ZR36057_VFEVCR 0x004 /* Video Front End, Vertical Configuration Register */ +#define ZR36057_VFEVCR_VSPol (1<<30) +#define ZR36057_VFEVCR_VStart 10 +#define ZR36057_VFEVCR_VEnd 0 +#define ZR36057_VFEVCR_Vmask 0x3ff + +#define ZR36057_VFESPFR 0x008 /* Video Front End, Scaler and Pixel Format Register */ +#define ZR36057_VFESPFR_ExtFl (1<<26) +#define ZR36057_VFESPFR_TopField (1<<25) +#define ZR36057_VFESPFR_VCLKPol (1<<24) +#define ZR36057_VFESPFR_HFilter 21 +#define ZR36057_VFESPFR_HorDcm 14 +#define ZR36057_VFESPFR_VerDcm 8 +#define ZR36057_VFESPFR_DispMode 6 +#define ZR36057_VFESPFR_YUV422 (0<<3) +#define ZR36057_VFESPFR_RGB888 (1<<3) +#define ZR36057_VFESPFR_RGB565 (2<<3) +#define ZR36057_VFESPFR_RGB555 (3<<3) +#define ZR36057_VFESPFR_ErrDif (1<<2) +#define ZR36057_VFESPFR_Pack24 (1<<1) +#define ZR36057_VFESPFR_LittleEndian (1<<0) + +#define ZR36057_VDTR 0x00c /* Video Display "Top" Register */ + +#define ZR36057_VDBR 0x010 /* Video Display "Bottom" Register */ + +#define ZR36057_VSSFGR 0x014 /* Video Stride, Status, and Frame Grab Register */ +#define ZR36057_VSSFGR_DispStride 16 +#define ZR36057_VSSFGR_VidOvf (1<<8) +#define ZR36057_VSSFGR_SnapShot (1<<1) +#define ZR36057_VSSFGR_FrameGrab (1<<0) + +#define ZR36057_VDCR 0x018 /* Video Display Configuration Register */ +#define ZR36057_VDCR_VidEn (1<<31) +#define ZR36057_VDCR_MinPix 24 +#define ZR36057_VDCR_Triton (1<<24) +#define ZR36057_VDCR_VidWinHt 12 +#define ZR36057_VDCR_VidWinWid 0 + +#define ZR36057_MMTR 0x01c /* Masking Map "Top" Register */ + +#define ZR36057_MMBR 0x020 /* Masking Map "Bottom" Register */ + +#define ZR36057_OCR 0x024 /* Overlay Control Register */ +#define ZR36057_OCR_OvlEnable (1 << 15) +#define ZR36057_OCR_MaskStride 0 + +#define ZR36057_SPGPPCR 0x028 /* System, PCI, and General Purpose Pins Control Register */ +#define ZR36057_SPGPPCR_SoftReset (1<<24) + +#define ZR36057_GPPGCR1 0x02c /* General Purpose Pins and GuestBus Control Register (1) */ + +#define ZR36057_MCSAR 0x030 /* MPEG Code Source Address Register */ + +#define ZR36057_MCTCR 0x034 /* MPEG Code Transfer Control Register */ +#define ZR36057_MCTCR_CodTime (1 << 30) +#define ZR36057_MCTCR_CEmpty (1 << 29) +#define ZR36057_MCTCR_CFlush (1 << 28) +#define ZR36057_MCTCR_CodGuestID 20 +#define ZR36057_MCTCR_CodGuestReg 16 + +#define ZR36057_MCMPR 0x038 /* MPEG Code Memory Pointer Register */ + +#define ZR36057_ISR 0x03c /* Interrupt Status Register */ +#define ZR36057_ISR_GIRQ1 (1<<30) +#define ZR36057_ISR_GIRQ0 (1<<29) +#define ZR36057_ISR_CodRepIRQ (1<<28) +#define ZR36057_ISR_JPEGRepIRQ (1<<27) + +#define ZR36057_ICR 0x040 /* Interrupt Control Register */ +#define ZR36057_ICR_GIRQ1 (1<<30) +#define ZR36057_ICR_GIRQ0 (1<<29) +#define ZR36057_ICR_CodRepIRQ (1<<28) +#define ZR36057_ICR_JPEGRepIRQ (1<<27) +#define ZR36057_ICR_IntPinEn (1<<24) + +#define ZR36057_I2CBR 0x044 /* I2C Bus Register */ +#define ZR36057_I2CBR_SDA (1<<1) +#define ZR36057_I2CBR_SCL (1<<0) + +#define ZR36057_JMC 0x100 /* JPEG Mode and Control */ +#define ZR36057_JMC_JPG (1 << 31) +#define ZR36057_JMC_JPGExpMode (0 << 29) +#define ZR36057_JMC_JPGCmpMode (1 << 29) +#define ZR36057_JMC_MJPGExpMode (2 << 29) +#define ZR36057_JMC_MJPGCmpMode (3 << 29) +#define ZR36057_JMC_RTBUSY_FB (1 << 6) +#define ZR36057_JMC_Go_en (1 << 5) +#define ZR36057_JMC_SyncMstr (1 << 4) +#define ZR36057_JMC_Fld_per_buff (1 << 3) +#define ZR36057_JMC_VFIFO_FB (1 << 2) +#define ZR36057_JMC_CFIFO_FB (1 << 1) +#define ZR36057_JMC_Stll_LitEndian (1 << 0) + +#define ZR36057_JPC 0x104 /* JPEG Process Control */ +#define ZR36057_JPC_P_Reset (1 << 7) +#define ZR36057_JPC_CodTrnsEn (1 << 5) +#define ZR36057_JPC_Active (1 << 0) + +#define ZR36057_VSP 0x108 /* Vertical Sync Parameters */ +#define ZR36057_VSP_VsyncSize 16 +#define ZR36057_VSP_FrmTot 0 + +#define ZR36057_HSP 0x10c /* Horizontal Sync Parameters */ +#define ZR36057_HSP_HsyncStart 16 +#define ZR36057_HSP_LineTot 0 + +#define ZR36057_FHAP 0x110 /* Field Horizontal Active Portion */ +#define ZR36057_FHAP_NAX 16 +#define ZR36057_FHAP_PAX 0 + +#define ZR36057_FVAP 0x114 /* Field Vertical Active Portion */ +#define ZR36057_FVAP_NAY 16 +#define ZR36057_FVAP_PAY 0 + +#define ZR36057_FPP 0x118 /* Field Process Parameters */ +#define ZR36057_FPP_Odd_Even (1 << 0) + +#define ZR36057_JCBA 0x11c /* JPEG Code Base Address */ + +#define ZR36057_JCFT 0x120 /* JPEG Code FIFO Threshold */ + +#define ZR36057_JCGI 0x124 /* JPEG Codec Guest ID */ +#define ZR36057_JCGI_JPEGuestID 4 +#define ZR36057_JCGI_JPEGuestReg 0 + +#define ZR36057_GCR2 0x12c /* GuestBus Control Register (2) */ + +#define ZR36057_POR 0x200 /* Post Office Register */ +#define ZR36057_POR_POPen (1<<25) +#define ZR36057_POR_POTime (1<<24) +#define ZR36057_POR_PODir (1<<23) + +#define ZR36057_STR 0x300 /* "Still" Transfer Register */ + +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/zr36060.h linux.ac/drivers/char/zr36060.h --- linux.vanilla/drivers/char/zr36060.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/char/zr36060.h Thu Jul 1 19:05:24 1999 @@ -0,0 +1,35 @@ +/* + zr36060.h - zr36060 register offsets + + Copyright (C) 1998 Dave Perks + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _ZR36060_H_ +#define _ZR36060_H_ + + +/* Zoran ZR36060 registers */ + +#define ZR36060_LoadParameters 0x000 +#define ZR36060_Load (1<<7) +#define ZR36060_SyncRst (1<<0) + +#define ZR36060_CodeFifoStatus 0x001 +#define ZR36060_Load (1<<7) +#define ZR36060_SyncRst (1<<0) + +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/capidrv.c linux.ac/drivers/isdn/avmb1/capidrv.c --- linux.vanilla/drivers/isdn/avmb1/capidrv.c Sun Nov 8 15:08:08 1998 +++ linux.ac/drivers/isdn/avmb1/capidrv.c Mon Jul 5 17:54:06 1999 @@ -1321,13 +1321,14 @@ handle_data(&s_cmsg, skb); 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); + + kfree_skb(skb); } } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/Config.in linux.ac/drivers/net/Config.in --- linux.vanilla/drivers/net/Config.in Tue Jun 15 16:49:49 1999 +++ linux.ac/drivers/net/Config.in Tue Jun 22 01:34:49 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.ac/drivers/net/Makefile --- linux.vanilla/drivers/net/Makefile Tue Jun 15 16:49:49 1999 +++ linux.ac/drivers/net/Makefile Tue Jun 22 01:34:49 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.ac/drivers/net/Space.c --- linux.vanilla/drivers/net/Space.c Tue Jun 15 16:49:49 1999 +++ linux.ac/drivers/net/Space.c Thu Jul 8 22:22:16 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.ac/drivers/net/arcnet.c --- linux.vanilla/drivers/net/arcnet.c Sun Nov 8 15:07:21 1998 +++ linux.ac/drivers/net/arcnet.c Mon Jul 5 04:31:20 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.ac/drivers/net/arlan-proc.c --- linux.vanilla/drivers/net/arlan-proc.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/net/arlan-proc.c Mon Jul 19 03:45:43 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.ac/drivers/net/arlan.c --- linux.vanilla/drivers/net/arlan.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/net/arlan.c Mon Jul 19 03:45:43 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.ac/drivers/net/arlan.h --- linux.vanilla/drivers/net/arlan.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/net/arlan.h Mon Jul 19 05:21:04 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.ac/drivers/net/bagetlance.c --- linux.vanilla/drivers/net/bagetlance.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/net/bagetlance.c Tue Jun 22 01:34:49 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.ac/drivers/net/com90xx.c --- linux.vanilla/drivers/net/com90xx.c Sun Nov 8 15:07:30 1998 +++ linux.ac/drivers/net/com90xx.c Sat Jul 3 20:32:15 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.ac/drivers/net/de4x5.c --- linux.vanilla/drivers/net/de4x5.c Thu May 27 22:11:54 1999 +++ linux.ac/drivers/net/de4x5.c Mon Jul 5 05:05:21 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.ac/drivers/net/declance.c --- linux.vanilla/drivers/net/declance.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/net/declance.c Tue Jun 22 01:34:49 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.ac/drivers/net/depca.c --- linux.vanilla/drivers/net/depca.c Thu Dec 3 13:48:35 1998 +++ linux.ac/drivers/net/depca.c Mon Jul 5 05:05:21 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.ac/drivers/net/eepro100.c --- linux.vanilla/drivers/net/eepro100.c Tue Feb 23 14:21:33 1999 +++ linux.ac/drivers/net/eepro100.c Thu Jun 17 16:15:34 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.ac/drivers/net/eql.c --- linux.vanilla/drivers/net/eql.c Thu May 27 22:11:54 1999 +++ linux.ac/drivers/net/eql.c Mon Jul 5 05:05:21 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.ac/drivers/net/ewrk3.c --- linux.vanilla/drivers/net/ewrk3.c Sun Nov 8 15:07:23 1998 +++ linux.ac/drivers/net/ewrk3.c Mon Jul 19 03:39:17 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.ac/drivers/net/hamradio/Config.in --- linux.vanilla/drivers/net/hamradio/Config.in Thu Dec 31 18:10:42 1998 +++ linux.ac/drivers/net/hamradio/Config.in Thu Jul 8 22:22:16 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.ac/drivers/net/hamradio/Makefile --- linux.vanilla/drivers/net/hamradio/Makefile Sun Nov 8 15:07:26 1998 +++ linux.ac/drivers/net/hamradio/Makefile Thu Jul 8 22:22:16 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/yam.c linux.ac/drivers/net/hamradio/yam.c --- linux.vanilla/drivers/net/hamradio/yam.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/net/hamradio/yam.c Thu Jul 8 22:22:16 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.ac/drivers/net/hamradio/yam1200.h --- linux.vanilla/drivers/net/hamradio/yam1200.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/net/hamradio/yam1200.h Thu Jul 8 22:22:16 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.ac/drivers/net/hamradio/yam9600.h --- linux.vanilla/drivers/net/hamradio/yam9600.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/net/hamradio/yam9600.h Thu Jul 8 22:22:16 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.ac/drivers/net/hostess_sv11.c --- linux.vanilla/drivers/net/hostess_sv11.c Tue Feb 23 14:21:33 1999 +++ linux.ac/drivers/net/hostess_sv11.c Wed Jun 30 00:25:59 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.ac/drivers/net/irda/toshoboe.c --- linux.vanilla/drivers/net/irda/toshoboe.c Tue Jun 15 16:49:49 1999 +++ linux.ac/drivers/net/irda/toshoboe.c Wed Jun 16 16:28:57 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.ac/drivers/net/jazzsonic.c --- linux.vanilla/drivers/net/jazzsonic.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/net/jazzsonic.c Tue Jun 22 01:34:49 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.ac/drivers/net/lance.c --- linux.vanilla/drivers/net/lance.c Mon Dec 28 23:09:43 1998 +++ linux.ac/drivers/net/lance.c Mon Jul 5 15:49:54 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/lne390.c linux.ac/drivers/net/lne390.c --- linux.vanilla/drivers/net/lne390.c Tue Dec 22 23:19:46 1998 +++ linux.ac/drivers/net/lne390.c Mon Jul 19 03:45:43 1999 @@ -31,6 +31,7 @@ static const char *version = "lne390.c: Driver revision v0.99, 12/05/98\n"; +#include #include #include #include @@ -316,6 +317,15 @@ lne390_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page) { unsigned long hdr_start = dev->mem_start + ((ring_page - LNE390_START_PG)<<8); +#ifdef CONFIG_ALPHA_JENSEN + if (((long)hdr&3)!=0) + { + memcpy_fromio_g32a(hdr, hdr_start, sizeof(struct e8390_pkt_hdr)); + hdr->count = (hdr->count + 3) & ~3; /* Round up allocation. */ + return; + } +#endif + memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr)); hdr->count = (hdr->count + 3) & ~3; /* Round up allocation. */ } @@ -331,6 +341,25 @@ { unsigned long xfer_start = dev->mem_start + ring_offset - (LNE390_START_PG<<8); +#ifdef CONFIG_ALPHA_JENSEN + if (((long)skb->data&3)!=0) + { + if (xfer_start + count > dev->rmem_end) { + /* Packet wraps over end of ring buffer. */ + int semi_count = dev->rmem_end - xfer_start; + memcpy_fromio_g32a(skb->data, xfer_start, semi_count); + count -= semi_count; + memcpy_fromio_g32a(skb->data + semi_count, dev->rmem_start, count); + } else { + /* Packet is in one chunk. */ + memcpy_fromio_g32a(skb->data, xfer_start, count); + } + return; + } +#endif + + /* printk("%s: lne390_block_input is called with unaligned buffer!\n", dev->name); */ + if (xfer_start + count > dev->rmem_end) { /* Packet wraps over end of ring buffer. */ int semi_count = dev->rmem_end - xfer_start; @@ -349,6 +378,15 @@ unsigned long shmem = dev->mem_start + ((start_page - LNE390_START_PG)<<8); count = (count + 3) & ~3; /* Round up to doubleword */ + /* printk ("%s: lne390_block_output is called!", dev->name); */ + +#ifdef CONFIG_ALPHA_JENSEN + if (((long)buf&3)!=0) { + memcpy_toio_g32a(shmem, buf, count); + return; + } +#endif + memcpy_toio(shmem, buf, count); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/ne2k-pci.c linux.ac/drivers/net/ne2k-pci.c --- linux.vanilla/drivers/net/ne2k-pci.c Tue Jan 26 09:44:21 1999 +++ linux.ac/drivers/net/ne2k-pci.c Wed Jun 23 03:06:35 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.ac/drivers/net/net_init.c --- linux.vanilla/drivers/net/net_init.c Wed Apr 28 19:14:27 1999 +++ linux.ac/drivers/net/net_init.c Mon Jul 5 04:33:02 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.ac/drivers/net/olympic.c --- linux.vanilla/drivers/net/olympic.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/net/olympic.c Mon Jul 19 03:45:43 1999 @@ -0,0 +1,1662 @@ +/* + * 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 + +#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.ac/drivers/net/olympic.h --- linux.vanilla/drivers/net/olympic.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/net/olympic.h Wed Jun 9 20:08:19 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.ac/drivers/net/rtl8139.c --- linux.vanilla/drivers/net/rtl8139.c Thu Dec 3 13:48:36 1998 +++ linux.ac/drivers/net/rtl8139.c Mon Jul 19 03:54:43 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.ac/drivers/net/sealevel.c --- linux.vanilla/drivers/net/sealevel.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/net/sealevel.c Fri Jun 4 23:52:39 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.ac/drivers/net/seeq8005.c --- linux.vanilla/drivers/net/seeq8005.c Thu Dec 31 18:10:43 1998 +++ linux.ac/drivers/net/seeq8005.c Sat Jun 12 14:00:10 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.ac/drivers/net/sgiseeq.c --- linux.vanilla/drivers/net/sgiseeq.c Thu Nov 19 18:38:38 1998 +++ linux.ac/drivers/net/sgiseeq.c Tue Jun 22 01:34:49 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.ac/drivers/net/sgiseeq.h --- linux.vanilla/drivers/net/sgiseeq.h Sun Nov 8 15:07:30 1998 +++ linux.ac/drivers/net/sgiseeq.h Tue Jun 22 01:34:49 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.ac/drivers/net/shaper.c --- linux.vanilla/drivers/net/shaper.c Tue Jun 15 16:49:50 1999 +++ linux.ac/drivers/net/shaper.c Mon Jun 21 13:20:06 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.ac/drivers/net/sonic.c --- linux.vanilla/drivers/net/sonic.c Sat Jan 9 21:50:42 1999 +++ linux.ac/drivers/net/sonic.c Tue Jun 22 01:34:49 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.ac/drivers/net/sonic.h --- linux.vanilla/drivers/net/sonic.h Sun Nov 8 15:07:30 1998 +++ linux.ac/drivers/net/sonic.h Tue Jun 22 01:34:49 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.ac/drivers/net/sunhme.c --- linux.vanilla/drivers/net/sunhme.c Tue Jun 15 16:49:50 1999 +++ linux.ac/drivers/net/sunhme.c Fri Jul 2 19:14:38 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.ac/drivers/net/syncppp.c --- linux.vanilla/drivers/net/syncppp.c Fri Apr 16 22:10:53 1999 +++ linux.ac/drivers/net/syncppp.c Mon Jul 19 05:25:52 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.ac/drivers/net/tulip.c --- linux.vanilla/drivers/net/tulip.c Sun Jan 24 19:55:35 1999 +++ linux.ac/drivers/net/tulip.c Mon Jul 5 17:04:54 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.ac/drivers/net/via-rhine.c --- linux.vanilla/drivers/net/via-rhine.c Thu May 27 22:11:54 1999 +++ linux.ac/drivers/net/via-rhine.c Wed Jun 23 03:15:34 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.ac/drivers/net/wavelan.c --- linux.vanilla/drivers/net/wavelan.c Thu May 27 22:11:55 1999 +++ linux.ac/drivers/net/wavelan.c Mon Jul 5 05:05:21 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.ac/drivers/net/yellowfin.c --- linux.vanilla/drivers/net/yellowfin.c Tue Dec 22 23:19:47 1998 +++ linux.ac/drivers/net/yellowfin.c Wed Jun 30 00:36:53 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.ac/drivers/net/z85230.c --- linux.vanilla/drivers/net/z85230.c Wed Apr 28 19:14:27 1999 +++ linux.ac/drivers/net/z85230.c Wed Jul 7 06:10:40 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.ac/drivers/pci/oldproc.c --- linux.vanilla/drivers/pci/oldproc.c Tue Jun 15 16:49:50 1999 +++ linux.ac/drivers/pci/oldproc.c Fri Jul 2 19:12:11 1999 @@ -303,6 +303,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 +461,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,6 +500,7 @@ 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"), @@ -536,6 +539,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"), @@ -826,6 +830,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.ac/drivers/pci/pci.c --- linux.vanilla/drivers/pci/pci.c Wed Mar 10 21:13:04 1999 +++ linux.ac/drivers/pci/pci.c Mon Jul 5 05:48:10 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/sbus/sbus.c linux.ac/drivers/sbus/sbus.c --- linux.vanilla/drivers/sbus/sbus.c Tue Jun 15 16:49:50 1999 +++ linux.ac/drivers/sbus/sbus.c Mon Jun 7 22:24:51 1999 @@ -8,7 +8,6 @@ #include #include #include -#include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/53c7,8xx.c linux.ac/drivers/scsi/53c7,8xx.c --- linux.vanilla/drivers/scsi/53c7,8xx.c Sun Nov 8 15:07:50 1998 +++ linux.ac/drivers/scsi/53c7,8xx.c Fri Jun 4 23:52:42 1999 @@ -1901,7 +1901,8 @@ */ timeout = jiffies + 5 * HZ / 10; - while ((hostdata->test_completed == -1) && jiffies < timeout) + while ((hostdata->test_completed == -1) && + time_before(jiffies,timeout)) barrier(); failed = 1; @@ -1986,7 +1987,8 @@ restore_flags(flags); timeout = jiffies + 5 * HZ; /* arbitrary */ - while ((hostdata->test_completed == -1) && jiffies < timeout) + while ((hostdata->test_completed == -1) && + time_before(jiffies, timeout)) barrier(); NCR53c7x0_write32 (DSA_REG, 0); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/53c7xx.c linux.ac/drivers/scsi/53c7xx.c --- linux.vanilla/drivers/scsi/53c7xx.c Sun Nov 8 15:07:55 1998 +++ linux.ac/drivers/scsi/53c7xx.c Fri Jun 4 23:52:42 1999 @@ -298,6 +298,10 @@ */ #undef inb #undef outb +#undef inw +#undef outw +#undef inl +#undef outl #define inb(x) 1 #define inw(x) 1 #define inl(x) 1 @@ -1612,7 +1616,8 @@ */ timeout = jiffies + 5 * HZ / 10; - while ((hostdata->test_completed == -1) && jiffies < timeout) + while ((hostdata->test_completed == -1) && + time_before(jiffies, timeout)) barrier(); failed = 1; @@ -1698,7 +1703,8 @@ restore_flags(flags); timeout = jiffies + 5 * HZ; /* arbitrary */ - while ((hostdata->test_completed == -1) && jiffies < timeout) + while ((hostdata->test_completed == -1) && + time_before(jiffies, timeout)) barrier(); NCR53c7x0_write32 (DSA_REG, 0); @@ -1899,7 +1905,7 @@ if (left < 0) printk("scsi%d: loop detected in ncr reconncect list\n", host->host_no); - else if (ncr_search) + else if (ncr_search) { if (found) printk("scsi%d: scsi %ld in ncr issue array and reconnect lists\n", host->host_no, c->pid); @@ -1910,6 +1916,7 @@ /* If we're at the tail end of the issue queue, update that pointer too. */ found = 1; } + } /* * Traverse the host running list until we find this command or discover @@ -2960,14 +2967,14 @@ NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM); else NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl); -#if 0 - /* Following disables snooping - run with caches disabled at first */ + /* Following disables snooping - snooping is not required, as non- + * cached pages are used for shared data, and appropriate use is + * made of cache_push/cache_clear. Indeed, for 68060 + * enabling snooping causes disk corruption of ext2fs free block + * bitmaps and the like. If you have a 68060 with snooping hardwared + * on, then you need to enable CONFIG_060_WRITETHROUGH. + */ NCR53c7x0_write8(CTEST7_REG, CTEST7_10_TT1|CTEST7_STD); -#else - /* Setup CTEST7 for SC1=0, SC0=1 - sink/source data without invalidating - * cache lines. */ - NCR53c7x0_write8(CTEST7_REG, CTEST7_10_TT1|CTEST7_STD|CTEST7_10_SC0); -#endif /* Actually burst of eight, according to my 53c710 databook */ NCR53c7x0_write8(hostdata->dmode, DMODE_10_BL_8 | DMODE_10_FC2); NCR53c7x0_write8(SCID_REG, 1 << host->this_id); @@ -5947,11 +5954,12 @@ } } } - if (!(istat & (ISTAT_SIP|ISTAT_DIP))) + if (!(istat & (ISTAT_SIP|ISTAT_DIP))) { if (stage == 0) ++stage; else if (stage == 3) break; + } } hostdata->state = STATE_HALTED; restore_flags(flags); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/NCR53C9x.c linux.ac/drivers/scsi/NCR53C9x.c --- linux.vanilla/drivers/scsi/NCR53C9x.c Tue Dec 22 23:19:48 1998 +++ linux.ac/drivers/scsi/NCR53C9x.c Thu Jun 17 16:14:05 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.ac/drivers/scsi/aha152x.c --- linux.vanilla/drivers/scsi/aha152x.c Fri May 28 00:32:59 1999 +++ linux.ac/drivers/scsi/aha152x.c Wed Jun 16 20:19:43 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.ac/drivers/scsi/aha1542.c --- linux.vanilla/drivers/scsi/aha1542.c Sun Nov 8 15:07:48 1998 +++ linux.ac/drivers/scsi/aha1542.c Mon Jul 19 03:58:53 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.ac/drivers/scsi/aic7xxx/aic7xxx.reg --- linux.vanilla/drivers/scsi/aic7xxx/aic7xxx.reg Tue Jun 15 16:49:50 1999 +++ linux.ac/drivers/scsi/aic7xxx/aic7xxx.reg Fri Jul 2 19:12:12 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.ac/drivers/scsi/aic7xxx.c --- linux.vanilla/drivers/scsi/aic7xxx.c Tue Jun 15 16:49:51 1999 +++ linux.ac/drivers/scsi/aic7xxx.c Fri Jul 2 19:12:12 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.18" #define NUMBER(arr) (sizeof(arr) / sizeof(arr[0])) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) @@ -7186,7 +7186,7 @@ static int acquire_seeprom(struct aic7xxx_host *p) { - int wait; + int count=0; /* * Request access of the memory port. When access is @@ -7196,11 +7196,10 @@ * should be no contention. */ aic_outb(p, SEEMS, SEECTL); - wait = 1000; /* 1000 msec = 1 second */ - while ((wait > 0) && ((aic_inb(p, SEECTL) & SEERDY) == 0)) - { - wait--; - mdelay(1); /* 1 msec */ + while( ((aic_inb(p, SEECTL) & SEERDY) == 0) && count < 1000) { + mb(); + udelay(1); + count++; } if ((aic_inb(p, SEECTL) & SEERDY) == 0) { @@ -7412,73 +7411,78 @@ /*+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; if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { - brdctl = BRDSTB; + brdctl = BRDRW; if (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; + brdctl = BRDRW_ULTRA2; else - brdctl &= ~BRDCS; + brdctl = BRDRW | BRDCS; aic_outb(p, brdctl, BRDCTL); - udelay(1); + udelay(10); + return (aic_inb(p, BRDCTL)); } /*+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) { - brdctl = BRDRW; + brdctl = BRDSTB; if (p->flags & AHC_CHNLB) brdctl |= BRDCS; + aic_outb(p, brdctl, BRDCTL); + udelay(4); + brdctl |= value; } else if (p->features & AHC_ULTRA2) - brdctl = BRDRW_ULTRA2; + { + brdctl = value; + } else - brdctl = BRDRW | BRDCS; + { + brdctl = BRDSTB | BRDCS; + aic_outb(p, brdctl, BRDCTL); + udelay(4); + brdctl |= value; + } aic_outb(p, brdctl, BRDCTL); - udelay(1); - value = aic_inb(p, BRDCTL); - aic_outb(p, 0, BRDCTL); - udelay(1); - return (value); + udelay(4); + if (p->features & AHC_ULTRA2) + brdctl |= BRDSTB_ULTRA2; + else + brdctl &= ~BRDSTB; + aic_outb(p, brdctl, BRDCTL); + udelay(4); + if (p->features & AHC_ULTRA2) + brdctl &= ~BRDSTB_ULTRA2; + else + brdctl &= ~BRDCS; + aic_outb(p, brdctl, BRDCTL); + udelay(4); + read_brdctl(p); } /*+F************************************************************************* @@ -7495,11 +7499,10 @@ unsigned char brdctl; aic_outb(p, BRDRW | BRDCS, BRDCTL); - udelay(1); + udelay(4); aic_outb(p, 0, BRDCTL); - udelay(1); + udelay(4); brdctl = aic_inb(p, BRDCTL); - udelay(1); *int_50 = !(brdctl & BRDDAT5); *ext_present = !(brdctl & BRDDAT6); *eeprom = (aic_inb(p, SPIOCAP) & EEPROM); @@ -7608,6 +7611,7 @@ else max_target = 8; aic_outb(p, SEEMS | SEECS, SEECTL); + udelay(4); sxfrctl1 &= ~STPWEN; if ( (p->adapter_control & CFAUTOTERM) || (p->features & AHC_ULTRA2) ) @@ -7732,25 +7736,33 @@ p->host_no); } - if (enableLVD_low != 0) + if (enableLVD_high != 0) { - sxfrctl1 |= STPWEN; - p->flags |= AHC_TERM_ENB_LVD; + brddat |= BRDDAT4; if (aic7xxx_verbose & VERBOSE_PROBE2) - printk(KERN_INFO "(scsi%d) LVD Low byte termination Enabled\n", + printk(KERN_INFO "(scsi%d) LVD High byte termination Enabled\n", p->host_no); } - if (enableLVD_high != 0) + if (enableLVD_low != 0) { - brddat |= BRDDAT4; + sxfrctl1 |= STPWEN; + p->flags |= AHC_TERM_ENB_LVD; if (aic7xxx_verbose & VERBOSE_PROBE2) - printk(KERN_INFO "(scsi%d) LVD High byte termination Enabled\n", + printk(KERN_INFO "(scsi%d) LVD Low byte termination Enabled\n", p->host_no); } } else { + if (p->adapter_control & CFWSTERM) + { + brddat |= BRDDAT6; + if (aic7xxx_verbose & VERBOSE_PROBE2) + printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n", + p->host_no); + } + if (p->adapter_control & CFSTERM) { if (p->features & AHC_ULTRA2) @@ -7761,18 +7773,10 @@ printk(KERN_INFO "(scsi%d) SE Low byte termination Enabled\n", p->host_no); } - - if (p->adapter_control & CFWSTERM) - { - brddat |= BRDDAT6; - if (aic7xxx_verbose & VERBOSE_PROBE2) - printk(KERN_INFO "(scsi%d) SE High byte termination Enabled\n", - p->host_no); - } } + aic_outb(p, sxfrctl1, SXFRCTL1); write_brdctl(p, brddat); release_seeprom(p); - aic_outb(p, sxfrctl1, SXFRCTL1); } } @@ -8086,7 +8090,7 @@ /* Select channel B */ aic_outb(p, aic_inb(p, SBLKCTL) | SELBUSB, SBLKCTL); - term = ((p->flags & AHC_TERM_ENB_B) != 0) ? STPWEN : 0; + term = (aic_inb(p, SXFRCTL1) & STPWEN); aic_outb(p, p->scsi_id_b, SCSIID); scsi_conf = aic_inb(p, SCSICONF + 1); aic_outb(p, DFON | SPIOEN, SXFRCTL0); @@ -8100,11 +8104,15 @@ 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); + } + term = (aic_inb(p, SXFRCTL1) & STPWEN); scsi_conf = aic_inb(p, SCSICONF); aic_outb(p, DFON | SPIOEN, SXFRCTL0); aic_outb(p, (scsi_conf & ENSPCHK) | STIMESEL | term | @@ -8794,27 +8802,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; } @@ -9290,6 +9304,10 @@ AHC_AIC7860_FE, 7, 32, C46 }, {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_3860, AHC_AIC7860, + 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 }, diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/aic7xxx_proc.c linux.ac/drivers/scsi/aic7xxx_proc.c --- linux.vanilla/drivers/scsi/aic7xxx_proc.c Tue Jun 15 16:49:51 1999 +++ linux.ac/drivers/scsi/aic7xxx_proc.c Mon Jul 19 03:45:43 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.ac/drivers/scsi/aic7xxx_reg.h --- linux.vanilla/drivers/scsi/aic7xxx_reg.h Tue Jun 15 16:49:51 1999 +++ linux.ac/drivers/scsi/aic7xxx_reg.h Fri Jul 2 19:12:12 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/amiga7xx.c linux.ac/drivers/scsi/amiga7xx.c --- linux.vanilla/drivers/scsi/amiga7xx.c Sun Nov 8 15:07:55 1998 +++ linux.ac/drivers/scsi/amiga7xx.c Fri Jun 4 23:52:42 1999 @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -33,9 +34,9 @@ S_IFDIR | S_IRUGO | S_IXUGO, 2 }; -extern ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip, - u32 base, int io_port, int irq, int dma, - long long options, int clock); +extern int ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip, + u32 base, int io_port, int irq, int dma, + long long options, int clock); int amiga7xx_detect(Scsi_Host_Template *tpnt) { diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/atari_NCR5380.c linux.ac/drivers/scsi/atari_NCR5380.c --- linux.vanilla/drivers/scsi/atari_NCR5380.c Sun Nov 8 15:07:54 1998 +++ linux.ac/drivers/scsi/atari_NCR5380.c Fri Jun 4 23:52:42 1999 @@ -1459,9 +1459,9 @@ unsigned long timeout = jiffies + 2*NCR_TIMEOUT; while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) - && jiffies < timeout && !hostdata->connected) + && time_before(jiffies, timeout) && !hostdata->connected) ; - if (jiffies >= timeout) + if (time_after_eq(jiffies, timeout)) { printk("scsi : arbitration timeout at %d\n", __LINE__); NCR5380_write(MODE_REG, MR_BASE); @@ -1616,7 +1616,7 @@ * only wait for BSY... (Famous german words: Der Klügere gibt nach :-) */ - while ((jiffies < timeout) && !(NCR5380_read(STATUS_REG) & + while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO))); if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == @@ -1629,7 +1629,7 @@ return -1; } #else - while ((jiffies < timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY)); + while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY)); #endif /* diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/atari_scsi.c linux.ac/drivers/scsi/atari_scsi.c --- linux.vanilla/drivers/scsi/atari_scsi.c Sun Nov 8 15:07:50 1998 +++ linux.ac/drivers/scsi/atari_scsi.c Fri Jun 4 23:52:42 1999 @@ -132,51 +132,51 @@ } while(0) #define SCSI_DMA_READ_P(elt) \ - (((unsigned long)tt_scsi_dma.elt##_hi << 24) | \ - ((unsigned long)tt_scsi_dma.elt##_hmd << 16) | \ - ((unsigned long)tt_scsi_dma.elt##_lmd << 8) | \ - (unsigned long)tt_scsi_dma.elt##_lo) - - -#define SCSI_DMA_SETADR(adr) \ - do { \ - unsigned long __adr = (adr); \ - st_dma.dma_lo = (unsigned char)__adr; \ - MFPDELAY(); \ - __adr >>= 8; \ - st_dma.dma_md = (unsigned char)__adr; \ - MFPDELAY(); \ - __adr >>= 8; \ - st_dma.dma_hi = (unsigned char)__adr; \ - MFPDELAY(); \ - } while(0) - -#define SCSI_DMA_GETADR() ({ \ - unsigned long __adr; \ - __adr = st_dma.dma_lo; \ - MFPDELAY(); \ - __adr |= (st_dma.dma_md & 0xff) << 8; \ - MFPDELAY(); \ - __adr |= (st_dma.dma_hi & 0xff) << 16; \ - MFPDELAY(); \ - __adr; \ -}) - -#define ENABLE_IRQ() \ - do { \ - if (IS_A_TT()) \ - atari_enable_irq( IRQ_TT_MFP_SCSI ); \ - else \ - atari_enable_irq( IRQ_MFP_FSCSI ); \ - } while(0) - -#define DISABLE_IRQ() \ - do { \ - if (IS_A_TT()) \ - atari_disable_irq( IRQ_TT_MFP_SCSI ); \ - else \ - atari_disable_irq( IRQ_MFP_FSCSI ); \ - } while(0) + (((((((unsigned long)tt_scsi_dma.elt##_hi << 8) | \ + (unsigned long)tt_scsi_dma.elt##_hmd) << 8) | \ + (unsigned long)tt_scsi_dma.elt##_lmd) << 8) | \ + (unsigned long)tt_scsi_dma.elt##_lo) + + +static inline void SCSI_DMA_SETADR(unsigned long adr) +{ + st_dma.dma_lo = (unsigned char)adr; + MFPDELAY(); + adr >>= 8; + st_dma.dma_md = (unsigned char)adr; + MFPDELAY(); + adr >>= 8; + st_dma.dma_hi = (unsigned char)adr; + MFPDELAY(); +} + +static inline unsigned long SCSI_DMA_GETADR(void) +{ + unsigned long adr; + adr = st_dma.dma_lo; + MFPDELAY(); + adr |= (st_dma.dma_md & 0xff) << 8; + MFPDELAY(); + adr |= (st_dma.dma_hi & 0xff) << 16; + MFPDELAY(); + return adr; +} + +static inline void ENABLE_IRQ(void) +{ + if (IS_A_TT()) + atari_enable_irq(IRQ_TT_MFP_SCSI); + else + atari_enable_irq(IRQ_MFP_FSCSI); +} + +static inline void DISABLE_IRQ(void) +{ + if (IS_A_TT()) + atari_disable_irq(IRQ_TT_MFP_SCSI); + else + atari_disable_irq(IRQ_MFP_FSCSI); +} #define HOSTDATA_DMALEN (((struct NCR5380_hostdata *) \ @@ -480,16 +480,17 @@ /* fetch rest bytes in the DMA register */ dst = (char *)SCSI_DMA_READ_P( dma_addr ); - if ((nr = ((long)dst & 3))) { + nr = ((long)dst & 3); + if (nr) { /* there are 'nr' bytes left for the last long address before the DMA pointer */ - dst = (char *)( (unsigned long)dst & ~3 ); + dst = (char *)((unsigned long)dst ^ nr); DMA_PRINTK("SCSI DMA: there are %d rest bytes for phys addr 0x%08lx", nr, (long)dst); dst = (char *)PTOV(dst); /* The content of the DMA pointer * is a physical address! */ DMA_PRINTK(" = virt addr 0x%08lx\n", (long)dst); - for( src = (char *)&tt_scsi_dma.dma_restdata; nr > 0; --nr ) + for (src = (char *)&tt_scsi_dma.dma_restdata; nr != 0; --nr) *dst++ = *src++; } } @@ -764,7 +765,7 @@ } #endif -__initfunc(void atari_scsi_setup( char *str, int *ints )) +void __init atari_scsi_setup(char *str, int *ints) { /* Format of atascsi parameter is: * atascsi=,,,, @@ -772,23 +773,6 @@ * Negative values mean don't change. */ - /* Grmbl... the standard parameter parsing can't handle negative numbers - * :-( So let's do it ourselves! - */ - - int i = ints[0]+1, fact; - - while( str && (isdigit(*str) || *str == '-') && i <= 10) { - if (*str == '-') - fact = -1, ++str; - else - fact = 1; - ints[i++] = simple_strtoul( str, NULL, 0 ) * fact; - if ((str = strchr( str, ',' )) != NULL) - ++str; - } - ints[0] = i-1; - if (ints[0] < 1) { printk( "atari_scsi_setup: no arguments!\n" ); return; @@ -869,7 +853,7 @@ #ifdef CONFIG_ATARI_SCSI_RESET_BOOT -__initfunc(static void atari_scsi_reset_boot( void )) +static void __init atari_scsi_reset_boot(void) { unsigned long end; @@ -892,7 +876,7 @@ NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE ); NCR5380_read( RESET_PARITY_INTERRUPT_REG ); - for( end = jiffies + AFTER_RESET_DELAY; jiffies < end; ) + for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies,end); ) barrier(); printk( " done\n" ); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/atp870u.c linux.ac/drivers/scsi/atp870u.c --- linux.vanilla/drivers/scsi/atp870u.c Wed Mar 10 21:13:04 1999 +++ linux.ac/drivers/scsi/atp870u.c Tue Jun 29 04:21:59 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.ac/drivers/scsi/constants.c --- linux.vanilla/drivers/scsi/constants.c Sun Nov 8 15:07:49 1998 +++ linux.ac/drivers/scsi/constants.c Fri Jun 4 23:52:42 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.ac/drivers/scsi/dec_esp.c --- linux.vanilla/drivers/scsi/dec_esp.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/scsi/dec_esp.c Tue Jun 22 01:35:45 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.ac/drivers/scsi/dec_esp.h --- linux.vanilla/drivers/scsi/dec_esp.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/scsi/dec_esp.h Tue Jun 22 01:35:45 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.ac/drivers/scsi/eata_dma.c --- linux.vanilla/drivers/scsi/eata_dma.c Thu Dec 31 18:10:44 1998 +++ linux.ac/drivers/scsi/eata_dma.c Thu Jul 8 23:07:05 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.ac/drivers/scsi/gdth_proc.c --- linux.vanilla/drivers/scsi/gdth_proc.c Fri Apr 16 22:10:54 1999 +++ linux.ac/drivers/scsi/gdth_proc.c Fri Jun 4 23:52:42 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.ac/drivers/scsi/ide-scsi.c --- linux.vanilla/drivers/scsi/ide-scsi.c Wed Apr 28 19:14:28 1999 +++ linux.ac/drivers/scsi/ide-scsi.c Mon Jul 5 16:13:00 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 @@ -606,6 +607,8 @@ host = scsi_register(host_template, 0); for (id = 0; id < MAX_HWIFS * MAX_DRIVES && idescsi_drives[id]; id++); host->max_id = id; + host->max_lun = 1; /* We should query the drive for multilun + support ? */ host->can_queue = host->cmd_per_lun * id; return 1; } @@ -632,9 +635,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); @@ -729,6 +736,9 @@ if (!drive) { printk (KERN_ERR "ide-scsi: drive id %d not present\n", cmd->target); + goto abort; + } + if (cmd->lun != 0) { /* Only respond to LUN 0. Drop others */ goto abort; } scsi = drive->driver_data; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/in2000.h linux.ac/drivers/scsi/in2000.h --- linux.vanilla/drivers/scsi/in2000.h Sun Nov 8 15:07:50 1998 +++ linux.ac/drivers/scsi/in2000.h Mon Jul 19 04:40:14 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.ac/drivers/scsi/jazz_esp.c --- linux.vanilla/drivers/scsi/jazz_esp.c Sun Nov 8 15:08:00 1998 +++ linux.ac/drivers/scsi/jazz_esp.c Tue Jun 22 01:35:45 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/ncr53c8xx.c linux.ac/drivers/scsi/ncr53c8xx.c --- linux.vanilla/drivers/scsi/ncr53c8xx.c Fri Apr 16 22:10:54 1999 +++ linux.ac/drivers/scsi/ncr53c8xx.c Fri Jul 2 19:14:38 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/qlogicfas.c linux.ac/drivers/scsi/qlogicfas.c --- linux.vanilla/drivers/scsi/qlogicfas.c Tue Feb 23 14:21:33 1999 +++ linux.ac/drivers/scsi/qlogicfas.c Fri Jul 2 19:22:11 1999 @@ -276,9 +276,9 @@ int i,k; k = 0; i = jiffies + WATCHDOG; - while ( i > jiffies && !qabort && !((k = inb(qbase + 4)) & 0xe0)) + while ( time_after(i, jiffies) && !qabort && !((k = inb(qbase + 4)) & 0xe0)) barrier(); - if (i <= jiffies) + if (time_before_eq(i, jiffies)) return (DID_TIME_OUT); if (qabort) return (qabort == 1 ? DID_ABORT : DID_RESET); @@ -408,8 +408,8 @@ } /*** Enter Status (and Message In) Phase ***/ k = jiffies + WATCHDOG; - while ( k > jiffies && !qabort && !(inb(qbase + 4) & 6)); /* wait for status phase */ - if ( k <= jiffies ) { + while ( time_after(k, jiffies) && !qabort && !(inb(qbase + 4) & 6)); /* wait for status phase */ + if ( time_before_eq(k, jiffies) ) { ql_zap(); return (DID_TIME_OUT << 16); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/qlogicfc.c linux.ac/drivers/scsi/qlogicfc.c --- linux.vanilla/drivers/scsi/qlogicfc.c Fri Apr 16 22:10:54 1999 +++ linux.ac/drivers/scsi/qlogicfc.c Mon Jul 19 03:18:18 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.ac/drivers/scsi/qlogicfc.h --- linux.vanilla/drivers/scsi/qlogicfc.h Wed Mar 10 21:13:05 1999 +++ linux.ac/drivers/scsi/qlogicfc.h Mon Jul 19 03:18:18 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.ac/drivers/scsi/qlogicfc_asm.c --- linux.vanilla/drivers/scsi/qlogicfc_asm.c Fri Apr 16 22:10:55 1999 +++ linux.ac/drivers/scsi/qlogicfc_asm.c Mon Jul 19 03:18:20 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.ac/drivers/scsi/qlogicisp.c --- linux.vanilla/drivers/scsi/qlogicisp.c Wed Apr 28 19:14:28 1999 +++ linux.ac/drivers/scsi/qlogicisp.c Fri Jul 2 19:22:45 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.ac/drivers/scsi/scsi.c --- linux.vanilla/drivers/scsi/scsi.c Tue Jun 15 16:49:51 1999 +++ linux.ac/drivers/scsi/scsi.c Thu Jul 8 22:42:00 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); @@ -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.ac/drivers/scsi/scsi.h --- linux.vanilla/drivers/scsi/scsi.h Tue Jun 15 16:49:51 1999 +++ linux.ac/drivers/scsi/scsi.h Mon Jul 19 04:40:11 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.ac/drivers/scsi/scsi_error.c --- linux.vanilla/drivers/scsi/scsi_error.c Wed Mar 10 21:13:06 1999 +++ linux.ac/drivers/scsi/scsi_error.c Sat Jun 12 18:09:05 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.ac/drivers/scsi/sd.c --- linux.vanilla/drivers/scsi/sd.c Tue Jun 15 16:49:51 1999 +++ linux.ac/drivers/scsi/sd.c Wed Jun 30 00:51:13 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, @@ -1139,8 +1140,8 @@ unsigned char cmd[10]; char nbuff[6]; unsigned char *buffer; - unsigned long spintime; - int the_result, retries; + unsigned long spintime_value = 0; + int the_result, retries, spintime; Scsi_Cmnd * SCpnt; /* @@ -1235,16 +1236,18 @@ SCpnt->request.sem = NULL; } - spintime = jiffies; + spintime = 1; + spintime_value = jiffies; } time1 = jiffies + HZ; spin_unlock_irq(&io_request_lock); - while(jiffies < time1); /* Wait 1 second for next try */ + while(time_before(jiffies, time1)); /* Wait 1 second for next try */ printk( "." ); spin_lock_irq(&io_request_lock); } - } while(the_result && spintime && spintime+100*HZ > jiffies); + } while(the_result && spintime && + time_after(spintime_value+100*HZ, jiffies)); if (spintime) { if (the_result) printk( "not responding...\n" ); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/sgiwd93.c linux.ac/drivers/scsi/sgiwd93.c --- linux.vanilla/drivers/scsi/sgiwd93.c Sun Nov 8 15:07:57 1998 +++ linux.ac/drivers/scsi/sgiwd93.c Tue Jun 22 01:36:47 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.ac/drivers/scsi/sgiwd93.h --- linux.vanilla/drivers/scsi/sgiwd93.h Sun Nov 8 15:07:57 1998 +++ linux.ac/drivers/scsi/sgiwd93.h Tue Jun 22 01:36:47 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.ac/drivers/scsi/sym53c416.c --- linux.vanilla/drivers/scsi/sym53c416.c Wed Mar 10 21:13:06 1999 +++ linux.ac/drivers/scsi/sym53c416.c Thu Jun 17 16:08:10 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.ac/drivers/scsi/wd33c93.h --- linux.vanilla/drivers/scsi/wd33c93.h Sun Nov 8 15:07:54 1998 +++ linux.ac/drivers/scsi/wd33c93.h Mon Jul 19 03:45:43 1999 @@ -23,6 +23,7 @@ #ifndef WD33C93_H #define WD33C93_H +#include #define PROC_INTERFACE /* add code for /proc/scsi/wd33c93/xxx interface */ #ifdef PROC_INTERFACE @@ -190,6 +191,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.ac/drivers/scsi/wd7000.c --- linux.vanilla/drivers/scsi/wd7000.c Sat Jan 9 21:50:44 1999 +++ linux.ac/drivers/scsi/wd7000.c Mon Jul 5 04:40:34 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.ac/drivers/sgi/Config.in --- linux.vanilla/drivers/sgi/Config.in Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/sgi/Config.in Tue Jun 22 01:35:17 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.ac/drivers/sgi/Makefile --- linux.vanilla/drivers/sgi/Makefile Sun Nov 8 15:08:16 1998 +++ linux.ac/drivers/sgi/Makefile Tue Jun 22 01:35:17 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.ac/drivers/sgi/char/Makefile --- linux.vanilla/drivers/sgi/char/Makefile Sun Nov 8 15:08:16 1998 +++ linux.ac/drivers/sgi/char/Makefile Tue Jun 22 01:35:17 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.ac/drivers/sgi/char/cons_newport.c --- linux.vanilla/drivers/sgi/char/cons_newport.c Sun Nov 8 15:08:16 1998 +++ linux.ac/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.ac/drivers/sgi/char/ds1286.c --- linux.vanilla/drivers/sgi/char/ds1286.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/sgi/char/ds1286.c Tue Jun 22 01:35:17 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.ac/drivers/sgi/char/graphics.c --- linux.vanilla/drivers/sgi/char/graphics.c Sun Nov 8 15:08:17 1998 +++ linux.ac/drivers/sgi/char/graphics.c Tue Jun 22 01:35:17 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.ac/drivers/sgi/char/graphics.h --- linux.vanilla/drivers/sgi/char/graphics.h Sun Nov 8 15:08:17 1998 +++ linux.ac/drivers/sgi/char/graphics.h Tue Jun 22 01:35:17 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.ac/drivers/sgi/char/graphics_syms.c --- linux.vanilla/drivers/sgi/char/graphics_syms.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/sgi/char/graphics_syms.c Mon Jul 19 03:45:44 1999 @@ -0,0 +1,36 @@ +/* + * 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 + +/* 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.ac/drivers/sgi/char/newport.c --- linux.vanilla/drivers/sgi/char/newport.c Sun Nov 8 15:08:17 1998 +++ linux.ac/drivers/sgi/char/newport.c Mon Jul 19 03:45:44 1999 @@ -4,13 +4,19 @@ * * Author: Miguel de Icaza */ + #include #include #include #include #include #include -#include "newport.h" +#include +#include + +struct newport_regs *npregs; + +EXPORT_SYMBOL(npregs); /* Kernel routines for supporting graphics context switching */ @@ -167,7 +173,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.ac/drivers/sgi/char/newport.h --- linux.vanilla/drivers/sgi/char/newport.h Sun Nov 8 15:08:17 1998 +++ linux.ac/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.ac/drivers/sgi/char/rrm.c --- linux.vanilla/drivers/sgi/char/rrm.c Sun Nov 8 15:08:17 1998 +++ linux.ac/drivers/sgi/char/rrm.c Tue Jun 22 01:35:18 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.ac/drivers/sgi/char/sgicons.c --- linux.vanilla/drivers/sgi/char/sgicons.c Sun Nov 8 15:08:17 1998 +++ linux.ac/drivers/sgi/char/sgicons.c Tue Jun 22 01:35:18 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.ac/drivers/sgi/char/sgiserial.c --- linux.vanilla/drivers/sgi/char/sgiserial.c Sun Nov 8 15:10:21 1998 +++ linux.ac/drivers/sgi/char/sgiserial.c Tue Jun 22 01:35:18 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.ac/drivers/sgi/char/sgiserial.h --- linux.vanilla/drivers/sgi/char/sgiserial.h Sun Nov 8 15:08:17 1998 +++ linux.ac/drivers/sgi/char/sgiserial.h Tue Jun 22 01:35:18 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.ac/drivers/sgi/char/shmiq.c --- linux.vanilla/drivers/sgi/char/shmiq.c Sun Nov 8 15:08:17 1998 +++ linux.ac/drivers/sgi/char/shmiq.c Tue Jun 22 01:35:18 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.ac/drivers/sgi/char/streamable.c --- linux.vanilla/drivers/sgi/char/streamable.c Sun Nov 8 15:08:17 1998 +++ linux.ac/drivers/sgi/char/streamable.c Tue Jun 22 01:35:18 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.ac/drivers/sgi/char/usema.c --- linux.vanilla/drivers/sgi/char/usema.c Sun Nov 8 15:08:17 1998 +++ linux.ac/drivers/sgi/char/usema.c Tue Jun 22 01:35:18 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.ac/drivers/sgi/char/usema.h --- linux.vanilla/drivers/sgi/char/usema.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/sgi/char/usema.h Tue Jun 22 01:35:18 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.ac/drivers/sgi/char/vga_font.c --- linux.vanilla/drivers/sgi/char/vga_font.c Sun Nov 8 15:08:17 1998 +++ linux.ac/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/Config.in linux.ac/drivers/sound/Config.in --- linux.vanilla/drivers/sound/Config.in Wed Mar 10 21:13:06 1999 +++ linux.ac/drivers/sound/Config.in Fri Jun 4 23:52:43 1999 @@ -97,6 +97,9 @@ comment 'Enter -1 to the following question if you have something else such as SB16/32.' int 'SB MPU401 IRQ (Jazz16, SM Wave and ES1688) Check from manual of the card' CONFIG_SB_MPU_IRQ -1 fi + + dep_tristate 'PCI Legacy soundblaster enabler' CONFIG_SOUND_PCISB $CONFIG_SOUND_OSS + dep_tristate 'ESS-Tech Maestro support' CONFIG_SOUND_ESSMAESTRO $CONFIG_SOUND_OSS dep_tristate 'Generic OPL2/OPL3 FM synthesizer support' CONFIG_SOUND_ADLIB $CONFIG_SOUND_OSS @@ -272,16 +275,18 @@ hex 'I/O base for UART 6850 MIDI port (Unknown)' CONFIG_U6850_BASE 0 int 'UART6850 IRQ (Unknown)' CONFIG_U6850_IRQ -1 fi + + #dep_tristate 'USB audio support' CONFIG_SOUND_USBAUDIO $CONFIG_SOUND_OSS if [ "$CONFIG_ARM" = "y" ]; then dep_tristate 'VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS - dep_tristate 'Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS - if [ "$CONFIG_SOUND_WAVEARTIST" != "n" ]; then - hex ' WaveArtist I/O base' CONFIG_WAVEARTIST_BASE 250 - int ' WaveArtist IRQ' CONFIG_WAVEARTIST_IRQ 28 - int ' WaveArtist DMA' CONFIG_WAVEARTIST_DMA 3 - int ' WaveArtist second DMA' CONFIG_WAVEARTIST_DMA2 7 - fi + fi + dep_tristate 'Rockwell WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS + if [ "$CONFIG_SOUND_WAVEARTIST" = "y" ]; then + hex ' WaveArtist I/O base' CONFIG_WAVEARTIST_BASE 250 + int ' WaveArtist IRQ' CONFIG_WAVEARTIST_IRQ 28 + int ' WaveArtist DMA' CONFIG_WAVEARTIST_DMA 3 + int ' WaveArtist second DMA' CONFIG_WAVEARTIST_DMA2 7 fi diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/Makefile linux.ac/drivers/sound/Makefile --- linux.vanilla/drivers/sound/Makefile Tue Jan 19 02:57:32 1999 +++ linux.ac/drivers/sound/Makefile Sat Jun 12 20:00:29 1999 @@ -53,6 +53,8 @@ obj-$(CONFIG_SOUND_CS4232) += uart401.o obj-$(CONFIG_SOUND_GUS) += gus.o ad1848.o obj-$(CONFIG_SOUND_MAD16) += mad16.o ad1848.o sb.o uart401.o +obj-$(CONFIG_SOUND_ESSMAESTRO) += ess_pci.o +obj-$(CONFIG_SOUND_PCISB) += pci_legacy.o sb.o uart401.o obj-$(CONFIG_SOUND_MAUI) += maui.o mpu401.o obj-$(CONFIG_SOUND_MPU401) += mpu401.o obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o @@ -64,11 +66,12 @@ obj-$(CONFIG_SOUND_PSS) += pss.o ad1848.o mpu401.o obj-$(CONFIG_SOUND_SB) += sb.o uart401.o obj-$(CONFIG_SOUND_SOFTOSS) += softoss2.o -obj-$(CONFIG_SOUND_SGALAXY) += sgalaxy.o +obj-$(CONFIG_SOUND_SGALAXY) += sgalaxy.o ad1848.o obj-$(CONFIG_SOUND_AD1816) += ad1816.o obj-$(CONFIG_SOUND_SSCAPE) += sscape.o ad1848.o mpu401.o obj-$(CONFIG_SOUND_TRIX) += trix.o ad1848.o sb.o uart401.o obj-$(CONFIG_SOUND_UART6850) += uart6850.o +obj-$(CONFIG_SOUND_USBAUDIO) += usb_audio.o obj-$(CONFIG_SOUND_VMIDI) += v_midi.o obj-$(CONFIG_SOUND_YM3812) += adlib_card.o opl3.o obj-$(CONFIG_SOUND_VIDC) += vidc_mod.o diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/dev_table.h linux.ac/drivers/sound/dev_table.h --- linux.vanilla/drivers/sound/dev_table.h Fri Apr 16 22:10:56 1999 +++ linux.ac/drivers/sound/dev_table.h Sat Jun 12 20:06:07 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.ac/drivers/sound/dmasound.c --- linux.vanilla/drivers/sound/dmasound.c Wed Mar 24 10:55:22 1999 +++ linux.ac/drivers/sound/dmasound.c Mon Jul 19 03:21:39 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.ac/drivers/sound/es1370.c --- linux.vanilla/drivers/sound/es1370.c Tue Jun 15 16:49:52 1999 +++ linux.ac/drivers/sound/es1370.c Mon Jul 19 03:56:19 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.ac/drivers/sound/es1371.c --- linux.vanilla/drivers/sound/es1371.c Fri Apr 16 22:10:56 1999 +++ linux.ac/drivers/sound/es1371.c Mon Jul 19 03:56:19 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/ess_pci.c linux.ac/drivers/sound/ess_pci.c --- linux.vanilla/drivers/sound/ess_pci.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/sound/ess_pci.c Fri Jun 4 23:52:44 1999 @@ -0,0 +1,962 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include "maestro.h" +#include "maestro_tables.h" + +#include "sound_config.h" +#include "soundmodule.h" +#include "sb_mixer.h" +#include "sb.h" + + +#ifndef PCI_VENDOR_ESS +#define PCI_VENDOR_ESS 0x125D +#define PCI_DEVICE_ID_ESS_ESS1969 0x1969 +#define PCI_DEVICE_ID_ESS_ESS1948 0x1948 /* Solo ?? */ +#define PCI_DEVICE_ID_ESS_ESS1968 0x1968 /* Maestro 2 */ +#define PCI_DEVICE_ID_ESS_ESS1978 0x1978 /* Maestro 2E */ +#endif + +#define ESS_SBBASE 0x220 + +struct address_info maestro_cfg; + + +/* + * ESS Maestro AC97 codec programming interface. + */ + +static void maestro_ac97_set(int io, u8 cmd, u16 val) +{ + int i; + /* + * Wait for the codec bus to be free + */ + + for(i=0;i<10000;i++) + { + if(!(inb(io+ESS_AC97_INDEX)&1)) + break; + } + /* + * Write the bus + */ + outw(val, io+ESS_AC97_DATA); + udelay(1); + outb(cmd, io+ESS_AC97_INDEX); + udelay(1); +} + +static u16 maestro_ac97_get(int io, u8 cmd) +{ + int sanity=100000; + u16 data; + int i; + + /* + * Wait for the codec bus to be free + */ + + for(i=0;i<10000;i++) + { + if(!(inb(io+ESS_AC97_INDEX)&1)) + break; + } + + outb(cmd|0x80, io+ESS_AC97_INDEX); + udelay(1); + + while(inb(io+ESS_AC97_INDEX)&1) + { + sanity--; + if(!sanity) + { + printk(KERN_ERR "ess_pci: ac97 codec timeout.\n"); + return 0; + } + } + data=inw(io+ESS_AC97_DATA); + udelay(1); + return data; +} + +/* + * The Maestro can be wired to a standard AC97 compliant codec + * (see www.intel.com for the pdf's on this), or to a PT101 codec + * which appears to be the ES1918 (data sheet on the esstech.com.tw site) + * + * The PT101 setup is untested. + */ + +static u16 maestro_ac97_init(int iobase) +{ + maestro_ac97_set(iobase, 0x02, 0x0000); + maestro_ac97_set(iobase, 0x04, 0x0000); + maestro_ac97_set(iobase, 0x06, 0x0000); + maestro_ac97_set(iobase, 0x08, 0x9F1F); + maestro_ac97_set(iobase, 0x0A, 0x9F1F); + maestro_ac97_set(iobase, 0x0C, 0x9F1F); + maestro_ac97_set(iobase, 0x0E, 0x9F1F); + maestro_ac97_set(iobase, 0x10, 0x9F1F); + maestro_ac97_set(iobase, 0x12, 0x9F1F); + maestro_ac97_set(iobase, 0x14, 0x9F1F); + maestro_ac97_set(iobase, 0x16, 0x9F1F); + maestro_ac97_set(iobase, 0x18, 0x0808); + maestro_ac97_set(iobase, 0x1A, 0x0000); + maestro_ac97_set(iobase, 0x1C, 0x0404); + maestro_ac97_set(iobase, 0x1E, 0x0404); + maestro_ac97_set(iobase, 0x20, 0x0000); + maestro_ac97_set(iobase, 0x26, 0x000F); + return 0; +} + +static u16 maestro_pt101_init(int iobase) +{ + maestro_ac97_set(iobase, 0x2A, 0x0001); + maestro_ac97_set(iobase, 0x2C, 0x0000); + maestro_ac97_set(iobase, 0x2C, 0xFFFF); + maestro_ac97_set(iobase, 0x10, 0x9F1F); + maestro_ac97_set(iobase, 0x12, 0x0808); + maestro_ac97_set(iobase, 0x14, 0x9F1F); + maestro_ac97_set(iobase, 0x16, 0x9F1F); + maestro_ac97_set(iobase, 0x18, 0x0404); + maestro_ac97_set(iobase, 0x1A, 0x0000); + maestro_ac97_set(iobase, 0x1C, 0x0000); + maestro_ac97_set(iobase, 0x02, 0x0404); + maestro_ac97_set(iobase, 0x04, 0x0808); + maestro_ac97_set(iobase, 0x0C, 0x801F); + maestro_ac97_set(iobase, 0x0E, 0x801F); + return 0; +} + +static void maestro_ac97_reset(int ioaddr) +{ + outw(0x2000, ioaddr+0x36); + udelay(100); + outw(0x0000, ioaddr+0x36); + udelay(100); +} + + +/* + * Indirect register access. Not all registers are readable so we + * need to keep register state ourselves + */ + +static u16 maestro_map[32]; +#define WRITEABLE_MAP 0xEFFFFF +#define READABLE_MAP 0x64003F + +/* + * The ESS engineers were a little indirection happy. These indirected + * registers themselves include indirect registers at another layer + */ + +static void maestro_write(int ioaddr, u16 reg, u16 data) +{ + unsigned long flags; + save_flags(flags); + cli(); + outw(reg, ioaddr+0x02); + outw(data, ioaddr+0x00); + maestro_map[reg]=data; + restore_flags(flags); +} + +static u16 maestro_read(int ioaddr, u16 reg) +{ + if(READABLE_MAP & (1<>=1; + + for(channel=low_apu; channel <= high_apu; channel++) + { + int i; + + pa = virt_to_bus(buffer); + wave_set_register(io, 0x01FC+channel, 0x0000); + wave_set_register(io,0x0000, pa&0xFFFF); + pa>>=1; + if(mode&1) /* Enable stereo */ + pa|=0x00800000; + pa|=0x00400000; /* System RAM */ + + /* Begin loading the APU */ + + for(i=0;i<15;i++) + apu_set_register(io, channel, i, 0x0000); + + /* Load the frequency, turn on 6dB, turn off the effects */ + apu_set_register(io, channel, 2, (rate&0xFF)<<8|0x10); + apu_set_register(io, channel, 3, rate>>8); + + /* Load the buffer into the wave engine */ + apu_set_register(io, channel, 4, ((pa>>16)&0xFF)<<8); + apu_set_register(io, channel, 5, pa&0xFFFF); + apu_set_register(io, channel, 6, (pa+size)&0xFFFF); + apu_set_register(io, channel, 7, size); + + apu_set_register(io, channel, 8, 0x0000); + apu_set_register(io, channel, 9, 0xD000); + + if(mode&1) + { + /* Set left or right */ + if(channel == low_apu) + apu_set_register(io, channel, 10, 0x8F00); + else + apu_set_register(io, channel, 10, 0x8F10); + } + else + apu_set_register(io, channel, 10, 0x8F08); + apu_set_register(io, channel, 11, 0x0000); + apu_set_register(io, channel, 0, 0x400F); + } + +// outw(1, io+0x04) +// outw(inw(io+0x18)|4, io+0x18); + + for(channel=low_apu; channel<=high_apu; channel++) + { + /* Turn on the DMA */ + if(mode&2) /* 16 bit */ + apu_set_register(io, channel, 0, + (apu_get_register(io, channel, 0)&0xFF0F)|0x20); + else + apu_set_register(io, channel, 0, + (apu_get_register(io, channel, 0)&0xFF0F)|0x40); + } +} + +static void ess_play_finish(int io, int channel, int mode) +{ + apu_set_register(io, channel, 0, + apu_get_register(io, channel, 0)&0xFF0F); + if(mode&1) + { + channel++; + apu_set_register(io, channel, 0, + apu_get_register(io, channel, 0)&0xFF0F); + } +} + +static void ess_play_test(int io) +{ + u8 *buf=kmalloc(8192, GFP_KERNEL|GFP_DMA); + int ct; + long time=jiffies; + for(ct=0; ct<8192;ct++) + { + buf[ct]=ct^39; + } + ess_play_setup(io, 10, 0, 0x39CD, buf, 8192); + + while((jiffies-time)<5*HZ) + { + schedule(); + } + printk("\n"); + ess_play_finish(io, 10, 0); + kfree(buf); +} + + +/* + * Configure up legacy mode on the ESS-Tech Maestro and Maestro-2 + * + * This is also pretty much the same set up to configure the native + * mode which is what we will finally use. This is the "2.2 at least + * you get sound" stopgap for the moment. + */ + +static int maestro_install(struct pci_dev *pcidev, char *name) +{ + u16 w; + u32 n; + int iobase; + int i; + + iobase = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; + + /* + * Ok card ready. Begin setup proper + */ + + printk(KERN_INFO "ess_pci: Configuring %s at 0x%04X\n", name, iobase); + + if(check_region(ESS_SBBASE, 16)) + { + printk(KERN_WARNING "ess_pci: skipping - I/O 0x%03X is not free.\n", + ESS_SBBASE); + return 0; + } + + /* + * Disable ACPI + */ + + pci_write_config_dword(pcidev, 0x54, 0x00000000); + + /* + * Use TDMA for now. TDMA works on all boards, so while its + * not the most efficient its the simplest. + */ + + pci_read_config_word(pcidev, 0x50, &w); + + /* Clear DMA bits */ + w&=~(1<<10|1<<9|1<<8); + + /* TDMA on */ + w|=(1<<8); + + /* + * MPU at 330 + */ + + w&=~((1<<4)|(1<<3)); + + /* + * SB at 0x220 + */ + + w&=~(1<<2); + + /* + * Reserved write as 0 + */ + + w&=~(1<<1); + + /* + * Some of these are undocumented bits + */ + + w&=~(1<<13)|(1<<14); /* PIC Snoop mode bits */ + w&=~(1<<11); /* Safeguard off */ + w|= (1<<7); /* Posted write */ + w|= (1<<6); /* ISA timing on */ + w&=~(1<<1); /* Subtractive decode off */ + w&=~(1<<5); /* Don't swap left/right */ + + pci_write_config_word(pcidev, 0x50, w); + + pci_read_config_word(pcidev, 0x52, &w); + w&=~(1<<15); /* Turn off internal clock multiplier */ + w&=~(1<<14); /* External clock */ + + w&=~(1<<7); /* HWV off */ + w&=~(1<<6); /* Debounce off */ + w&=~(1<<5); /* GPIO 4:5 */ + w&=~(1<<4); /* Disconnect from the CHI */ + w&=~(1<<3); /* IDMA off (undocumented) */ + w&=~(1<<2); /* MIDI fix off (undoc) */ + w&=~(1<<0); /* IRQ to ISA off (undoc) */ + pci_write_config_word(pcidev, 0x52, w); + + /* + * DDMA off + */ + + pci_read_config_word(pcidev, 0x60, &w); + w&=~(1<<0); + pci_write_config_word(pcidev, 0x60, w); + + /* + * Legacy mode + */ + + pci_read_config_word(pcidev, 0x40, &w); + w&=~(1<<15); /* legacy decode on */ + w&=~(1<<14); /* Disable SIRQ */ + w&=~(1<<13|1<<12|1<<11); + + /* + * We don't use the emulation IRQ's + */ + + w|=(1<<11); /* MPU IRQ 7 */ + w&=~(1<<10|1<<9|1<<8); /* SB IRQ 5 */ + w|=(1<<3)|(1<<1)|(1<<0); /* SB on , FM on, MPU on */ + w&=~(1<<7|1<<6); + w|=(1<<6); /* DMA 1 */ + + /* + * Default to DMA 1 + */ + + pci_write_config_word(pcidev, 0x40, w); + + sound_reset(iobase); + + + /* + * Reset the CODEC + */ + + maestro_ac97_reset(iobase); + + /* + * Ring Bus Setup + */ + + n=inl(iobase+0x34); + n&=~0xF000; + n|=12<<12; /* Direct Sound, Stereo */ + + n=inl(iobase+0x34); + n&=~0x0F00; /* Modem off */ + outl(n, iobase+0x34); + + n=inl(iobase+0x34); + n&=~0x00F0; + n|=9<<4; /* DAC, Stereo */ + outl(n, iobase+0x34); + + n=inl(iobase+0x34); + n&=~0x000F; /* ASSP off */ + outl(n, iobase+0x34); + + + n=inl(iobase+0x34); + n|=(1<<29); /* Enable ring bus */ + outl(n, iobase+0x34); + + + n=inl(iobase+0x34); + n|=(1<<28); /* Enable serial bus */ + outl(n, iobase+0x34); + + n=inl(iobase+0x34); + n&=~0x00F00000; /* MIC off */ + outl(n, iobase+0x34); + + n=inl(iobase+0x34); + n&=~0x000F0000; /* I2S off */ + outl(n, iobase+0x34); + + w=inw(iobase+0x18); + w&=~(1<<7); /* ClkRun off */ + outw(w, iobase+0x18); + + w=inw(iobase+0x18); + w&=~(1<<6); /* Harpo off */ + outw(w, iobase+0x18); + + w=inw(iobase+0x18); + w&=~(1<<4); /* ASSP irq off */ + outw(w, iobase+0x18); + + w=inw(iobase+0x18); + w&=~(1<<3); /* ISDN irq off */ + outw(w, iobase+0x18); + + w=inw(iobase+0x18); + w|=(1<<2); /* Direct Sound IRQ on */ + outw(w, iobase+0x18); + + w=inw(iobase+0x18); + w&=~(1<<1); /* MPU401 IRQ off */ + outw(w, iobase+0x18); + + w=inw(iobase+0x18); + w|=(1<<0); /* SB IRQ on */ + outw(w, iobase+0x18); + + + outb(0, iobase+0xA4); + outb(3, iobase+0xA2); + outb(0, iobase+0xA6); + + for(i=0;i<16;i++) + { + /* Write 0 into the buffer area 0x1E0->1EF */ + outw(0x01E0+i, 0x10+iobase); + outw(0x0000, 0x12+iobase); + } + + wave_set_register(iobase, IDR7_WAVE_ROMRAM, + (wave_get_register(iobase, IDR7_WAVE_ROMRAM)&0xFF00)); + wave_set_register(iobase, IDR7_WAVE_ROMRAM, + wave_get_register(iobase, IDR7_WAVE_ROMRAM)|0x100); + wave_set_register(iobase, IDR7_WAVE_ROMRAM, + wave_get_register(iobase, IDR7_WAVE_ROMRAM)&~0x200); + wave_set_register(iobase, IDR7_WAVE_ROMRAM, + wave_get_register(iobase, IDR7_WAVE_ROMRAM)|~0x400); + + maestro_write(iobase, IDR2_CRAM_DATA, 0x0000); + maestro_write(iobase, 0x08, 0xB004); + /* Now back to the DirectSound stuff */ + maestro_write(iobase, 0x09, 0x001B); + maestro_write(iobase, 0x0A, 0x8000); + maestro_write(iobase, 0x0B, 0x3F37); + maestro_write(iobase, 0x0C, 0x0098); + + maestro_write(iobase, 0x0C, + (maestro_read(iobase, 0x0C)&~0xF000)|0x8000); + maestro_write(iobase, 0x0C, + (maestro_read(iobase, 0x0C)&~0x0F00)|0x0500); + + maestro_write(iobase, 0x0D, 0x7632); + + /* Wave cache control on - test off, sg off, + enable, enable extra chans 1Mb */ + + outw(inw(0x14+iobase)|(1<<8),0x14+iobase); + outw(inw(0x14+iobase)&0xFE03,0x14+iobase); + outw((inw(0x14+iobase)&0xFFFC), 0x14+iobase); + outw(inw(0x14+iobase)|(1<<7),0x14+iobase); + + outw(0xA1A0, 0x14+iobase); + + if(maestro_ac97_get(iobase, 0x00)==0x0080) + { + printk(KERN_INFO "ess_pci: PT101 Codec detected\n"); + maestro_pt101_init(iobase); + } + else + { + printk(KERN_INFO "ess_pci: AC97 Codec detected\n"); + maestro_ac97_init(iobase); + } + + /* Now clear the channel data */ + + for(i=0;i<64;i++) + { + for(w=0;w<0x0E;w++) + apu_set_register(iobase, i, w, 0); + } + + /* Now we program up the APU's */ + + /* + * APU 6 is the mixer + */ + + apu_set_register(iobase, 6, 0, + apu_get_register(iobase, 6, 0)&~(1<<14)); + apu_set_register(iobase, 6, 0, + apu_get_register(iobase, 6, 0)&~(1<<13)); + apu_set_register(iobase, 6, 0, + apu_get_register(iobase, 6, 0)&~(1<<12)); + apu_set_register(iobase, 6, 0, + apu_get_register(iobase, 6, 0)&0xFCFF); + apu_set_register(iobase, 6, 0, + apu_get_register(iobase, 6, 0)&0xF3FF); + apu_set_register(iobase, 6, 0, + (apu_get_register(iobase, 6, 0)&0xFFF0)|0x0F); + apu_set_register(iobase, 6, 2, + apu_get_register(iobase, 6, 2)&0x00FF); + apu_set_register(iobase, 6, 3, 0x0000); + apu_set_register(iobase, 6, 2, + apu_get_register(iobase, 6, 2)&0xFF3F); + apu_set_register(iobase, 6, 2, + apu_get_register(iobase, 6, 2)|(1<<5)); + apu_set_register(iobase, 6, 2, + apu_get_register(iobase, 6, 2)&~(1<<4)); + apu_set_register(iobase, 6, 2, + apu_get_register(iobase, 6, 2)&0xFFF0); + apu_set_register(iobase, 6, 4, 0x4B5F); + apu_set_register(iobase, 6, 5, 0xFDD5); + apu_set_register(iobase, 6, 6, 0xFE00); + apu_set_register(iobase, 6, 7, 0x0100); + apu_set_register(iobase, 6, 8, 0x78FF); + apu_set_register(iobase, 6, 9, 0xFFFF); + apu_set_register(iobase, 6, 0xA,0x8A10); + apu_set_register(iobase, 6, 0xB,0x8009); + + /* + * APU 62 - Right channel DSP + */ + + apu_set_register(iobase, 62, 0, + apu_get_register(iobase, 62, 0)&~(1<<14)); + apu_set_register(iobase, 62, 0, + apu_get_register(iobase, 62, 0)&~(1<<13)); + apu_set_register(iobase, 62, 0, + apu_get_register(iobase, 62, 0)&~(1<<12)); + apu_set_register(iobase, 62, 0, + apu_get_register(iobase, 62, 0)&0xFCFF); + apu_set_register(iobase, 62, 0, + apu_get_register(iobase, 62, 0)&0xF3FF); + apu_set_register(iobase, 62, 0, + (apu_get_register(iobase, 62, 0)&0xFFF0)|0x0F); + apu_set_register(iobase, 62, 2, + apu_get_register(iobase, 62, 2)&0x00FF); + apu_set_register(iobase, 62, 3, 0x1000); + apu_set_register(iobase, 62, 2, + apu_get_register(iobase, 62, 2)&0xFF3F); + apu_set_register(iobase, 62, 2, + apu_get_register(iobase, 62, 2)&~(1<<5)); + apu_set_register(iobase, 62, 2, + apu_get_register(iobase, 62, 2)&~(1<<4)); + apu_set_register(iobase, 62, 2, + apu_get_register(iobase, 62, 2)&0xFFF0); + apu_set_register(iobase, 62, 4, 0x7F00); + apu_set_register(iobase, 62, 5, 0x8000); + apu_set_register(iobase, 62, 6, 0x8080); + apu_set_register(iobase, 62, 7, 0x0080); + apu_set_register(iobase, 62, 8, 0x7F00); + apu_set_register(iobase, 62, 9, 0xFFFF); + apu_set_register(iobase, 62, 0xA,0x7F00); + apu_set_register(iobase, 62, 0xB,0x00F0); + + /* + * APU 63 - Left channel DSP + */ + + apu_set_register(iobase, 63, 0, + apu_get_register(iobase, 63, 0)&~(1<<14)); + apu_set_register(iobase, 63, 0, + apu_get_register(iobase, 63, 0)&~(1<<13)); + apu_set_register(iobase, 63, 0, + apu_get_register(iobase, 63, 0)&~(1<<12)); + apu_set_register(iobase, 63, 0, + apu_get_register(iobase, 63, 0)&0xFCFF); + apu_set_register(iobase, 63, 0, + apu_get_register(iobase, 63, 0)&0xF3FF); + apu_set_register(iobase, 63, 0, + (apu_get_register(iobase, 63, 0)&0xFFF0)|0x0F); + apu_set_register(iobase, 63, 2, + apu_get_register(iobase, 63, 2)&0x00FF); + apu_set_register(iobase, 63, 3, 0x1000); + apu_set_register(iobase, 63, 2, + apu_get_register(iobase, 63, 2)&0xFF3F); + apu_set_register(iobase, 63, 2, + apu_get_register(iobase, 63, 2)&~(1<<5)); + apu_set_register(iobase, 63, 2, + apu_get_register(iobase, 63, 2)&~(1<<4)); + apu_set_register(iobase, 63, 2, + apu_get_register(iobase, 63, 2)&0xFFF0); + apu_set_register(iobase, 63, 4, 0x7F00); + apu_set_register(iobase, 63, 5, 0x0000); + apu_set_register(iobase, 63, 6, 0x0080); + apu_set_register(iobase, 63, 7, 0x0080); + apu_set_register(iobase, 63, 8, 0x7F00); + apu_set_register(iobase, 63, 9, 0xFFFF); + apu_set_register(iobase, 63, 0xA,0x7F10); + apu_set_register(iobase, 63, 0xB,0x00F0); + + apu_set_register(iobase, 6, 0, + (apu_get_register(iobase,6, 0)&0xFF0F)|(9<<4)); + + udelay(30); + + apu_set_register(iobase, 62, 0, + (apu_get_register(iobase,6, 0)&0xFF0F)|(1<<4)); + apu_set_register(iobase, 63, 0, + (apu_get_register(iobase,6, 0)&0xFF0F)|(1<<4)); + + load_tables(iobase); + + outb(0x41, ESS_SETUP_A4+iobase); + udelay(1); + + printk(KERN_INFO "ess_pci: Programmed %s at 0x%X to legacy mode.\n", + name, iobase); + + ess_play_test(iobase); + maestro_cfg.dma = 1; + maestro_cfg.irq = pcidev->irq; + maestro_cfg.io_base = ESS_SBBASE; + maestro_cfg.dma2 = -1; + if(sb_dsp_detect(&maestro_cfg, SB_PCI_ESSMAESTRO, iobase)==-1) + { + printk(KERN_WARNING "esspci: Sound blaster emulation not responding.\n"); + return 0; + } + attach_sb_card(&maestro_cfg); + return 1; +} + + + +/* + * For now this does one card only. It is written this way as it will change + */ + +int init_ess19xx(void) +{ + struct pci_dev *pcidev=NULL; + int count=0; + + if(!pci_present()) + return -ENODEV; + + pcidev = NULL; + + /* + * Find the ESS Maestro 2. + */ + + while((pcidev = pci_find_device(PCI_VENDOR_ESS, PCI_DEVICE_ID_ESS_ESS1968, pcidev))!=NULL) + { + count+=maestro_install(pcidev, "ESS Maestro 2"); + if(count) + return 0; + } + + /* + * Find the ESS Maestro 2E + */ + + while((pcidev = pci_find_device(PCI_VENDOR_ESS, PCI_DEVICE_ID_ESS_ESS1978, pcidev))!=NULL) + { +// count+=maestro_install(pcidev, "ESS Maestro 2E"); + printk(KERN_INFO "ESS Maestro 2E not yet supported.\n"); + if(count) + return 0; + } + + /* + * ESS Maestro 1 + */ + + while((pcidev = pci_find_device(0x1285, 0x100, pcidev))!=NULL) + { + count+=maestro_install(pcidev, "ESS Maestro"); + if(count) + return 0; + } + if(count==0) + return -ENODEV; + return 0; +} + + +int init_module(void) +{ + if(init_ess19xx()<0) + { + printk(KERN_ERR "No ESS Maestro cards found.\n"); + return -ENODEV; + } + return 0; +} + +void cleanup_module(void) +{ + if(maestro_cfg.slots[0] != -1) + unload_sb(&maestro_cfg); +} + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/mad16.c linux.ac/drivers/sound/mad16.c --- linux.vanilla/drivers/sound/mad16.c Wed Mar 10 21:13:07 1999 +++ linux.ac/drivers/sound/mad16.c Wed Jul 7 07:01:56 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/maestro.c linux.ac/drivers/sound/maestro.c --- linux.vanilla/drivers/sound/maestro.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/sound/maestro.c Tue Jun 22 19:36:54 1999 @@ -0,0 +1,2797 @@ +/*****************************************************************************/ + +/* + * ESS Maestro/Maestro-2 driver for Linux 2.2.x + * + * + * This program is free software; you can redistribute 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. + * + * (c) Copyright 1999 Alan Cox + * + * Based heavily on SonicVibes.c: + * Copyright (C) 1998-1999 Thomas Sailer (sailer@ife.ee.ethz.ch) + * + * + * Supported devices: + * /dev/dsp0-7 standard /dev/dsp device, (mostly) OSS compatible + * /dev/mixer standard /dev/mixer device, (mostly) OSS compatible + * + * Revision history + * + */ + +/*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "maestro.h" +#include "maestro_tables.h" + + + + +/* --------------------------------------------------------------------- */ + +#undef OSS_DOCUMENTED_MIXER_SEMANTICS + +/* --------------------------------------------------------------------- */ + +#ifndef PCI_VENDOR_ESS +#define PCI_VENDOR_ESS 0x125D +#define PCI_DEVICE_ID_ESS_ESS1969 0x1969 +#define PCI_DEVICE_ID_ESS_ESS1948 0x1948 /* Solo ?? */ +#define PCI_DEVICE_ID_ESS_ESS1968 0x1968 /* Maestro 2 */ +#define PCI_DEVICE_ID_ESS_ESS1978 0x1978 /* Maestro 2E */ +#endif + +#define ESS_CHAN_HARD 0x100 + +#define ESS_CFMT_STEREO 0x01 +#define ESS_CFMT_16BIT 0x02 +#define ESS_CFMT_MASK 0x03 +#define ESS_CFMT_ASHIFT 0 +#define ESS_CFMT_CSHIFT 4 + +#define ESS_ENABLE_PE 1 +#define ESS_ENABLE_RE 2 + +#define ESS_MAGIC 0x125D1968 + +#define DAC_RUNNING 1 +#define ADC_RUNNING 2 + +static const unsigned sample_size[] = { 1, 2, 2, 4 }; +static const unsigned sample_shift[] = { 0, 1, 1, 2 }; + +#define SND_DEV_DSP16 5 + +/* --------------------------------------------------------------------- */ + +struct ess_state { + unsigned int magic; + /* FIXME: we probably want submixers in here, but only one record pair */ + u8 apu[4]; /* Left, Right, Left In, Right In */ + u8 apu_mode[4]; /* Running mode for this APU */ + u8 apu_pan[4]; /* Panning setup for this APU */ + struct ess_card *card; /* Card info */ + /* wave stuff */ + unsigned int rateadc, ratedac; + unsigned char fmt, enable; + + spinlock_t lock; + struct semaphore open_sem; + mode_t open_mode; + struct wait_queue *open_wait; + + /* soundcore stuff */ + int dev_audio; + int dev_mixer; + + struct dmabuf { + void *rawbuf; + unsigned buforder; + unsigned numfrag; + unsigned fragshift; + unsigned hwptr, swptr; + unsigned total_bytes; + int count; + unsigned error; /* over/underrun */ + struct wait_queue *wait; + /* redundant, but makes calculations easier */ + unsigned fragsize; + unsigned dmasize; + unsigned fragsamples; + /* OSS stuff */ + unsigned mapped:1; + unsigned ready:1; + unsigned endcleared:1; + unsigned ossfragshift; + int ossmaxfrags; + unsigned subdivision; + u16 base; /* Offset for ptr */ + } dma_dac, dma_adc; +}; + +struct ess_card { + unsigned int magic; + + /* We keep maestro cards in a linked list */ + struct ess_card *next; + + struct ess_state channels[8]; + u16 maestro_map[32]; /* Register map */ + + /* hardware resources */ + u32 iobase; + u32 irq; + + /* mixer stuff */ + struct { + unsigned int modcnt; +#ifndef OSS_DOCUMENTED_MIXER_SEMANTICS + unsigned short vol[13]; +#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */ + } mix; +}; + +extern __inline__ unsigned ld2(unsigned int x) +{ + unsigned r = 0; + + if (x >= 0x10000) { + x >>= 16; + r += 16; + } + if (x >= 0x100) { + x >>= 8; + r += 8; + } + if (x >= 0x10) { + x >>= 4; + r += 4; + } + if (x >= 4) { + x >>= 2; + r += 2; + } + if (x >= 2) + r++; + return r; +} + + +/* --------------------------------------------------------------------- */ + +static struct ess_card *devs = NULL; + +/* --------------------------------------------------------------------- */ + + +/* + * ESS Maestro AC97 codec programming interface. + */ + +static void maestro_ac97_set(int io, u8 cmd, u16 val) +{ + int i; + /* + * Wait for the codec bus to be free + */ + + for(i=0;i<10000;i++) + { + if(!(inb(io+ESS_AC97_INDEX)&1)) + break; + } + /* + * Write the bus + */ + outw(val, io+ESS_AC97_DATA); + udelay(1); + outb(cmd, io+ESS_AC97_INDEX); + udelay(1); +} + +static u16 maestro_ac97_get(int io, u8 cmd) +{ + int sanity=100000; + u16 data; + int i; + + /* + * Wait for the codec bus to be free + */ + + for(i=0;i<10000;i++) + { + if(!(inb(io+ESS_AC97_INDEX)&1)) + break; + } + + outb(cmd|0x80, io+ESS_AC97_INDEX); + udelay(1); + + while(inb(io+ESS_AC97_INDEX)&1) + { + sanity--; + if(!sanity) + { + printk(KERN_ERR "ess_pci: ac97 codec timeout.\n"); + return 0; + } + } + data=inw(io+ESS_AC97_DATA); + udelay(1); + return data; +} + +/* + * The Maestro can be wired to a standard AC97 compliant codec + * (see www.intel.com for the pdf's on this), or to a PT101 codec + * which appears to be the ES1918 (data sheet on the esstech.com.tw site) + * + * The PT101 setup is untested. + */ + +static u16 maestro_ac97_init(int iobase) +{ + maestro_ac97_set(iobase, 0x02, 0x0000); + maestro_ac97_set(iobase, 0x04, 0x0000); + maestro_ac97_set(iobase, 0x06, 0x0000); + maestro_ac97_set(iobase, 0x08, 0x9F1F); + maestro_ac97_set(iobase, 0x0A, 0x9F1F); + maestro_ac97_set(iobase, 0x0C, 0x9F1F); + maestro_ac97_set(iobase, 0x0E, 0x9F1F); + maestro_ac97_set(iobase, 0x10, 0x9F1F); + maestro_ac97_set(iobase, 0x12, 0x9F1F); + maestro_ac97_set(iobase, 0x14, 0x9F1F); + maestro_ac97_set(iobase, 0x16, 0x9F1F); + maestro_ac97_set(iobase, 0x18, 0x0808); + maestro_ac97_set(iobase, 0x1A, 0x0000); + maestro_ac97_set(iobase, 0x1C, 0x0404); + maestro_ac97_set(iobase, 0x1E, 0x0404); + maestro_ac97_set(iobase, 0x20, 0x0000); + maestro_ac97_set(iobase, 0x26, 0x000F); + return 0; +} + +static u16 maestro_pt101_init(int iobase) +{ + maestro_ac97_set(iobase, 0x2A, 0x0001); + maestro_ac97_set(iobase, 0x2C, 0x0000); + maestro_ac97_set(iobase, 0x2C, 0xFFFF); + maestro_ac97_set(iobase, 0x10, 0x9F1F); + maestro_ac97_set(iobase, 0x12, 0x0808); + maestro_ac97_set(iobase, 0x14, 0x9F1F); + maestro_ac97_set(iobase, 0x16, 0x9F1F); + maestro_ac97_set(iobase, 0x18, 0x0404); + maestro_ac97_set(iobase, 0x1A, 0x0000); + maestro_ac97_set(iobase, 0x1C, 0x0000); + maestro_ac97_set(iobase, 0x02, 0x0404); + maestro_ac97_set(iobase, 0x04, 0x0808); + maestro_ac97_set(iobase, 0x0C, 0x801F); + maestro_ac97_set(iobase, 0x0E, 0x801F); + return 0; +} + +static void maestro_ac97_reset(int ioaddr) +{ + outw(0x2000, ioaddr+0x36); + udelay(20); + outw(0x0000, ioaddr+0x36); + udelay(200); +} + + + +/* + * Indirect register access. Not all registers are readable so we + * need to keep register state ourselves + */ + +#define WRITEABLE_MAP 0xEFFFFF +#define READABLE_MAP 0x64003F + +/* + * The ESS engineers were a little indirection happy. These indirected + * registers themselves include indirect registers at another layer + */ + +static void maestro_write(struct ess_state *ess, u16 reg, u16 data) +{ + long ioaddr = ess->card->iobase; + unsigned long flags; + save_flags(flags); + cli(); + outw(reg, ioaddr+0x02); + outw(data, ioaddr+0x00); + ess->card->maestro_map[reg]=data; + restore_flags(flags); +} + +static u16 maestro_read(struct ess_state *ess, u16 reg) +{ + long ioaddr = ess->card->iobase; + if(READABLE_MAP & (1<card->maestro_map[reg]=inw(ioaddr+0x00); + restore_flags(flags); + } + return ess->card->maestro_map[reg]; +} + +/* + * These routines handle accessing the second level indirections to the + * wave ram. + */ + +/* + * The register names are the ones ESS uses (see 104T31.ZIP) + */ + +#define IDR0_DATA_PORT 0x00 +#define IDR1_CRAM_POINTER 0x01 +#define IDR2_CRAM_DATA 0x02 +#define IDR3_WAVE_DATA 0x03 +#define IDR4_WAVE_PTR_LOW 0x04 +#define IDR5_WAVE_PTR_HI 0x05 +#define IDR6_TIMER_CTRL 0x06 +#define IDR7_WAVE_ROMRAM 0x07 + +static void apu_index_set(struct ess_state *ess, u16 index) +{ + int i; + maestro_write(ess, IDR1_CRAM_POINTER, index); + for(i=0;i<1000;i++) + if(maestro_read(ess, IDR1_CRAM_POINTER)==index) + return; + printk(KERN_WARNING "ess_pci: APU register select failed.\n"); +} + +static void apu_data_set(struct ess_state *ess, u16 data) +{ + int i; + for(i=0;i<1000;i++) + { + if(maestro_read(ess, IDR0_DATA_PORT)==data) + return; + maestro_write(ess, IDR0_DATA_PORT, data); + } +} + +/* + * This is the public interface for APU manipulation. It handles the + * interlock to avoid two APU writes in parallel etc. Don't diddle + * directly with the stuff above. + */ + +static void apu_set_register(struct ess_state *ess, u16 channel, u8 reg, u16 data) +{ + unsigned long flags; + + if(channel&ESS_CHAN_HARD) + channel&=~ESS_CHAN_HARD; + else + { + if(channel>3) + printk("BAD CHANNEL %d.\n",channel); + else + channel = ess->apu[channel]; + } + + reg|=(channel<<4); + + save_flags(flags); + cli(); + apu_index_set(ess, reg); + apu_data_set(ess, data); + restore_flags(flags); +} + +static u16 apu_get_register(struct ess_state *ess, u16 channel, u8 reg) +{ + unsigned long flags; + u16 v; + + if(channel&ESS_CHAN_HARD) + channel&=~ESS_CHAN_HARD; + else + channel = ess->apu[channel]; + + reg|=(channel<<4); + + save_flags(flags); + cli(); + apu_index_set(ess, reg); + v=maestro_read(ess, IDR0_DATA_PORT); + restore_flags(flags); + return v; +} + + +/* + * The ASSP is fortunately not double indexed + */ + +static void assp_set_register(int ioaddr, u32 reg, u32 value) +{ + unsigned long flags; + + save_flags(flags); + cli(); + outl(reg, ioaddr+0x80); + outl(value, ioaddr+0x84); + restore_flags(flags); +} + +static u32 assp_get_register(int ioaddr, u32 reg) +{ + unsigned long flags; + u32 value; + + save_flags(flags); + cli(); + outl(reg, ioaddr+0x80); + value=inl(ioaddr+0x84); + restore_flags(flags); + + return value; +} + +/* + * The wavecache is also sane + */ + +static void wave_set_register(struct ess_state *ess, u16 reg, u16 value) +{ + long ioaddr = ess->card->iobase; + unsigned long flags; + + save_flags(flags); + cli(); + outw(reg, ioaddr+0x10); + outw(value, ioaddr+0x12); + restore_flags(flags); +} + +static u16 wave_get_register(struct ess_state *ess, u16 reg) +{ + long ioaddr = ess->card->iobase; + unsigned long flags; + u16 value; + + save_flags(flags); + cli(); + outw(reg, ioaddr+0x10); + value=inw(ioaddr+0x12); + restore_flags(flags); + + return value; +} + +/* + * Additional Reset Functions + */ + +static void maestro_reset(int ioaddr) +{ + outw(0x8000, 0x18+ioaddr); + udelay(10); + outw(0x0000, 0x18+ioaddr); + udelay(10); +} + +static void sound_reset(int ioaddr) +{ + outw(0x2000, 0x18+ioaddr); + udelay(10); + outw(0x0000, 0x18+ioaddr); + udelay(10); +} + +static void asp_load(int ioaddr, u16 l, u16 h, u16 *data, int len) +{ + int i; + outw(l, ioaddr+0x80); + outw(h, ioaddr+0x82); + for(i=0;i>=1; + + + for(channel=0; channel <= high_apu; channel++) + { + int i; + + /* + * To understand this it helps to know how the + * wave cache works. There are 4 DSP wavecache + * blocks which are 0x1FC->0x1FF. They are selected + * by setting bits 22,21,20 of the address to + * 1 X Y where X Y select the block. + * + * In addition stereo pairing is supported. This is + * set in the wave cache control for the channel as is + * 8bit unsigned. + * + * Note that this causes a problem. With our limit of + * about 12 full duplex pairs (48 channels active) we + * will need to do a lot of juggling to get all the + * memory we want sufficiently close together. + * + * Even with 64K blocks that means + * 24 channel pairs + * 6 pairs/block + * + * 10K per channel pair = 5000 samples. + */ + + pa = virt_to_bus(buffer); + + wave_set_register(ess, 0x01FC, (pa&0xFFE00000)>>12); + + /* Flush the wave cache entry */ + if(!(mode&1)) + wave_set_register(ess, ess->apu[channel]<<3, (pa&0xFFFF)-0x10); + else + wave_set_register(ess, ess->apu[channel]<<3, ((pa&0xFFFF)-0x10)|2); + + pa&=0x1FFFFF; /* Low 21 bits */ + pa>>=1; + + ess->dma_dac.base = pa&0xFFFF; + + if(mode&1) /* Enable stereo */ + pa|=0x00800000; + pa|=0x00400000; /* System RAM */ + + /* Begin loading the APU */ + + for(i=0;i<15;i++) + apu_set_register(ess, channel, i, 0x0000); + + /* Load the frequency, turn on 6dB, turn off the effects */ + apu_set_register(ess, channel, 2, (rate&0xFF)<<8|0x10); + apu_set_register(ess, channel, 3, rate>>8); + + /* Load the buffer into the wave engine */ + apu_set_register(ess, channel, 4, ((pa>>16)&0xFF)<<8); + apu_set_register(ess, channel, 5, pa&0xFFFF); + apu_set_register(ess, channel, 6, (pa+size)&0xFFFF); + apu_set_register(ess, channel, 7, size); + + apu_set_register(ess, channel, 8, 0x0000); + apu_set_register(ess, channel, 9, 0xD000); + + if(mode&1) + { + /* Set left or right */ + if(channel == 0) + apu_set_register(ess, channel, 10, 0x8F00); + else + apu_set_register(ess, channel, 10, 0x8F10); + } + else + apu_set_register(ess, channel, 10, 0x8F08); + apu_set_register(ess, channel, 11, 0x0000); + apu_set_register(ess, channel, 0, 0x400F); + } + + outw(1, ess->card->iobase+0x04); + outw(inw(ess->card->iobase+0x18)|4, ess->card->iobase+0x18); + + for(channel=0; channel<=high_apu; channel++) + { + /* Turn on the DMA */ + if(mode&2) + { /* 16 bit */ + apu_set_register(ess, channel, 0, + (apu_get_register(ess, channel, 0)&0xFF0F)|0x20); + ess->apu_mode[channel]=0x20; + } + else + { + apu_set_register(ess, channel, 0, + (apu_get_register(ess, channel, 0)&0xFF0F)|0x40); + ess->apu_mode[channel]=0x40; + } + } +} + +static void ess_play_finish(struct ess_state *ess, int mode) +{ + apu_set_register(ess, 0, 0, + apu_get_register(ess, 0, 0)&0xFF0F); + if(mode&1) + { + apu_set_register(ess, 1, 0, + apu_get_register(ess, 1, 0)&0xFF0F); + } +} + +static void ess_play_test(struct ess_state *ess) +{ + u8 *buf=kmalloc(16384, GFP_KERNEL|GFP_DMA); + int ct; + long time=jiffies; + if(buf!=NULL) + { + for(ct=0; ct<16384;ct++) + { + buf[ct]=ct^39; + } + } + ess_play_setup(ess, 0, 0x39CD, buf, 16384); + + while((jiffies-time)<5*HZ) + { + schedule(); + } + printk("\n"); + ess_play_finish(ess, 0); + if(buf) + kfree(buf); +} + + + + +/* --------------------------------------------------------------------- */ + +static void set_dmaa(struct ess_state *s, unsigned int addr, unsigned int count) +{ +} + +static void set_dmac(struct ess_state *s, unsigned int addr, unsigned int count) +{ +} + +/* Playback pointer */ + +extern __inline__ unsigned get_dmaa(struct ess_state *s) +{ + long ioport = s->card->iobase; + int offset; + + outw(1, ioport+2); + outw(s->apu[0]<<4|5, ioport); + outw(0, ioport+2); + offset=inw(ioport); + + offset-=s->dma_dac.base; + +// printk("Offset = %d\n", (offset&0x0FFFE)<<1); + return (offset&0xFFFE)/*<<1*/; +} + +/* Record pointer */ +extern __inline__ unsigned get_dmac(struct ess_state *s) +{ + long ioport = s->card->iobase; + int offset; + + outw(1, ioport+2); + outw(s->apu[2]<<4|5, ioport); + outw(0, ioport+2); + offset=inw(ioport); + + /* The offset is an address not a position relative to base */ + + + return (offset&0xFFFE)<<1; +} + +static void set_apu_fmt(struct ess_state *s, int apu, int mode) +{ + if(mode&ESS_CFMT_16BIT) + { + s->apu_mode[apu] = 2; + s->apu_mode[apu+1] = 2; + } + else + { + s->apu_mode[apu] = 4; + s->apu_mode[apu+1] = 4; + } +} + +static void set_fmt(struct ess_state *s, unsigned char mask, unsigned char data) +{ + s->fmt = (s->fmt & mask) | data; + set_apu_fmt(s, 0, s->fmt & ESS_CFMT_MASK); + set_apu_fmt(s, 2, (s->fmt >> ESS_CFMT_CSHIFT) & ESS_CFMT_MASK); +} + +static u16 compute_rate(u32 freq) +{ + if(freq==48000) + return 0xFFFF; + freq<<=16; + freq/=48000; + return freq; +} + +static void set_dac_rate(struct ess_state *s, unsigned rate) +{ + u32 freq; + + if (rate > 48000) + rate = 48000; + if (rate < 4000) + rate = 4000; + freq = compute_rate(rate); + + /* Load the frequency, turn on 6dB, turn off the effects */ + apu_set_register(s, 0, 2, (freq&0xFF)<<8|0x10); + apu_set_register(s, 0, 3, freq>>8); + apu_set_register(s, 1, 2, (freq&0xFF)<<8|0x10); + apu_set_register(s, 1, 3, freq>>8); + s->ratedac = rate; +} + +static void set_adc_rate(struct ess_state *s, unsigned rate) +{ + u32 freq; + + if (rate > 48000) + rate = 48000; + if (rate < 4000) + rate = 4000; + freq = compute_rate(rate); + + /* Load the frequency, turn on 6dB, turn off the effects */ + apu_set_register(s, 2, 2, (freq&0xFF)<<8|0x10); + apu_set_register(s, 2, 3, freq>>8); + apu_set_register(s, 3, 2, (freq&0xFF)<<8|0x10); + apu_set_register(s, 3, 3, freq>>8); + s->rateadc = rate; +} + +/* + * Meet Bob, the timer... + */ + + +static struct timer_list tmp_timer; + +static int bob_stopped; + +static int ess_interrupt_fake(unsigned long v) +{ + extern int ess_interrupt(int, void *, struct pt_regs *); + ess_interrupt(5, (void *)v, NULL); + del_timer(&tmp_timer); + if(!bob_stopped) + { + tmp_timer.expires=jiffies+1; + add_timer(&tmp_timer); + } + else + printk("Stopping bob\n"); + return 0; +} + +static void stop_bob(struct ess_state *s) +{ + bob_stopped=1; +// /* Mask IDR 11,17 */ +// maestro_write(s, 0x11, maestro_read(s, 11)&~1); +// maestro_write(s, 0x17, maestro_read(s, 11)&~1); +} + +static void kill_bob(struct ess_state *s) +{ + del_timer(&tmp_timer); + printk("Killing bob\n"); +// /* Mask IDR 11,17 */ +// maestro_write(s, 0x11, maestro_read(s, 11)&~1); +// maestro_write(s, 0x17, maestro_read(s, 11)&~1); +} + +static void start_bob(struct ess_state *s) +{ +// stop_bob(s); +// maestro_write(s, 6, 0x8000 |(1<<12) | (5<<5) | 11); +// /* Now set IDR 11/17 */ +// maestro_write(s, 0x11, maestro_read(s, 11)|1); +// maestro_write(s, 0x17, maestro_read(s, 11)|1); + static int init=1; + if(init) + { + init=0; + init_timer(&tmp_timer); + tmp_timer.function = ess_interrupt_fake; + } + bob_stopped = 0; + if(!timer_pending(&tmp_timer)) + { + del_timer(&tmp_timer); + tmp_timer.expires = jiffies+1; + tmp_timer.data = (unsigned long)s->card; + add_timer(&tmp_timer); + printk("Starting bob\n"); + } +} + +/* --------------------------------------------------------------------- */ + +static int adc_active = 0; + +extern inline void stop_adc(struct ess_state *s) +{ + unsigned long flags; + + spin_lock_irqsave(&s->lock, flags); + /* Stop left and right recording APU */ + s->enable &= ~ADC_RUNNING; + apu_set_register(s, 2, 0, apu_get_register(s, 2, 0)&0xFF0F); + apu_set_register(s, 3, 0, apu_get_register(s, 3, 0)&0xFF0F); + adc_active&=~1; +// if(!adc_active) +// stop_bob(s); + spin_unlock_irqrestore(&s->lock, flags); +} + +extern inline void stop_dac(struct ess_state *s) +{ + unsigned long flags; + + spin_lock_irqsave(&s->lock, flags); + s->enable &= ~DAC_RUNNING; + apu_set_register(s, 0, 0, apu_get_register(s, 0, 0)&0xFF0F); + apu_set_register(s, 1, 0, apu_get_register(s, 1, 0)&0xFF0F); + adc_active&=~2; +// if(!adc_active) +// stop_bob(s); + spin_unlock_irqrestore(&s->lock, flags); +} + +static void start_dac(struct ess_state *s) +{ + unsigned long flags; + + spin_lock_irqsave(&s->lock, flags); + if ((s->dma_dac.mapped || s->dma_dac.count > 0) && s->dma_dac.ready) { + s->enable |= DAC_RUNNING; + apu_set_register(s, 0, 0, + (apu_get_register(s, 0, 0)&0xFF0F)|s->apu_mode[0]); + apu_set_register(s, 1, 0, + (apu_get_register(s, 1, 0)&0xFF0F)|s->apu_mode[1]); + } +// if(!adc_active) +// start_bob(s); + adc_active|=2; + spin_unlock_irqrestore(&s->lock, flags); +} + +static void start_adc(struct ess_state *s) +{ + unsigned long flags; + + spin_lock_irqsave(&s->lock, flags); + if ((s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize)) + && s->dma_adc.ready) { + s->enable |= ADC_RUNNING; + apu_set_register(s, 2, 0, + (apu_get_register(s, 2, 0)&0xFF0F)|s->apu_mode[2]); + apu_set_register(s, 3, 0, + (apu_get_register(s, 3, 0)&0xFF0F)|s->apu_mode[3]); + } +// if(!adc_active) +// start_bob(s); + adc_active|=1; + spin_unlock_irqrestore(&s->lock, flags); +} + +/* --------------------------------------------------------------------- */ + +#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT) +#define DMABUF_MINORDER 1 + +static void dealloc_dmabuf(struct dmabuf *db) +{ + unsigned long map, mapend; + + if (db->rawbuf) { + /* undo marking the pages as reserved */ + mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); + for (map = MAP_NR(db->rawbuf); map <= mapend; map++) + clear_bit(PG_reserved, &mem_map[map].flags); + free_pages((unsigned long)db->rawbuf, db->buforder); + } + db->rawbuf = NULL; + db->mapped = db->ready = 0; +} + + +static int prog_dmabuf(struct ess_state *s, unsigned rec) +{ + struct dmabuf *db = rec ? &s->dma_adc : &s->dma_dac; + unsigned rate = rec ? s->rateadc : s->ratedac; + int order; + unsigned bytepersec; + unsigned bufs; + unsigned long map, mapend; + unsigned char fmt; + unsigned long flags; + + spin_lock_irqsave(&s->lock, flags); + fmt = s->fmt; + if (rec) { + s->enable &= ~ESS_ENABLE_RE; + fmt >>= ESS_CFMT_CSHIFT; + } else { + s->enable &= ~ESS_ENABLE_PE; + fmt >>= ESS_CFMT_ASHIFT; + } + spin_unlock_irqrestore(&s->lock, flags); + + 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); + if (!db->rawbuf) + return -ENOMEM; + db->buforder = order; + if ((virt_to_bus(db->rawbuf) ^ (virt_to_bus(db->rawbuf) + (PAGE_SIZE << db->buforder) - 1)) & ~0xffff) + printk(KERN_DEBUG "maestro: DMA buffer crosses 64k boundary: busaddr 0x%lx size %ld\n", + virt_to_bus(db->rawbuf), PAGE_SIZE << db->buforder); + if ((virt_to_bus(db->rawbuf) + (PAGE_SIZE << db->buforder) - 1) & ~0xffffff) + printk(KERN_DEBUG "maestro: DMA buffer beyond 16MB: busaddr 0x%lx size %ld\n", + virt_to_bus(db->rawbuf), PAGE_SIZE << db->buforder); + /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */ + mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); + for (map = MAP_NR(db->rawbuf); map <= mapend; map++) + set_bit(PG_reserved, &mem_map[map].flags); + } + bytepersec = rate << sample_shift[fmt]; + bufs = PAGE_SIZE << db->buforder; + if (db->ossfragshift) { + if ((1000 << db->ossfragshift) < bytepersec) + db->fragshift = ld2(bytepersec/1000); + else + db->fragshift = db->ossfragshift; + } else { + db->fragshift = ld2(bytepersec/100/(db->subdivision ? db->subdivision : 1)); + if (db->fragshift < 3) + db->fragshift = 3; + } + db->numfrag = bufs >> db->fragshift; + while (db->numfrag < 4 && db->fragshift > 3) { + db->fragshift--; + db->numfrag = bufs >> db->fragshift; + } + db->fragsize = 1 << db->fragshift; + if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag) + db->numfrag = db->ossmaxfrags; + db->fragsamples = db->fragsize >> sample_shift[fmt]; + db->dmasize = db->numfrag << db->fragshift; + memset(db->rawbuf, (fmt & ESS_CFMT_16BIT) ? 0 : 0x80, db->dmasize); + spin_lock_irqsave(&s->lock, flags); + if (rec) { + set_dmac(s, virt_to_bus(db->rawbuf), db->numfrag << db->fragshift); + /* program enhanced mode registers */ + /* FILL */ + } else { + //set_dmaa(s, virt_to_bus(db->rawbuf), db->numfrag << db->fragshift); + /* program enhanced mode registers */ + /* FILL */ + set_dac_rate(s, s->ratedac); + ess_play_setup(s, fmt, compute_rate(s->ratedac), + db->rawbuf, db->numfrag << db->fragshift); + + } + spin_unlock_irqrestore(&s->lock, flags); + db->ready = 1; + return 0; +} + +extern __inline__ void clear_advance(struct ess_state *s) +{ + unsigned char c = (s->fmt & (ESS_CFMT_16BIT << ESS_CFMT_ASHIFT)) ? 0 : 0x80; + unsigned char *buf = s->dma_dac.rawbuf; + unsigned bsize = s->dma_dac.dmasize; + unsigned bptr = s->dma_dac.swptr; + unsigned len = s->dma_dac.fragsize; + + if (bptr + len > bsize) { + unsigned x = bsize - bptr; + memset(buf + bptr, c, x); + bptr = 0; + len -= x; + } + memset(buf + bptr, c, len); +} + +/* call with spinlock held! */ +static void ess_update_ptr(struct ess_state *s) +{ + unsigned hwptr; + int diff; + + /* update ADC pointer */ + if (s->dma_adc.ready) { + hwptr = (/*s->dma_adc.dmasize - */get_dmac(s)) % s->dma_adc.dmasize; + diff = (s->dma_adc.dmasize + hwptr - s->dma_adc.hwptr) % s->dma_adc.dmasize; + s->dma_adc.hwptr = hwptr; + s->dma_adc.total_bytes += diff; + s->dma_adc.count += diff; + if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) + wake_up(&s->dma_adc.wait); + if (!s->dma_adc.mapped) { + if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) { + s->enable &= ~ESS_ENABLE_RE; + /* FILL ME */ +// wrindir(s, SV_CIENABLE, s->enable); + stop_adc(s); + s->dma_adc.error++; + } + } + } + /* update DAC pointer */ + if (s->dma_dac.ready) { + hwptr = (s->dma_dac.dmasize - get_dmaa(s)) % s->dma_dac.dmasize; + diff = (s->dma_dac.dmasize + hwptr - s->dma_dac.hwptr) % s->dma_dac.dmasize; + s->dma_dac.hwptr = hwptr; + s->dma_dac.total_bytes += diff; + if (s->dma_dac.mapped) { + s->dma_dac.count += diff; + if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) + wake_up(&s->dma_dac.wait); + } else { + s->dma_dac.count -= diff; + if (s->dma_dac.count <= 0) { + s->enable &= ~ESS_ENABLE_PE; +/* FILL ME */ +// wrindir(s, SV_CIENABLE, s->enable); + + stop_dac(s); + s->dma_dac.error++; + } else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize && !s->dma_dac.endcleared) { + clear_advance(s); + s->dma_dac.endcleared = 1; + } + if (s->dma_dac.count + (signed)s->dma_dac.fragsize <= (signed)s->dma_dac.dmasize) + wake_up(&s->dma_dac.wait); + } + } +} + +static void ess_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct ess_state *s; + struct ess_card *c = (struct ess_card *)dev_id; + int i; + u32 event; +/* + * 0x1A is a byte on maestro2E + * Turning this to byte cause the ess_play_test to play something + * but I don't know if it is what is intended to play .... seems a single + * note, in the medium range. + */ + event = inb(c->iobase+0x1A); + + outw(inw(c->iobase+4)&1, c->iobase+4); + + if(event&(1<<6)) + { + event = inw(c->iobase+0x18); + outb(0xFF, c->iobase+0x1A); + } + else + { + outb(0xFF, c->iobase+0x1A); + } + + /* + * Update the pointers for all 32 APU's we are running. + */ + for(i=0;i<8;i++) + { + s=&c->channels[i]; + if(s->dev_audio == -1) + break; + spin_lock(&s->lock); + ess_update_ptr(s); + spin_unlock(&s->lock); + } +} + + +/* --------------------------------------------------------------------- */ + +static const char invalid_magic[] = KERN_CRIT "maestro: invalid magic value\n"; + +#define VALIDATE_STATE(s) \ +({ \ + if (!(s) || (s)->magic != ESS_MAGIC) { \ + printk(invalid_magic); \ + return -ENXIO; \ + } \ +}) + +/* --------------------------------------------------------------------- */ +#if 0 + +#define MT_4 1 +#define MT_5MUTE 2 +#define MT_4MUTEMONO 3 +#define MT_6MUTE 4 + +static const struct { + unsigned left:5; + unsigned right:5; + unsigned type:3; + unsigned rec:3; +} mixtable[SOUND_MIXER_NRDEVICES] = { + [SOUND_MIXER_RECLEV] = { SV_CIMIX_ADCINL, SV_CIMIX_ADCINR, MT_4, 0 }, + [SOUND_MIXER_LINE1] = { SV_CIMIX_AUX1INL, SV_CIMIX_AUX1INR, MT_5MUTE, 5 }, + [SOUND_MIXER_CD] = { SV_CIMIX_CDINL, SV_CIMIX_CDINR, MT_5MUTE, 1 }, + [SOUND_MIXER_LINE] = { SV_CIMIX_LINEINL, SV_CIMIX_LINEINR, MT_5MUTE, 4 }, + [SOUND_MIXER_MIC] = { SV_CIMIX_MICIN, SV_CIMIX_ADCINL, MT_4MUTEMONO, 6 }, + [SOUND_MIXER_SYNTH] = { SV_CIMIX_SYNTHINL, SV_CIMIX_SYNTHINR, MT_5MUTE, 2 }, + [SOUND_MIXER_LINE2] = { SV_CIMIX_AUX2INL, SV_CIMIX_AUX2INR, MT_5MUTE, 3 }, + [SOUND_MIXER_VOLUME] = { SV_CIMIX_ANALOGINL, SV_CIMIX_ANALOGINR, MT_5MUTE, 7 }, + [SOUND_MIXER_PCM] = { SV_CIMIX_PCMINL, SV_CIMIX_PCMINR, MT_6MUTE, 0 } +}; + +#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS + +static int return_mixval(struct ess_state *s, unsigned i, int *arg) +{ + unsigned long flags; + unsigned char l, r, rl, rr; + + spin_lock_irqsave(&s->lock, flags); +// l = rdindir(s, mixtable[i].left); +// r = rdindir(s, mixtable[i].right); + /* FILL ME */ + spin_unlock_irqrestore(&s->lock, flags); + switch (mixtable[i].type) { + case MT_4: + r &= 0xf; + l &= 0xf; + rl = 10 + 6 * (l & 15); + rr = 10 + 6 * (r & 15); + break; + + case MT_4MUTEMONO: + rl = 55 - 3 * (l & 15); + if (r & 0x10) + rl += 45; + rr = rl; + r = l; + break; + + case MT_5MUTE: + default: + rl = 100 - 3 * (l & 31); + rr = 100 - 3 * (r & 31); + break; + + case MT_6MUTE: + rl = 100 - 3 * (l & 63) / 2; + rr = 100 - 3 * (r & 63) / 2; + break; + } + if (l & 0x80) + rl = 0; + if (r & 0x80) + rr = 0; + return put_user((rr << 8) | rl, arg); +} + +#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */ + +static const unsigned char volidx[SOUND_MIXER_NRDEVICES] = +{ + [SOUND_MIXER_RECLEV] = 1, + [SOUND_MIXER_LINE1] = 2, + [SOUND_MIXER_CD] = 3, + [SOUND_MIXER_LINE] = 4, + [SOUND_MIXER_MIC] = 5, + [SOUND_MIXER_SYNTH] = 6, + [SOUND_MIXER_LINE2] = 7, + [SOUND_MIXER_VOLUME] = 8, + [SOUND_MIXER_PCM] = 9 +}; + +#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */ + +static unsigned mixer_recmask(struct ess_state *s) +{ + unsigned long flags; + int i, j; + + spin_lock_irqsave(&s->lock, flags); +// j = rdindir(s, SV_CIMIX_ADCINL) >> 5; + /* FILL ME */ + spin_unlock_irqrestore(&s->lock, flags); + j &= 7; + for (i = 0; i < SOUND_MIXER_NRDEVICES && mixtable[i].rec != j; i++); + return 1 << i; +} + +static int mixer_ioctl(struct ess_state *s, unsigned int cmd, unsigned long arg) +{ + unsigned long flags; + int i, val; + unsigned char l, r, rl, rr; + + VALIDATE_STATE(s); + if (cmd == SOUND_MIXER_INFO) { + mixer_info info; + strncpy(info.id, "SonicVibes", sizeof(info.id)); + strncpy(info.name, "S3 SonicVibes", sizeof(info.name)); + info.modify_counter = s->mix.modcnt; + if (copy_to_user((void *)arg, &info, sizeof(info))) + return -EFAULT; + return 0; + } + if (cmd == SOUND_OLD_MIXER_INFO) { + _old_mixer_info info; + strncpy(info.id, "SonicVibes", sizeof(info.id)); + strncpy(info.name, "S3 SonicVibes", sizeof(info.name)); + if (copy_to_user((void *)arg, &info, sizeof(info))) + return -EFAULT; + return 0; + } + if (cmd == OSS_GETVERSION) + return put_user(SOUND_VERSION, (int *)arg); + if (cmd == SOUND_MIXER_PRIVATE1) { /* SRS settings */ + get_user_ret(val, (int *)arg, -EFAULT); + spin_lock_irqsave(&s->lock, flags); + if (val & 1) { + if (val & 2) { + l = 4 - ((val >> 2) & 7); + if (l & ~3) + l = 4; + r = 4 - ((val >> 5) & 7); + if (r & ~3) + r = 4; + wrindir(s, SV_CISRSSPACE, l); + wrindir(s, SV_CISRSCENTER, r); + } else + wrindir(s, SV_CISRSSPACE, 0x80); + } + l = rdindir(s, SV_CISRSSPACE); + r = rdindir(s, SV_CISRSCENTER); + spin_unlock_irqrestore(&s->lock, flags); + if (l & 0x80) + return put_user(0, (int *)arg); + return put_user(((4 - (l & 7)) << 2) | ((4 - (r & 7)) << 5) | 2, (int *)arg); + } + if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int)) + return -EINVAL; + if (_IOC_DIR(cmd) == _IOC_READ) { + switch (_IOC_NR(cmd)) { + case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ + return put_user(mixer_recmask(s), (int *)arg); + + case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */ + for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++) + if (mixtable[i].type) + val |= 1 << i; + return put_user(val, (int *)arg); + + case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */ + for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++) + if (mixtable[i].rec) + val |= 1 << i; + return put_user(val, (int *)arg); + + case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */ + for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++) + if (mixtable[i].type && mixtable[i].type != MT_4MUTEMONO) + val |= 1 << i; + return put_user(val, (int *)arg); + + case SOUND_MIXER_CAPS: + return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg); + + default: + i = _IOC_NR(cmd); + if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type) + return -EINVAL; +#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS + return return_mixval(s, i, (int *)arg); +#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */ + if (!volidx[i]) + return -EINVAL; + return put_user(s->mix.vol[volidx[i]-1], (int *)arg); +#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */ + } + } + if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) + return -EINVAL; + s->mix.modcnt++; + switch (_IOC_NR(cmd)) { + case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ + get_user_ret(val, (int *)arg, -EFAULT); + i = hweight32(val); + if (i == 0) + return 0; /*val = mixer_recmask(s);*/ + else if (i > 1) + val &= ~mixer_recmask(s); + for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { + if (!(val & (1 << i))) + continue; + if (mixtable[i].rec) + break; + } + if (!mixtable[i].rec) + return 0; + spin_lock_irqsave(&s->lock, flags); + frobindir(s, SV_CIMIX_ADCINL, 0x1f, mixtable[i].rec << 5); + frobindir(s, SV_CIMIX_ADCINR, 0x1f, mixtable[i].rec << 5); + spin_unlock_irqrestore(&s->lock, flags); + return 0; + + default: + i = _IOC_NR(cmd); + if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type) + return -EINVAL; + get_user_ret(val, (int *)arg, -EFAULT); + l = val & 0xff; + r = (val >> 8) & 0xff; + if (mixtable[i].type == MT_4MUTEMONO) + l = (r + l) / 2; + if (l > 100) + l = 100; + if (r > 100) + r = 100; + spin_lock_irqsave(&s->lock, flags); + switch (mixtable[i].type) { + case MT_4: + if (l >= 10) + l -= 10; + if (r >= 10) + r -= 10; + frobindir(s, mixtable[i].left, 0xf0, l / 6); + frobindir(s, mixtable[i].right, 0xf0, l / 6); + break; + + case MT_4MUTEMONO: + rr = 0; + if (l < 10) + rl = 0x80; + else { + if (l >= 55) { + rr = 0x10; + l -= 45; + } + rl = (55 - l) / 3; + } + wrindir(s, mixtable[i].left, rl); + frobindir(s, mixtable[i].right, ~0x10, rr); + break; + + case MT_5MUTE: + if (l < 7) + rl = 0x80; + else + rl = (100 - l) / 3; + if (r < 7) + rr = 0x80; + else + rr = (100 - r) / 3; + wrindir(s, mixtable[i].left, rl); + wrindir(s, mixtable[i].right, rr); + break; + + case MT_6MUTE: + if (l < 6) + rl = 0x80; + else + rl = (100 - l) * 2 / 3; + if (r < 6) + rr = 0x80; + else + rr = (100 - r) * 2 / 3; + wrindir(s, mixtable[i].left, rl); + wrindir(s, mixtable[i].right, rr); + break; + } + spin_unlock_irqrestore(&s->lock, flags); +#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS + return return_mixval(s, i, (int *)arg); +#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */ + if (!volidx[i]) + return -EINVAL; + s->mix.vol[volidx[i]-1] = val; + return put_user(s->mix.vol[volidx[i]-1], (int *)arg); +#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */ + } +} + +#endif + +/* --------------------------------------------------------------------- */ + +static loff_t ess_llseek(struct file *file, loff_t offset, int origin) +{ + return -ESPIPE; +} + +/* --------------------------------------------------------------------- */ + +#if 0 +static int ess_open_mixdev(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + struct ess_state *s = devs; + + while (s && s->dev_mixer != minor) + s = s->next; + if (!s) + return -ENODEV; + VALIDATE_STATE(s); + file->private_data = s; + MOD_INC_USE_COUNT; + return 0; +} + +static int ess_release_mixdev(struct inode *inode, struct file *file) +{ + struct ess_state *s = (struct ess_state *)file->private_data; + + VALIDATE_STATE(s); + MOD_DEC_USE_COUNT; + return 0; +} + +static int ess_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + return mixer_ioctl((struct ess_state *)file->private_data, cmd, arg); +} + +static /*const*/ struct file_operations ess_mixer_fops = { + &ess_llseek, + NULL, /* read */ + NULL, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + &ess_ioctl_mixdev, + NULL, /* mmap */ + &ess_open_mixdev, + NULL, /* flush */ + &ess_release_mixdev, + NULL, /* fsync */ + NULL, /* fasync */ + NULL, /* check_media_change */ + NULL, /* revalidate */ + NULL, /* lock */ +}; + +#endif + +/* --------------------------------------------------------------------- */ + +static int drain_dac(struct ess_state *s, int nonblock) +{ + struct wait_queue wait = { current, NULL }; + unsigned long flags; + int count, tmo; + + if (s->dma_dac.mapped || !s->dma_dac.ready) + return 0; + current->state = TASK_INTERRUPTIBLE; + add_wait_queue(&s->dma_dac.wait, &wait); + for (;;) { + spin_lock_irqsave(&s->lock, flags); + count = s->dma_dac.count; + spin_unlock_irqrestore(&s->lock, flags); + if (count <= 0) + break; + if (signal_pending(current)) + break; + if (nonblock) { + remove_wait_queue(&s->dma_dac.wait, &wait); + current->state = TASK_RUNNING; + return -EBUSY; + } + tmo = (count * HZ) / s->ratedac; + tmo >>= sample_shift[(s->fmt >> ESS_CFMT_ASHIFT) & ESS_CFMT_MASK]; + if (!schedule_timeout(tmo ? : 1) && tmo) + printk(KERN_DEBUG "maestro: dma timed out??\n"); + } + remove_wait_queue(&s->dma_dac.wait, &wait); + current->state = TASK_RUNNING; + if (signal_pending(current)) + return -ERESTARTSYS; + return 0; +} + +/* --------------------------------------------------------------------- */ + +static ssize_t ess_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +{ + struct ess_state *s = (struct ess_state *)file->private_data; + ssize_t ret; + unsigned long flags; + unsigned swptr; + int cnt; + + VALIDATE_STATE(s); + if (ppos != &file->f_pos) + return -ESPIPE; + if (s->dma_adc.mapped) + return -ENXIO; + if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) + return ret; + if (!access_ok(VERIFY_WRITE, buffer, count)) + return -EFAULT; + ret = 0; +#if 0 + spin_lock_irqsave(&s->lock, flags); + ess_update_ptr(s); + spin_unlock_irqrestore(&s->lock, flags); +#endif + while (count > 0) { + spin_lock_irqsave(&s->lock, flags); + swptr = s->dma_adc.swptr; + cnt = s->dma_adc.dmasize-swptr; + if (s->dma_adc.count < cnt) + cnt = s->dma_adc.count; + spin_unlock_irqrestore(&s->lock, flags); + if (cnt > count) + cnt = count; + if (cnt <= 0) { + start_adc(s); + if (file->f_flags & O_NONBLOCK) + return ret ? ret : -EAGAIN; + if (!interruptible_sleep_on_timeout(&s->dma_adc.wait, HZ)) { + printk(KERN_DEBUG "maestro: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n", + s->dma_adc.dmasize, s->dma_adc.fragsize, s->dma_adc.count, + s->dma_adc.hwptr, s->dma_adc.swptr); + stop_adc(s); + spin_lock_irqsave(&s->lock, flags); + set_dmac(s, virt_to_bus(s->dma_adc.rawbuf), s->dma_adc.numfrag << s->dma_adc.fragshift); + /* program enhanced mode registers */ + /* FILL ME */ +// wrindir(s, SV_CIDMACBASECOUNT1, (s->dma_adc.fragsamples-1) >> 8); +// wrindir(s, SV_CIDMACBASECOUNT0, s->dma_adc.fragsamples-1); + s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0; + spin_unlock_irqrestore(&s->lock, flags); + } + if (signal_pending(current)) + return ret ? ret : -ERESTARTSYS; + continue; + } + if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) + return ret ? ret : -EFAULT; + swptr = (swptr + cnt) % s->dma_adc.dmasize; + spin_lock_irqsave(&s->lock, flags); + s->dma_adc.swptr = swptr; + s->dma_adc.count -= cnt; + spin_unlock_irqrestore(&s->lock, flags); + count -= cnt; + buffer += cnt; + ret += cnt; + start_adc(s); + } + return ret; +} + +static ssize_t ess_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) +{ + struct ess_state *s = (struct ess_state *)file->private_data; + ssize_t ret; + unsigned long flags; + unsigned swptr; + int cnt; + + VALIDATE_STATE(s); + if (ppos != &file->f_pos) + return -ESPIPE; + if (s->dma_dac.mapped) + return -ENXIO; + if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0))) + return ret; + if (!access_ok(VERIFY_READ, buffer, count)) + return -EFAULT; + ret = 0; +#if 0 + spin_lock_irqsave(&s->lock, flags); + ess_update_ptr(s); + spin_unlock_irqrestore(&s->lock, flags); +#endif + while (count > 0) { + spin_lock_irqsave(&s->lock, flags); + if (s->dma_dac.count < 0) { + s->dma_dac.count = 0; + s->dma_dac.swptr = s->dma_dac.hwptr; + } + swptr = s->dma_dac.swptr; + cnt = s->dma_dac.dmasize-swptr; + if (s->dma_dac.count + cnt > s->dma_dac.dmasize) + cnt = s->dma_dac.dmasize - s->dma_dac.count; + spin_unlock_irqrestore(&s->lock, flags); + if (cnt > count) + cnt = count; + if (cnt <= 0) { + start_dac(s); + if (file->f_flags & O_NONBLOCK) + return ret ? ret : -EAGAIN; + if (!interruptible_sleep_on_timeout(&s->dma_dac.wait, HZ)) { + printk(KERN_DEBUG "maestro: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n", + s->dma_dac.dmasize, s->dma_dac.fragsize, s->dma_dac.count, + s->dma_dac.hwptr, s->dma_dac.swptr); + stop_dac(s); + spin_lock_irqsave(&s->lock, flags); + set_dmaa(s, virt_to_bus(s->dma_dac.rawbuf), s->dma_dac.numfrag << s->dma_dac.fragshift); + /* program enhanced mode registers */ +// wrindir(s, SV_CIDMAABASECOUNT1, (s->dma_dac.fragsamples-1) >> 8); +// wrindir(s, SV_CIDMAABASECOUNT0, s->dma_dac.fragsamples-1); + /* FILL ME */ + s->dma_dac.count = s->dma_dac.hwptr = s->dma_dac.swptr = 0; + spin_unlock_irqrestore(&s->lock, flags); + } + if (signal_pending(current)) + return ret ? ret : -ERESTARTSYS; + continue; + } + if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) + return ret ? ret : -EFAULT; + swptr = (swptr + cnt) % s->dma_dac.dmasize; + spin_lock_irqsave(&s->lock, flags); + s->dma_dac.swptr = swptr; + s->dma_dac.count += cnt; + s->dma_dac.endcleared = 0; + spin_unlock_irqrestore(&s->lock, flags); + count -= cnt; + buffer += cnt; + ret += cnt; + start_dac(s); + } + return ret; +} + +static unsigned int ess_poll(struct file *file, struct poll_table_struct *wait) +{ + struct ess_state *s = (struct ess_state *)file->private_data; + unsigned long flags; + unsigned int mask = 0; + + VALIDATE_STATE(s); + if (file->f_mode & FMODE_WRITE) + poll_wait(file, &s->dma_dac.wait, wait); + if (file->f_mode & FMODE_READ) + poll_wait(file, &s->dma_adc.wait, wait); + spin_lock_irqsave(&s->lock, flags); + ess_update_ptr(s); + if (file->f_mode & FMODE_READ) { + if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) + mask |= POLLIN | POLLRDNORM; + } + if (file->f_mode & FMODE_WRITE) { + if (s->dma_dac.mapped) { + if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) + mask |= POLLOUT | POLLWRNORM; + } else { + if ((signed)s->dma_dac.dmasize >= s->dma_dac.count + (signed)s->dma_dac.fragsize) + mask |= POLLOUT | POLLWRNORM; + } + } + spin_unlock_irqrestore(&s->lock, flags); + return mask; +} + +static int ess_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct ess_state *s = (struct ess_state *)file->private_data; + struct dmabuf *db; + int ret; + unsigned long size; + + VALIDATE_STATE(s); + if (vma->vm_flags & VM_WRITE) { + if ((ret = prog_dmabuf(s, 1)) != 0) + return ret; + db = &s->dma_dac; + } else if (vma->vm_flags & VM_READ) { + if ((ret = prog_dmabuf(s, 0)) != 0) + return ret; + db = &s->dma_adc; + } else + return -EINVAL; + if (vma->vm_offset != 0) + return -EINVAL; + size = vma->vm_end - vma->vm_start; + if (size > (PAGE_SIZE << db->buforder)) + return -EINVAL; + if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot)) + return -EAGAIN; + db->mapped = 1; + return 0; +} + +static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + struct ess_state *s = (struct ess_state *)file->private_data; + unsigned long flags; + audio_buf_info abinfo; + count_info cinfo; + int val, mapped, ret; + unsigned char fmtm, fmtd; + + VALIDATE_STATE(s); + mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) || + ((file->f_mode & FMODE_READ) && s->dma_adc.mapped); + switch (cmd) { + case OSS_GETVERSION: + return put_user(SOUND_VERSION, (int *)arg); + + case SNDCTL_DSP_SYNC: + if (file->f_mode & FMODE_WRITE) + return drain_dac(s, 0/*file->f_flags & O_NONBLOCK*/); + return 0; + + case SNDCTL_DSP_SETDUPLEX: + return 0; + + case SNDCTL_DSP_GETCAPS: + return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg); + + case SNDCTL_DSP_RESET: + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + synchronize_irq(); + s->dma_dac.swptr = s->dma_dac.hwptr = s->dma_dac.count = s->dma_dac.total_bytes = 0; + } + if (file->f_mode & FMODE_READ) { + stop_adc(s); + synchronize_irq(); + s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = s->dma_adc.total_bytes = 0; + } + return 0; + + case SNDCTL_DSP_SPEED: + get_user_ret(val, (int *)arg, -EFAULT); + if (val >= 0) { + if (file->f_mode & FMODE_READ) { + stop_adc(s); + s->dma_adc.ready = 0; + set_adc_rate(s, val); + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + s->dma_dac.ready = 0; + set_dac_rate(s, val); + } + } + return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg); + + case SNDCTL_DSP_STEREO: + get_user_ret(val, (int *)arg, -EFAULT); + fmtd = 0; + fmtm = ~0; + if (file->f_mode & FMODE_READ) { + stop_adc(s); + s->dma_adc.ready = 0; + if (val) + fmtd |= ESS_CFMT_STEREO << ESS_CFMT_CSHIFT; + else + fmtm &= ~(ESS_CFMT_STEREO << ESS_CFMT_CSHIFT); + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + s->dma_dac.ready = 0; + if (val) + fmtd |= ESS_CFMT_STEREO << ESS_CFMT_ASHIFT; + else + fmtm &= ~(ESS_CFMT_STEREO << ESS_CFMT_ASHIFT); + } + set_fmt(s, fmtm, fmtd); + return 0; + + case SNDCTL_DSP_CHANNELS: + get_user_ret(val, (int *)arg, -EFAULT); + if (val != 0) { + fmtd = 0; + fmtm = ~0; + if (file->f_mode & FMODE_READ) { + stop_adc(s); + s->dma_adc.ready = 0; + if (val >= 2) + fmtd |= ESS_CFMT_STEREO << ESS_CFMT_CSHIFT; + else + fmtm &= ~(ESS_CFMT_STEREO << ESS_CFMT_CSHIFT); + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + s->dma_dac.ready = 0; + if (val >= 2) + fmtd |= ESS_CFMT_STEREO << ESS_CFMT_ASHIFT; + else + fmtm &= ~(ESS_CFMT_STEREO << ESS_CFMT_ASHIFT); + } + set_fmt(s, fmtm, fmtd); + } + return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (ESS_CFMT_STEREO << ESS_CFMT_CSHIFT) + : (ESS_CFMT_STEREO << ESS_CFMT_ASHIFT))) ? 2 : 1, (int *)arg); + + case SNDCTL_DSP_GETFMTS: /* Returns a mask */ + return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg); + + case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ + get_user_ret(val, (int *)arg, -EFAULT); + if (val != AFMT_QUERY) { + fmtd = 0; + fmtm = ~0; + if (file->f_mode & FMODE_READ) { + stop_adc(s); + s->dma_adc.ready = 0; + if (val == AFMT_S16_LE) + fmtd |= ESS_CFMT_16BIT << ESS_CFMT_CSHIFT; + else + fmtm &= ~(ESS_CFMT_16BIT << ESS_CFMT_CSHIFT); + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + s->dma_dac.ready = 0; + if (val == AFMT_S16_LE) + fmtd |= ESS_CFMT_16BIT << ESS_CFMT_ASHIFT; + else + fmtm &= ~(ESS_CFMT_16BIT << ESS_CFMT_ASHIFT); + } + set_fmt(s, fmtm, fmtd); + } + return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (ESS_CFMT_16BIT << ESS_CFMT_CSHIFT) + : (ESS_CFMT_16BIT << ESS_CFMT_ASHIFT))) ? AFMT_S16_LE : AFMT_U8, (int *)arg); + + case SNDCTL_DSP_POST: + return 0; + + case SNDCTL_DSP_GETTRIGGER: + val = 0; + if (file->f_mode & FMODE_READ && s->enable & ESS_ENABLE_RE) + val |= PCM_ENABLE_INPUT; + if (file->f_mode & FMODE_WRITE && s->enable & ESS_ENABLE_PE) + val |= PCM_ENABLE_OUTPUT; + return put_user(val, (int *)arg); + + case SNDCTL_DSP_SETTRIGGER: + get_user_ret(val, (int *)arg, -EFAULT); + if (file->f_mode & FMODE_READ) { + if (val & PCM_ENABLE_INPUT) { + if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) + return ret; + start_adc(s); + } else + stop_adc(s); + } + if (file->f_mode & FMODE_WRITE) { + if (val & PCM_ENABLE_OUTPUT) { + if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0))) + return ret; + start_dac(s); + } else + stop_dac(s); + } + return 0; + + case SNDCTL_DSP_GETOSPACE: + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + if (!(s->enable & ESS_ENABLE_PE) && (val = prog_dmabuf(s, 0)) != 0) + return val; + spin_lock_irqsave(&s->lock, flags); + ess_update_ptr(s); + abinfo.fragsize = s->dma_dac.fragsize; + abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count; + abinfo.fragstotal = s->dma_dac.numfrag; + abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift; + spin_unlock_irqrestore(&s->lock, flags); + return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; + + case SNDCTL_DSP_GETISPACE: + if (!(file->f_mode & FMODE_READ)) + return -EINVAL; + if (!(s->enable & ESS_ENABLE_RE) && (val = prog_dmabuf(s, 1)) != 0) + return val; + spin_lock_irqsave(&s->lock, flags); + ess_update_ptr(s); + abinfo.fragsize = s->dma_adc.fragsize; + abinfo.bytes = s->dma_adc.count; + abinfo.fragstotal = s->dma_adc.numfrag; + abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift; + spin_unlock_irqrestore(&s->lock, flags); + return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; + + case SNDCTL_DSP_NONBLOCK: + file->f_flags |= O_NONBLOCK; + return 0; + + case SNDCTL_DSP_GETODELAY: + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + spin_lock_irqsave(&s->lock, flags); + ess_update_ptr(s); + val = s->dma_dac.count; + spin_unlock_irqrestore(&s->lock, flags); + return put_user(val, (int *)arg); + + case SNDCTL_DSP_GETIPTR: + if (!(file->f_mode & FMODE_READ)) + return -EINVAL; + spin_lock_irqsave(&s->lock, flags); + ess_update_ptr(s); + cinfo.bytes = s->dma_adc.total_bytes; + cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift; + cinfo.ptr = s->dma_adc.hwptr; + if (s->dma_adc.mapped) + s->dma_adc.count &= s->dma_adc.fragsize-1; + spin_unlock_irqrestore(&s->lock, flags); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + + case SNDCTL_DSP_GETOPTR: + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + spin_lock_irqsave(&s->lock, flags); + ess_update_ptr(s); + cinfo.bytes = s->dma_dac.total_bytes; + cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift; + cinfo.ptr = s->dma_dac.hwptr; + if (s->dma_dac.mapped) + s->dma_dac.count &= s->dma_dac.fragsize-1; + spin_unlock_irqrestore(&s->lock, flags); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + + case SNDCTL_DSP_GETBLKSIZE: + if (file->f_mode & FMODE_WRITE) { + if ((val = prog_dmabuf(s, 0))) + return val; + return put_user(s->dma_dac.fragsize, (int *)arg); + } + if ((val = prog_dmabuf(s, 1))) + return val; + return put_user(s->dma_adc.fragsize, (int *)arg); + + case SNDCTL_DSP_SETFRAGMENT: + get_user_ret(val, (int *)arg, -EFAULT); + if (file->f_mode & FMODE_READ) { + s->dma_adc.ossfragshift = val & 0xffff; + s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff; + if (s->dma_adc.ossfragshift < 4) + s->dma_adc.ossfragshift = 4; + if (s->dma_adc.ossfragshift > 15) + s->dma_adc.ossfragshift = 15; + if (s->dma_adc.ossmaxfrags < 4) + s->dma_adc.ossmaxfrags = 4; + } + if (file->f_mode & FMODE_WRITE) { + s->dma_dac.ossfragshift = val & 0xffff; + s->dma_dac.ossmaxfrags = (val >> 16) & 0xffff; + if (s->dma_dac.ossfragshift < 4) + s->dma_dac.ossfragshift = 4; + if (s->dma_dac.ossfragshift > 15) + s->dma_dac.ossfragshift = 15; + if (s->dma_dac.ossmaxfrags < 4) + s->dma_dac.ossmaxfrags = 4; + } + return 0; + + case SNDCTL_DSP_SUBDIVIDE: + if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || + (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision)) + return -EINVAL; + get_user_ret(val, (int *)arg, -EFAULT); + if (val != 1 && val != 2 && val != 4) + return -EINVAL; + if (file->f_mode & FMODE_READ) + s->dma_adc.subdivision = val; + if (file->f_mode & FMODE_WRITE) + s->dma_dac.subdivision = val; + return 0; + + case SOUND_PCM_READ_RATE: + return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg); + + case SOUND_PCM_READ_CHANNELS: + return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (ESS_CFMT_STEREO << ESS_CFMT_CSHIFT) + : (ESS_CFMT_STEREO << ESS_CFMT_ASHIFT))) ? 2 : 1, (int *)arg); + + case SOUND_PCM_READ_BITS: + return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (ESS_CFMT_16BIT << ESS_CFMT_CSHIFT) + : (ESS_CFMT_16BIT << ESS_CFMT_ASHIFT))) ? 16 : 8, (int *)arg); + + case SOUND_PCM_WRITE_FILTER: + case SNDCTL_DSP_SETSYNCRO: + case SOUND_PCM_READ_FILTER: + return -EINVAL; + + } +// return mixer_ioctl(s, cmd, arg); + return -EINVAL; +} + +static int ess_open(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + struct ess_card *c = devs; + struct ess_state *s = NULL, *sp; + int i; + unsigned char fmtm = ~0, fmts = 0; + + /* + * Scan the cards and find the channel. We only + * do this at open time so it is ok + */ + + while (c!=NULL) + { + for(i=0;i<8;i++) + { + sp=&c->channels[i]; + if(sp->dev_audio < 0) + continue; + if((sp->dev_audio ^ minor) & ~0xf) + continue; + s=sp; + } + c=c->next; + } + + if (!s) + return -ENODEV; + + VALIDATE_STATE(s); + file->private_data = s; + /* wait for device to become free */ + down(&s->open_sem); + while (s->open_mode & file->f_mode) { + if (file->f_flags & O_NONBLOCK) { + up(&s->open_sem); + return -EWOULDBLOCK; + } + up(&s->open_sem); + interruptible_sleep_on(&s->open_wait); + if (signal_pending(current)) + return -ERESTARTSYS; + down(&s->open_sem); + } + if (file->f_mode & FMODE_READ) { + fmtm &= ~((ESS_CFMT_STEREO | ESS_CFMT_16BIT) << ESS_CFMT_CSHIFT); + if ((minor & 0xf) == SND_DEV_DSP16) + fmts |= ESS_CFMT_16BIT << ESS_CFMT_CSHIFT; + s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0; + set_adc_rate(s, 8000); + } + if (file->f_mode & FMODE_WRITE) { + fmtm &= ~((ESS_CFMT_STEREO | ESS_CFMT_16BIT) << ESS_CFMT_ASHIFT); + if ((minor & 0xf) == SND_DEV_DSP16) + fmts |= ESS_CFMT_16BIT << ESS_CFMT_ASHIFT; + s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = s->dma_dac.subdivision = 0; + set_dac_rate(s, 8000); + } + set_fmt(s, fmtm, fmts); + s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); + start_bob(s); + up(&s->open_sem); + MOD_INC_USE_COUNT; + return 0; +} + +static int ess_release(struct inode *inode, struct file *file) +{ + struct ess_state *s = (struct ess_state *)file->private_data; + + VALIDATE_STATE(s); + if (file->f_mode & FMODE_WRITE) + drain_dac(s, file->f_flags & O_NONBLOCK); + down(&s->open_sem); + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + dealloc_dmabuf(&s->dma_dac); + } + if (file->f_mode & FMODE_READ) { + stop_adc(s); + dealloc_dmabuf(&s->dma_adc); + } + s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); + stop_bob(s); + up(&s->open_sem); + wake_up(&s->open_wait); + MOD_DEC_USE_COUNT; + return 0; +} + +static /*const*/ struct file_operations ess_audio_fops = { + &ess_llseek, + &ess_read, + &ess_write, + NULL, /* readdir */ + &ess_poll, + &ess_ioctl, + &ess_mmap, + &ess_open, + NULL, /* flush */ + &ess_release, + NULL, /* fsync */ + NULL, /* fasync */ + NULL, /* check_media_change */ + NULL, /* revalidate */ + NULL, /* lock */ +}; + + +/* --------------------------------------------------------------------- */ + +/* maximum number of devices */ +#define NR_DEVICE 4 + +/* --------------------------------------------------------------------- */ + +#if 0 +static struct initvol { + int mixch; + int vol; +} initvol[] __initdata = { + { SOUND_MIXER_WRITE_RECLEV, 0x4040 }, + { SOUND_MIXER_WRITE_LINE1, 0x4040 }, + { SOUND_MIXER_WRITE_CD, 0x4040 }, + { SOUND_MIXER_WRITE_LINE, 0x4040 }, + { SOUND_MIXER_WRITE_MIC, 0x4040 }, + { SOUND_MIXER_WRITE_SYNTH, 0x4040 }, + { SOUND_MIXER_WRITE_LINE2, 0x4040 }, + { SOUND_MIXER_WRITE_VOLUME, 0x4040 }, + { SOUND_MIXER_WRITE_PCM, 0x4040 } +}; + +#endif + +static int maestro_install(struct pci_dev *pcidev, char *name, int index) +{ + u16 w; + u32 n; + int iobase; + int i; + struct ess_card *card; + struct ess_state *ess; + int apu; + int num = 0; + + iobase = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; + + card = kmalloc(sizeof(struct ess_card), GFP_KERNEL); + if(card == NULL) + { + printk(KERN_WARNING "maestro: out of memory\n"); + return 0; + } + + memset(card, 0, sizeof(*card)); + + card->iobase = iobase; + card->irq = pcidev->irq; + card->next = devs; + devs = card; + + for(i=0;i<8;i++) + { + struct ess_state *s=&card->channels[i]; + + s->card = card; + init_waitqueue(&s->dma_adc.wait); + init_waitqueue(&s->dma_dac.wait); + init_waitqueue(&s->open_wait); + s->open_sem = MUTEX; + s->magic = ESS_MAGIC; + + s->apu[0] = 4*i; + s->apu[1] = (4*i)+1; + s->apu[2] = (4*i)+2; + s->apu[3] = (4*i)+3; + + if(s->dma_adc.ready || s->dma_dac.ready || s->dma_adc.rawbuf) + printk("BOTCH!\n"); + /* register devices */ + if ((s->dev_audio = register_sound_dsp(&ess_audio_fops, -1)) < 0) + break; +// if ((s->dev_mixer = register_sound_mixer(&ess_mixer_fops, -1)) < 0) +// break; + } + + num = i; + + for(;i<8;i++) + { + struct ess_state *s=&card->channels[i]; + s->dev_audio = -1; + } + + ess = &card->channels[0]; + + /* + * Ok card ready. Begin setup proper + */ + + printk(KERN_INFO "ess_pci: Configuring %s at 0x%04X\n", name, iobase); + + /* + * Disable ACPI + */ + + pci_write_config_dword(pcidev, 0x54, 0x00000000); + + /* + * Use TDMA for now. TDMA works on all boards, so while its + * not the most efficient its the simplest. + */ + + pci_read_config_word(pcidev, 0x50, &w); + + /* Clear DMA bits */ + w&=~(1<<10|1<<9|1<<8); + + /* TDMA on */ + w|=(1<<8); + + /* + * MPU at 330 + */ + + w&=~((1<<4)|(1<<3)); + + /* + * SB at 0x220 + */ + + w&=~(1<<2); + + /* + * Reserved write as 0 + */ + + w&=~(1<<1); + + /* + * Some of these are undocumented bits + */ + + w&=~(1<<13)|(1<<14); /* PIC Snoop mode bits */ + w&=~(1<<11); /* Safeguard off */ + w|= (1<<7); /* Posted write */ + w|= (1<<6); /* ISA timing on */ + w&=~(1<<1); /* Subtractive decode off */ + w&=~(1<<5); /* Don't swap left/right */ + + pci_write_config_word(pcidev, 0x50, w); + + pci_read_config_word(pcidev, 0x52, &w); + w&=~(1<<15); /* Turn off internal clock multiplier */ + w&=~(1<<14); /* External clock */ + + w&=~(1<<7); /* HWV off */ + w&=~(1<<6); /* Debounce off */ + w&=~(1<<5); /* GPIO 4:5 */ + w&=~(1<<4); /* Disconnect from the CHI */ + w&=~(1<<3); /* IDMA off (undocumented) */ + w&=~(1<<2); /* MIDI fix off (undoc) */ + w&=~(1<<0); /* IRQ to ISA off (undoc) */ + pci_write_config_word(pcidev, 0x52, w); + + /* + * DDMA off + */ + + pci_read_config_word(pcidev, 0x60, &w); + w&=~(1<<0); + pci_write_config_word(pcidev, 0x60, w); + + /* + * Legacy mode + */ + + pci_read_config_word(pcidev, 0x40, &w); + w&=~(1<<15); /* legacy decode on */ + w&=~(1<<14); /* Disable SIRQ */ + w&=~(1<<13|1<<12|1<<11); + + /* + * We don't use the emulation IRQ's + */ + + w|=(1<<11); /* MPU IRQ 7 */ + w&=~(1<<10|1<<9|1<<8); /* SB IRQ 5 */ + w|=(1<<3)|(1<<1)|(1<<0); /* SB on , FM on, MPU on */ + w&=~(1<<7|1<<6); + w|=(1<<6); /* DMA 1 */ + + /* + * Default to DMA 1 + */ + + pci_write_config_word(pcidev, 0x40, w); + + sound_reset(iobase); + + + /* + * Reset the CODEC + */ + + maestro_ac97_reset(iobase); + + /* + * Ring Bus Setup + */ + + n=inl(iobase+0x34); + n&=~0xF000; + n|=12<<12; /* Direct Sound, Stereo */ + + n=inl(iobase+0x34); + n&=~0x0F00; /* Modem off */ + outl(n, iobase+0x34); + + n=inl(iobase+0x34); + n&=~0x00F0; + n|=9<<4; /* DAC, Stereo */ + outl(n, iobase+0x34); + + n=inl(iobase+0x34); + n&=~0x000F; /* ASSP off */ + outl(n, iobase+0x34); + + + n=inl(iobase+0x34); + n|=(1<<29); /* Enable ring bus */ + outl(n, iobase+0x34); + + + n=inl(iobase+0x34); + n|=(1<<28); /* Enable serial bus */ + outl(n, iobase+0x34); + + n=inl(iobase+0x34); + n&=~0x00F00000; /* MIC off */ + outl(n, iobase+0x34); + + n=inl(iobase+0x34); + n&=~0x000F0000; /* I2S off */ + outl(n, iobase+0x34); + + w=inw(iobase+0x18); + w&=~(1<<7); /* ClkRun off */ + outw(w, iobase+0x18); + + w=inw(iobase+0x18); + w&=~(1<<6); /* Harpo off */ + outw(w, iobase+0x18); + + w=inw(iobase+0x18); + w&=~(1<<4); /* ASSP irq off */ + outw(w, iobase+0x18); + + w=inw(iobase+0x18); + w&=~(1<<3); /* ISDN irq off */ + outw(w, iobase+0x18); + + w=inw(iobase+0x18); + w|=(1<<2); /* Direct Sound IRQ on */ + outw(w, iobase+0x18); + + w=inw(iobase+0x18); + w&=~(1<<1); /* MPU401 IRQ off */ + outw(w, iobase+0x18); + + w=inw(iobase+0x18); + w|=(1<<0); /* SB IRQ on */ + outw(w, iobase+0x18); + + + outb(0, iobase+0xA4); + outb(3, iobase+0xA2); + outb(0, iobase+0xA6); + + for(apu=0;apu<16;apu++) + { + /* Write 0 into the buffer area 0x1E0->1EF */ + outw(0x01E0+apu, 0x10+iobase); + outw(0x0000, 0x12+iobase); + + /* + * The 1.10 test program seem to write 0 into the buffer area + * 0x1D0-0x1DF too. + */ + outw(0x01D0+apu, 0x10+iobase); + outw(0x0000, 0x12+iobase); + } + +#if 1 + wave_set_register(ess, IDR7_WAVE_ROMRAM, + (wave_get_register(ess, IDR7_WAVE_ROMRAM)&0xFF00)); + wave_set_register(ess, IDR7_WAVE_ROMRAM, + wave_get_register(ess, IDR7_WAVE_ROMRAM)|0x100); + wave_set_register(ess, IDR7_WAVE_ROMRAM, + wave_get_register(ess, IDR7_WAVE_ROMRAM)&~0x200); + wave_set_register(ess, IDR7_WAVE_ROMRAM, + wave_get_register(ess, IDR7_WAVE_ROMRAM)|~0x400); +#else + maestro_write(ess, IDR7_WAVE_ROMRAM, + (maestro_read(ess, IDR7_WAVE_ROMRAM)&0xFF00)); + maestro_write(ess, IDR7_WAVE_ROMRAM, + maestro_read(ess, IDR7_WAVE_ROMRAM)|0x100); + maestro_write(ess, IDR7_WAVE_ROMRAM, + maestro_read(ess, IDR7_WAVE_ROMRAM)&~0x200); + maestro_write(ess, IDR7_WAVE_ROMRAM, + maestro_read(ess, IDR7_WAVE_ROMRAM)|0x400); +#endif + + maestro_write(ess, IDR2_CRAM_DATA, 0x0000); + maestro_write(ess, 0x08, 0xB004); + /* Now back to the DirectSound stuff */ + maestro_write(ess, 0x09, 0x001B); + maestro_write(ess, 0x0A, 0x8000); + maestro_write(ess, 0x0B, 0x3F37); + maestro_write(ess, 0x0C, 0x0098); + + maestro_write(ess, 0x0C, + (maestro_read(ess, 0x0C)&~0xF000)|0x8000); + maestro_write(ess, 0x0C, + (maestro_read(ess, 0x0C)&~0x0F00)|0x0500); + + maestro_write(ess, 0x0D, 0x7632); + + /* Wave cache control on - test off, sg off, + enable, enable extra chans 1Mb */ + + outw(inw(0x14+iobase)|(1<<8),0x14+iobase); + outw(inw(0x14+iobase)&0xFE03,0x14+iobase); + outw((inw(0x14+iobase)&0xFFFC), 0x14+iobase); + outw(inw(0x14+iobase)|(1<<7),0x14+iobase); + + outw(0xA1A0, 0x14+iobase); /* 0300 ? */ + + if(maestro_ac97_get(iobase, 0x00)==0x0080) + { + printk(KERN_INFO "ess_pci: PT101 Codec detected\n"); + maestro_pt101_init(iobase); + } + else + { + printk(KERN_INFO "ess_pci: AC97 Codec detected\n"); + maestro_ac97_init(iobase); + } + + /* Now clear the channel data */ + for(apu=0;apu<64;apu++) + { + for(w=0;w<0x0E;w++) + apu_set_register(ess, apu|ESS_CHAN_HARD, w, 0); + } + + + /* Now we program up the APU's */ + + /* + * APU 6 is the mixer + */ + + apu_set_register(ess, 6|ESS_CHAN_HARD, 0, + apu_get_register(ess, 6|ESS_CHAN_HARD, 0)&~(1<<14)); + apu_set_register(ess, 6|ESS_CHAN_HARD, 0, + apu_get_register(ess, 6|ESS_CHAN_HARD, 0)&~(1<<13)); + apu_set_register(ess, 6|ESS_CHAN_HARD, 0, + apu_get_register(ess, 6|ESS_CHAN_HARD, 0)&~(1<<12)); + apu_set_register(ess, 6|ESS_CHAN_HARD, 0, + apu_get_register(ess, 6|ESS_CHAN_HARD, 0)&0xFCFF); + apu_set_register(ess, 6|ESS_CHAN_HARD, 0, + apu_get_register(ess, 6|ESS_CHAN_HARD, 0)&0xF3FF); + apu_set_register(ess, 6|ESS_CHAN_HARD, 0, + (apu_get_register(ess, 6|ESS_CHAN_HARD, 0)&0xFFF0)|0x0F); + apu_set_register(ess, 6|ESS_CHAN_HARD, 2, + apu_get_register(ess, 6|ESS_CHAN_HARD, 2)&0x00FF); + apu_set_register(ess, 6|ESS_CHAN_HARD, 3, 0x0000); + apu_set_register(ess, 6|ESS_CHAN_HARD, 2, + apu_get_register(ess, 6|ESS_CHAN_HARD, 2)&0xFF3F); + apu_set_register(ess, 6|ESS_CHAN_HARD, 2, + apu_get_register(ess, 6|ESS_CHAN_HARD, 2)|(1<<5)); + apu_set_register(ess, 6|ESS_CHAN_HARD, 2, + apu_get_register(ess, 6|ESS_CHAN_HARD, 2)&~(1<<4)); + apu_set_register(ess, 6|ESS_CHAN_HARD, 2, + apu_get_register(ess, 6|ESS_CHAN_HARD, 2)&0xFFF0); + apu_set_register(ess, 6|ESS_CHAN_HARD, 4, 0x4B5F); + apu_set_register(ess, 6|ESS_CHAN_HARD, 5, 0xFDD5); + apu_set_register(ess, 6|ESS_CHAN_HARD, 6, 0xFE00); + apu_set_register(ess, 6|ESS_CHAN_HARD, 7, 0x0100); + apu_set_register(ess, 6|ESS_CHAN_HARD, 8, 0x78FF); + apu_set_register(ess, 6|ESS_CHAN_HARD, 9, 0xFFFF); + apu_set_register(ess, 6|ESS_CHAN_HARD, 0xA,0x8A10); + apu_set_register(ess, 6|ESS_CHAN_HARD, 0xB,0x8009); + + /* + * APU 62 - Right channel DSP + */ + + apu_set_register(ess, 62|ESS_CHAN_HARD, 0, + apu_get_register(ess, 62|ESS_CHAN_HARD, 0)&~(1<<14)); + apu_set_register(ess, 62|ESS_CHAN_HARD, 0, + apu_get_register(ess, 62|ESS_CHAN_HARD, 0)&~(1<<13)); + apu_set_register(ess, 62|ESS_CHAN_HARD, 0, + apu_get_register(ess, 62|ESS_CHAN_HARD, 0)&~(1<<12)); + apu_set_register(ess, 62|ESS_CHAN_HARD, 0, + apu_get_register(ess, 62|ESS_CHAN_HARD, 0)&0xFCFF); + apu_set_register(ess, 62|ESS_CHAN_HARD, 0, + apu_get_register(ess, 62|ESS_CHAN_HARD, 0)&0xF3FF); + apu_set_register(ess, 62|ESS_CHAN_HARD, 0, + (apu_get_register(ess, 62|ESS_CHAN_HARD, 0)&0xFFF0)|0x0F); + apu_set_register(ess, 62|ESS_CHAN_HARD, 2, + apu_get_register(ess, 62|ESS_CHAN_HARD, 2)&0x00FF); + apu_set_register(ess, 62|ESS_CHAN_HARD, 3, 0x1000); + apu_set_register(ess, 62|ESS_CHAN_HARD, 2, + apu_get_register(ess, 62|ESS_CHAN_HARD, 2)&0xFF3F); + apu_set_register(ess, 62|ESS_CHAN_HARD, 2, + apu_get_register(ess, 62|ESS_CHAN_HARD, 2)&~(1<<5)); + apu_set_register(ess, 62|ESS_CHAN_HARD, 2, + apu_get_register(ess, 62|ESS_CHAN_HARD, 2)&~(1<<4)); + apu_set_register(ess, 62|ESS_CHAN_HARD, 2, + apu_get_register(ess, 62|ESS_CHAN_HARD, 2)&0xFFF0); + apu_set_register(ess, 62|ESS_CHAN_HARD, 4, 0x7F00); + apu_set_register(ess, 62|ESS_CHAN_HARD, 5, 0x8000); + apu_set_register(ess, 62|ESS_CHAN_HARD, 6, 0x8080); + apu_set_register(ess, 62|ESS_CHAN_HARD, 7, 0x0080); + apu_set_register(ess, 62|ESS_CHAN_HARD, 8, 0x7F00); + apu_set_register(ess, 62|ESS_CHAN_HARD, 9, 0xFFFF); + apu_set_register(ess, 62|ESS_CHAN_HARD, 0xA,0x7F00); + apu_set_register(ess, 62|ESS_CHAN_HARD, 0xB,0x00F0); + + /* + * APU 63 - Left channel DSP + */ + + apu_set_register(ess, 63|ESS_CHAN_HARD, 0, + apu_get_register(ess, 63|ESS_CHAN_HARD, 0)&~(1<<14)); + apu_set_register(ess, 63|ESS_CHAN_HARD, 0, + apu_get_register(ess, 63|ESS_CHAN_HARD, 0)&~(1<<13)); + apu_set_register(ess, 63|ESS_CHAN_HARD, 0, + apu_get_register(ess, 63|ESS_CHAN_HARD, 0)&~(1<<12)); + apu_set_register(ess, 63|ESS_CHAN_HARD, 0, + apu_get_register(ess, 63|ESS_CHAN_HARD, 0)&0xFCFF); + apu_set_register(ess, 63|ESS_CHAN_HARD, 0, + apu_get_register(ess, 63|ESS_CHAN_HARD, 0)&0xF3FF); + apu_set_register(ess, 63|ESS_CHAN_HARD, 0, + (apu_get_register(ess, 63|ESS_CHAN_HARD, 0)&0xFFF0)|0x0F); + apu_set_register(ess, 63|ESS_CHAN_HARD, 2, + apu_get_register(ess, 63|ESS_CHAN_HARD, 2)&0x00FF); + apu_set_register(ess, 63|ESS_CHAN_HARD, 3, 0x1000); + apu_set_register(ess, 63|ESS_CHAN_HARD, 2, + apu_get_register(ess, 63|ESS_CHAN_HARD, 2)&0xFF3F); + apu_set_register(ess, 63|ESS_CHAN_HARD, 2, + apu_get_register(ess, 63|ESS_CHAN_HARD, 2)&~(1<<5)); + apu_set_register(ess, 63|ESS_CHAN_HARD, 2, + apu_get_register(ess, 63|ESS_CHAN_HARD, 2)&~(1<<4)); + apu_set_register(ess, 63|ESS_CHAN_HARD, 2, + apu_get_register(ess, 63|ESS_CHAN_HARD, 2)&0xFFF0); + apu_set_register(ess, 63|ESS_CHAN_HARD, 4, 0x7F00); + apu_set_register(ess, 63|ESS_CHAN_HARD, 5, 0x0000); + apu_set_register(ess, 63|ESS_CHAN_HARD, 6, 0x0080); + apu_set_register(ess, 63|ESS_CHAN_HARD, 7, 0x0080); + apu_set_register(ess, 63|ESS_CHAN_HARD, 8, 0x7F00); + apu_set_register(ess, 63|ESS_CHAN_HARD, 9, 0xFFFF); + apu_set_register(ess, 63|ESS_CHAN_HARD, 0xA,0x7F10); + apu_set_register(ess, 63|ESS_CHAN_HARD, 0xB,0x00F0); + + apu_set_register(ess, 6|ESS_CHAN_HARD, 0, + (apu_get_register(ess, 6|ESS_CHAN_HARD, 0)&0xFF0F)|(9<<4)); + + udelay(30); + + apu_set_register(ess, 62|ESS_CHAN_HARD, 0, + (apu_get_register(ess,6|ESS_CHAN_HARD, 0)&0xFF0F)|(1<<4)); + apu_set_register(ess, 63|ESS_CHAN_HARD, 0, + (apu_get_register(ess,6|ESS_CHAN_HARD, 0)&0xFF0F)|(1<<4)); + + + load_tables(iobase); + + udelay(1); + + + if(request_irq(card->irq, ess_interrupt, SA_SHIRQ, name, card)) + { + printk(KERN_ERR "ess_maestro: unable to allocate irq %d,\n", card->irq); + return 0; + } + + ess_play_test(ess); + printk("ess_maestro: %d channels configured.\n", num); + return 1; +} + +#ifdef MODULE + +__initfunc(int init_module(void)) +#else +__initfunc(int init_maestro(void)) +#endif +{ + struct pci_dev *pcidev = NULL; + int index = 0; + + if (!pci_present()) /* No PCI bus in this machine! */ + return -ENODEV; + printk(KERN_INFO "maestro: version v0.01 time " __TIME__ " " __DATE__ "\n"); + + pcidev = NULL; + + /* + * Find the ESS Maestro 2. + */ + + while((pcidev = pci_find_device(PCI_VENDOR_ESS, PCI_DEVICE_ID_ESS_ESS1968, pcidev))!=NULL) + { + index+=maestro_install(pcidev, "ESS Maestro 2", index); + if(index == NR_DEVICE) + return index; + } + + /* + * Find the ESS Maestro 2E + */ + + while((pcidev = pci_find_device(PCI_VENDOR_ESS, PCI_DEVICE_ID_ESS_ESS1978, pcidev))!=NULL) + { + index+=maestro_install(pcidev, "ESS Maestro 2E", index); +// printk(KERN_INFO "ESS Maestro 2E not yet supported.\n"); + if(index == NR_DEVICE) + return index; + } + + /* + * ESS Maestro 1 + */ + + while((pcidev = pci_find_device(0x1285, 0x100, pcidev))!=NULL) + { + index+=maestro_install(pcidev, "ESS Maestro", index); + if(index == NR_DEVICE) + return index; + } + if(index==0) + return -ENODEV; + return 0;; +} + +/* --------------------------------------------------------------------- */ + +#ifdef MODULE + +MODULE_AUTHOR("Alan Cox "); +MODULE_DESCRIPTION("ESS Maestro Driver"); + +void cleanup_module(void) +{ + struct ess_card *s; + + while ((s = devs)) { + int i; + devs = devs->next; +// ess_play_test(&s->channels[0]); + kill_bob(&s->channels[0]); +// outb(~0, s->ioenh + SV_CODEC_INTMASK); /* disable ints */ +// synchronize_irq(); +// inb(s->ioenh + SV_CODEC_STATUS); /* ack interrupts */ +// wrindir(s, SV_CIENABLE, 0); /* disable DMAA and DMAC */ + //outb(0, s->iodmaa + SV_DMA_RESET); + //outb(0, s->iodmac + SV_DMA_RESET); + free_irq(s->irq, s); +// unregister_sound_mixer(s->dev_mixer); + for(i=0;i<8;i++) + { + struct ess_state *ess = &s->channels[i]; + if(ess->dev_audio != -1) + unregister_sound_dsp(ess->dev_audio); + } + kfree(s); + } + printk(KERN_INFO "maestro: unloading\n"); +} + +#endif /* MODULE */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/maestro.h linux.ac/drivers/sound/maestro.h --- linux.vanilla/drivers/sound/maestro.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/sound/maestro.h Fri Jun 4 23:52:44 1999 @@ -0,0 +1,60 @@ +/* + * Registers for the ESS PCI cards + */ + +/* + * Memory access + */ + +#define ESS_MEM_DATA 0x00 +#define ESS_MEM_INDEX 0x02 + +/* + * AC-97 Codec port. Delay 1uS after each write. This is used to + * talk AC-97 (see intel.com). Write data then register. + */ + +#define ESS_AC97_INDEX 0x30 /* byte wide */ +#define ESS_AC97_DATA 0x32 + +/* + * Reading is a bit different. You write register|0x80 to ubdex + * delay 1uS poll the low bit of index, when it clears read the + * data value. + */ + +/* + * Control port. Not yet fully understood + * The value 0xC090 gets loaded to it then 0x0000 and 0x2800 + * to the data port. Then after 4uS the value 0x300 is written + */ + +#define RING_BUS_CTRL_L 0x34 +#define RING_BUS_CTRL_H 0x36 + +/* + * This is also used during setup. The value 0x17 is written to it + */ + +#define ESS_SETUP_18 0x18 + +/* + * And this one gets 0x000b + */ + +#define ESS_SETUP_A2 0xA2 + +/* + * And this 0x0000 + */ + +#define ESS_SETUP_A4 0xA4 +#define ESS_SETUP_A6 0xA6 + +/* + * Stuff to do with Harpo - the wave stuff + */ + +#define ESS_WAVETABLE_SIZE 0x14 +#define ESS_WAVETABLE_2M 0xA180 + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/maestro_tables.h linux.ac/drivers/sound/maestro_tables.h --- linux.vanilla/drivers/sound/maestro_tables.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/sound/maestro_tables.h Fri Jun 4 23:52:44 1999 @@ -0,0 +1,333 @@ +/* + * Set up data block for the ESS soundblaster emulation. This is like + * the example code from ftp.esstech.com.tw (104T31.ZIP) + */ + +u16 asp_block_0[]= { + 0x7980, 0x003a, 0x7980, 0x007d, 0xbe3a, 0x8b00, 0xbe3a, 0x8b00, + 0xbe3a, 0x8b00, 0xbe3a, 0x8b00, 0xbe3a, 0x8b00, 0xbe3a, 0x8b00, + 0x7980, 0x0be6, 0x7980, 0x0069, 0xbe3a, 0x8b00, 0x8048, 0x6945, + 0xb801, 0x9045, 0x6941, 0xe388, 0x0031, 0x6944, 0xba50, 0xe38c, + 0x0031, 0x8b88, 0x6942, 0x304a, 0xe308, 0x0028, 0x6949, 0x9042, + 0x0042, 0xafa0, 0x8000, 0xafa0, 0x8000, 0x8042, 0x6944, 0xb801, + 0x9044, 0x0048, 0xbe3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0xbe41, 0xbf80, 0x0101, 0x8806, 0x8804, 0xb912, + 0x8807, 0xbc26, 0xbe40, 0xb92f, 0x9001, 0x9002, 0x003b, 0x0122, + 0x7a88, 0x0055, 0x003a, 0x013c, 0x7a88, 0x0055, 0x4902, 0xe100, + 0x0800, 0x0c02, 0xa000, 0x7980, 0x004e, 0xb908, 0x8809, 0xbec6, + 0x0067, 0x4a80, 0xe200, 0x0065, 0x4880, 0xe200, 0x0063, 0xb97f, + 0x6e80, 0x7980, 0x0066, 0x1089, 0x9088, 0xb900, 0x90a9, 0x8ba8, + 0xef00, 0x803d, 0x0003, 0x1007, 0x881f, 0x8b88, 0xbb0f, 0xada0, + 0x0810, 0x9003, 0x4903, 0xe200, 0x007b, 0x9002, 0x6a05, 0x6d04, + 0x9803, 0x9804, 0x9005, 0x003d, 0xbe3a, 0xaf06, 0x0000, 0x803d, + 0x8b88, 0x6906, 0x8810, 0xaf06, 0x0001, 0xbfb0, 0x00ff, 0xbaf5, + 0xe3cc, 0x009a, 0x5e06, 0x003f, 0xbf80, 0x0080, 0x4a06, 0xe200, + 0x0095, 0x6e80, 0x6d06, 0x7980, 0x009b, 0x9080, 0x0810, 0xba46, + 0x8810, 0x8b00, 0x1006, 0x9080, 0x003d, 0xbe3a, 0x1024, 0x2009, + 0x8810, 0x8b88, 0x8b00, 0x1089, 0xbfb0, 0x000e, 0xbe0a, 0x880d, + 0x903e, 0x1038, 0x2008, 0x8810, 0x1037, 0x2008, 0x8811, 0x5f3e, + 0x0000, 0x8b00, 0xf500, 0x5e80, 0xfffe, 0x1039, 0x2008, 0x8815, + 0x8b8d, 0x0231, 0x0333, 0x108a, 0x90ad, 0x1025, 0x200a, 0x8815, + 0x0605, 0xb91f, 0x8809, 0x4f16, 0x1080, 0xf600, 0xbfb0, + 0x0003, 0xbfb0, 0x0007, 0x9089, 0xbe47, 0xbe43, 0xbec6, + 0x00f6, 0x4f8b, 0x14a8, 0xe500, 0x6380, 0x8b89, 0x4e8a, + 0xbfe3, 0xe500, 0x2480, 0xbe46, 0x8b9d, 0xbfe7, 0xbfb0, + 0x00ff, 0x288c, 0x2026, 0x8814, 0xbe47, 0x8b00, 0x738f, + 0x54aa, 0xbe03, 0xbe0a, 0x2fa8, 0x988a, 0x8da9, 0xbe03, + 0x4d8e, 0xbfe1, 0xf500, 0x6180, 0x9880, 0x8ba9, 0xbe03, + 0x4c8e, 0xbfe1, 0xf500, 0x6180, 0x9880, 0x8ba9, 0xbe42, + 0x1039, 0x2008, 0x8815, 0x8b8d, 0x8b00, 0x8d8a, 0x7980, + 0x0bcf}; + +u16 asp_block_1[]={ + 0x0005, 0xb900, 0x9008, 0x9009, 0x900a, 0xbb3f, 0x90a0, + 0x001a, 0x011b, 0x021c, 0x0323, 0x1089, 0x9015, 0x108a, + 0x9016, 0x108b, 0x9017, 0x1088, 0x9018, 0x0137, 0x0524, + 0x8b8d, 0x4f16, 0xe200, 0x0827, 0x4f15, 0xe200, 0x0827, + 0x7a80, 0x08e6, 0x102c, 0xb802, 0x8813, 0x8b8b, 0xb900, + 0x90a0, 0x908d, 0x7980, 0x0833, 0x7a80, 0x0913, 0x7803, + 0x7a80, 0x0913, 0x102c, 0xb802, 0x8813, 0x8b8b, 0xb903, + 0x90a0, 0x908d, 0x7c02, 0x4f16, 0xe200, 0x0845, 0x4e15, + 0xe200, 0x0845, 0x7a80, 0x08e6, 0x102c, 0xb806, 0x8813, + 0x8b8b, 0xb901, 0x90a0, 0x908d, 0x7980, 0x0851, 0x7a80, + 0x0913, 0x7803, 0x7a80, 0x0913, 0x102c, 0xb806, 0x8813, + 0x8b8b, 0xb904, 0x90a0, 0x908d, 0x7c02, 0x4f16, 0xe200, + 0x0863, 0x4d15, 0xe200, 0x0863, 0x7a80, 0x08e6, 0x102c, + 0xb80a, 0x8813, 0x8b8b, 0xb902, 0x90a0, 0x908d, 0x7980, + 0x086f, 0x7a80, 0x0913, 0x7803, 0x7a80, 0x0913, 0x102c, + 0xb80a, 0x8813, 0x8b8b, 0xb905, 0x90a0, 0x908d, 0x7801, + 0x7a80, 0x0913, 0x7801, 0x7a80, 0x0913, 0x7801, 0x7a80, + 0x0913, 0x1024, 0xbf90, 0x0100, 0x8815, 0x4f16, 0xe200, + 0x088e, 0x4c15, 0xe200, 0x088e, 0x7a80, 0x08e6, 0x102c, + 0xb814, 0x8813, 0x8b8b, 0xbf80, 0x0100, 0x90a0, 0x908d, + 0x7980, 0x089b, 0x7a80, 0x0913, 0x7803, 0x7a80, 0x0913, + 0x102c, 0xb814, 0x8813, 0x8b8b, 0xbf80, 0x0103, 0x90a0, + 0x908d, 0x7c02, 0x4f16, 0xe200, 0x08ae, 0x4b15, 0xe200, + 0x08ae, 0x7a80, 0x08e6, 0x102c, 0xb818, 0x8813, 0x8b8b, + 0xbf80, 0x0101, 0x90a0, 0x908d, 0x7980, 0x08bb, 0x7a80, + 0x0913, 0x7803, 0x7a80, 0x0913, 0x102c, 0xb818, 0x8813, + 0x8b8b, 0xbf80, 0x0104, 0x90a0, 0x908d, 0x7c02, 0x4f16, + 0xe200, 0x08ce, 0x4a15, 0xe200, 0x08ce, 0x7a80, 0x08e6, + 0x102c, 0xb81c, 0x8813, 0x8b8b, 0xbf80, 0x0102, 0x90a0, + 0x908d, 0x7980, 0x08db, 0x7a80, 0x0913, 0x7803, 0x7a80, + 0x0913, 0x102c, 0xb81c, 0x8813, 0x8b8b, 0xbf80, 0x0105, + 0x90a0, 0x908d, 0x7801, 0x7a80, 0x0913, 0x7801, 0x7a80, + 0x0913, 0x7801, 0x7a80, 0x0913, 0x7980, 0x0920, 0x4f80, + 0x7803, 0xe100, 0x08fe, 0x4f89, 0xe100, 0x08f5, 0xb901, + 0x90a0, 0xb902, 0x90a0, 0x90a0, 0xb906, 0x90ad, 0xef00, + 0xb901, 0x90a0, 0xb906, 0x90a0, 0xb900, 0x90a0, 0xb906, + 0x90ad, 0xef00, 0x4f89, 0xe100, 0x090a, 0xb905, 0x90a0, + 0xb900, 0x90a0, 0xb902, 0x90a0, 0xb906, 0x90ad, 0xef00, + 0xb905, 0x90a0, 0xb900, 0x90a0, 0xb906, 0x90a0, 0xb904, + 0x90ad, 0xef00, 0x4f89, 0xe100, 0x091b, 0xb901, 0x90a0, + 0xb906, 0x90ad, 0xef00, 0xb905, 0x90a0, 0xb904, 0x90ad, + 0xef00, 0xb91f, 0x8809, 0x0034, 0x8b88, 0xbec6, 0x0932, + 0x1313, 0xbe1e, 0x1014, 0xbe1a, 0xbe01, 0xbfe8, 0xbe17, + 0x6a13, 0x6214, 0xbe14, 0x9813, 0x9014, 0x98a0, 0xbe47, + 0x5f0f, 0x002e, 0xe200, 0x093d, 0xbf80, 0xffd2, 0x900f, + 0x7980, 0x0940, 0x100f, 0xb801, 0x900f, 0x400f, 0x8b00, + 0xe500, 0xbe01, 0xbe09, 0x9010, 0xbe46, 0x5f11, 0x003f, + 0xe200, 0x094f, 0xb900, 0x9011, 0x7980, 0x0952, 0x1011, + 0xb801, 0x9011, 0x1001, 0xe388, 0x0bcf, 0x1021, 0x2009, + 0x8813, 0x8b8b, 0x8b00, 0x1080, 0xbfe6, 0x7810, 0x8b00, + 0x8b00, 0x2180, 0xbfb0, 0x0007, 0x4c11, 0x8b00, 0xe100, + 0x096c, 0x4b11, 0x8b00, 0xe600, 0xb900, 0x7980, 0x096d, + 0xbe0a, 0x4a11, 0x8b00, 0xe500, 0xbe01, 0x9012, 0x1037, + 0x2008, 0x8811, 0x102e, 0x2008, 0x8812, 0x4a89, 0xb901, + 0xe500, 0x9019, 0xe100, 0x09c9, 0xb900, 0x9019, 0x4a18, + 0xe200, 0x09c9, 0x5f0a, 0x0010, 0xe200, 0x098d, 0x4b18, + 0xb901, 0xe500, 0x9019, 0x7980, 0x09c9, 0x5f0a, 0x0013, + 0xe200, 0x0997, 0x4b18, 0xb901, 0xe500, 0x9019, 0x7980, + 0x09c9, 0x5f0a, 0x0011, 0xe200, 0x09a4, 0x4f18, 0xb905, + 0xe500, 0x9080, 0xb901, 0xe500, 0x9019, 0x7980, 0x09c9, + 0x5f0a, 0x0014, 0xe200, 0x09b1, 0x4c18, 0xb904, 0xe500, + 0x9080, 0xb901, 0xe500, 0x9019, 0x7980, 0x09c9, 0x5f0a, + 0x0012, 0xe200, 0x09be, 0x4d18, 0xb905, 0xe500, 0x9080, + 0xb901, 0xe500, 0x9019, 0x7980, 0x09c9, 0x5f0a, 0x0015, + 0xe200, 0x09c9, 0x4e18, 0xb904, 0xe500, 0x9080, 0xb901, + 0xe500, 0x9019, 0x8b8a, 0x4f19, 0xe200, 0x09d4, 0x4b80, + 0xe200, 0x09d6, 0x5d80, 0x0020, 0x7980, 0x09d9, 0x5d80, + 0x0010, 0x4a80, 0xe200, 0x0bca, 0x1001, 0xba01, 0x9001, + 0x1024, 0x2009, 0x8815, 0x8b89, 0x4d8d, 0xe200, 0x09f8, + 0x4f16, 0xe100, 0x09ed, 0x8b89, 0x1080, 0xbfc0, 0x000c, + 0x908c, 0x7980, 0x09f8, 0x4b89, 0x108d, 0xf600, 0xbfb0, + 0x0003, 0x4a89, 0x8b00, 0xf500, 0xbfc0, 0x0008, 0x908c, + 0x1022, 0x2009, 0x8811, 0x102e, 0x2008, 0x8812, 0x102f, + 0x2008, 0x8813, 0x1020, 0x200a, 0x8814, 0x101d, 0x200a, + 0x8815, 0x8b8a, 0x4f19, 0xe100, 0x0a11, 0x5e80, 0x0020, + 0x5d80, 0x0018, 0x7980, 0x0a3e, 0x4f80, 0xe200, 0x0a1e, + 0x8b8b, 0x108a, 0xbfa0, 0x7fc0, 0x8b00, 0xf704, 0x5c80, + 0x0003, 0x7980, 0x0a3e, 0x4e80, 0xe200, 0x0a36, 0x8b8c, + 0x178b, 0xbe01, 0xbfb7, 0x00f0, 0x308a, 0xe344, 0x0a3e, + 0x8b8d, 0x4a8a, 0x8b00, 0xe200, 0x0a32, 0x5c80, 0x0006, + 0x7980, 0x0a3e, 0x5c80, 0x000a, 0x7980, 0x0a3e, 0x4c80, + 0xe200, 0x0a3e, 0x4b80, 0x8b00, 0xf500, 0x5c80, 0x0019, + 0x4f80, 0xe200, 0x0a4d, 0x101f, 0x200a, 0x8816, 0x8b00, + 0x8b00, 0x8b8e, 0x1780, 0xbfb7, 0x00f0, 0x900b, 0x7980, + 0x0a64, 0x4e80, 0xe200, 0x0a5c, 0x101f, 0x200a, 0x8816, + 0x8b00, 0x8b00, 0x8b8e, 0x1b80, 0xbfbb, 0x000f, 0x900b, + 0x7980, 0x0a64, 0x4c80, 0xe200, 0x0a64, 0x8b8c, 0x1b80, + 0xbfbb, 0x000f, 0x900b, 0x8b89, 0x1880, 0xbfb8, 0x001c, + 0x4917, 0xe100, 0x0a6e, 0x4f80, 0x7980, 0x0a70, 0x4e80, + 0x8b00, 0xf500, 0xbf98, 0x0002, 0x8b8d, 0x4b89, 0x8b00, + 0xe600, 0xbfe1, 0x903e, 0xbe43, 0x6a0b, 0x613e, 0xbfe8, + 0x980c, 0xbe42, 0x7c10, 0x1080, 0xbfe5, 0xbe1e, 0x7810, + 0x1280, 0xbfb2, 0x001f, 0xbe11, 0x2027, 0x8811, 0x101e, + 0x200a, 0x8816, 0x8b00, 0x128e, 0x4980, 0xe100, 0x0a9b, + 0x4880, 0xe100, 0x0a98, 0xb900, 0x7980, 0x0a9f, 0xbe0a, + 0x7980, 0x0a9f, 0x4880, 0xe200, 0x0a9f, 0xbe09, 0xbe1e, + 0x158d, 0xbfb5, 0x003f, 0xbe11, 0x4889, 0xe200, 0x0aae, + 0xbe1e, 0x1010, 0x4818, 0x8b00, 0xe600, 0xbfe1, 0xbe11, + 0xbfe1, 0x8811, 0xbe1e, 0xb9ff, 0x8819, 0x8b00, 0x8b00, + 0xbf46, 0x8b00, 0xe600, 0xbe1f, 0xbe01, 0xbfb0, 0x00ff, + 0x202a, 0x8811, 0x8b00, 0x8b00, 0x108a, 0x900d, 0xb91f, + 0x8809, 0x0732, 0x730d, 0x4f80, 0xe200, 0x0ad8, 0x1028, + 0x200c, 0x8815, 0xbe43, 0x8b8b, 0x6a8d, 0xbec6, 0x0ad4, + 0x618b, 0x9880, 0x548f, 0x8dad, 0xbe42, 0x7980, 0x0b24, + 0x4e80, 0xe200, 0x0af9, 0x8b8c, 0x178b, 0xbe01, 0xbfb7, + 0x00f0, 0x903e, 0x1029, 0x200c, 0x8815, 0x108d, 0xbec6, + 0x0af6, 0x308b, 0xbe1e, 0x303e, 0x903f, 0x403f, 0xbe1f, + 0xe500, 0x103e, 0x9080, 0xbfe6, 0x202a, 0x8811, 0x8b00, + 0x1089, 0x548f, 0x8dad, 0x7980, 0x0b24, 0x4c8b, 0xe200, + 0x0b1b, 0x1029, 0x200c, 0x8815, 0xbf80, 0x007f, 0x903e, + 0x108d, 0xbec6, 0x0b14, 0x308b, 0xbe1e, 0x303e, 0x903f, + 0x403f, 0xbe1f, 0xe500, 0xb900, 0x9080, 0xbfe6, 0x202a, + 0x8811, 0x8b00, 0x1089, 0x548f, 0x8dad, 0x8b8a, 0xf500, + 0x5e80, 0xffdf, 0x7980, 0x0b24, 0x1089, 0xbfe6, 0x202a, + 0x8811, 0x8b00, 0x8b00, 0x548f, 0xbb1f, 0x8da0, 0x8b8f, + 0x0732, 0x1021, 0x2009, 0x8811, 0x8b89, 0x101d, 0x200a, + 0x8812, 0x1080, 0x7810, 0x8b00, 0xbe47, 0x288a, 0xbfb0, + 0x03ff, 0x4989, 0xe200, 0x0b3e, 0xbe1e, 0x1012, 0x4918, + 0x8b00, 0xe600, 0xbe0a, 0xbe11, 0x900e, 0xbe46, 0x108a, + 0xbfb0, 0x001c, 0xbfe1, 0x880d, 0x8b00, 0x6b0e, 0xbe0a, + 0x880c, 0x108c, 0xbfb0, 0x000f, 0x202d, 0x8814, 0x8b00, + 0x8b00, 0x5589, 0xbf03, 0x8c0e, 0xbf00, 0x1030, 0x2008, + 0x8811, 0xb91f, 0x8809, 0x108b, 0x0333, 0xbec6, 0x0b5f, + 0x200e, 0x90a0, 0x8b00, 0x8b89, 0x9080, 0x4a18, 0xe200, + 0x0b7a, 0x5f0a, 0x0011, 0xe200, 0x0b6c, 0x4f18, 0xe900, + 0x0b7c, 0x5f0a, 0x0014, 0xe200, 0x0b73, 0x4c18, 0xe900, + 0x0b9b, 0x5f0a, 0x0015, 0xe200, 0x0b7a, 0x4e18, 0xe900, + 0x0bb2, 0x7980, 0x009e, 0x0034, 0xb91f, 0x8809, 0x0333, + 0x8b8b, 0xbec6, 0x0b99, 0x1280, 0x6c80, 0xbfea, 0xbe1e, + 0x1580, 0x6c88, 0xbfec, 0xbe13, 0x903e, 0x6cab, 0x903f, + 0x4f3e, 0xb900, 0xf500, 0xbf80, 0x8000, 0x4f3f, 0xbf90, + 0x0d00, 0xf500, 0xbf90, 0x2700, 0x90a0, 0xef00, 0x0034, + 0xb91f, 0x8809, 0x0333, 0x8b88, 0xbec6, 0x0bb0, 0x1eab, + 0x6c80, 0xbfed, 0x903e, 0x4180, 0xb900, 0xf500, 0xbf80, + 0x8000, 0x4f3e, 0x8b00, 0xf500, 0xbf90, 0x4000, 0x90a8, + 0xef00, 0x0034, 0xb91f, 0x8809, 0x0333, 0x8b8b, 0xbec6, + 0x0bc8, 0x1280, 0x6c8b, 0xbfea, 0xbe1e, 0x1580, 0x6c80, + 0xbfec, 0xbe13, 0x903e, 0x4f3e, 0xbf80, 0x4000, 0xf500, + 0xbf90, 0x8000, 0x90a0, 0xef00, 0x0231, 0x8b8a, 0xb900, + 0xbb20, 0x90a0, 0x5f08, 0x0023, 0xe100, 0x0043, 0x1008, + 0xb801, 0x9008, 0x102b, 0x2008, 0x8812, 0x8b00, 0x8b00, + 0x1080, 0x900a, 0x102c, 0x2008, 0x8812, 0x8b00, 0x8b00, + 0x1080, 0x9009, 0x7980, 0x0952, 0x8148, 0x6946, 0xb801, + 0x9046, 0xb901, 0x9041, 0x6944, 0xba08, 0xe344, 0x0bfe, + 0x9044, 0x8b89, 0x0143, 0x694b, 0x881f, 0xbb0f, 0xada0, + 0x8143, 0x0811, 0x304a, 0xe308, 0x0bfe, 0x6949, 0x9043, + 0x0148, 0xbe3a +}; + +u16 asp_block_2[]={ + 0x0000, 0x0000, 0x0003, 0x0003, 0x0001, 0x0001, + 0x0004, 0x0004, 0x0002, 0x0002, 0x0005, 0x0005, + 0x0006, 0x0006, 0x0007, 0x0007, 0x0008, 0x0008, + 0x0100, 0x0100, 0x0103, 0x0103, 0x0101, 0x0101, + 0x0104, 0x0104, 0x0102, 0x0102, 0x0105, 0x0105, + 0x0106, 0x0106, 0x0107, 0x0107, 0x0108, 0x0108 +}; + +u16 asp_block_3[]={ + 0x0000, 0x0000, 0x0000, 0x1200, 0x1200, 0x1280, 0x0000, 0x05d0, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x1104, 0x1105, 0x1008, 0x1020, 0x1040, 0x1060, + 0x1080, 0x10a0, 0x10b0, 0x100d, 0x1010, 0x10e0, 0x2000, 0x2980, + 0x2b00, 0x2b40, 0x2a00, 0x2b90, 0x13dc, 0x2b80, 0x11bc, 0x134c, + 0x1370, 0x12e0, 0x1240, 0x1260, 0x12c0, 0x009e, 0x0045, 0x10bc, + 0x1394, 0x13b8, 0x11f6, 0x10f6, 0x11b0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0815, 0x0956, 0x09df, 0x0be5, 0x0a19, 0x0a48, 0x0b37, + 0x0b5d, 0x0a8b, 0x0aae, 0x0ad2 }; + + +u16 asp_block_4[] = { + 0x0192, 0x04b6, 0x07d9, 0x0afb, 0x0e1c, 0x113a, 0x1455, 0x176e, + 0x1a83, 0x1d93, 0x209f, 0x23a7, 0x26a8, 0x29a4, 0x2c99, 0x2f87, + 0x326e, 0x354e, 0x3825, 0x3af3, 0x3db8, 0x4074, 0x4326, 0x45cd, + 0x486a, 0x4afb, 0x4d81, 0x4ffb, 0x5269, 0x54ca, 0x571e, 0x5964, + 0x5b9d, 0x5dc8, 0x5fe4, 0x61f1, 0x63ef, 0x65de, 0x67bd, 0x698c, + 0x6b4b, 0x6cf9, 0x6e97, 0x7023, 0x719e, 0x7308, 0x7460, 0x75a6, + 0x76d9, 0x77fb, 0x790a, 0x7a06, 0x7aef, 0x7bc6, 0x7c89, 0x7d3a, + 0x7dd6, 0x7e60, 0x7ed6, 0x7f38, 0x7f87, 0x7fc2, 0x7fea, 0x7ffe, + 0x7ffe, 0x7fea, 0x7fc2, 0x7f87, 0x7f38, 0x7ed6, 0x7e60, 0x7dd6, + 0x7d3a, 0x7c89, 0x7bc6, 0x7aef, 0x7a06, 0x790a, 0x77fb, 0x76d9, + 0x75a6, 0x7460, 0x7308, 0x719e, 0x7023, 0x6e97, 0x6cf9, 0x6b4b, + 0x698c, 0x67bd, 0x65de, 0x63ef, 0x61f1, 0x5fe4, 0x5dc8, 0x5b9d, + 0x5964, 0x571e, 0x54ca, 0x5269, 0x4ffb, 0x4d81, 0x4afb, 0x486a, + 0x45cd, 0x4326, 0x4074, 0x3db8, 0x3af3, 0x3825, 0x354e, 0x326e, + 0x2f87, 0x2c99, 0x29a4, 0x26a8, 0x23a7, 0x209f, 0x1d93, 0x1a83, + 0x176e, 0x1455, 0x113a, 0x0e1c, 0x0afb, 0x07d9, 0x04b6, 0x0192, + 0xfe6f, 0xfb4b, 0xf828, 0xf506, 0xf1e5, 0xeec7, 0xebac, 0xe893, + 0xe57e, 0xe26e, 0xdf62, 0xdc5a, 0xd959, 0xd65d, 0xd368, 0xd07a, + 0xcd93, 0xcab3, 0xc7dc, 0xc50e, 0xc249, 0xbf8d, 0xbcdb, 0xba34, + 0xb797, 0xb506, 0xb280, 0xb006, 0xad98, 0xab37, 0xa8e3, 0xa69d, + 0xa464, 0xa239, 0xa01d, 0x9e10, 0x9c12, 0x9a23, 0x9844, 0x9675, + 0x94b6, 0x9308, 0x916a, 0x8fde, 0x8e63, 0x8cf9, 0x8ba1, 0x8a5b, + 0x8928, 0x8806, 0x86f7, 0x85fb, 0x8512, 0x843b, 0x8378, 0x82c7, + 0x822b, 0x81a1, 0x812b, 0x80c9, 0x807a, 0x803f, 0x8017, 0x8003, + 0x8003, 0x8017, 0x803f, 0x807a, 0x80c9, 0x812b, 0x81a1, 0x822b, + 0x82c7, 0x8378, 0x843b, 0x8512, 0x85fb, 0x86f7, 0x8806, 0x8928, + 0x8a5b, 0x8ba1, 0x8cf9, 0x8e63, 0x8fde, 0x916a, 0x9308, 0x94b6, + 0x9675, 0x9844, 0x9a23, 0x9c12, 0x9e10, 0xa01d, 0xa239, 0xa464, + 0xa69d, 0xa8e3, 0xab37, 0xad98, 0xb006, 0xb280, 0xb506, 0xb797, + 0xba34, 0xbcdb, 0xbf8d, 0xc249, 0xc50e, 0xc7dc, 0xcab3, 0xcd93, + 0xd07a, 0xd368, 0xd65d, 0xd959, 0xdc5a, 0xdf62, 0xe26e, 0xe57e, + 0xe893, 0xebac, 0xeec7, 0xf1e5, 0xf506, 0xf828, 0xfb4b, 0xfe6f, + 0x7cc3, 0x725e, 0x68d5, 0x6017, 0x5813, 0x50b9, 0x49fb, 0x43cd, + 0x3e22, 0x38ef, 0x342b, 0x2fcc, 0x2bc9, 0x281c, 0x24be, 0x21a6, + 0x1ed1, 0x1c37, 0x19d5, 0x17a6, 0x15a5, 0x13ce, 0x121f, 0x1093, + 0x0f28, 0x0ddc, 0x0cab, 0x0b93, 0x0a92, 0x09a7, 0x08cf, 0x080a, + 0x0754, 0x06ae, 0x0615, 0x0589, 0x0509, 0x0494, 0x0428, 0x03c5, + 0x036a, 0x0317, 0x02cb, 0x0285, 0x0245, 0x020a, 0x01d4, 0x01a2, + 0x0175, 0x014b, 0x0125, 0x0102, 0x00e2, 0x00c5, 0x00aa, 0x0091, + 0x007b, 0x0066, 0x0053, 0x0041, 0x0031, 0x0022, 0x0015, 0x0009, + 0xfffe, 0xfff2, 0xffe5, 0xffd7, 0xffc8, 0xffb7, 0xffa5, 0xff91, + 0xff7b, 0xff64, 0xff4a, 0xff2e, 0xff0f, 0xfeee, 0xfec9, 0xfea1, + 0xfe76, 0xfe46, 0xfe13, 0xfdda, 0xfd9d, 0xfd5a, 0xfd11, 0xfcc1, + 0xfc6b, 0xfc0c, 0xfba5, 0xfb34, 0xfab9, 0xfa33, 0xf9a1, 0xf902, + 0xf854, 0xf797, 0xf6c8, 0xf5e7, 0xf4f1, 0xf3e5, 0xf2c1, 0xf183, + 0xf027, 0xeeac, 0xed0f, 0xeb4d, 0xe961, 0xe74a, 0xe501, 0xe284, + 0xdfcd, 0xdcd8, 0xd99d, 0xd618, 0xd242, 0xce12, 0xc982, 0xc487, + 0xbf1a, 0xb92e, 0xb2ba, 0xabaf, 0xa402, 0x9ba3, 0x9282, 0x888d, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e, 0x0010, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0006, 0x000a, 0x000e, + 0x0010, 0x0014, 0x0016, 0x0018, 0x001a, 0x001c, 0x001e, 0x0020, + 0x0000, 0x0000, 0x0000, 0x000a, 0x0010, 0x0016, 0x001a, 0x001e, + 0x0020, 0x0024, 0x0026, 0x0028, 0x002a, 0x002c, 0x002e, 0x0030, + 0x0000, 0x0000, 0x0010, 0x001a, 0x0020, 0x0026, 0x002a, 0x002e, + 0x0030, 0x0034, 0x0036, 0x0038, 0x003a, 0x003c, 0x003e, 0x0040, + 0x0000, 0x0010, 0x0020, 0x002a, 0x0030, 0x0036, 0x003a, 0x003e, + 0x0040, 0x0044, 0x0046, 0x0048, 0x004a, 0x004c, 0x004e, 0x0050, + 0x0000, 0x0020, 0x0030, 0x003a, 0x0040, 0x0046, 0x004a, 0x004e, + 0x0050, 0x0054, 0x0056, 0x0058, 0x005a, 0x005c, 0x005e, 0x0060, + 0x0000, 0x0030, 0x0040, 0x004a, 0x0050, 0x0056, 0x005a, 0x005e, + 0x0060, 0x0064, 0x0066, 0x0068, 0x006a, 0x006c, 0x006e, 0x0070, + 0x0008, 0x0021, 0x0042, 0x0064, 0x0086, 0x00a8, 0x00cb, 0x00ee, + 0x0111, 0x0135, 0x0158, 0x017d, 0x01a1, 0x01c6, 0x01eb, 0x0211, + 0x0236, 0x025d, 0x0283, 0x02aa, 0x02d1, 0x02f9, 0x0321, 0x0349, + 0x0372, 0x039b, 0x03c4, 0x03ee, 0x0418, 0x0442, 0x046d, 0x0499, + 0x04c4, 0x04f0, 0x051d, 0x054a, 0x0577, 0x05a5, 0x05d3, 0x0601, + 0x0630, 0x0660, 0x0690, 0x06c0, 0x06f1, 0x0722, 0x0753, 0x0785, + 0x07b8, 0x07eb, 0x081e, 0x0852, 0x0886, 0x08bb, 0x08f0, 0x0926, + 0x095c, 0x0993, 0x09ca, 0x0a02, 0x0a3a, 0x0a73, 0x0aac, 0x0ae6, + 0x0b20, 0x0b5b, 0x0b96, 0x0bd2, 0x0c0e, 0x0c4b, 0x0c89, 0x0cc7, + 0x0d05, 0x0d44, 0x0d84, 0x0dc5, 0x0e05, 0x0e47, 0x0e89, 0x0ecc, + 0x0f0f, 0x0f53, 0x0f97, 0x0fdd, 0x1022, 0x1069, 0x10b0, 0x10f7, + 0x1140, 0x1189, 0x11d2, 0x121c, 0x1267, 0x12b3, 0x12ff, 0x134c, + 0x139a, 0x13e8, 0x1438, 0x1487, 0x14d8, 0x1529, 0x157b, 0x15ce, + 0x1621, 0x1676, 0x16cb, 0x1720, 0x1777, 0x17ce, 0x1826, 0x187f, + 0x18d9, 0x1934, 0x198f, 0x19eb, 0x1a48, 0x1aa6, 0x1b05, 0x1b64, + 0x1bc5, 0x1c26, 0x1c88, 0x1ceb, 0x1d4f, 0x1db4, 0x1e1a, 0x1e80, + 0x1ee8, 0x1f51, 0x1fba, 0x2025, 0x2090, 0x20fc, 0x216a, 0x21d8, + 0x2247, 0x22b8, 0x2329, 0x239b, 0x240f, 0x2483, 0x24f9, 0x256f, + 0x25e7, 0x2660, 0x26da, 0x2755, 0x27d1, 0x284e, 0x28cc, 0x294b, + 0x29cc, 0x2a4e, 0x2ad1, 0x2b55, 0x2bda, 0x2c61, 0x2ce8, 0x2d71, + 0x2dfb, 0x2e87, 0x2f13, 0x2fa1, 0x3031, 0x30c1, 0x3153, 0x31e6, + 0x327b, 0x3310, 0x33a8, 0x3440, 0x34da, 0x3575, 0x3612, 0x36b0, + 0x3750, 0x37f1, 0x3893, 0x3937, 0x39dc, 0x3a83, 0x3b2c, 0x3bd6, + 0x3c81, 0x3d2e, 0x3ddd, 0x3e8d, 0x3f3f, 0x3ff2, 0x40a7, 0x415d, + 0x4216, 0x42d0, 0x438b, 0x4448, 0x4507, 0x45c8, 0x468b, 0x474f, + 0x4815, 0x48dd, 0x49a6, 0x4a72, 0x4b3f, 0x4c0e, 0x4cdf, 0x4db2, + 0x4e87, 0x4f5d, 0x5036, 0x5111, 0x51ed, 0x52cc, 0x53ac, 0x548f, + 0x5573, 0x565a, 0x5743, 0x582e, 0x591b, 0x5a0a, 0x5afb, 0x5bef, + 0x5ce4, 0x5ddc, 0x5ed7, 0x5fd3, 0x60d2, 0x61d3, 0x62d6, 0x63dc, + 0x64e4, 0x65ee, 0x66fb, 0x680a, 0x691c, 0x6a30, 0x6b47, 0x6c60, + 0x6d7c, 0x6e9a, 0x6fbb, 0x70de, 0x7204, 0x732d, 0x7459, 0x7587, + 0x76b8, 0x77eb, 0x7922, 0x7a5b, 0x7b97, 0x7cd6, 0x7e18, 0x7f5d, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0002, 0x0002, 0x0003, + 0x0003, 0x0004, 0x0004, 0x0005, 0x0006, 0x0008, 0x0009, 0x000a, + 0x000c, 0x0010, 0x0012, 0x0015, 0x0019, 0x0022, 0x0024, 0x002a, + 0x0031, 0x003e, 0x0049, 0x0055, 0x0062, 0x007c, 0x0092, 0x00a9, + 0x00c4, 0x00fc, 0x0125, 0x0152, 0x0187, 0x01f2, 0x024a, 0x02a4, + 0x030d, 0x03e3, 0x0492, 0x0547, 0x061b, 0x07c7, 0x0923, 0x0a8d, + 0x0c19, 0x0eb3, 0x1228, 0x14c1, 0x17fb, 0x1d17, 0x22f2, 0x2835, + 0x2dd4, 0x3cd0, 0x4cf5, 0x51cc, 0x7fff, 0x7fff, 0x7fff, 0x7fff, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0002, 0x0002, + 0x0002, 0x0003, 0x0004, 0x0005, 0x0005, 0x0007, 0x0008, 0x000a, + 0x000b, 0x000e, 0x0011, 0x0014, 0x0017, 0x001c, 0x0022, 0x0028, + 0x002e, 0x0039, 0x0045, 0x0050, 0x005c, 0x0073, 0x008a, 0x00a0, + 0x00b9, 0x00e7, 0x0114, 0x0141, 0x0172, 0x01ce, 0x0228, 0x0283, + 0x02e3, 0x039b, 0x0454, 0x0501, 0x05bf, 0x072a, 0x0899, 0x0a18, + 0x0b7e, 0x0e55, 0x10d3, 0x1404, 0x16c3, 0x16c3, 0x16c3, 0x16c3, + 0x0012, 0x0024, 0x0048, 0x006c, 0x0090, 0x00b4, 0x00d8, 0x00fc, + 0x0120, 0x0144, 0x0168, 0x0168, 0x01b0, 0x01b0, 0x021c, 0x021c, + 0x0000, 0x0003, 0x0008, 0x000b, 0x0001, 0x0004, 0x0009, 0x000c, + 0x0002, 0x0005, 0x000a, 0x000d, 0x0010, 0x0013, 0x0011, 0x0014, + 0x0012, 0x0015, 0x0100, 0x0103, 0x0108, 0x010b, 0x0101, 0x0104, + 0x0109, 0x010c, 0x0102, 0x0105, 0x010a, 0x010d, 0x0110, 0x0113, + 0x0111, 0x0114, 0x0112, 0x0115 }; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/maui.c linux.ac/drivers/sound/maui.c --- linux.vanilla/drivers/sound/maui.c Sun Nov 8 15:10:21 1998 +++ linux.ac/drivers/sound/maui.c Sat Jul 3 20:33:06 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.ac/drivers/sound/mpu401.c --- linux.vanilla/drivers/sound/mpu401.c Sun Nov 8 15:08:01 1998 +++ linux.ac/drivers/sound/mpu401.c Mon Jun 14 13:56:17 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.ac/drivers/sound/opl3sa2.c --- linux.vanilla/drivers/sound/opl3sa2.c Sat Jan 9 21:50:45 1999 +++ linux.ac/drivers/sound/opl3sa2.c Sat Jun 12 20:06:07 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/pci_legacy.c linux.ac/drivers/sound/pci_legacy.c --- linux.vanilla/drivers/sound/pci_legacy.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/sound/pci_legacy.c Fri Jun 4 23:52:44 1999 @@ -0,0 +1,273 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include "sound_config.h" +#include "soundmodule.h" +#include "sb_mixer.h" +#include "sb.h" + +/* + * Legacy initialisation tables + */ + +struct pci_legacy +{ + int vendor; + int device; + char *description; + int (*install)(struct pci_dev *, struct pci_legacy *); + int flags; +}; + +#define MAX_CARDS 8 + +static struct address_info pci_cards[MAX_CARDS]; +static int card_count=0; + +static struct address_info pci_mpu_cards[MAX_CARDS]; +static int mpu_count=0; + +static int find_space(int *array, int len) +{ + int i; + for(i=0;array[i]!=0;i++) + { + if(check_region(array[i],len)==0) + return i; + } + return -1; +} + +static int find_dma(int *array) +{ + int i; + for(i=0;array[i]!= -1;i++) + { + if(request_dma(array[i],"pci_legacy")==0) + { + free_dma(array[i]); + return i; + } + } + return -1; +} + +/* + * Setup the Yamaha cards. For now don't do the MPU401/OPL3 ports. + * Does anyone actually use the glorified doorbell mode on an SB ? + * + * For now we only support PC/PCI. If you don't have a PC/PCI sideband + * connector on your board bad luck - you can write the DDMA support. + */ + +static int ymf_init(struct pci_dev *pci_dev, struct pci_legacy *pl) +{ + u16 r; + int slot; + int dma; + int doorbell; + int mpu; + static int ymf_sb[]={0x220, 0x240, 0x260, 0x280, 0}; + static int ymf_opl3[]={0x3A8,0x3A0, 0x398, 0x388, 0}; + static int ymf_dma[]={1,3,0, -1}; + static int ymf_mpu[]={0x330, 0x300, 0x332, 0x334, 0}; + struct address_info *card; + + if((slot=find_space(ymf_sb, 16))==-1) + { + printk(KERN_WARNING "%s: no free soundblaster addresses.\n", + pl->description); + return 0; + } + if((dma=find_dma(ymf_dma))==-1) + { + printk(KERN_WARNING "%s: no free DMA channels.\n", + pl->description); + return 0; + } + + doorbell = find_space(ymf_opl3, 4); + mpu = find_space(ymf_mpu, 4); + + printk(KERN_INFO "Found a %s. Due to lack of documentation this card will\n", + pl->description); + printk(KERN_INFO "be configured as an 8bit soundblaster.\n"); + switch(pl->flags) + { + case 0: + case 1: + pci_read_config_word(pci_dev, 0x42, &r); + /* Mask the fields we will set */ + r&=~0x783F; + /* Set the I/O */ + r|=(slot<<2); + /* Serialized IRQ crap off */ + r|=(1<<15); + /* Set the OPL3 */ + if(doorbell != -1) + { + printk(KERN_INFO "Enabling OPL3 at 0x%03X.\n", + ymf_opl3[doorbell]); + r|=(3-doorbell); + } + if(mpu != -1) + { + r|=(mpu<<4); + printk(KERN_INFO "Enabling MPU at I/O 0x%03X.\n", + ymf_mpu[mpu]); + } + pci_write_config_word(pci_dev, 0x42, r); + pci_read_config_word(pci_dev, 0x40, &r); + /* Set DMA */ + r&=~0x00C0; + r|=(ymf_dma[dma])<<6; + /* SB port only */ + r&=~0xF; + r|=1; + if(doorbell != -1) + r|=2; + if(mpu != -1) + r|=24; + /* SIRQ off, I/O on */ + r&=~(1<<14); + r&=~(1<<15); + pci_write_config_word(pci_dev, 0x40, r); + + + pci_read_config_word(pci_dev, 0x4C, &r); + r&=~1; + pci_write_config_word(pci_dev, 0x4C, r); + + pci_read_config_word(pci_dev, 0x48, &r); + r=1; + pci_write_config_word(pci_dev, 0x48, r); + + + pci_read_config_word(pci_dev, 0x48, &r); + udelay(2000); + r=0; + pci_write_config_word(pci_dev, 0x48, r); + + + pci_read_config_word(pci_dev, 0x48, &r); + r=3; + udelay(2000); + pci_write_config_word(pci_dev, 0x48, r); + + printk(KERN_INFO "%s: set to I/O 0x%03X DMA %d.\n", + pl->description, + ymf_sb[slot], ymf_dma[dma]); + break; + } + + card=&pci_cards[card_count]; + + card->dma = ymf_dma[dma]; + card->irq = pci_dev->irq; + card->io_base = ymf_sb[slot]; + card->dma2 = -1; + + if(sb_dsp_detect(card, SB_PCI_YAMAHA, 0)==-1) + { + printk(KERN_WARNING "pci_legacy: Sound blaster emulation not responding.\n"); + return 0; + } + + attach_sb_card(card); + + if(mpu != -1) + { + card=&pci_mpu_cards[mpu_count]; + card->dma = -1; + card->irq = -1; + card->io_base = ymf_mpu[mpu]; + card->dma2 = -1; + if(probe_sbmpu(card)) + { + attach_sbmpu(card); + mpu_count++; + } + else + printk(KERN_WARNING "pci_legacy: MPU401 emulation not responding.\n"); + + } + + card_count++; + return 1; +} + +/* + * Important; Put the less flexible cards first so that they get + * the SB emulation slots they need. + */ + +struct pci_legacy pci_legacy_table[]={ + { 0x1073, 0x0003, "Yamaha YFM-740C", ymf_init, 0 }, + { 0x1073, 0x000D, "Yamaha YFM-724F", ymf_init, 1 }, + { 0x1073, 0x0004, "Yamaha YFM-724", ymf_init, 1 }, + { 0, 0, NULL, 0, 0} +}; + + +int init_legacy_pci(void) +{ + struct pci_dev *pcidev=NULL; + int count=0; + struct pci_legacy *pt=&pci_legacy_table[0]; + + if(!pci_present()) + return -ENODEV; + + while(pt->vendor) + { + pcidev = NULL; + + printk("Scan for %04X %04X\n", + pt->vendor, pt->device); + while((pcidev = pci_find_device(pt->vendor, pt->device, pcidev))!=NULL) + { + printk("Trying to init %04X %04X\n", + pt->vendor, pt->device); + count+=pt->install(pcidev, pt); + if(count >= MAX_CARDS) + return 0; + } + pt++; + } + + if(count==0) + return -ENODEV; + + printk(KERN_INFO "pci_legacy: %d unsupported PCI card%s placed in legacy 8bit mode.\n", + card_count, + card_count==1?"s":""); + return 0; +} + + +int init_module(void) +{ + if(init_legacy_pci()<0) + { + printk(KERN_ERR "No supported devices found.\n"); + return -ENODEV; + } + return 0; +} + +void cleanup_module(void) +{ + int i; + for(i=0;iirq, devc->midi_irq_cookie, NULL); + if(devc->midi_irq_cookie) + uart401intr(devc->irq, devc->midi_irq_cookie, NULL); #endif if (!(src & 3)) @@ -1191,8 +1192,12 @@ void attach_sbmpu(struct address_info *hw_config) { #if defined(CONFIG_MIDI) && defined(CONFIG_UART401) + hw_config->slots[4] = -1; attach_uart401(hw_config); - last_sb->midi_irq_cookie=midi_devs[hw_config->slots[4]]->devc; + if(hw_config->slots[4] != -1) + last_sb->midi_irq_cookie=midi_devs[hw_config->slots[4]]->devc; + else + last_sb->midi_irq_cookie=NULL; #endif } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/sb_ess.c linux.ac/drivers/sound/sb_ess.c --- linux.vanilla/drivers/sound/sb_ess.c Thu May 27 22:11:56 1999 +++ linux.ac/drivers/sound/sb_ess.c Thu Jul 8 00:35:56 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.ac/drivers/sound/sb_mixer.c --- linux.vanilla/drivers/sound/sb_mixer.c Fri Apr 16 22:10:57 1999 +++ linux.ac/drivers/sound/sb_mixer.c Wed Jun 9 20:07:30 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.ac/drivers/sound/sb_mixer.h --- linux.vanilla/drivers/sound/sb_mixer.h Sat Jan 9 21:50:45 1999 +++ linux.ac/drivers/sound/sb_mixer.h Wed Jun 9 20:07:30 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.ac/drivers/sound/sgalaxy.c --- linux.vanilla/drivers/sound/sgalaxy.c Fri Nov 13 01:37:15 1998 +++ linux.ac/drivers/sound/sgalaxy.c Sat Jun 12 20:00:29 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.ac/drivers/sound/sonicvibes.c --- linux.vanilla/drivers/sound/sonicvibes.c Fri Apr 16 22:10:57 1999 +++ linux.ac/drivers/sound/sonicvibes.c Mon Jul 19 03:56:19 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.ac/drivers/sound/sound_calls.h --- linux.vanilla/drivers/sound/sound_calls.h Wed Jan 6 23:02:26 1999 +++ linux.ac/drivers/sound/sound_calls.h Mon Jun 14 13:56:17 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.ac/drivers/sound/sound_syms.c --- linux.vanilla/drivers/sound/sound_syms.c Wed Jan 6 23:02:26 1999 +++ linux.ac/drivers/sound/sound_syms.c Sat Jul 3 20:33:06 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.ac/drivers/sound/trix.c --- linux.vanilla/drivers/sound/trix.c Wed Mar 10 21:13:08 1999 +++ linux.ac/drivers/sound/trix.c Tue Jun 22 19:50:28 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/sound/waveartist.c linux.ac/drivers/sound/waveartist.c --- linux.vanilla/drivers/sound/waveartist.c Sat Jan 9 21:50:46 1999 +++ linux.ac/drivers/sound/waveartist.c Fri Jun 4 23:52:44 1999 @@ -5,6 +5,7 @@ * codec chip used in the Corel Computer NetWinder. * * Cleaned up and integrated into 2.1 by Russell King (rmk@arm.linux.org.uk) + * Tweaked for X86 by Alan Cox */ /* @@ -40,12 +41,19 @@ #include #include +#ifdef CONFIG_ARCH_NETWINDER #include +#define IS_VNC +#endif #include "soundmodule.h" #include "sound_config.h" #include "waveartist.h" +#ifndef NO_DMA +#define NO_DMA 255 +#endif + #define VNC_TIMER_PERIOD (HZ/4) //check slider 4 times/sec #define MIXER_PRIVATE3_RESET 0x53570000 @@ -203,7 +211,7 @@ } while (timeout--); if (timeout == 0) { - printk("WaveArtist: reset timeout "); + printk(KERN_WARNING "WaveArtist: reset timeout "); if (res != (unsigned int)-1) printk("(res=%04X)", res); printk("\n"); @@ -222,7 +230,7 @@ unsigned int i; if (debug_flg & DEBUG_CMD) { - printk("waveartist_cmd: cmd="); + printk(KERN_DEBUG "waveartist_cmd: cmd="); for (i = 0; i < nr_cmd; i++) printk("%04X ", cmd[i]); @@ -239,7 +247,7 @@ old_data = inw(io_base + CMDR); if (debug_flg & DEBUG_CMD) - printk("flushed %04X...", old_data); + printk(KERN_DEBUG "flushed %04X...", old_data); udelay(10); } @@ -272,14 +280,14 @@ if (debug_flg & DEBUG_CMD) { if (!timed_out) { - printk("waveartist_cmd: resp="); + printk(KERN_DEBUG "waveartist_cmd: resp="); for (i = 0; i < nr_resp; i++) printk("%04X ", resp[i]); printk("\n"); } else - printk("waveartist_cmd: timed out\n"); + printk(KERN_WARNING "waveartist_cmd: timed out\n"); } return timed_out ? 1 : 0; @@ -317,7 +325,7 @@ int count; if (debug_flg & DEBUG_CMD) - printk("waveartist_sendcmd: cmd=0x%04X...", cmd); + printk(KERN_DEBUG "waveartist_sendcmd: cmd=0x%04X...", cmd); udelay(10); @@ -330,7 +338,7 @@ udelay(10); if (debug_flg & DEBUG_CMD) - printk(" flushed %04X...", count); + printk(KERN_DEBUG " flushed %04X...", count); } /* @@ -350,7 +358,7 @@ /* ready BEFORE timeout? */ if (debug_flg & DEBUG_CMD) - printk(" %s\n", count ? "Done OK." : "Error!"); + printk(KERN_DEBUG " %s\n", count ? "Done OK." : "Error!"); udelay(10); @@ -455,7 +463,7 @@ unsigned int count = __count; if (debug_flg & DEBUG_OUT) - printk("waveartist: output block, buf=0x%lx, count=0x%x...\n", + printk(KERN_DEBUG "waveartist: output block, buf=0x%lx, count=0x%x...\n", buf, count); /* * 16 bit data @@ -501,7 +509,7 @@ unsigned int count = __count; if (debug_flg & DEBUG_IN) - printk("waveartist: start input, buf=0x%lx, count=0x%x...\n", + printk(KERN_DEBUG "waveartist: start input, buf=0x%lx, count=0x%x...\n", buf, count); if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE)) /* 16 bit data */ @@ -604,26 +612,26 @@ cli(); if (waveartist_cmd2(devc, WACMD_INPUTFORMAT, bits)) - printk("waveartist: error setting the record format to %d\n", + printk(KERN_WARNING "waveartist: error setting the record format to %d\n", portc->audio_format); if (waveartist_cmd2(devc, WACMD_INPUTCHANNELS, portc->channels)) - printk("waveartist: error setting record to %d channels\n", + printk(KERN_WARNING "waveartist: error setting record to %d channels\n", portc->channels); /* * write cmd SetSampleSpeedTimeConstant */ if (waveartist_cmd2(devc, WACMD_INPUTSPEED, speed)) - printk("waveartist: error setting the record speed " + printk(KERN_WARNING "waveartist: error setting the record speed " "to %dHz.\n", portc->speed); if (waveartist_cmd2(devc, WACMD_INPUTDMA, 1)) - printk("waveartist: error setting the record data path " + printk(KERN_WARNING "waveartist: error setting the record data path " "to 0x%X\n", 1); if (waveartist_cmd2(devc, WACMD_INPUTFORMAT, bits)) - printk("waveartist: error setting the record format to %d\n", + printk(KERN_WARNING "waveartist: error setting the record format to %d\n", portc->audio_format); devc->xfer_count = 0; @@ -631,9 +639,9 @@ waveartist_halt_input(dev); if (debug_flg & DEBUG_INTR) { - printk("WA CTLR reg: 0x%02X.\n",inb(devc->hw.io_base + CTLR)); - printk("WA STAT reg: 0x%02X.\n",inb(devc->hw.io_base + STATR)); - printk("WA IRQS reg: 0x%02X.\n",inb(devc->hw.io_base + IRQSTAT)); + printk(KERN_DEBUG "WA CTLR reg: 0x%02X.\n",inb(devc->hw.io_base + CTLR)); + printk(KERN_DEBUG "WA STAT reg: 0x%02X.\n",inb(devc->hw.io_base + STATR)); + printk(KERN_DEBUG "WA IRQS reg: 0x%02X.\n",inb(devc->hw.io_base + IRQSTAT)); } return 0; @@ -658,19 +666,19 @@ if (waveartist_cmd2(devc, WACMD_OUTPUTSPEED, speed) && waveartist_cmd2(devc, WACMD_OUTPUTSPEED, speed)) - printk("waveartist: error setting the playback speed " + printk(KERN_WARNING "waveartist: error setting the playback speed " "to %dHz.\n", portc->speed); if (waveartist_cmd2(devc, WACMD_OUTPUTCHANNELS, portc->channels)) - printk("waveartist: error setting the playback to" + printk(KERN_WARNING "waveartist: error setting the playback to" " %d channels\n", portc->channels); if (waveartist_cmd2(devc, WACMD_OUTPUTDMA, 0)) - printk("waveartist: error setting the playback data path " + printk(KERN_WARNING "waveartist: error setting the playback data path " "to 0x%X\n", 0); if (waveartist_cmd2(devc, WACMD_OUTPUTFORMAT, bits)) - printk("waveartist: error setting the playback format to %d\n", + printk(KERN_WARNING "waveartist: error setting the playback format to %d\n", portc->audio_format); devc->xfer_count = 0; @@ -678,9 +686,9 @@ waveartist_halt_output(dev); if (debug_flg & DEBUG_INTR) { - printk("WA CTLR reg: 0x%02X.\n",inb(devc->hw.io_base + CTLR)); - printk("WA STAT reg: 0x%02X.\n",inb(devc->hw.io_base + STATR)); - printk("WA IRQS reg: 0x%02X.\n",inb(devc->hw.io_base + IRQSTAT)); + printk(KERN_DEBUG "WA CTLR reg: 0x%02X.\n",inb(devc->hw.io_base + CTLR)); + printk(KERN_DEBUG "WA STAT reg: 0x%02X.\n",inb(devc->hw.io_base + STATR)); + printk(KERN_DEBUG "WA IRQS reg: 0x%02X.\n",inb(devc->hw.io_base + IRQSTAT)); } return 0; @@ -775,7 +783,7 @@ unsigned long flags; if (debug_flg & DEBUG_TRIGGER) { - printk("wavnc: audio trigger "); + printk(KERN_DEBUG "wavnc: audio trigger "); if (state & PCM_ENABLE_INPUT) printk("in "); if (state & PCM_ENABLE_OUTPUT) @@ -883,15 +891,14 @@ status = inb(devc->hw.io_base + STATR); if (debug_flg & DEBUG_INTR) - printk("waveartist_intr: stat=%02x, irqstat=%02x\n", + printk(KERN_DEBUG "waveartist_intr: stat=%02x, irqstat=%02x\n", status, irqstatus); if (status & IRQ_REQ) /* Clear interrupt */ waveartist_iack(devc); else - printk("waveartist: unexpected interrupt\n"); + printk(KERN_WARNING "waveartist: unexpected interrupt\n"); -#ifdef CONFIG_AUDIO if (irqstatus & 0x01) { int temp = 1; @@ -906,12 +913,11 @@ temp = 0; } if (temp) //default: - printk("WaveArtist: Unknown interrupt\n"); + printk(KERN_WARNING "WaveArtist: Unknown interrupt\n"); } -#endif if (irqstatus & 0x2) // We do not use SB mode natively... - printk("WaveArtist: Unexpected SB interrupt...\n"); + printk(KERN_WARNING "WaveArtist: Unexpected SB interrupt...\n"); } /* ------------------------------------------------------------------------- @@ -1032,7 +1038,7 @@ waveartist_cmd(devc, 1, vals, 1, vals + 2); if (debug_flg & DEBUG_MIXER) - printk("RECSRC: old left: 0x%04X, old right: 0x%04X.\n", + printk(KERN_DEBUG "RECSRC: old left: 0x%04X, old right: 0x%04X.\n", vals[1] & 0x07, (vals[1] >> 3) & 0x07); vals[1] &= ~0x03F; //kill current left/right mux input select @@ -1106,7 +1112,7 @@ } if (debug_flg & DEBUG_MIXER) - printk("RECSRC %d: left=0x%04X, right=0x%04X.\n", input, + printk(KERN_DEBUG "RECSRC %d: left=0x%04X, right=0x%04X.\n", input, vals[1] & 0x07, (vals[1] >> 3) & 0x07); #else @@ -1127,7 +1133,7 @@ waveartist_cmd(devc, 1, vals, 1, vals + 2); if (debug_flg & DEBUG_MIXER) - printk("RECSRC: old left: 0x%04X, old right: 0x%04X.\n", + printk(KERN_DEBUG "RECSRC: old left: 0x%04X, old right: 0x%04X.\n", vals[1], vals[2]); /* @@ -1197,7 +1203,7 @@ } if (debug_flg & DEBUG_MIXER) - printk("RECSRC %d: left(4) 0x%04X, right(8) 0x%04X.\n", + printk(KERN_DEBUG "RECSRC %d: left(4) 0x%04X, right(8) 0x%04X.\n", level, vals[1], vals[2]); #endif /* @@ -1220,7 +1226,7 @@ right = (level & 0x7f00) >> 8; if (debug_flg & DEBUG_MIXER) - printk("wa_mixer_set(dev=%d, level=%X)\n", + printk(KERN_DEBUG "wa_mixer_set(dev=%d, level=%X)\n", whichDev, level); switch (whichDev) { @@ -1321,7 +1327,7 @@ int i; if (debug_flg & DEBUG_MIXER) - printk("%s: mixer_reset\n", devc->hw.name); + printk(KERN_DEBUG "%s: mixer_reset\n", devc->hw.name); /* * reset mixer cmd @@ -1615,20 +1621,20 @@ waveartist_iack(devc); if (request_irq(devc->hw.irq, waveartist_intr, 0, devc->hw.name, devc) < 0) { - printk("%s: IRQ %d in use\n", + printk(KERN_ERR "%s: IRQ %d in use\n", devc->hw.name, devc->hw.irq); goto uninstall; } if (sound_alloc_dma(devc->hw.dma, devc->hw.name)) { - printk("%s: Can't allocate DMA%d\n", + printk(KERN_ERR "%s: Can't allocate DMA%d\n", devc->hw.name, devc->hw.dma); goto uninstall_irq; } if (devc->hw.dma != devc->hw.dma2 && devc->hw.dma2 != NO_DMA) if (sound_alloc_dma(devc->hw.dma2, devc->hw.name)) { - printk("%s: can't allocate DMA%d\n", + printk(KERN_ERR "%s: can't allocate DMA%d\n", devc->hw.name, devc->hw.dma2); goto uninstall_dma; } @@ -1660,6 +1666,14 @@ return -1; } +#ifndef IS_VNC + +static void vnc_mute(wavnc_info *devc, int mute) +{ +} + +#else + /* * Corel Netwinder specifics... */ @@ -1793,31 +1807,34 @@ mod_timer(&vnc_timer, jiffies + next_timeout); } +#endif + int probe_waveartist(struct address_info *hw_config) { wavnc_info *devc = &adev_info[nr_waveartist_devs]; if (nr_waveartist_devs >= MAX_AUDIO_DEV) { - printk("waveartist: too many audio devices\n"); + printk(KERN_ERR "waveartist: too many audio devices\n"); return 0; } if (check_region(hw_config->io_base, 15)) { - printk("WaveArtist: I/O port conflict\n"); + printk(KERN_ERR "WaveArtist: I/O port conflict\n"); return 0; } +#ifdef IS_NW if (hw_config->irq > 31 || hw_config->irq < 16) { - printk("WaveArtist: Bad IRQ %d\n", hw_config->irq); + printk(KERN_ERR "WaveArtist: Bad IRQ %d\n", hw_config->irq); return 0; } if (hw_config->dma != 3) { - printk("WaveArtist: Bad DMA %d\n", hw_config->dma); + printk(KERN_ERR "WaveArtist: Bad DMA %d\n", hw_config->dma); return 0; } - +#endif hw_config->name = "WaveArtist"; devc->hw = *hw_config; devc->open_mode = 0; @@ -1854,12 +1871,13 @@ if (devc->dev_no < 0) release_region(hw->io_base, 15); else { +#ifdef IS_VNC init_timer(&vnc_timer); vnc_timer.function = vnc_slider_tick; vnc_timer.expires = jiffies; vnc_timer.data = nr_waveartist_devs; add_timer(&vnc_timer); - +#endif nr_waveartist_devs += 1; vnc_mute(devc, 0); @@ -1909,7 +1927,7 @@ for (; i < nr_waveartist_devs; i++) adev_info[i] = adev_info[i + 1]; } else - printk("waveartist: can't find device to unload\n"); + printk(KERN_ERR "waveartist: can't find device to unload\n"); } #ifdef MODULE @@ -1919,10 +1937,10 @@ MODULE_PARM(dma, "i"); /* DMA */ MODULE_PARM(dma2, "i"); /* DMA2 */ -int io = CONFIG_WAVEARTIST_BASE; -int irq = CONFIG_WAVEARTIST_IRQ; -int dma = CONFIG_WAVEARTIST_DMA; -int dma2 = CONFIG_WAVEARTIST_DMA2; +int io = -1; +int irq = -1; +int dma = -1; +int dma2 = NO_DMA; static int attached; @@ -1930,6 +1948,11 @@ int init_module(void) { + if(io == -1 || irq == -1 || dma == -1) + { + printk(KERN_ERR "waveartist:io, irq and dma are mandatory.\n"); + return -EINVAL; + } hw_config.io_base = io; hw_config.irq = irq; hw_config.dma = dma; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/tc/Makefile linux.ac/drivers/tc/Makefile --- linux.vanilla/drivers/tc/Makefile Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/tc/Makefile Tue Jun 22 01:35:01 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.ac/drivers/tc/tc.c --- linux.vanilla/drivers/tc/tc.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/tc/tc.c Tue Jun 22 01:35:01 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.ac/drivers/tc/tcsyms.c --- linux.vanilla/drivers/tc/tcsyms.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/tc/tcsyms.c Mon Jul 19 03:45:44 1999 @@ -0,0 +1,13 @@ +/* + * Turbo Channel Services -- Exported Symbols + * + */ + +#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.ac/drivers/tc/zs.c --- linux.vanilla/drivers/tc/zs.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/tc/zs.c Tue Jun 22 01:35:01 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.ac/drivers/tc/zs.h --- linux.vanilla/drivers/tc/zs.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/tc/zs.h Tue Jun 22 01:35:01 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/usb/Config.in linux.ac/drivers/usb/Config.in --- linux.vanilla/drivers/usb/Config.in Thu May 27 22:11:56 1999 +++ linux.ac/drivers/usb/Config.in Fri Jun 4 23:52:47 1999 @@ -21,6 +21,7 @@ bool 'OHCI-HCD Virtual Root Hub' CONFIG_USB_OHCI_VROOTHUB fi + bool 'USB hub support (just say yes)' CONFIG_USB_HUB bool 'USB mouse support' CONFIG_USB_MOUSE bool 'USB keyboard support' CONFIG_USB_KBD bool 'USB audio parsing support' CONFIG_USB_AUDIO diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/usb/Makefile linux.ac/drivers/usb/Makefile --- linux.vanilla/drivers/usb/Makefile Thu May 27 22:11:56 1999 +++ linux.ac/drivers/usb/Makefile Fri Jun 4 23:52:47 1999 @@ -18,7 +18,11 @@ M_OBJS := L_OBJS := LX_OBJS := -USBX_OBJS := usb.o hub.o usb-debug.o +USBX_OBJS := usb.o usb-debug.o + +ifeq ($(CONFIG_USB_HUB),y) + USBX_OBJS += hub.o +endif ifeq ($(CONFIG_USB_MOUSE),y) USBX_OBJS += mouse.o diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/usb/README.ohci_hcd linux.ac/drivers/usb/README.ohci_hcd --- linux.vanilla/drivers/usb/README.ohci_hcd Thu May 27 22:11:56 1999 +++ linux.ac/drivers/usb/README.ohci_hcd Thu Jan 1 01:00:00 1970 @@ -1,112 +0,0 @@ - -The OHCI HCD layer is a simple but nearly complete implementation of what the -USB people would call a HCD for the OHCI. - (ISO comming soon, Bulk disabled, INT u. CTRL transfers enabled) -It is based on Linus Torvalds UHCI code and Gregory Smith OHCI fragments (0.03 source tree). -The layer (functions) on top of it, is for interfacing to the alternate-usb device-drivers. - -- Roman Weissgaerber - - - * v2.1 1999/05/09 ep_addr correction, code cleanup - * v0.2.0 1999/05/04 - * everything has been moved into 2 files (ohci-hcd.c, ohci-hub-root.c and headers) - * virtual root hub is now an option, - * memory allocation based on kmalloc and kfree now, simple Bus error handling, - * INT and CTRL transfers enabled, Bulk included but disabled, ISO needs completion - * - * from Linus Torvalds (uhci.c): APM (not tested); hub, usb_device, bus and related stuff - * from Greg Smith (ohci.c): better reset ohci-controller handling, hub - * - * v0.1.0 1999/04/27 initial release - -to remove the module try: -killall root-hub -: -rmmod usb-ohci-hcd - -Features: -- virtual root hub, all basic hub descriptors and commands (state: complete) - this is an option now (v0.2.0) - #define CONFIG_USB_OHCI_VROOTHUB includes the virtual hub code, (VROOTHUB) - default is without. - (at the moment: the Virtual Root Hub option is not recommended) - - files: ohci-root-hub.c, ohci-root-hub.h - - -- Endpoint Descriptor (ED) handling more static approach - (EDs should be allocated in parallel to the SET CONFIGURATION command and they live - as long as the function (device) is alive or another configuration is choosen. - In the HCD layer the EDs has to be allocated manually either by calling a subroutine - or by sending a USB root hub vendor specific command to the virtual root hub. - At the alternate linux usb stack EDs will be added (allocated) at their first use. - - files: ohci-hcd.c ohci-hcd.h - routines: (do not use for drivers, use the top layer alternate usb commands instead) - - int usb_ohci_add_ep(struct ohci * ohci, unsigned int ep_addr1, - int interval, int load, f_handler handler, int ep_size, int speed) - adds an endpoint, (if the endpoint already exists some parameters will be updated) - - int usb_ohci_rm_ep(struct usb_ohci_ed *ed, struct ohci * ohci) - removes an endpoint and all pending TDs of that EP - - usb_ohci_rm_function( struct ohci * ohci, union ep_addr_ ep_addr) - removes all Endpoints of a function (device) - -- Transfer Descriptors (TD): handling and allocation of TDs is transparent to the upper layers - The HCD takes care of TDs and EDs memory allocation whereas the upper layers (UBSD ...) has - to take care of buffer allocation. - files: ohci-hcd.c ohci-hcd.h - - There is one basic command for all types of bus transfers (INT, BULK, ISO, CTRL): - - int ohci_trans_req(struct ohci * ohci, int ep_addr, int ctrl_len, void *ctrl, void * data, int data_len, __OHCI_BAG lw0, __OHCI_BAG lw1) - - CTRL: ctrl, ctrl_len ... cmd buffer - data, data_len ... data buffer (in or out) - INT, BULK: ctrl = NULL, ctrl_len=0, - data, data_len ... data buffer (in or out) - ISO: tbd - - There is no buffer reinsertion done by the internal HCD function. - (The interface layer does this for a INT-pipe on request.) - If you want a transfer then you have to - provide buffers by sending ohci_trans_req requests. As they are queued as TDs on an ED - you can send as many as you like. They should come back by the callback f_handler in - the same order (for each endpoint, not globally) If an error occurs all - queued transfers of an endpoint will return unsent. They will be marked with an error status. - - e.g double-buffering for int transfers: - - ohci_trans_req(ohci, ep_addr, 0, NULL, data0, data0_len, 0,0) - ohci_trans_req(ohci, ep_addr, 0, NULL, data1, data1_len, 0,0) - - and when a data0 packet returns by the callback f_handler requeue it: - ohci_trans_req(ohci, ep_addr, 0, NULL, data0, data0_len, 0,0) - and when a data1 packet returns by the callback f_handler requeue it: - ohci_trans_req(ohci, ep_addr, 0, NULL, data1, data1_len, 0,0) - - lw0, lw1 are private fields for upper layers for ids or fine grained handlers. - The alternate usb uses them for dev_id and usb_device_irq handler. - - -- Done list handling: returns the requests (callback f_handler in ED) and does - some error handling, root-hub request dequeuing - (files: ohci-done-list.c in ohci-hcd.c now(v0.2.0)) - -ep_addr union or int is for addressing devices&endpoints: -__u8 ep_addr.bep.ep ... bit 3..0 endpoint address - bit 4 0 - bit 6,5 type: eg. 10 CTRL, 11 BULK, 01 INT, 00 ISO - bit 7 direction 1 IN, 0 OUT - -__u8 ep_addr.bep.fa ... bit 6..0 function address - bit 7 0 - -(__u8 ep_addr.bep.hc ... host controller nr) not used -(__u8 ep_addr.bep.host ... host nr) not used - - - diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/usb/audio.c linux.ac/drivers/usb/audio.c --- linux.vanilla/drivers/usb/audio.c Wed Apr 28 19:14:28 1999 +++ linux.ac/drivers/usb/audio.c Fri Jun 4 23:52:47 1999 @@ -4,6 +4,7 @@ #include #include #include "usb.h" +#include "audio.h" static int usb_audio_probe(struct usb_device *dev); static void usb_audio_disconnect(struct usb_device *dev); @@ -108,6 +109,7 @@ int usb_audio_init(void) { + printk("Registering audio devices.\n"); usb_register(&usb_audio_driver); return 0; } @@ -118,9 +120,95 @@ void usb_audio_interface(struct usb_interface_descriptor *interface, u8 *data) { + if(interface->audio==NULL) + { + interface->audio = (struct usb_audio_if *)kmalloc(sizeof(struct usb_audio_if), GFP_KERNEL); + if(interface->audio==NULL) + { + printk(KERN_WARNING "usb_audio: out of memory.\n"); + return; + } + memset(interface->audio, 0, sizeof(struct usb_audio_if)); + } + printk("audio_if: type %d subtype %d.\n", data[1], data[2]); + switch(data[2]) + { + case 1:printk(" header.\n");break; + case 2:printk(" input.\n");break; + case 3:printk(" output.\n");break; + case 4:printk(" mixer.\n");break; + case 5:printk(" selector.\n");break; + case 6:printk(" feature.\n");break; + case 7:printk(" processor.\n");break; + case 8:printk(" extension.\n");break; + } } -void usb_audio_endpoint(struct usb_endpoint_descriptor *interface, u8 *data) +void usb_audio_endpoint(struct usb_endpoint_descriptor *endpoint, u8 *data) { + if(endpoint->audio==NULL) + { + endpoint->audio = (struct usb_audio_endpoint *)kmalloc(sizeof(struct usb_audio_endpoint), GFP_KERNEL); + if(endpoint->audio==NULL) + { + printk(KERN_WARNING "usb_audio: out of memory.\n"); + return; + } + memset(endpoint->audio, 0, sizeof(struct usb_audio_endpoint)); + } + printk("audio_ep: type %d subtype %d.\n", data[1], data[2]); + switch(data[2]) + { + + case 0x01: + if(data[3]&1) + printk(" ep has frequency control.\n"); + if(data[3]&2) + printk(" ep has pitch control.\n"); + if(data[3]&128) + printk(" ep supports no partial frames.\n"); + printk(" ep lock delay %04X", + data[5]|data[6]<<8); + switch(data[4]) + { + case 1:printk("mS");break; + case 2:printk(" samples");break; + } + printk("\n"); + break; + } } + +/* + * There is duplication of the loops here, but it avoids the core + * code having to know anything about audio. + */ + +void usb_audio_destroy(struct usb_device *dev) +{ + int c, i; + struct usb_config_descriptor *cf; + struct usb_interface_descriptor *ifp; + + if(dev->config==NULL) + return; + + for(c=0;cdescriptor.bNumConfigurations;c++) + { + cf=&dev->config[c]; + if(cf->interface==NULL) + break; + for(i=0;ibNumInterfaces;i++) + { + ifp=&cf->interface[i]; + if(ifp->endpoint==NULL) + break; + if(ifp->endpoint->audio) + kfree(ifp->endpoint->audio); + } + if(cf->interface->audio) + kfree(cf->interface->audio); + } +} + \ No newline at end of file diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/usb/audio.h linux.ac/drivers/usb/audio.h --- linux.vanilla/drivers/usb/audio.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/usb/audio.h Fri Jun 4 23:52:47 1999 @@ -0,0 +1,33 @@ +#define MAX_AUDIO_IFACE 8 +#define MAX_AUDIO_ENDPOINT 8 + +/* + * This isnt a byte valid image of the descriptor. + * The dorks didnt do sensible alignment + */ + +struct usb_audio_if_data +{ + u8 data[MAX_AUDIO_IFACE*2+32]; +}; + +struct usb_audio_ep_data +{ + u8 data[7]; +}; + + +struct usb_audio_if +{ + u16 count; + struct usb_audio_if_data iface[MAX_AUDIO_IFACE]; +}; + +struct usb_audio_endpoint +{ + u16 count; + struct usb_audio_ep_data endpoint[MAX_AUDIO_ENDPOINT]; +}; + + + \ No newline at end of file diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/usb/uhci.c linux.ac/drivers/usb/uhci.c --- linux.vanilla/drivers/usb/uhci.c Thu May 27 22:11:57 1999 +++ linux.ac/drivers/usb/uhci.c Fri Jun 4 23:52:47 1999 @@ -898,6 +898,7 @@ dev = uhci->root_hub = usb_to_uhci(usb); usb->bus = bus; + bus->root_hub = uhci_to_usb(uhci->root_hub); /* Initialize the root hub */ /* UHCI specs says devices must have 2 ports, but goes on to say */ @@ -1191,7 +1192,9 @@ #ifdef CONFIG_USB_KBD usb_kbd_init(); #endif +#ifdef CONFIG_USB_HUB hub_init(); +#endif #ifdef CONFIG_USB_AUDIO usb_audio_init(); #endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/usb/usb.c linux.ac/drivers/usb/usb.c --- linux.vanilla/drivers/usb/usb.c Thu May 27 22:11:57 1999 +++ linux.ac/drivers/usb/usb.c Fri Jun 4 23:52:47 1999 @@ -311,6 +311,9 @@ if(dev->config==NULL) return; + + usb_audio_destroy(dev); + for(c=0;cdescriptor.bNumConfigurations;c++) { cf=&dev->config[c]; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/usb/usb.h linux.ac/drivers/usb/usb.h --- linux.vanilla/drivers/usb/usb.h Thu May 27 22:11:57 1999 +++ linux.ac/drivers/usb/usb.h Sat Jun 5 00:12:41 1999 @@ -367,9 +367,11 @@ #ifdef CONFIG_USB_AUDIO void usb_audio_interface(struct usb_interface_descriptor *, u8 *); void usb_audio_endpoint(struct usb_endpoint_descriptor *, u8 *); +void usb_audio_destroy(struct usb_device *); #else extern inline void usb_audio_interface(struct usb_interface_descriptor *interface, u8 *data) {} extern inline void usb_audio_endpoint(struct usb_endpoint_descriptor *interface, u8 *data) {} +extern inline void usb_audio_destroy(struct usb_device *) {} #endif #endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/Config.in linux.ac/drivers/video/Config.in --- linux.vanilla/drivers/video/Config.in Fri May 28 00:32:59 1999 +++ linux.ac/drivers/video/Config.in Fri Jun 4 23:52:46 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.ac/drivers/video/Makefile --- linux.vanilla/drivers/video/Makefile Fri May 28 00:32:59 1999 +++ linux.ac/drivers/video/Makefile Mon Jul 19 04:20:38 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.ac/drivers/video/fbcon-vga-planes.c --- linux.vanilla/drivers/video/fbcon-vga-planes.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/video/fbcon-vga-planes.c Fri Jun 4 23:52:46 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