diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/CREDITS linux.ac/CREDITS --- linux.vanilla/CREDITS Thu Jan 28 22:00:13 1999 +++ linux.ac/CREDITS Sat Jan 30 18:31:58 1999 @@ -46,6 +46,7 @@ P: 1024/85AD9EED AD C0 49 08 91 67 DF D7 FA 04 1A EE 09 E8 44 B0 D: Unix98 pty support. D: APM update to 1.2 spec. +D: psaux bug-fixes N: Erik Andersen E: andersee@debian.org diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/Configure.help linux.ac/Documentation/Configure.help --- linux.vanilla/Documentation/Configure.help Sun Jan 24 19:55:29 1999 +++ linux.ac/Documentation/Configure.help Sat Jan 30 18:29:12 1999 @@ -1749,6 +1749,18 @@ except that your Apollo won't be able to boot from it (because the code in the ROM will be for a PC). +Apollo support +CONFIG_APOLLO + Say Y here if you want to run Linux on an MC680x0-based Apollo + Domain workstation such as the DN3500. + +Apollo 3c505 support +CONFIG_APOLLO_ELPLUS + Say Y or M here if your Apollo has a 3Com 3c505 ISA Ethernet card. + If you don't have one made for Apollos, you can use one from a PC, + except that your Apollo won't be able to boot from it (because the + code in the ROM will be for a PC). + Atari native chipset support CONFIG_FB_ATARI This is the frame buffer device driver for the builtin graphics @@ -4176,6 +4188,17 @@ say M here and read Documentation/modules.txt. The module will be called initio.o +Initio 91XXU(W) SCSI support +CONFIG_SCSI_INITIO + This is support for the Initio 91XXU(W) SCSI host adapter. + Please read the SCSI-HOWTO, available via FTP (user: anonymous) at + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + + 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. The module will be + called initio.o + PAS16 SCSI support CONFIG_SCSI_PAS16 This is support for a SCSI host adapter. It is explained in section @@ -4189,6 +4212,17 @@ The module will be called pas16.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +Initio INI-A100U2W SCSI support +CONFIG_SCSI_INIA100 + This is support for the Initio INI-A100U2W SCSI host adapter. + Please read the SCSI-HOWTO, available via FTP (user: anonymous) at + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + + 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. The module will be + called a100u2w.o + PCI2000 support CONFIG_SCSI_PCI2000 This is support for the PCI2000I EIDE interface card which acts as a @@ -4366,6 +4400,23 @@ say M here and read Documentation/modules.txt. The module will be called NCR53c406.o. +Symbios Logic sym53c416 support +CONFIG_SCSI_SYM53C416 + This is support for the sym53c416 SCSI host adapter. This is the + SCSI adapter that comes with some hp scanners. This driver requires that + the sym53c416 is configured first using some sort of pnp configuration + program (e.g. isapnp) or by a PnP aware BIOS. If you are using isapnp then + you need to compile it as a module and then load it using insmod after + isapnp has run. The parameters of the configured card(s) should be passed + to the driver. The format is: + + insmod sym53c416 sym53c416=, [sym53c416_1=,] + + There is support for up to four adapters. If you want to compile this + driver as a module ( = code which can be inserted in and removed from + the running kernel whenever you want), say M here and read + Documentation/modules.txt. + Tekram DC390(T) and Am53/79C974 (PCscsi) SCSI support CONFIG_SCSI_DC390T This driver supports PCI SCSI host adapters based on the Am53C974A @@ -5206,27 +5257,6 @@ up to 256Kbits. It supports both PPP and Cisco HDLC At this point, the driver can only be compiled as a module. -COSA/SRP sync serial boards support -CONFIG_COSA - This is a driver for COSA and SRP synchronous serial boards. - These boards enable to connect synchronous serial devices (for - example base-band modems, or any other device with the X.21, V.24, - V.35 or V.36 interface) to your Linux box. The cards can work - as the character device, synchronous PPP network device, or the Cisco - HDLC network device. - - To actually use the COSA or SRP board, you will need user-space - utilities for downloading the firmware to the cards and to set - them up. Look at the http://www.fi.muni.cz/~kas/cosa/ for more - information about the cards (including the pointer to the user-space - utilities). You can also read the comment at the top of the - drivers/net/cosa.c for details about the cards and the driver itself. - - The driver will be compiled as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cosa.o. For general information about - modules read Documentation/modules.txt. - WAN Drivers CONFIG_WAN_DRIVERS Say Y to this option if your Linux box contains a WAN card and you @@ -9353,6 +9383,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 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 Thu Jan 14 04:02:58 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/sound/ESS linux.ac/Documentation/sound/ESS --- linux.vanilla/Documentation/sound/ESS Thu Jan 1 01:00:00 1970 +++ linux.ac/Documentation/sound/ESS Sat Jan 30 18:26:08 1999 @@ -0,0 +1,33 @@ +Documentation for the ESS AudioDrive chips + +In 2.2 kernels the SoundBlaster driver not only tries to detect an ESS chip, it +tries to detect the type of ESS chip too. The correct detection of the chip +doesn't always succeed however, so the default behaviour is 2.0 behaviour +which means: only detect ES688 and ES1688. + +All ESS chips now have a recording level setting. This is a need-to-have for +people who want to use their ESS for recording sound. + +Every chip that's detected as a later-than-es1688 chip has a 6 bits logarithmic +master volume control. + +Every chip that's detected as a ES1887 now has Full Duplex support. Made a +little testprogram that showes that is works, haven't seen a real program that +needs this however. + +For ESS chips an additional parameter "esstype" can be specified. This controls +the (auto) detection of the ESS chips. It can have 3 kinds of values: + +-1 Act like 2.0 kernels: only detect ES688 or ES1688. +0 Try to auto-detect the chip (may fail for ES1688) +688 The chip will be treated as ES688 +1688 ,, ,, ,, ,, ,, ,, ES1688 +1868 ,, ,, ,, ,, ,, ,, ES1868 +1869 ,, ,, ,, ,, ,, ,, ES1869 +1788 ,, ,, ,, ,, ,, ,, ES1788 +1887 ,, ,, ,, ,, ,, ,, ES1887 +1888 ,, ,, ,, ,, ,, ,, ES1888 + +Because Full Duplex is supported for ES1887 you can specify a second DMA +channel by specifying module parameter dma16. It can be one of: 0, 1, 3 or 5. + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sound/OPL3-SA linux.ac/Documentation/sound/OPL3-SA --- linux.vanilla/Documentation/sound/OPL3-SA Sun Nov 8 15:08:50 1998 +++ linux.ac/Documentation/sound/OPL3-SA Tue Jan 26 10:06:26 1999 @@ -2,8 +2,7 @@ --- Note: This howto only describes how to setup the OPL3-SA1 chip; this info -does not apply to the SA2, SA3, or SA4. Contact hannu@opensound.com for -the support details of these other SAx chips. +does not apply to the SA2, SA3, or SA4. --- The Yamaha OPL3-SA1 sound chip is usually found built into motherboards, and diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/video4linux/bttv/INSTALL linux.ac/Documentation/video4linux/bttv/INSTALL --- linux.vanilla/Documentation/video4linux/bttv/INSTALL Fri Nov 13 01:37:09 1998 +++ linux.ac/Documentation/video4linux/bttv/INSTALL Mon Feb 1 21:38:35 1999 @@ -41,6 +41,9 @@ 10: Newer Hauppage (Bt878) 11: Miro PCTV Pro 12: ADS Tech Channel Surfer TV (and maybe TV+FM) + 13: AVerMedia TVCapture 98 + 14: Aimslab VHX + 15: Zoltrix TV-Max - You may have to adjust BTTV_MAJOR to a different number depending on your kernel version. The official number 81 does not work on some setups. diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/video4linux/bttv/README.FIRST linux.ac/Documentation/video4linux/bttv/README.FIRST --- linux.vanilla/Documentation/video4linux/bttv/README.FIRST Sun Nov 8 15:08:51 1998 +++ linux.ac/Documentation/video4linux/bttv/README.FIRST Mon Feb 1 21:38:35 1999 @@ -1,4 +1,4 @@ o Please direct queries about the in kernel version of this driver to Alan Cox first not to Ralph, or better yet join the video4linux mailing - list (mail majordomo@phunk.org with "subscribe video4linux") + list (mail video4linux-list-request@redhat.com with "subscribe") diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/MAINTAINERS linux.ac/MAINTAINERS --- linux.vanilla/MAINTAINERS Sun Jan 24 19:55:29 1999 +++ linux.ac/MAINTAINERS Mon Feb 1 22:06:55 1999 @@ -530,6 +530,12 @@ L: netdev@roxanne.nuclecu.unam.mx S: Maintained +NFS CLIENT +P: Trond Myklebust +M: trond.myklebust@fys.uio.no +L: linux-kernel@vger.rutgers.edu +S: Maintained + NI5010 NETWORK DRIVER P: Jan-Pascal van Best and Andreas Mohr M: jvbest@qv3pluto.leidenuniv.nl (Best) @@ -672,9 +678,18 @@ S: Supported SPARC: +P: David S. Miller +M: davem@dm.cobaltmicro.com P: Eddie C. Dost M: ecd@skynet.be +P: Jakub Jelinek +M: jj@sunsite.ms.mff.cuni.cz +P: Anton Blanchard +M: anton@jubilex.progsoc.uts.edu.au L: sparclinux@vger.rutgers.edu +L: ultralinux@vger.rutgers.edu +W: http://ultra.linux.cz +W: http://www.geog.ubc.ca/s_linux.html S: Maintained SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Makefile linux.ac/Makefile --- linux.vanilla/Makefile Thu Jan 28 22:00:13 1999 +++ linux.ac/Makefile Mon Feb 1 00:45:08 1999 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 2 SUBLEVEL = 1 -EXTRAVERSION = +EXTRAVERSION = -ac3 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) @@ -397,7 +397,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 @@ -407,7 +407,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/kernel/process.c linux.ac/arch/alpha/kernel/process.c --- linux.vanilla/arch/alpha/kernel/process.c Sun Jan 24 19:55:29 1999 +++ linux.ac/arch/alpha/kernel/process.c Sun Jan 24 20:20:25 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; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/Makefile linux.ac/arch/arm/Makefile --- linux.vanilla/arch/arm/Makefile Tue Dec 22 23:19:25 1998 +++ linux.ac/arch/arm/Makefile Sun Jan 24 21:11:30 1999 @@ -15,9 +15,8 @@ CFLAGS_PROC := ASFLAGS_PROC := -# All processors get `-mshort-load-bytes' for now, to work around alignment -# problems. This is more of a hack that just happens to work than a real fix -# but it will do for now. +# GCC 2.7 uses different options to later compilers; sort out which we have +CONFIG_BINUTILS_NEW := $(shell if $(CC) --version 2>&1 | grep '^2\.7' > /dev/null; then echo n; else echo y; fi) ifeq ($(CONFIG_CPU_26),y) PROCESSOR = armo @@ -103,7 +102,7 @@ ZRELADDR = 0x00008000 endif -ifeq ($(CONFIG_ARCH_EBSA285),y) +ifeq ($(CONFIG_HOST_FOOTBRIDGE),y) MACHINE = ebsa285 ARCHDIR = ebsa285 ZTEXTADDR = 0x00008000 @@ -119,19 +118,6 @@ COMPRESSED_HEAD = head-nexuspci.o endif -ifeq ($(CONFIG_ARCH_VNC),y) -TEXTADDR = 0xC000C000 -MACHINE = vnc -ARCHDIR = vnc -endif - -ifeq ($(CONFIG_ARCH_TBOX),y) -MACHINE = tbox -ARCHDIR = tbox -ZTEXTADDR = 0x80008000 -ZRELDIR = 0x80008000 -endif - PERL = perl ifeq ($(CONFIG_BINUTILS_NEW),y) LD = $(CROSS_COMPILE)ld -m elf32arm @@ -143,7 +129,6 @@ CPP = $(CC) -E ARCHCC := $(word 1,$(CC)) GCCLIB := `$(CC) $(CFLAGS_PROC) --print-libgcc-file-name` -#GCCARCH := -B/usr/bin/arm-linuxelf- HOSTCFLAGS := $(CFLAGS:-fomit-frame-pointer=) ifeq ($(CONFIG_FRAME_POINTER),y) CFLAGS := $(CFLAGS:-fomit-frame-pointer=) @@ -153,6 +138,15 @@ LINKFLAGS = -T $(TOPDIR)/arch/arm/vmlinux-$(PROCESSOR).lds -e stext -Ttext $(TEXTADDR) ZLINKFLAGS = -Ttext $(ZTEXTADDR) +# If we're intending to debug the kernel, make sure it has line number +# information. This gets stripped out when building (z)Image so it doesn't +# add anything to the footprint of the running kernel. +# Only do this on new binutils - old binutils run out of memory on the +# final link +ifeq ($(CONFIG_DEBUG_INFO),y) +CFLAGS += -g +endif + SUBDIRS := $(SUBDIRS:drivers=arch/arm/drivers) arch/arm/lib arch/arm/kernel arch/arm/mm HEAD := arch/arm/kernel/head-$(PROCESSOR).o arch/arm/kernel/init_task.o CORE_FILES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES) @@ -161,10 +155,10 @@ BLOCK_DRIVERS := drivers/block/block.a CDROM_DRIVERS := drivers/cdrom/cdrom.a ifeq ($(CONFIG_FB),y) -CHAR_DRIVERS := arch/arm/drivers/char1/char1.a drivers/char/char.a arch/arm/drivers/char1/char1.a +CHAR_DRIVERS := arch/arm/drivers/char1/char1.a drivers/char/char.a else ifeq ($(CONFIG_VGA_CONSOLE),y) -CHAR_DRIVERS := arch/arm/drivers/char1/char1.a drivers/char/char.a arch/arm/drivers/char1/char1.a +CHAR_DRIVERS := arch/arm/drivers/char1/char1.a drivers/char/char.a else CHAR_DRIVERS := arch/arm/drivers/char/char.a endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/config.in linux.ac/arch/arm/config.in --- linux.vanilla/arch/arm/config.in Tue Jan 19 02:57:23 1999 +++ linux.ac/arch/arm/config.in Sun Jan 24 21:11:30 1999 @@ -14,18 +14,22 @@ A5000 CONFIG_ARCH_A5K \ RiscPC CONFIG_ARCH_RPC \ EBSA-110 CONFIG_ARCH_EBSA110 \ - EBSA-285 CONFIG_ARCH_EBSA285 \ - NexusPCI CONFIG_ARCH_NEXUSPCI \ - Corel-VNC CONFIG_ARCH_VNC \ - Tbox CONFIG_ARCH_TBOX" RiscPC + DC21285-based-machines CONFIG_FOOTBRIDGE" RiscPC -if [ "$CONFIG_ARCH_EBSA285" = "y" ]; then - bool ' Include support for CATS boards' CONFIG_CATS +if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then + choice 'DC21285 FootBridge mode' \ + "HostBridge CONFIG_HOST_FOOTBRIDGE \ + Add-in CONFIG_ADDIN_FOOTBRIDGE" HostBridge +fi + +if [ "$CONFIG_HOST_FOOTBRIDGE" = "y" ]; then + bool ' Include support for Intel EBSA285' CONFIG_ARCH_EBSA285 + bool ' Include support for Chalice CATS boards' CONFIG_CATS + bool ' Include support for Corel NetWinder' CONFIG_ARCH_NETWINDER fi # Select various configuration options depending on the machine type # Easy check for Acorn-style architectures - if [ "$CONFIG_ARCH_ARC" = "y" -o \ "$CONFIG_ARCH_A5K" = "y" -o \ "$CONFIG_ARCH_RPC" = "y" ]; then @@ -39,18 +43,14 @@ fi # These machines always have PCI - if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o \ - "$CONFIG_ARCH_VNC" = "y" ]; then + "$CONFIG_FOOTBRIDGE" = "y" ]; then define_bool CONFIG_PCI y fi -if [ "$CONFIG_ARCH_EBSA285" = "y" ]; then - bool "PCI support" CONFIG_PCI -fi # These machines have ISA-DMA if [ "$CONFIG_CATS" = "y" -o \ - "$CONFIG_ARCH_VNC" = "y" ]; then + "$CONFIG_ARCH_NETWINDER" = "y" ]; then define_bool CONFIG_ISA_DMA y else define_bool CONFIG_ISA_DMA n @@ -59,7 +59,6 @@ # Figure out whether this system uses 26-bit or 32-bit CPUs. Nobody has # ever built a machine that can take both, and now that ARM3 is obsolete # nobody is likely to either. - if [ "$CONFIG_ARCH_ARC" = "y" -o \ "$CONFIG_ARCH_A5K" = "y" ]; then define_bool CONFIG_CPU_32 n @@ -71,7 +70,6 @@ # Now allow the user to choose a more precise CPU. This is only used to set # the flags we pass to GCC, not in any code. - choice 'Optimise for CPU' \ "ARM2 CONFIG_CPU_ARM2 \ ARM3 CONFIG_CPU_ARM3 \ @@ -80,10 +78,8 @@ SA110 CONFIG_CPU_SA110" ARM6 if [ "$CONFIG_CPU_26" = "y" ]; then - # For 26-bit CPUs, the page size changes with the amount of physical RAM! # The default is 4MB but if the user has less they have to own up to it here. - choice 'Physical memory size' \ "4MB+ CONFIG_PAGESIZE_32 \ 2MB CONFIG_PAGESIZE_16 \ @@ -94,8 +90,10 @@ mainmenu_option next_comment comment 'Code maturity level options' bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL -bool 'Use new compilation options (for GCC 2.8)' CONFIG_BINUTILS_NEW -bool 'Compile kernel with frame pointer (for useful debugging)' CONFIG_FRAME_POINTER +if [ "$CONFIG_CPU_32" = "y" ]; then + bool 'Enable kernel-mode alignment trap handler (EXPERIMENTAL)' CONFIG_ALIGNMENT_TRAP +fi +bool 'Split text into discardable sections' CONFIG_TEXT_SECTIONS endmenu mainmenu_option next_comment @@ -119,7 +117,9 @@ tristate 'Parallel port support' CONFIG_PARPORT if [ "$CONFIG_PARPORT" != "n" ]; then - dep_tristate ' Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT + if [ "$CONFIG_ARCH_ARC" = "y" ]; then + dep_tristate ' Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT + fi dep_tristate ' PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT # If exactly one hardware type is selected then parport will optimise away # support for loading any others. Defeat this if the user is keen. @@ -129,11 +129,22 @@ fi fi fi -if [ "$CONFIG_ARCH_EBSA285" = "y" -o \ - "$CONFIG_ARCH_EBSA110" = "y" -o \ - "$CONFIG_ARCH_VNC" = "y" ]; then +if [ "$CONFIG_ARCH_EBSA110" = "y" -o \ + "$CONFIG_ARCH_NETWINDER" = "y" ]; then string 'Initial kernel command string' CONFIG_CMDLINE fi +if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \ + "$CONFIG_ARCH_EBSA110" = "y" -o \ + "$CONFIG_ARCH_EBSA285" = "y" ]; then + bool 'Timer and CPU usage LEDs' CONFIG_LEDS + if [ "$CONFIG_LEDS" = "y" ]; then + if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \ + "$CONFIG_ARCH_EBSA285" = "y" ]; then + bool 'Timer LED' CONFIG_LEDS_TIMER + bool 'CPU usage LED' CONFIG_LEDS_CPU + fi + fi +fi endmenu source drivers/pnp/Config.in @@ -150,7 +161,13 @@ source drivers/char/Config.in fi if [ "$CONFIG_ARCH_ACORN" = "y" ]; then - source drivers/acorn/char/Config.in + if [ "$CONFIG_MOUSE" = "y" ]; then + if [ "$CONFIG_ARCH_RPC" != "y" ]; then + define_bool CONFIG_KBDMOUSE y + else + define_bool CONFIG_RPCMOUSE y + fi + fi fi if [ "$CONFIG_VT" = "y" ]; then @@ -166,9 +183,11 @@ if [ "$CONFIG_NET" = "y" ]; then source net/Config.in -fi -if [ "$CONFIG_NET" = "y" ]; then + source net/ax25/Config.in + + source net/irda/Config.in + mainmenu_option next_comment comment 'Network device support' @@ -179,6 +198,15 @@ endmenu fi +# 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 'SCSI support' @@ -200,21 +228,21 @@ endmenu fi -# mainmenu_option next_comment -# comment 'ISDN subsystem' -# -# tristate 'ISDN support' CONFIG_ISDN -# if [ "$CONFIG_ISDN" != "n" ]; then -# source drivers/isdn/Config.in -# fi -# endmenu - source fs/Config.in mainmenu_option next_comment comment 'Kernel hacking' -bool 'Debug kernel errors' CONFIG_DEBUG_ERRORS +bool 'Compile kernel with frame pointer (for useful debugging)' CONFIG_FRAME_POINTER +bool 'Verbose kernel error messages' CONFIG_DEBUG_ERRORS +bool 'Verbose user fault messages' CONFIG_DEBUG_USER +bool 'Include debugging information in kernel binary' CONFIG_DEBUG_INFO #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ +if [ "$CONFIG_CPU_26" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool 'Disable pgtable cache (EXPERIMENTAL)' CONFIG_NO_PGT_CACHE +fi +if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_CPU_32" = "y" ]; then + tristate 'RISC OS personality' CONFIG_ARTHUR +fi endmenu diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/defconfig linux.ac/arch/arm/defconfig --- linux.vanilla/arch/arm/defconfig Sun Nov 8 15:08:43 1998 +++ linux.ac/arch/arm/defconfig Sun Jan 24 21:11:30 1999 @@ -4,47 +4,72 @@ CONFIG_ARM=y # +# System and processor type +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_EBSA110 is not set +CONFIG_FOOTBRIDGE=y +CONFIG_HOST_FOOTBRIDGE=y +# CONFIG_ADDIN_FOOTBRIDGE is not set +CONFIG_ARCH_EBSA285=y +# CONFIG_CATS is not set +CONFIG_ARCH_NETWINDER=y +# CONFIG_ARCH_ACORN is not set +CONFIG_PCI=y +CONFIG_ISA_DMA=y +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +# CONFIG_CPU_ARM2 is not set +# CONFIG_CPU_ARM3 is not set +# CONFIG_CPU_ARM6 is not set +# CONFIG_CPU_ARM7 is not set +CONFIG_CPU_SA110=y +# CONFIG_PAGESIZE_32 is not set +# CONFIG_PAGESIZE_16 is not set +# CONFIG_PAGESIZE_8 is not set + +# # Code maturity level options # CONFIG_EXPERIMENTAL=y +# CONFIG_ALIGNMENT_TRAP is not set +# CONFIG_TEXT_SECTIONS is not set # # Loadable module support # CONFIG_MODULES=y -CONFIG_MODVERSIONS=y +# CONFIG_MODVERSIONS is not set CONFIG_KMOD=y # # General setup # -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set -CONFIG_ARCH_RPC=y -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_NEXUSPCI is not set -CONFIG_ARCH_ACORN=y -# CONFIG_PCI is not set -# CONFIG_CPU_ARM2 is not set -# CONFIG_CPU_ARM3 is not set -# CONFIG_CPU_ARM6 is not set -CONFIG_CPU_SA110=y -CONFIG_FRAME_POINTER=y -# CONFIG_BINUTILS_NEW is not set -CONFIG_DEBUG_ERRORS=y CONFIG_NET=y CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y CONFIG_BINFMT_AOUT=y -CONFIG_BINFMT_ELF=m -# CONFIG_BINFMT_JAVA is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set CONFIG_PARPORT=y CONFIG_PARPORT_PC=y +CONFIG_CMDLINE="root=/dev/hda2 ro mem=32M parport=0x378,23 ide0=autotune" +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +# CONFIG_LEDS_CPU is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set # -# Floppy, IDE, and other block devices +# Block devices # -CONFIG_BLK_DEV_FD=y +# CONFIG_BLK_DEV_FD is not set CONFIG_BLK_DEV_IDE=y # @@ -52,47 +77,186 @@ # # CONFIG_BLK_DEV_HD_IDE is not set CONFIG_BLK_DEV_IDEDISK=y -CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDECD is not set # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_BLK_DEV_IDE_PCMCIA is not set -CONFIG_BLK_DEV_IDE_CARDS=y -CONFIG_BLK_DEV_IDE_ICSIDE=y -# CONFIG_BLK_DEV_IDE_RAPIDE is not set -# CONFIG_BLK_DEV_XD is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_RZ1000 is not set +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_BLK_DEV_IDEDMA=y +CONFIG_BLK_DEV_OFFBOARD=y +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_VIA82C586 is not set +# CONFIG_BLK_DEV_CMD646 is not set +CONFIG_BLK_DEV_SL82C105=y +# CONFIG_IDE_CHIPSETS is not set # # Additional Block Devices # CONFIG_BLK_DEV_LOOP=m -# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_STRIPED=m +CONFIG_MD_MIRRORING=m +CONFIG_MD_RAID5=m CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_BLK_DEV_XD is not set CONFIG_PARIDE_PARPORT=y -# CONFIG_PARIDE is not set -CONFIG_BLK_DEV_PART=y +CONFIG_PARIDE=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m # CONFIG_BLK_DEV_HD is not set # +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set +CONFIG_PRINTER=m +CONFIG_PRINTER_READBACK=y +CONFIG_MOUSE=y + +# +# Mice +# +# CONFIG_ATIXL_BUSMOUSE is not set +# CONFIG_BUSMOUSE is not set +# CONFIG_MS_BUSMOUSE is not set +CONFIG_PSMOUSE=y +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set +CONFIG_DS1620=y +# CONFIG_QIC02_TAPE is not set +CONFIG_WATCHDOG=y + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_WDT is not set +CONFIG_SOFT_WATCHDOG=y +# CONFIG_PCWATCHDOG is not set +# CONFIG_ACQUIRE_WDT is not set +CONFIG_DS1620=y +# CONFIG_NVRAM is not set +CONFIG_NWBUTTON=y +CONFIG_NWBUTTON_REBOOT=y +CONFIG_RTC=y + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set + +# +# Joystick support +# +# CONFIG_JOYSTICK is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_FT_NORMAL_DEBUG is not set +# CONFIG_FT_FULL_DEBUG is not set +# CONFIG_FT_NO_TRACE is not set +# CONFIG_FT_NO_TRACE_AT_ALL is not set +# CONFIG_FT_STD_FDC is not set +# CONFIG_FT_MACH2 is not set +# CONFIG_FT_PROBE_FC10 is not set +# CONFIG_FT_ALT_FDC is not set + +# +# Console drivers +# +CONFIG_VGA_CONSOLE=y +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FB_CYBER2000=y +# CONFIG_FB_MATROX is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_VIRTUAL is not set +CONFIG_FBCON_ADVANCED=y +# CONFIG_FBCON_MFB is not set +# CONFIG_FBCON_CFB2 is not set +# CONFIG_FBCON_CFB4 is not set +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +CONFIG_FBCON_CFB24=y +# CONFIG_FBCON_CFB32 is not set +# CONFIG_FBCON_AFB is not set +# CONFIG_FBCON_ILBM is not set +# CONFIG_FBCON_IPLAN2P2 is not set +# CONFIG_FBCON_IPLAN2P4 is not set +# CONFIG_FBCON_IPLAN2P8 is not set +# CONFIG_FBCON_MAC is not set +CONFIG_FBCON_VGA=y +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +CONFIG_FBCON_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_PEARL_8x8 is not set +CONFIG_FONT_ACORN_8x8=y + +# # Networking options # -# CONFIG_PACKET is not set +CONFIG_PACKET=y # CONFIG_NETLINK is not set # CONFIG_FIREWALL is not set -# CONFIG_NET_ALIAS is not set +CONFIG_NET_ALIAS=y # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_IP_ACCT is not set -# CONFIG_IP_MASQUERADE is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set -# CONFIG_IP_ALIAS is not set +CONFIG_IP_ALIAS=y # CONFIG_SYN_COOKIES is not set # @@ -100,7 +264,7 @@ # # CONFIG_INET_RARP is not set CONFIG_IP_NOSR=y -# CONFIG_SKB_LARGE is not set +CONFIG_SKB_LARGE=y # CONFIG_IPV6 is not set # @@ -112,155 +276,228 @@ # CONFIG_LAPB is not set # CONFIG_BRIDGE is not set # CONFIG_LLC is not set +# CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_FASTROUTE is not set # CONFIG_NET_HW_FLOWCONTROL is not set # CONFIG_CPU_IS_SLOW is not set + +# +# QoS and/or fair queueing +# # CONFIG_NET_SCHED is not set -# CONFIG_NET_PROFILE is not set # -# SCSI support +# Amateur Radio support # -CONFIG_SCSI=y +# CONFIG_HAMRADIO is not set # -# SCSI support type (disk, tape, CD-ROM) +# IrDA subsystem support # -CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set -CONFIG_BLK_DEV_SR=y -# CONFIG_BLK_DEV_SR_VENDOR is not set -# CONFIG_CHR_DEV_SG is not set +# CONFIG_IRDA is not set # -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# Network device support # -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y +CONFIG_NETDEVICES=y +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +CONFIG_NET_VENDOR_3COM=y +# CONFIG_EL1 is not set +# CONFIG_EL2 is not set +# CONFIG_ELPLUS is not set +# CONFIG_EL16 is not set +# CONFIG_EL3 is not set +# CONFIG_3C515 is not set +CONFIG_VORTEX=y +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_RTL8139 is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_EISA=y +# CONFIG_PCNET32 is not set +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +# CONFIG_DE4X5 is not set +CONFIG_DEC_ELCP=m +# CONFIG_DGRS is not set +# CONFIG_EEXPRESS_PRO100 is not set +# CONFIG_LNE390 is not set +# CONFIG_NE3210 is not set +CONFIG_NE2K_PCI=y +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_ES3210 is not set +# CONFIG_EPIC100 is not set +# CONFIG_ZNET is not set +# CONFIG_NET_POCKET is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_DLCI is not set +# CONFIG_PLIP is not set +CONFIG_PPP=m # -# SCSI low-level drivers +# CCP compressors for PPP are only built as modules. # -CONFIG_SCSI_ACORNSCSI_3=m -CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE=y -CONFIG_SCSI_ACORNSCSI_SYNC=y -CONFIG_SCSI_CUMANA_2=m -CONFIG_SCSI_POWERTECSCSI=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y +# CONFIG_NET_RADIO is not set +# CONFIG_TR is not set +# CONFIG_SHAPER is not set +# CONFIG_HOSTESS_SV11 is not set +# CONFIG_COSA is not set +# CONFIG_RCPCI is not set # -# The following drives are not fully supported +# SCSI support # -CONFIG_SCSI_CUMANA_1=m -CONFIG_SCSI_OAK1=m -CONFIG_SCSI_PPA=m -CONFIG_SCSI_PPA_HAVE_PEDANTIC=2 +# CONFIG_SCSI is not set +# CONFIG_SCSI_G_NCR5380_PORT is not set +# CONFIG_SCSI_G_NCR5380_MEM is not set # -# Network device support +# Sound # -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_EQUALIZER is not set -CONFIG_PPP=m +CONFIG_SOUND=m +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +CONFIG_SOUND_OSS=m +# CONFIG_SOUND_PAS is not set +# CONFIG_SOUND_SB is not set +CONFIG_SOUND_ADLIB=m +# CONFIG_SOUND_GUS is not set +# CONFIG_SOUND_MPU401 is not set +# CONFIG_SOUND_PSS is not set +# CONFIG_SOUND_MSS is not set +# CONFIG_SOUND_SSCAPE is not set +# CONFIG_SOUND_TRIX is not set +# CONFIG_SOUND_MAD16 is not set +# CONFIG_SOUND_WAVEFRONT is not set +# CONFIG_SOUND_CS4232 is not set +CONFIG_SOUND_OPL3SA2=m +# CONFIG_SOUND_MAUI is not set +# CONFIG_SOUND_SGALAXY is not set +# CONFIG_SOUND_AD1816 is not set +# CONFIG_SOUND_OPL3SA1 is not set +# CONFIG_SOUND_SOFTOSS is not set +# CONFIG_SOUND_YM3812 is not set +# CONFIG_SOUND_VMIDI is not set +# CONFIG_SOUND_UART6850 is not set +# CONFIG_SOUND_VIDC is not set +CONFIG_SOUND_WAVEARTIST=m +CONFIG_WAVEARTIST_BASE=250 +CONFIG_WAVEARTIST_IRQ=28 +CONFIG_WAVEARTIST_DMA=5 +CONFIG_WAVEARTIST_DMA2=9 # -# CCP compressors for PPP are only built as modules. +# Additional low level sound drivers # -# CONFIG_SLIP is not set -CONFIG_ETHER1=m -CONFIG_ETHER3=m -CONFIG_ETHERH=m +# CONFIG_LOWLEVEL_SOUND is not set # # Filesystems # # CONFIG_QUOTA is not set -# CONFIG_MINIX_FS is not set -CONFIG_EXT2_FS=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -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_AUTOFS_FS is not set +CONFIG_ADFS_FS=y # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +# CONFIG_UMSDOS_FS is not set +CONFIG_VFAT_FS=m +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set -# CONFIG_AUTOFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set -CONFIG_ADFS_FS=y -CONFIG_ADFS_FS=y -# CONFIG_MAC_PARTITION is not set -CONFIG_NLS=y # -# Native Language Support +# Network File Systems # -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_KOI8_R is not set +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_NFSD=m +# CONFIG_NFSD_SUN is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set # -# Character devices +# Partition Types # -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -# CONFIG_SERIAL_CONSOLE is not set -# CONFIG_SERIAL_EXTENDED is not set -CONFIG_ATOMWIDE_SERIAL=y -CONFIG_DUALSP_SERIAL=y -CONFIG_MOUSE=y -CONFIG_PRINTER=m -CONFIG_PRINTER_READBACK=y -# CONFIG_UMISC is not set -# CONFIG_WATCHDOG is not set -CONFIG_RPCMOUSE=y +# CONFIG_OSF_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +CONFIG_ACORN_PARTITION=y +CONFIG_ACORN_PARTITION_ADFS=y +# CONFIG_ACORN_PARTITION_ICS is not set +# CONFIG_ACORN_PARTITION_POWERTEC is not set +# CONFIG_ACORN_PARTITION_RISCIX is not set +CONFIG_NLS=y # -# Sound +# Native Language Support # -CONFIG_SOUND=m -CONFIG_VIDC=y -CONFIG_AUDIO=y -DSP_BUFFSIZE=65536 +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 is not set +CONFIG_NLS_KOI8_R=m # # Kernel hacking # +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_USER is not set CONFIG_MAGIC_SYSRQ=y +# CONFIG_ARTHUR is not set diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/Makefile linux.ac/arch/arm/kernel/Makefile --- linux.vanilla/arch/arm/kernel/Makefile Tue Dec 22 23:19:26 1998 +++ linux.ac/arch/arm/kernel/Makefile Sun Jan 24 21:11:30 1999 @@ -9,31 +9,39 @@ ENTRY_OBJ = entry-$(PROCESSOR).o O_TARGET := kernel.o -O_OBJS := $(ENTRY_OBJ) ioport.o irq.o process.o ptrace.o setup.o \ +O_OBJS := $(ENTRY_OBJ) irq.o process.o ptrace.o setup.o \ signal.o sys_arm.o time.o traps.o -DMA_OBJS_arc = dma-arc.o -DMA_OBJS_a5k = dma-a5k.o -DMA_OBJS_rpc = dma-rpc.o -DMA_OBJS_ebsa110 = dma-dummy.o -DMA_OBJS_ebsa285 = dma-ebsa285.o -DMA_OBJS_nexuspci = -DMA_OBJS_vnc = dma-vnc.o - -O_OBJS_arc = ecard.o iic.o fiq.o oldlatches.o -O_OBJS_a5k = ecard.o iic.o fiq.o -O_OBJS_rpc = ecard.o iic.o fiq.o -O_OBJS_ebsa110 = leds-ebsa110.o -O_OBJS_ebsa285 = leds-ebsa285.o hw-ebsa285.o -O_OBJS_nexuspci = -O_OBJS_vnc = leds-ebsa285.o hw-vnc.o +ifeq ($(CONFIG_ISA_DMA),y) + ISA_DMA_OBJS += dma-isa.o +endif + +O_OBJS_arc = dma-arc.o iic.o fiq.o oldlatches.o +O_OBJS_a5k = dma-a5k.o iic.o fiq.o +O_OBJS_rpc = dma-rpc.o iic.o fiq.o +O_OBJS_ebsa110 = dma-dummy.o +O_OBJS_ebsa285 = dma-ebsa285.o $(ISA_DMA_OBJS) +O_OBJS_nexuspci = dma-dummy.o +O_OBJS_co285 = dma-ebsa285.o $(ISA_DMA_OBJS) + +OX_OBJS_arc = dma.o +OX_OBJS_a5k = dma.o +OX_OBJS_rpc = dma.o +OX_OBJS_ebsa110 = +OX_OBJS_ebsa285 = dma.o hw-ebsa285.o +OX_OBJS_nexuspci = +OX_OBJS_co285 = dma.o all: lib kernel.o $(HEAD_OBJ) init_task.o +O_OBJS += $(O_OBJS_$(MACHINE)) + ifeq ($(CONFIG_MODULES),y) OX_OBJS = armksyms.o -else - O_OBJS += armksyms.o +endif + +ifeq ($(CONFIG_ARCH_ACORN),y) + OX_OBJS += ecard.o endif ifeq ($(MACHINE),nexuspci) @@ -46,17 +54,23 @@ endif endif -ifneq ($(DMA_OBJS_$(MACHINE)),) - OX_OBJS += dma.o - O_OBJS += $(DMA_OBJS_$(MACHINE)) - ifeq ($(CONFIG_ISA_DMA),y) - O_OBJS += dma-isa.o - endif +ifdef CONFIG_LEDS + O_OBJS += leds-$(MACHINE).o +endif + +ifeq ($(CONFIG_MODULES),y) + OX_OBJS += $(OX_OBJS_$(MACHINE)) else - O_OBJS += dma-dummy.o + O_OBJS += $(OX_OBJS_$(MACHINE)) endif -O_OBJS += $(O_OBJS_$(MACHINE)) +ifeq ($(CONFIG_ARTHUR),y) + O_OBJS += arthur.o +else + ifeq ($(CONFIG_ARTHUR),m) + M_OBJS += arthur.o + endif +endif $(HEAD_OBJ): $(HEAD_OBJ:.o=.S) $(CC) -D__ASSEMBLY__ -DTEXTADDR=$(TEXTADDR) -traditional -c $(HEAD_OBJ:.o=.S) -o $@ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/armksyms.c linux.ac/arch/arm/kernel/armksyms.c --- linux.vanilla/arch/arm/kernel/armksyms.c Sun Nov 8 15:08:43 1998 +++ linux.ac/arch/arm/kernel/armksyms.c Sun Jan 24 21:11:30 1999 @@ -7,11 +7,11 @@ #include #include -#include #include #include #include #include +#include #include #include @@ -20,6 +20,19 @@ extern void inswb(unsigned int port, void *to, int len); extern void outswb(unsigned int port, const void *to, int len); +extern unsigned int local_bh_count[NR_CPUS]; +extern unsigned int local_irq_count[NR_CPUS]; + +/* + * syscalls + */ +extern int sys_write(int, const char *, int); +extern int sys_read(int, char *, int); +extern int sys_lseek(int, off_t, int); +extern int sys_open(const char *, int, int); +extern int sys_exit(int); +extern int sys_wait4(int, int *, int, struct rusage *); + /* * libgcc functions - functions that are used internally by the * compiler... (prototypes are not correct though, but that @@ -62,14 +75,8 @@ EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(udelay); EXPORT_SYMBOL(xchg_str); - - /* expansion card support */ -#ifdef CONFIG_ARCH_ACORN -EXPORT_SYMBOL(ecard_startfind); -EXPORT_SYMBOL(ecard_find); -EXPORT_SYMBOL(ecard_readchunk); -EXPORT_SYMBOL(ecard_address); -#endif +EXPORT_SYMBOL(local_bh_count); +EXPORT_SYMBOL(local_irq_count); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); @@ -167,3 +174,17 @@ EXPORT_SYMBOL(armidlist); EXPORT_SYMBOL(armidindex); EXPORT_SYMBOL(elf_platform); + + /* syscalls */ +EXPORT_SYMBOL(sys_write); +EXPORT_SYMBOL(sys_read); +EXPORT_SYMBOL(sys_lseek); +EXPORT_SYMBOL(sys_open); +EXPORT_SYMBOL(sys_exit); +EXPORT_SYMBOL(sys_wait4); + + /* semaphores */ +EXPORT_SYMBOL_NOVERS(__down_failed); +EXPORT_SYMBOL_NOVERS(__down_interruptible_failed); +EXPORT_SYMBOL_NOVERS(__up_wakeup); + diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/arthur.c linux.ac/arch/arm/kernel/arthur.c --- linux.vanilla/arch/arm/kernel/arthur.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/arm/kernel/arthur.c Sun Jan 24 21:11:30 1999 @@ -0,0 +1,88 @@ +/* + * Arthur personality + * Copyright (C) 1998 Philip Blundell + */ + +#include +#include +#include +#include +#include + +#include + +/* RISC OS doesn't have many signals, and a lot of those that it does + have don't map easily to any Linux equivalent. Never mind. */ + +#define RISCOS_SIGABRT 1 +#define RISCOS_SIGFPE 2 +#define RISCOS_SIGILL 3 +#define RISCOS_SIGINT 4 +#define RISCOS_SIGSEGV 5 +#define RISCOS_SIGTERM 6 +#define RISCOS_SIGSTAK 7 +#define RISCOS_SIGUSR1 8 +#define RISCOS_SIGUSR2 9 +#define RISCOS_SIGOSERROR 10 + +static unsigned long riscos_to_linux_signals[32] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31 +}; + +static unsigned long linux_to_riscos_signals[32] = { + 0, -1, RISCOS_SIGINT, -1, + RISCOS_SIGILL, 5, RISCOS_SIGABRT, 7, + RISCOS_SIGFPE, 9, RISCOS_SIGUSR1, RISCOS_SIGSEGV, + RISCOS_SIGUSR2, 13, 14, RISCOS_SIGTERM, + 16, 17, 18, 19, + 20, 21, 22, 23, + 24, 25, 26, 27, + 28, 29, 30, 31 +}; + +static void arthur_lcall7(int nr, struct pt_regs *regs) +{ + struct siginfo info; + info.si_signo = SIGSWI; + info.si_code = nr; + /* Bounce it to the emulator */ + send_sig_info(SIGSWI, &info, current); +} + +static struct exec_domain riscos_exec_domain = { + "Arthur", /* name */ + (lcall7_func)arthur_lcall7, + PER_RISCOS, PER_RISCOS, + riscos_to_linux_signals, + linux_to_riscos_signals, +#ifdef MODULE + &__this_module, /* No usage counter. */ +#else + NULL, +#endif + NULL /* Nothing after this in the list. */ +}; + +/* + * We could do with some locking to stop Arthur being removed while + * processes are using it. + */ + +#ifdef MODULE +int init_module(void) +#else +int initialise_arthur(void) +#endif +{ + return register_exec_domain(&riscos_exec_domain); +} + +#ifdef MODULE +void cleanup_module(void) +{ + unregister_exec_domain(&riscos_exec_domain); +} +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/calls.S linux.ac/arch/arm/kernel/calls.S --- linux.vanilla/arch/arm/kernel/calls.S Tue Dec 22 23:19:26 1998 +++ linux.ac/arch/arm/kernel/calls.S Sun Jan 24 21:11:30 1999 @@ -110,7 +110,7 @@ .long SYMBOL_NAME(sys_ni_syscall) /* was sys_profil */ .long SYMBOL_NAME(sys_statfs) /* 100 */ .long SYMBOL_NAME(sys_fstatfs) - .long SYMBOL_NAME(sys_ni_syscall) /* .long _sys_ioperm */ + .long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_socketcall) .long SYMBOL_NAME(sys_syslog) .long SYMBOL_NAME(sys_setitimer) @@ -119,7 +119,7 @@ .long SYMBOL_NAME(sys_newlstat) .long SYMBOL_NAME(sys_newfstat) .long SYMBOL_NAME(sys_uname) -/* 110 */ .long SYMBOL_NAME(sys_iopl) +/* 110 */ .long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_vhangup) .long SYMBOL_NAME(sys_idle) .long SYMBOL_NAME(sys_syscall) /* call a syscall */ @@ -196,6 +196,10 @@ .long SYMBOL_NAME(sys_capget) /* 185 */ .long SYMBOL_NAME(sys_capset) .long SYMBOL_NAME(sys_sigaltstack_wrapper) + .long SYMBOL_NAME(sys_sendfile) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) +/* 190 */ .long SYMBOL_NAME(sys_vfork_wrapper) .rept NR_syscalls-186 .long SYMBOL_NAME(sys_ni_syscall) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/dec21285.c linux.ac/arch/arm/kernel/dec21285.c --- linux.vanilla/arch/arm/kernel/dec21285.c Tue Dec 22 23:19:26 1998 +++ linux.ac/arch/arm/kernel/dec21285.c Sun Jan 24 21:11:30 1999 @@ -17,8 +17,6 @@ extern void pcibios_fixup_ebsa285(struct pci_dev *dev); extern void pcibios_init_ebsa285(void); -extern void pcibios_fixup_vnc(struct pci_dev *dev); -extern void pcibios_init_vnc(void); int pcibios_present(void) @@ -151,10 +149,7 @@ struct pci_dev *dev; for (dev = pci_devices; dev; dev = dev->next) { - if (machine_is_ebsa285() || machine_is_cats()) - pcibios_fixup_ebsa285(dev); - if (machine_is_netwinder()) - pcibios_fixup_vnc(dev); + pcibios_fixup_ebsa285(dev); pcibios_write_config_byte(dev->bus->number, dev->devfn, PCI_INTERRUPT_LINE, dev->irq); @@ -164,18 +159,18 @@ dev->bus->number, dev->devfn, dev->vendor, dev->device, dev->irq); } + /* + * this ought to have a better home + */ if (machine_is_netwinder()) hw_init(); } __initfunc(void pcibios_init(void)) { - if (machine_is_ebsa285() || machine_is_cats()) - pcibios_init_ebsa285(); - if (machine_is_netwinder()) - pcibios_init_vnc(); + pcibios_init_ebsa285(); - printk("DEC21285 PCI revision %02X\n", *(unsigned char *)0xfe000008); + printk(KERN_DEBUG "PCI: DEC21285 revision %02X\n", *(unsigned char *)0xfe000008); } __initfunc(void pcibios_fixup_bus(struct pci_bus *bus)) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/dma-arc.c linux.ac/arch/arm/kernel/dma-arc.c --- linux.vanilla/arch/arm/kernel/dma-arc.c Sun Nov 8 15:08:43 1998 +++ linux.ac/arch/arm/kernel/dma-arc.c Sun Jan 24 21:11:31 1999 @@ -14,7 +14,7 @@ #include "dma.h" -int arch_request_dma(dmach_t channel, dma_t *dma) +int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id) { if (channel == DMA_VIRTUAL_FLOPPY0 || channel == DMA_VIRTUAL_FLOPPY1) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/dma-ebsa285.c linux.ac/arch/arm/kernel/dma-ebsa285.c --- linux.vanilla/arch/arm/kernel/dma-ebsa285.c Tue Dec 22 23:19:26 1998 +++ linux.ac/arch/arm/kernel/dma-ebsa285.c Sun Jan 24 21:11:31 1999 @@ -30,10 +30,11 @@ case 0: case 1: /* 21285 internal channels */ return 0; - +#ifdef CONFIG_ISA_DMA case 2 ... 9: - if (machine_is_cats()) + if (machine_is_cats() || machine_is_netwinder()) return isa_request_dma(channel - 2, dma, dev_name); +#endif } return -EINVAL; @@ -52,10 +53,9 @@ case 0: case 1: break; -#ifdef CONFIG_CATS +#ifdef CONFIG_ISA_DMA case 2 ... 9: - if (machine_is_cats()) - residue = isa_get_dma_residue(channel - 2); + residue = isa_get_dma_residue(channel - 2, dma); #endif } return residue; @@ -70,10 +70,9 @@ * Not yet implemented */ break; -#ifdef CONFIG_CATS +#ifdef CONFIG_ISA_DMA case 2 ... 9: - if (machine_is_cats()) - isa_enable_dma(channel - 2, dma); + isa_enable_dma(channel - 2, dma); #endif } } @@ -87,15 +86,17 @@ * Not yet implemented */ break; -#ifdef CONFIG_CATS +#ifdef CONFIG_ISA_DMA case 2 ... 9: - if (machine_is_cats()) - isa_disable_dma(channel - 2, dma); + isa_disable_dma(channel - 2, dma); #endif } } __initfunc(void arch_dma_init(dma_t *dma)) { - /* Nothing to do */ +#ifdef CONFIG_ISA_DMA + if (machine_is_cats() || machine_is_netwinder()) + isa_init_dma(); +#endif } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/dma-isa.c linux.ac/arch/arm/kernel/dma-isa.c --- linux.vanilla/arch/arm/kernel/dma-isa.c Tue Dec 22 23:19:26 1998 +++ linux.ac/arch/arm/kernel/dma-isa.c Sun Jan 24 21:11:31 1999 @@ -11,6 +11,7 @@ * Copyright (C) 1998 Phil Blundell */ #include +#include #include #include @@ -18,6 +19,10 @@ #include "dma.h" #include "dma-isa.h" +#define ISA_DMA_MODE_READ 0x44 +#define ISA_DMA_MODE_WRITE 0x48 +#define ISA_DMA_AUTOINIT 0x10 + #define ISA_DMA_MASK 0 #define ISA_DMA_MODE 1 #define ISA_DMA_CLRFF 2 @@ -56,25 +61,27 @@ unsigned int io_port = isa_dma_port[channel][ISA_DMA_COUNT]; int count; - count = 1 + inb(io_port) + (inb(io_port) << 8); + count = 1 + inb(io_port); + count |= inb(io_port) << 8; return channel < 4 ? count : (count << 1); } void isa_enable_dma(int channel, dma_t *dma) { - unsigned long address, length; - if (dma->invalid) { + unsigned long address, length; + unsigned int mode; + address = dma->buf.address; length = dma->buf.length - 1; - outb(address >> 24, isa_dma_port[channel][ISA_DMA_PGHI]); outb(address >> 16, isa_dma_port[channel][ISA_DMA_PGLO]); + outb(address >> 24, isa_dma_port[channel][ISA_DMA_PGHI]); if (channel >= 4) { address >>= 1; - length = (length >> 1) & 0xfe; /* why &0xfe? */ + length >>= 1; } outb(0, isa_dma_port[channel][ISA_DMA_CLRFF]); @@ -85,17 +92,27 @@ outb(length, isa_dma_port[channel][ISA_DMA_COUNT]); outb(length >> 8, isa_dma_port[channel][ISA_DMA_COUNT]); - outb(dma->dma_mode | (channel & 3), isa_dma_port[channel][ISA_DMA_MODE]); + mode = channel & 3; - switch (dma->dma_mode) { + switch (dma->dma_mode & DMA_MODE_MASK) { case DMA_MODE_READ: + mode |= ISA_DMA_MODE_READ; dma_cache_inv(__bus_to_virt(dma->buf.address), dma->buf.length); break; case DMA_MODE_WRITE: + mode |= ISA_DMA_MODE_WRITE; dma_cache_wback(__bus_to_virt(dma->buf.address), dma->buf.length); break; + + default: + break; } + + if (dma->dma_mode & DMA_AUTOINIT) + mode |= ISA_DMA_AUTOINIT; + + outb(mode, isa_dma_port[channel][ISA_DMA_MODE]); dma->invalid = 0; } outb(channel & 3, isa_dma_port[channel][ISA_DMA_MASK]); @@ -104,4 +121,39 @@ void isa_disable_dma(int channel, dma_t *dma) { outb(channel | 4, isa_dma_port[channel][ISA_DMA_MASK]); +} + +__initfunc(void isa_init_dma(void)) +{ + int channel; + + outb(0xff, 0x0d); + outb(0xff, 0xda); + + for (channel = 0; channel < 8; channel++) + isa_disable_dma(channel, NULL); + + outb(0x40, 0x0b); + outb(0x41, 0x0b); + outb(0x42, 0x0b); + outb(0x43, 0x0b); + + outb(0xc0, 0xd6); + outb(0x41, 0xd6); + outb(0x42, 0xd6); + outb(0x43, 0xd6); + + outb(0, 0xd4); + + outb(0x10, 0x08); + outb(0x10, 0xd0); + + outb(0x30, 0x40b); + outb(0x31, 0x40b); + outb(0x32, 0x40b); + outb(0x33, 0x40b); + + outb(0x31, 0x4d6); + outb(0x32, 0x4d6); + outb(0x33, 0x4d6); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/dma-isa.h linux.ac/arch/arm/kernel/dma-isa.h --- linux.vanilla/arch/arm/kernel/dma-isa.h Tue Dec 22 23:19:26 1998 +++ linux.ac/arch/arm/kernel/dma-isa.h Sun Jan 24 21:11:31 1999 @@ -23,3 +23,7 @@ */ void isa_disable_dma(int channel, dma_t *dma); +/* + * Initialise DMA + */ +void isa_init_dma(void); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/dma-rpc.c linux.ac/arch/arm/kernel/dma-rpc.c --- linux.vanilla/arch/arm/kernel/dma-rpc.c Sun Nov 8 15:08:43 1998 +++ linux.ac/arch/arm/kernel/dma-rpc.c Sun Jan 24 21:11:31 1999 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/dma-vnc.c linux.ac/arch/arm/kernel/dma-vnc.c --- linux.vanilla/arch/arm/kernel/dma-vnc.c Tue Dec 22 23:19:26 1998 +++ linux.ac/arch/arm/kernel/dma-vnc.c Thu Jan 1 01:00:00 1970 @@ -1,51 +0,0 @@ -/* - * arch/arm/kernel/dma-vnc.c - * - * Copyright (C) 1998 Russell King - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "dma.h" -#include "dma-isa.h" - -int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name) -{ - if (channel < 8) - return isa_request_dma(channel, dma, dev_name); - return -EINVAL; -} - -void arch_free_dma(dmach_t channel, dma_t *dma) -{ - isa_free_dma(channel, dma); -} - -int arch_get_dma_residue(dmach_t channel, dma_t *dma) -{ - return isa_get_dma_residue(channel, dma); -} - -void arch_enable_dma(dmach_t channel, dma_t *dma) -{ - isa_enable_dma(channel, dma); -} - -void arch_disable_dma(dmach_t channel, dma_t *dma) -{ - isa_disable_dma(channel, dma); -} - -__initfunc(void arch_dma_init(dma_t *dma)) -{ - /* Nothing to do */ -} - diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/ecard.c linux.ac/arch/arm/kernel/ecard.c --- linux.vanilla/arch/arm/kernel/ecard.c Mon Dec 28 23:09:40 1998 +++ linux.ac/arch/arm/kernel/ecard.c Sun Jan 24 21:11:31 1999 @@ -7,32 +7,41 @@ * * Created from information from Acorns RiscOS3 PRMs * - * 08-Dec-1996 RMK Added code for the 9'th expansion card - the ether podule slot. + * 08-Dec-1996 RMK Added code for the 9'th expansion card - the ether + * podule slot. * 06-May-1997 RMK Added blacklist for cards whose loader doesn't work. - * 12-Sep-1997 RMK Created new handling of interrupt enables/disables - cards can - * now register their own routine to control interrupts (recommended). - * 29-Sep-1997 RMK Expansion card interrupt hardware not being re-enabled on reset from - * Linux. (Caused cards not to respond under RiscOS without hard reset). + * 12-Sep-1997 RMK Created new handling of interrupt enables/disables + * - cards can now register their own routine to control + * interrupts (recommended). + * 29-Sep-1997 RMK Expansion card interrupt hardware not being re-enabled + * on reset from Linux. (Caused cards not to respond + * under RiscOS without hard reset). * 15-Feb-1998 RMK Added DMA support * 12-Sep-1998 RMK Added EASI support + * 10-Jan-1999 RMK Run loaders in a simulated RISC OS environment. */ #define ECARD_C +#define __KERNEL_SYSCALLS__ #include +#include #include #include #include #include #include #include +#include +#include #include -#include -#include +#include #include +#include +#include #include -#include +#include #ifdef CONFIG_ARCH_ARC #include @@ -40,45 +49,418 @@ #define oldlatch_init() #endif -#define BLACKLIST_NAME(m,p,s) { m, p, NULL, s } -#define BLACKLIST_LOADER(m,p,l) { m, p, l, NULL } -#define BLACKLIST_NOLOADER(m,p) { m, p, noloader, blacklisted_str } -#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE) +enum req { + req_readbytes, + req_reset +}; -extern unsigned long atomwide_serial_loader[], oak_scsi_loader[], noloader[]; -static const char blacklisted_str[] = "*loader s/w is not 32-bit compliant*"; +struct ecard_request { + enum req req; + ecard_t *ec; + unsigned int address; + unsigned int length; + unsigned int use_loader; + void *buffer; +}; -static const struct expcard_blacklist { +struct expcard_blacklist { unsigned short manufacturer; unsigned short product; - const loader_t loader; const char *type; -} blacklist[] = { -/* Cards without names */ - BLACKLIST_NAME(MANU_ACORN, PROD_ACORN_ETHER1, "Acorn Ether1"), - -/* Cards with corrected loader */ - BLACKLIST_LOADER(MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL, atomwide_serial_loader), - BLACKLIST_LOADER(MANU_OAK, PROD_OAK_SCSI, oak_scsi_loader), +}; -/* Supported cards with broken loader */ - { MANU_ALSYSTEMS, PROD_ALSYS_SCSIATAPI, noloader, "AlSystems PowerTec SCSI" }, +static pid_t ecard_pid; +static struct wait_queue *ecard_wait; +static struct wait_queue *ecard_done; +static struct ecard_request *ecard_req; +static struct task_struct *ecard_tsk; +static ecard_t *cards; +static ecard_t *slot_to_expcard[MAX_ECARDS]; +#ifdef HAS_EXPMASK +static unsigned int have_expmask; +#endif -/* Unsupported cards with no loader */ - BLACKLIST_NOLOADER(MANU_MCS, PROD_MCS_CONNECT32) +/* List of descriptions of cards which don't have an extended + * identification, or chunk directories containing a description. + */ +static const struct expcard_blacklist blacklist[] = { + { MANU_ACORN, PROD_ACORN_ETHER1, "Acorn Ether1" } }; +asmlinkage extern int ecard_loader_reset(volatile unsigned char *pa, + loader_t loader); +asmlinkage extern int ecard_loader_read(int off, volatile unsigned char *pa, + loader_t loader); extern int setup_arm_irq(int, struct irqaction *); +extern void do_ecard_IRQ(int, struct pt_regs *); + + +static void +ecard_irq_noexpmask(int intr_no, void *dev_id, struct pt_regs *regs); + +static struct irqaction irqexpansioncard = { + ecard_irq_noexpmask, SA_INTERRUPT, 0, "expansion cards", NULL, NULL +}; + +static inline unsigned short +ecard_getu16(unsigned char *v) +{ + return v[0] | v[1] << 8; +} + +static inline signed long +ecard_gets24(unsigned char *v) +{ + return v[0] | v[1] << 8 | v[2] << 16 | ((v[2] & 0x80) ? 0xff000000 : 0); +} + +static inline ecard_t * +slot_to_ecard(unsigned int slot) +{ + return slot < MAX_ECARDS ? slot_to_expcard[slot] : NULL; +} +/* ===================== Expansion card daemon ======================== */ /* - * from linux/arch/arm/kernel/irq.c + * Since the loader programs on the expansion cards need to be run + * in a specific environment, create a separate task with this + * environment up, and pass requests to this task as and when we + * need to. + * + * This should allow 99% of loaders to be called from Linux. + * + * From a security standpoint, we trust the card vendors. This + * may be a misplaced trust. */ -extern void do_ecard_IRQ(int irq, struct pt_regs *); +#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE) +#define POD_INT_ADDR(x) ((volatile unsigned char *)\ + ((BUS_ADDR((x)) - IO_BASE) + IO_START)) -static ecard_t expcard[MAX_ECARDS]; -static signed char irqno_to_expcard[16]; -static unsigned int ecard_numcards, ecard_numirqcards; -static unsigned int have_expmask; +static void +ecard_task_reset(struct ecard_request *req) +{ + if (req->ec == NULL) { + ecard_t *ec; + + for (ec = cards; ec; ec = ec->next) { + printk(KERN_DEBUG "Resetting card %d\n", + ec->slot_no); + + if (ec->loader) + ecard_loader_reset(POD_INT_ADDR(ec->podaddr), + ec->loader); + } + printk(KERN_DEBUG "All cards reset\n"); + } else if (req->ec->loader) + ecard_loader_reset(POD_INT_ADDR(req->ec->podaddr), + req->ec->loader); +} + +static void +ecard_task_readbytes(struct ecard_request *req) +{ + unsigned char *buf = (unsigned char *)req->buffer; + volatile unsigned char *base_addr = + (volatile unsigned char *)POD_INT_ADDR(req->ec->podaddr); + unsigned int len = req->length; + + if (req->ec->slot_no == 8) { + /* + * The card maintains an index which + * increments the address into a 4096-byte + * page on each access. We need to keep + * track of the counter. + */ + static unsigned int index; + unsigned int offset, page; + unsigned char byte = 0; /* keep gcc quiet */ + + offset = req->address & 4095; + page = req->address >> 12; + + if (page > 256) + return; + + page *= 4; + + if (offset == 0 || index > offset) { + /* + * We need to reset the index counter. + */ + *base_addr = 0; + index = 0; + } + + while (index <= offset) { + byte = base_addr[page]; + index += 1; + } + + while (len--) { + *buf++ = byte; + if (len) { + byte = base_addr[page]; + index += 1; + } + } + } else { + unsigned int off = req->address; + + if (!req->use_loader || !req->ec->loader) { + off *= 4; + while (len--) { + *buf++ = base_addr[off]; + off += 4; + } + } else { + while(len--) { + /* + * The following is required by some + * expansion card loader programs. + */ + *(unsigned long *)0x108 = 0; + *buf++ = ecard_loader_read(off++, base_addr, + req->ec->loader); + } + } + } + +} + +#ifdef CONFIG_CPU_32 +/* + * Set up the expansion card daemon's environment. + */ +static void +ecard_init_task(void) +{ + /* We want to set up the page tables for the following mapping: + * Virtual Physical + * 0x03000000 0x03000000 + * 0x03010000 unmapped + * 0x03210000 0x03210000 + * 0x03400000 unmapped + * 0x08000000 0x08000000 + * 0x10000000 unmapped + * + * FIXME: we don't follow this 100% yet. + */ + pgd_t *src_pgd, *dst_pgd; + unsigned int dst_addr = IO_START; + + src_pgd = pgd_offset(current->mm, IO_BASE); + dst_pgd = pgd_offset(current->mm, dst_addr); + + while (dst_addr < IO_START + IO_SIZE) { + *dst_pgd++ = *src_pgd++; + dst_addr += PGDIR_SIZE; + } + + flush_tlb_range(current->mm, IO_START, IO_START + IO_SIZE); + + dst_addr = EASI_START; + src_pgd = pgd_offset(current->mm, EASI_BASE); + dst_pgd = pgd_offset(current->mm, dst_addr); + + while (dst_addr < EASI_START + EASI_SIZE) { + *dst_pgd++ = *src_pgd++; + dst_addr += PGDIR_SIZE; + } + + flush_tlb_range(current->mm, EASI_START, EASI_START + EASI_SIZE); +} + +static int +ecard_task(void * unused) +{ + ecard_tsk = current; + + current->session = 1; + current->pgrp = 1; + + /* + * We don't want /any/ signals, not even SIGKILL + */ + sigfillset(¤t->blocked); + sigemptyset(¤t->signal); + + strcpy(current->comm, "kecardd"); + + /* + * Set up the environment + */ + ecard_init_task(); + + while (1) { + struct ecard_request *req; + + do { + req = xchg(&ecard_req, NULL); + + if (req == NULL) { + sigemptyset(¤t->signal); + interruptible_sleep_on(&ecard_wait); + } + } while (req == NULL); + + switch (req->req) { + case req_readbytes: + ecard_task_readbytes(req); + break; + + case req_reset: + ecard_task_reset(req); + break; + } + wake_up(&ecard_done); + } +} + +/* + * Wake the expansion card daemon to action our request. + * + * FIXME: The test here is not sufficient to detect if the + * kcardd is running. + */ +static inline void +ecard_call(struct ecard_request *req) +{ + /* + * If we're called from task 0, or from an + * interrupt (will be keyboard interrupt), + * we forcefully set up the memory map, and + * call the loader. We can't schedule, or + * sleep for this call. + */ + if ((current == task[0] || in_interrupt()) && + req->req == req_reset && req->ec == NULL) { + ecard_init_task(); + ecard_task_reset(req); + } else { + if (ecard_pid <= 0) + ecard_pid = kernel_thread(ecard_task, NULL, 0); + + ecard_req = req; + + wake_up(&ecard_wait); + + sleep_on(&ecard_done); + } +} +#else +/* + * On 26-bit processors, we don't need the kcardd thread to access the + * expansion card loaders. We do it directly. + */ +static inline void +ecard_call(struct ecard_request *req) +{ + if (req->req == req_reset) + ecard_task_reset(req); + else + ecard_task_readbytes(req); +} +#endif + +/* ======================= Mid-level card control ===================== */ +/* + * This is called to reset the loaders for each expansion card on reboot. + * + * This is required to make sure that the card is in the correct state + * that RiscOS expects it to be. + */ +void +ecard_reset(int slot) +{ + struct ecard_request req; + + req.req = req_reset; + + if (slot < 0) + req.ec = NULL; + else + req.ec = slot_to_ecard(slot); + + ecard_call(&req); + +#ifdef HAS_EXPMASK + if (have_expmask && slot < 0) { + have_expmask |= ~0; + EXPMASK_ENABLE = have_expmask; + } +#endif +} + +static void +ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld) +{ + struct ecard_request req; + + req.req = req_readbytes; + req.ec = ec; + req.address = off; + req.length = len; + req.use_loader = useld; + req.buffer = addr; + + ecard_call(&req); +} + +int ecard_readchunk(struct in_chunk_dir *cd, ecard_t *ec, int id, int num) +{ + struct ex_chunk_dir excd; + int index = 16; + int useld = 0; + + if (!ec->cid.cd) + return 0; + + while(1) { + ecard_readbytes(&excd, ec, index, 8, useld); + index += 8; + if (c_id(&excd) == 0) { + if (!useld && ec->loader) { + useld = 1; + index = 0; + continue; + } + return 0; + } + if (c_id(&excd) == 0xf0) { /* link */ + index = c_start(&excd); + continue; + } + if (c_id(&excd) == 0x80) { /* loader */ + if (!ec->loader) { + ec->loader = (loader_t)kmalloc(c_len(&excd), + GFP_KERNEL); + ecard_readbytes(ec->loader, ec, + (int)c_start(&excd), + c_len(&excd), useld); + } + continue; + } + if (c_id(&excd) == id && num-- == 0) + break; + } + + if (c_id(&excd) & 0x80) { + switch (c_id(&excd) & 0x70) { + case 0x70: + ecard_readbytes((unsigned char *)excd.d.string, ec, + (int)c_start(&excd), c_len(&excd), + useld); + break; + case 0x00: + break; + } + } + cd->start_offset = c_start(&excd); + memcpy(cd->d.string, excd.d.string, 256); + return 1; +} + +/* ======================= Interrupt control ============================ */ static void ecard_def_irq_enable(ecard_t *ec, int irqnr) { @@ -100,6 +482,11 @@ #endif } +static int ecard_def_irq_pending(ecard_t *ec) +{ + return !ec->irqmask || ec->irqaddr[0] & ec->irqmask; +} + static void ecard_def_fiq_enable(ecard_t *ec, int fiqnr) { panic("ecard_def_fiq_enable called - impossible"); @@ -110,11 +497,18 @@ panic("ecard_def_fiq_disable called - impossible"); } +static int ecard_def_fiq_pending(ecard_t *ec) +{ + return !ec->fiqmask || ec->fiqaddr[0] & ec->fiqmask; +} + static expansioncard_ops_t ecard_default_ops = { ecard_def_irq_enable, ecard_def_irq_disable, + ecard_def_irq_pending, ecard_def_fiq_enable, - ecard_def_fiq_disable + ecard_def_fiq_disable, + ecard_def_fiq_pending }; /* @@ -125,10 +519,9 @@ */ void ecard_enableirq(unsigned int irqnr) { - irqnr &= 7; - if (irqnr < MAX_ECARDS && irqno_to_expcard[irqnr] != -1) { - ecard_t *ec = expcard + irqno_to_expcard[irqnr]; + ecard_t *ec = slot_to_ecard(irqnr); + if (ec) { if (!ec->ops) ec->ops = &ecard_default_ops; @@ -142,10 +535,9 @@ void ecard_disableirq(unsigned int irqnr) { - irqnr &= 7; - if (irqnr < MAX_ECARDS && irqno_to_expcard[irqnr] != -1) { - ecard_t *ec = expcard + irqno_to_expcard[irqnr]; + ecard_t *ec = slot_to_ecard(irqnr); + if (ec) { if (!ec->ops) ec->ops = &ecard_default_ops; @@ -156,10 +548,9 @@ void ecard_enablefiq(unsigned int fiqnr) { - fiqnr &= 7; - if (fiqnr < MAX_ECARDS && irqno_to_expcard[fiqnr] != -1) { - ecard_t *ec = expcard + irqno_to_expcard[fiqnr]; + ecard_t *ec = slot_to_ecard(fiqnr); + if (ec) { if (!ec->ops) ec->ops = &ecard_default_ops; @@ -173,10 +564,9 @@ void ecard_disablefiq(unsigned int fiqnr) { - fiqnr &= 7; - if (fiqnr < MAX_ECARDS && irqno_to_expcard[fiqnr] != -1) { - ecard_t *ec = expcard + irqno_to_expcard[fiqnr]; + ecard_t *ec = slot_to_ecard(fiqnr); + if (ec) { if (!ec->ops) ec->ops = &ecard_default_ops; @@ -185,41 +575,89 @@ } } -static void ecard_irq_noexpmask(int intr_no, void *dev_id, struct pt_regs *regs) +static void +ecard_dump_irq_state(ecard_t *ec) { - const int num_cards = ecard_numirqcards; - int i, called = 0; + printk(" %d: %sclaimed, ", + ec->slot_no, + ec->claimed ? "" : "not "); + + if (ec->ops && ec->ops->irqpending && + ec->ops != &ecard_default_ops) + printk("irq %spending\n", + ec->ops->irqpending(ec) ? "" : "not "); + else + printk("irqaddr %p, mask = %02X, status = %02X\n", + ec->irqaddr, ec->irqmask, *ec->irqaddr); +} - for (i = 0; i < num_cards; i++) { - if (expcard[i].claimed && expcard[i].irq && - (!expcard[i].irqmask || - expcard[i].irqaddr[0] & expcard[i].irqmask)) { - do_ecard_IRQ(expcard[i].irq, regs); - called ++; +static void +ecard_check_lockup(void) +{ + static int last, lockup; + ecard_t *ec; + + /* + * If the timer interrupt has not run since the last million + * unrecognised expansion card interrupts, then there is + * something seriously wrong. Disable the expansion card + * interrupts so at least we can continue. + * + * Maybe we ought to start a timer to re-enable them some time + * later? + */ + if (last == jiffies) { + lockup += 1; + if (lockup > 1000000) { + printk(KERN_ERR "\nInterrupt lockup detected - " + "disabling all expansion card interrupts\n"); + + disable_irq(IRQ_EXPANSIONCARD); + + printk("Expansion card IRQ state:\n"); + + for (ec = cards; ec; ec = ec->next) + ecard_dump_irq_state(ec); } + } else + lockup = 0; + + /* + * If we did not recognise the source of this interrupt, + * warn the user, but don't flood the user with these messages. + */ + if (!last || time_after(jiffies, last + 5*HZ)) { + last = jiffies; + printk(KERN_WARNING "Unrecognised interrupt from backplane\n"); } - cli(); - if (called == 0) { - static int last, lockup; +} - if (last == jiffies) { - lockup += 1; - if (lockup > 1000000) { - printk(KERN_ERR "\nInterrupt lockup detected - disabling expansion card IRQs\n"); - disable_irq(intr_no); - printk("Expansion card IRQ state:\n"); - for (i = 0; i < num_cards; i++) - printk(" %d: %sclaimed, irqaddr = %p, irqmask = %X, status=%X\n", expcard[i].irq - 32, - expcard[i].claimed ? "" : "not", expcard[i].irqaddr, expcard[i].irqmask, *expcard[i].irqaddr); - } - } else - lockup = 0; +static void +ecard_irq_noexpmask(int intr_no, void *dev_id, struct pt_regs *regs) +{ + ecard_t *ec; + int called = 0; + + for (ec = cards; ec; ec = ec->next) { + int pending; + + if (!ec->claimed || ec->irq == NO_IRQ || ec->slot_no == 8) + continue; - if (!last || time_after(jiffies, last + 5*HZ)) { - last = jiffies; - printk(KERN_ERR "\nUnrecognised interrupt from backplane\n"); + if (ec->ops && ec->ops->irqpending) + pending = ec->ops->irqpending(ec); + else + pending = ecard_default_ops.irqpending(ec); + + if (pending) { + do_ecard_IRQ(ec->irq, regs); + called ++; } } + cli(); + + if (called == 0) + ecard_check_lockup(); } #ifdef HAS_EXPMASK @@ -234,31 +672,35 @@ 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00 }; -static void ecard_irq_expmask(int intr_no, void *dev_id, struct pt_regs *regs) +static void +ecard_irq_expmask(int intr_no, void *dev_id, struct pt_regs *regs) { const unsigned int statusmask = 15; unsigned int status; status = EXPMASK_STATUS & statusmask; if (status) { - unsigned int irqno; + unsigned int slot; ecard_t *ec; again: - irqno = first_set[status]; - ec = expcard + irqno_to_expcard[irqno]; + slot = first_set[status]; + ec = slot_to_ecard(slot); if (ec->claimed) { unsigned int oldexpmask; /* - * this ugly code is so that we can operate a prioritorising system. + * this ugly code is so that we can operate a + * prioritorising system: + * * Card 0 highest priority * Card 1 * Card 2 * Card 3 lowest priority + * * Serial cards should go in 0/1, ethernet/scsi in 2/3 * otherwise you will lose serial data at high speeds! */ oldexpmask = have_expmask; - EXPMASK_ENABLE = (have_expmask &= priority_masks[irqno]); + EXPMASK_ENABLE = (have_expmask &= priority_masks[slot]); sti(); do_ecard_IRQ(ec->irq, regs); cli(); @@ -267,15 +709,18 @@ if (status) goto again; } else { - printk(KERN_WARNING "card%d: interrupt from unclaimed card???\n", irqno); - EXPMASK_ENABLE = (have_expmask &= ~(1 << irqno)); + printk(KERN_WARNING "card%d: interrupt from unclaimed " + "card???\n", slot); + EXPMASK_ENABLE = (have_expmask &= ~(1 << slot)); } } else printk(KERN_WARNING "Wild interrupt from backplane (masks)\n"); } -static int ecard_checkirqhw(void) +static void +ecard_probeirqhw(void) { + ecard_t *ec; int found; EXPMASK_ENABLE = 0x00; @@ -283,62 +728,75 @@ found = ((EXPMASK_STATUS & 15) == 0); EXPMASK_ENABLE = 0xff; - return found; + if (!found) + return; + + printk(KERN_DEBUG "Expansion card interrupt " + "management hardware found\n"); + + irqexpansioncard.handler = ecard_irq_expmask; + + /* for each card present, set a bit to '1' */ + have_expmask = 0x80000000; + + for (ec = cards; ec; ec = ec->next) + have_expmask |= 1 << ec->slot_no; + + EXPMASK_ENABLE = have_expmask; } +#else +#define ecard_probeirqhw() #endif -static void ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld) +unsigned int ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed) { - extern int ecard_loader_read(int off, volatile unsigned int pa, loader_t loader); - unsigned char *a = (unsigned char *)addr; - - if (ec->slot_no == 8) { - static unsigned int lowaddress; - unsigned int laddr, haddr; - unsigned char byte = 0; /* keep gcc quiet */ - - laddr = off & 4095; /* number of bytes to read from offset + base addr */ - haddr = off >> 12; /* offset into card from base addr */ + switch (ec->slot_no) { + case 0 ... 3: + switch (type) { + case ECARD_MEMC: + return IO_EC_MEMC_BASE + (ec->slot_no << 12); - if (haddr > 256) - return; + case ECARD_IOC: + return IO_EC_IOC_BASE + (speed << 17) + + (ec->slot_no << 12); - /* - * If we require a low address or address 0, then reset, and start again... - */ - if (!off || lowaddress > laddr) { - outb(0, ec->podaddr); - lowaddress = 0; - } - while (lowaddress <= laddr) { - byte = inb(ec->podaddr + haddr); - lowaddress += 1; - } - while (len--) { - *a++ = byte; - if (len) { - byte = inb(ec->podaddr + haddr); - lowaddress += 1; - } +#ifdef IO_EC_EASI_BASE + case ECARD_EASI: + return IO_EC_EASI_BASE + (ec->slot_no << 22); +#endif } - } else { - if (!useld || !ec->loader) { - while(len--) - *a++ = inb(ec->podaddr + (off++)); - } else { - while(len--) { - *(unsigned long *)0x108 = 0; /* hack for some loaders!!! */ - *a++ = ecard_loader_read(off++, BUS_ADDR(ec->podaddr), ec->loader); - } + break; + + case 4 ... 7: + switch (type) { +#ifdef IO_EC_IOC4_BASE + case ECARD_IOC: + return IO_EC_IOC4_BASE + (speed << 17) + + ((ec->slot_no - 4) << 12); +#endif +#ifdef IO_EC_EASI_BASE + case ECARD_EASI: + return IO_EC_EASI_BASE + (ec->slot_no << 22); +#endif + default: + break; } + break; + +#ifdef IO_EC_MEMC8_BASE + case 8: + return IO_EC_MEMC8_BASE; +#endif } + return 0; } static int ecard_prints(char *buffer, ecard_t *ec) { char *start = buffer; - buffer += sprintf(buffer, "\n %d: ", ec->slot_no); + buffer += sprintf(buffer, " %d: %s ", ec->slot_no, + ec->type == ECARD_EASI ? "EASI" : " "); if (ec->cid.id == 0) { struct in_chunk_dir incd; @@ -346,63 +804,59 @@ buffer += sprintf(buffer, "[%04X:%04X] ", ec->cid.manufacturer, ec->cid.product); - if (!ec->card_desc && ec->cid.is && ec->cid.cd && + if (!ec->card_desc && ec->cid.cd && ecard_readchunk(&incd, ec, 0xf5, 0)) ec->card_desc = incd.d.string; if (!ec->card_desc) ec->card_desc = "*unknown*"; - buffer += sprintf(buffer, "%s", ec->card_desc); + buffer += sprintf(buffer, "%s\n", ec->card_desc); } else - buffer += sprintf(buffer, "Simple card %d", ec->cid.id); + buffer += sprintf(buffer, "Simple card %d\n", ec->cid.id); return buffer - start; } -static inline unsigned short ecard_getu16(unsigned char *v) -{ - return v[0] | v[1] << 8; -} - -static inline signed long ecard_gets24(unsigned char *v) -{ - return v[0] | v[1] << 8 | v[2] << 16 | ((v[2] & 0x80) ? 0xff000000 : 0); -} - /* * Probe for an expansion card. * * If bit 1 of the first byte of the card is set, then the * card does not exist. */ -__initfunc(static int ecard_probe(int card, int freeslot, card_type_t type)) +__initfunc(static int +ecard_probe(int slot, card_type_t type)) { - ecard_t *ec = expcard + freeslot; + ecard_t **ecp; + ecard_t *ec; struct ex_ecid cid; char buffer[200]; - int i; + int i, rc = -ENOMEM; + + ec = kmalloc(sizeof(ecard_t), GFP_KERNEL); - irqno_to_expcard[card] = -1; + if (!ec) + goto nodev; - ec->slot_no = card; + memset(ec, 0, sizeof(ecard_t)); + + ec->slot_no = slot; + ec->type = type; ec->irq = NO_IRQ; ec->fiq = NO_IRQ; ec->dma = NO_DMA; ec->card_desc = NULL; ec->ops = &ecard_default_ops; + rc = -ENODEV; if ((ec->podaddr = ecard_address(ec, type, ECARD_SYNC)) == 0) - return 0; + goto nodev; cid.r_zero = 1; ecard_readbytes(&cid, ec, 0, 16, 0); if (cid.r_zero) - return 0; - - irqno_to_expcard[card] = freeslot; + goto nodev; - ec->type = type; ec->cid.id = cid.r_id; ec->cid.cd = cid.r_cd; ec->cid.is = cid.r_is; @@ -415,9 +869,9 @@ ec->cid.fiqmask = cid.r_fiqmask; ec->cid.fiqoff = ecard_gets24(cid.r_fiqoff); ec->fiqaddr = - ec->irqaddr = (unsigned char *)BUS_ADDR(ec->podaddr); + ec->irqaddr = (unsigned char *)ioaddr(ec->podaddr); - if (ec->cid.cd && ec->cid.is) { + if (ec->cid.is) { ec->irqmask = ec->cid.irqmask; ec->irqaddr += ec->cid.irqoff; ec->fiqmask = ec->cid.fiqmask; @@ -430,88 +884,69 @@ for (i = 0; i < sizeof(blacklist) / sizeof(*blacklist); i++) if (blacklist[i].manufacturer == ec->cid.manufacturer && blacklist[i].product == ec->cid.product) { - ec->loader = blacklist[i].loader; ec->card_desc = blacklist[i].type; break; } - ecard_prints(buffer, ec); - printk("%s", buffer); - - ec->irq = 32 + card; + ec->irq = 32 + slot; #ifdef IO_EC_MEMC8_BASE - if (card == 8) + if (slot == 8) ec->irq = 11; #endif #ifdef CONFIG_ARCH_RPC /* On RiscPC, only first two slots have DMA capability */ - if (card < 2) - ec->dma = 2 + card; + if (slot < 2) + ec->dma = 2 + slot; #endif #if 0 /* We don't support FIQs on expansion cards at the moment */ - ec->fiq = 96 + card; + ec->fiq = 96 + slot; #endif - return 1; -} + rc = 0; -/* - * This is called to reset the loaders for each expansion card on reboot. - * - * This is required to make sure that the card is in the correct state - * that RiscOS expects it to be. - */ -void ecard_reset(int card) -{ - extern int ecard_loader_reset(volatile unsigned int pa, loader_t loader); + for (ecp = &cards; *ecp; ecp = &(*ecp)->next); - if (card >= ecard_numcards) - return; - - if (card < 0) { - for (card = 0; card < ecard_numcards; card++) - if (expcard[card].loader) - ecard_loader_reset(BUS_ADDR(expcard[card].podaddr), - expcard[card].loader); - } else - if (expcard[card].loader) - ecard_loader_reset(BUS_ADDR(expcard[card].podaddr), - expcard[card].loader); + *ecp = ec; -#ifdef HAS_EXPMASK - if (have_expmask) { - have_expmask |= ~0; - EXPMASK_ENABLE = have_expmask; +nodev: + if (rc && ec) + kfree(ec); + else { + slot_to_expcard[slot] = ec; + + ecard_prints(buffer, ec); + printk("%s", buffer); } -#endif + return rc; } -static unsigned int ecard_startcard; +static ecard_t *finding_pos; void ecard_startfind(void) { - ecard_startcard = 0; + finding_pos = NULL; } ecard_t *ecard_find(int cid, const card_ids *cids) { - int card; + if (!finding_pos) + finding_pos = cards; + else + finding_pos = finding_pos->next; + + for (; finding_pos; finding_pos = finding_pos->next) { + if (finding_pos->claimed) + continue; - if (!cids) { - for (card = ecard_startcard; card < ecard_numcards; card++) - if (!expcard[card].claimed && - (expcard[card].cid.id ^ cid) == 0) + if (!cids) { + if ((finding_pos->cid.id ^ cid) == 0) break; - } else { - for (card = ecard_startcard; card < ecard_numcards; card++) { + } else { unsigned int manufacturer, product; int i; - if (expcard[card].claimed) - continue; - - manufacturer = expcard[card].cid.manufacturer; - product = expcard[card].cid.product; + manufacturer = finding_pos->cid.manufacturer; + product = finding_pos->cid.product; for (i = 0; cids[i].manufacturer != 65535; i++) if (manufacturer == cids[i].manufacturer && @@ -523,111 +958,24 @@ } } - ecard_startcard = card + 1; - - return card < ecard_numcards ? &expcard[card] : NULL; + return finding_pos; } -int ecard_readchunk(struct in_chunk_dir *cd, ecard_t *ec, int id, int num) +__initfunc(static void ecard_free_all(void)) { - struct ex_chunk_dir excd; - int index = 16; - int useld = 0; + ecard_t *ec, *ecn; - if (!ec->cid.is || !ec->cid.cd) - return 0; - - while(1) { - ecard_readbytes(&excd, ec, index, 8, useld); - index += 8; - if (c_id(&excd) == 0) { - if (!useld && ec->loader) { - useld = 1; - index = 0; - continue; - } - return 0; - } - if (c_id(&excd) == 0xf0) { /* link */ - index = c_start(&excd); - continue; - } - if (c_id(&excd) == 0x80) { /* loader */ - if (!ec->loader) { - ec->loader = (loader_t)kmalloc(c_len(&excd), GFP_KERNEL); - ecard_readbytes(ec->loader, ec, (int)c_start(&excd), c_len(&excd), useld); - } - continue; - } - if (c_id(&excd) == id && num-- == 0) - break; - } + for (ec = cards; ec; ec = ecn) { + ecn = ec->next; - if (c_id(&excd) & 0x80) { - switch (c_id(&excd) & 0x70) { - case 0x70: - ecard_readbytes((unsigned char *)excd.d.string, ec, - (int)c_start(&excd), c_len(&excd), useld); - break; - case 0x00: - break; - } + kfree(ec); } - cd->start_offset = c_start(&excd); - memcpy(cd->d.string, excd.d.string, 256); - return 1; -} - -unsigned int ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed) -{ - switch (ec->slot_no) { - case 0 ... 3: - switch (type) { - case ECARD_MEMC: - return IO_EC_MEMC_BASE + (ec->slot_no << 12); - case ECARD_IOC: - return IO_EC_IOC_BASE + (speed << 17) + (ec->slot_no << 12); - -#ifdef IO_EC_EASI_BASE - case ECARD_EASI: - return IO_EC_EASI_BASE + (ec->slot_no << 22); -#endif - } - break; - - case 4 ... 7: - switch (type) { -#ifdef IO_EC_IOC4_BASE - case ECARD_IOC: - return IO_EC_IOC4_BASE + (speed << 17) + ((ec->slot_no - 4) << 12); -#endif -#ifdef IO_EC_EASI_BASE - case ECARD_EASI: - return IO_EC_EASI_BASE + (ec->slot_no << 22); -#endif - default: - break; - } - break; + cards = NULL; -#ifdef IO_EC_MEMC8_BASE - case 8: - return IO_EC_MEMC8_BASE; -#endif - } - return 0; + memset(slot_to_expcard, 0, sizeof(slot_to_expcard)); } -static struct irqaction irqexpansioncard = { - ecard_irq_noexpmask, - SA_INTERRUPT, - 0, - "expansion cards", - NULL, - NULL -}; - /* * Initialise the expansion card system. * Locate all hardware - interrupt management and @@ -635,51 +983,31 @@ */ __initfunc(void ecard_init(void)) { - int i, nc = 0; - - memset(expcard, 0, sizeof(expcard)); - -#ifdef HAS_EXPMASK - if (ecard_checkirqhw()) { - printk(KERN_DEBUG "Expansion card interrupt management hardware found\n"); - irqexpansioncard.handler = ecard_irq_expmask; - irqexpansioncard.flags |= SA_IRQNOMASK; - have_expmask = -1; - } -#endif + int slot; - printk("Installed expansion cards:"); + oldlatch_init(); - /* - * First of all, probe all cards on the expansion card interrupt line - */ - for (i = 0; i < 8; i++) - if (ecard_probe(i, nc, ECARD_IOC) || ecard_probe(i, nc, ECARD_EASI)) - nc += 1; - else - have_expmask &= ~(1< + .equ ioc_base_high, IOC_BASE & 0xff000000 .equ ioc_base_low, IOC_BASE & 0x00ff0000 .macro disable_fiq @@ -187,20 +191,79 @@ .endm #elif defined(CONFIG_ARCH_EBSA285) +#include .macro disable_fiq .endm + .equ irq_mask_pci_err_high, IRQ_MASK_PCI_ERR & 0xff000000 + .equ irq_mask_pci_err_low, IRQ_MASK_PCI_ERR & 0x00ff0000 + .macro get_irqnr_and_base, irqnr, irqstat, base mov r4, #0xfe000000 ldr \irqstat, [r4, #0x180] @ get interrupts - mov \irqnr, #0 -1001: tst \irqstat, #1 - addeq \irqnr, \irqnr, #1 - moveq \irqstat, \irqstat, lsr #1 - tsteq \irqnr, #32 - beq 1001b - teq \irqnr, #32 + + tst \irqstat, #IRQ_MASK_SDRAMPARITY + movne \irqnr, #IRQ_SDRAMPARITY + bne 1001f + + tst \irqstat, #IRQ_MASK_UART_RX + movne \irqnr, #IRQ_CONRX + bne 1001f + + tst \irqstat, #IRQ_MASK_DMA1 + movne \irqnr, #IRQ_DMA1 + bne 1001f + + tst \irqstat, #IRQ_MASK_DMA2 + movne \irqnr, #IRQ_DMA2 + bne 1001f + + tst \irqstat, #IRQ_MASK_IN0 + movne \irqnr, #IRQ_IN0 + bne 1001f + + tst \irqstat, #IRQ_MASK_IN1 + movne \irqnr, #IRQ_IN1 + bne 1001f + + tst \irqstat, #IRQ_MASK_IN2 + movne \irqnr, #IRQ_IN2 + bne 1001f + + tst \irqstat, #IRQ_MASK_IN3 + movne \irqnr, #IRQ_IN3 + bne 1001f + + tst \irqstat, #IRQ_MASK_PCI + movne \irqnr, #IRQ_PCI + bne 1001f + + tst \irqstat, #IRQ_MASK_I2OINPOST + movne \irqnr, #IRQ_I2OINPOST + bne 1001f + + tst \irqstat, #IRQ_MASK_TIMER1 + movne \irqnr, #IRQ_TIMER1 + bne 1001f + + tst \irqstat, #IRQ_MASK_TIMER2 + movne \irqnr, #IRQ_TIMER2 + bne 1001f + + tst \irqstat, #IRQ_MASK_TIMER3 + movne \irqnr, #IRQ_TIMER3 + bne 1001f + + tst \irqstat, #IRQ_MASK_UART_TX + movne \irqnr, #IRQ_CONTX + bne 1001f + + tst \irqstat, #irq_mask_pci_err_high + tsteq \irqstat, #irq_mask_pci_err_low + movne \irqnr, #IRQ_PCI_ERR + bne 1001f +1001: .endm .macro irq_prio_table @@ -227,15 +290,18 @@ .endm #elif defined(CONFIG_ARCH_VNC) +#include .macro disable_fiq .endm .equ pci_iack_high, PCI_IACK & 0xff000000 .equ pci_iack_low, PCI_IACK & 0x00ff0000 + .equ irq_mask_pci_err_high, IRQ_MASK_PCI_ERR & 0xff000000 + .equ irq_mask_pci_err_low, IRQ_MASK_PCI_ERR & 0x00ff0000 .macro get_irqnr_and_base, irqnr, irqstat, base - mov r4, #IO_BASE_ARM_CSR + mov r4, #ARMCSR_BASE ldr \irqstat, [r4, #CSR_IRQ_STATUS] @ just show us the unmasked ones @ run through hard priorities @@ -269,7 +335,8 @@ b 1001f 1002: @ PCI errors - tst \irqstat, #IRQ_MASK_PCI_ERR + tst \irqstat, #irq_mask_pci_err_high + tsteq \irqstat, #irq_mask_pci_err_low movne \irqnr, #IRQ_PCI_ERR bne 1001f @@ -348,25 +415,6 @@ msr cpsr, \temp .endm - .macro initialise_traps_extra - mrs r0, cpsr - bic r0, r0, #31 - orr r0, r0, #0xd3 - msr cpsr, r0 - .endm - - -#ifndef __ARM_ARCH_4__ -.Larm700bug: str lr, [r8] - ldr r0, [sp, #S_PSR] @ Get calling cpsr - msr spsr, r0 - ldmia sp, {r0 - lr}^ @ Get calling r0 - lr - mov r0, r0 - add sp, sp, #S_PC - ldr lr, [sp], #S_FRAME_SIZE - S_PC @ Get PC and jump over PC, PSR, OLD_R0 - movs pc, lr -#endif - .macro get_current_task, rd mov \rd, sp, lsr #13 mov \rd, \rd, lsl #13 @@ -379,231 +427,89 @@ adr\cond \reg, \label .endm -/*============================================================================= - * Address exception handler - *----------------------------------------------------------------------------- - * These aren't too critical. - * (they're not supposed to happen, and won't happen in 32-bit mode). - */ - -vector_addrexcptn: - b vector_addrexcptn - -/*============================================================================= - * Undefined FIQs - *----------------------------------------------------------------------------- - * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC - * MUST PRESERVE SVC SPSR, but need to switch to SVC mode to show our msg. - * Basically to switch modes, we *HAVE* to clobber one register... brain - * damage alert! I don't think that we can execute any code in here in any - * other mode than FIQ... Ok you can switch to another mode, but you can't - * get out of that mode without clobbering one register. - */ -_unexp_fiq: disable_fiq - subs pc, lr, #4 - -/*============================================================================= - * Interrupt entry dispatcher - *----------------------------------------------------------------------------- - * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC - */ -vector_IRQ: @ - @ save mode specific registers - @ - ldr r13, .LCirq - sub lr, lr, #4 - str lr, [r13] @ save lr_IRQ - mrs lr, spsr - str lr, [r13, #4] @ save spsr_IRQ - @ - @ now branch to the relevent MODE handling routine - @ - mrs sp, cpsr @ switch to SVC mode - bic sp, sp, #31 - orr sp, sp, #0x13 - msr spsr, sp - and lr, lr, #15 - cmp lr, #4 - addlts pc, pc, lr, lsl #2 @ Changes mode and branches - b __irq_invalid @ 4 - 15 - b __irq_usr @ 0 (USR_26 / USR_32) - b __irq_invalid @ 1 (FIQ_26 / FIQ_32) - b __irq_invalid @ 2 (IRQ_26 / IRQ_32) - b __irq_svc @ 3 (SVC_26 / SVC_32) -/* - *------------------------------------------------------------------------------------------------ - * Undef instr entry dispatcher - dispatches it to the correct handler for the processor mode - *------------------------------------------------------------------------------------------------ - * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC - */ -.LCirq: .word __temp_irq -.LCund: .word __temp_und -.LCabt: .word __temp_abt - -vector_undefinstr: - @ - @ save mode specific registers - @ - ldr r13, [pc, #.LCund - . - 8] - str lr, [r13] - mrs lr, spsr - str lr, [r13, #4] - @ - @ now branch to the relevent MODE handling routine - @ - mrs sp, cpsr - bic sp, sp, #31 - orr sp, sp, #0x13 - msr spsr, sp - and lr, lr, #15 - cmp lr, #4 - addlts pc, pc, lr, lsl #2 @ Changes mode and branches - b __und_invalid @ 4 - 15 - b __und_usr @ 0 (USR_26 / USR_32) - b __und_invalid @ 1 (FIQ_26 / FIQ_32) - b __und_invalid @ 2 (IRQ_26 / IRQ_32) - b __und_svc @ 3 (SVC_26 / SVC_32) -/* - *------------------------------------------------------------------------------------------------ - * Prefetch abort dispatcher - dispatches it to the correct handler for the processor mode - *------------------------------------------------------------------------------------------------ - * Enter in ABT mode, spsr = USR CPSR, lr = USR PC - */ -vector_prefetch: - @ - @ save mode specific registers - @ - sub lr, lr, #4 - ldr r13, .LCabt - str lr, [r13] - mrs lr, spsr - str lr, [r13, #4] - @ - @ now branch to the relevent MODE handling routine - @ - mrs sp, cpsr - bic sp, sp, #31 - orr sp, sp, #0x13 - msr spsr, sp - and lr, lr, #15 - adds pc, pc, lr, lsl #2 @ Changes mode and branches - b __pabt_invalid @ 4 - 15 - b __pabt_usr @ 0 (USR_26 / USR_32) - b __pabt_invalid @ 1 (FIQ_26 / FIQ_32) - b __pabt_invalid @ 2 (IRQ_26 / IRQ_32) - b __pabt_invalid @ 3 (SVC_26 / SVC_32) /* - *------------------------------------------------------------------------------------------------ - * Data abort dispatcher - dispatches it to the correct handler for the processor mode - *------------------------------------------------------------------------------------------------ - * Enter in ABT mode, spsr = USR CPSR, lr = USR PC + * Invalid mode handlers */ -vector_data: @ - @ save mode specific registers - @ - sub lr, lr, #8 - ldr r13, .LCabt - str lr, [r13] - mrs lr, spsr - str lr, [r13, #4] - @ - @ now branch to the relevent MODE handling routine - @ - mrs sp, cpsr - bic sp, sp, #31 - orr sp, sp, #0x13 - msr spsr, sp - and lr, lr, #15 - cmp lr, #4 - addlts pc, pc, lr, lsl #2 @ Changes mode & branches - b __dabt_invalid @ 4 - 15 - b __dabt_usr @ 0 (USR_26 / USR_32) - b __dabt_invalid @ 1 (FIQ_26 / FIQ_32) - b __dabt_invalid @ 2 (IRQ_26 / IRQ_32) - b __dabt_svc @ 3 (SVC_26 / SVC_32) +__pabt_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go + stmia sp, {r0 - lr} @ Save XXX r0 - lr + ldr r4, .LCabt + mov r1, #BAD_PREFETCH + b 1f -/*============================================================================= - * Prefetch abort handler - *----------------------------------------------------------------------------- - */ -pabtmsg: .ascii "Pabt: %08lX\n\0" - .align -__pabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go - stmia sp, {r0 - r12} @ Save r0 - r12 - add r8, sp, #S_PC - stmdb r8, {sp, lr}^ @ Save sp_usr lr_usr +__dabt_invalid: sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - lr} @ Save SVC r0 - lr [lr *should* be intact] ldr r4, .LCabt - ldmia r4, {r5 - r7} @ Get USR pc, cpsr - stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0 + mov r1, #BAD_DATA + b 1f - mrs r7, cpsr @ Enable interrupts if they were - bic r7, r7, #I_BIT @ previously - msr cpsr, r7 - mov r0, r5 @ address (pc) - mov r1, sp @ regs - bl SYMBOL_NAME(do_PrefetchAbort) @ call abort handler - teq r0, #0 @ Does this still apply??? - bne ret_from_exception @ Return from exception -#ifdef DEBUG_UNDEF - adr r0, t - bl SYMBOL_NAME(printk) -#endif - mov r0, r5 - mov r1, sp - and r2, r6, #31 - bl SYMBOL_NAME(do_undefinstr) - ldr lr, [sp, #S_PSR] @ Get USR cpsr - msr spsr, lr - ldmia sp, {r0 - pc}^ @ Restore USR registers +__irq_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate space on stack for frame + stmfd sp, {r0 - lr} @ Save r0 - lr + ldr r4, .LCirq + mov r1, #BAD_IRQ + b 1f -__pabt_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go - stmia sp, {r0 - lr} @ Save XXX r0 - lr - mov r7, r0 @ OLD R0 - ldr r4, .LCabt - ldmia r4, {r5 - r7} @ Get XXX pc, cpsr +__und_invalid: sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - lr} + ldr r4, .LCund + mov r1, #BAD_UNDEFINSTR @ int reason + +1: mov fp, #0 + ldmia r4, {r5 - r7} @ Get XXX pc, cpsr, old_r0 add r4, sp, #S_PC stmia r4, {r5 - r7} @ Save XXX pc, cpsr, old_r0 - mov r0, sp @ Prefetch aborts are definitely *not* - mov r1, #BAD_PREFETCH @ allowed in non-user modes. We cant - and r2, r6, #31 @ recover from this problem. + mov r0, sp + and r2, r6, #31 @ int mode b SYMBOL_NAME(bad_mode) -#ifdef DEBUG_UNDEF -t: .ascii "*** undef ***\r\n\0" - .align -#endif -/*============================================================================= - * Data abort handler code - *----------------------------------------------------------------------------- - */ -.LCprocfns: .word SYMBOL_NAME(processor) +wfs_mask_data: .word 0x0e200110 @ WFS/RFS + .word 0x0fef0fff + .word 0x0d0d0100 @ LDF [sp]/STF [sp] + .word 0x0d0b0100 @ LDF [fp]/STF [fp] + .word 0x0f0f0f00 -__dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go - stmia sp, {r0 - r12} @ save r0 - r12 - add r3, sp, #S_PC - stmdb r3, {sp, lr}^ - ldr r0, .LCabt - ldmia r0, {r0 - r2} @ Get USR pc, cpsr - stmia r3, {r0 - r2} @ Save USR pc, cpsr, old_r0 - mov fp, #0 - mrs r2, cpsr @ Enable interrupts if they were - bic r2, r2, #I_BIT @ previously - msr cpsr, r2 - ldr r2, .LCprocfns - mov lr, pc - ldr pc, [r2, #8] @ call processor specific code - mov r3, sp - bl SYMBOL_NAME(do_DataAbort) - b ret_from_sys_call +/* We get here if an undefined instruction happens and the floating + * point emulator is not present. If the offending instruction was + * a WFS, we just perform a normal return as if we had emulated the + * operation. This is a hack to allow some basic userland binaries + * to run so that the emulator module proper can be loaded. --philb + */ +fpe_not_present: + adr r10, wfs_mask_data + ldmia r10, {r4, r5, r6, r7, r8} + ldr r10, [sp, #S_PC] @ Load PC + sub r10, r10, #-4 + mask_pc r10, r10 + ldrt r10, [r10] @ get instruction + and r5, r10, r5 + teq r5, r4 @ Is it WFS? + moveq pc, r9 + and r5, r10, r8 + teq r5, r6 @ Is it LDF/STF on sp or fp? + teqne r5, r7 + movne pc, lr + tst r10, #0x00200000 @ Does it have WB + moveq pc, r9 + and r4, r10, #255 @ get offset + and r6, r10, #0x000f0000 + tst r10, #0x00800000 @ +/- + rsbeq r4, r4, #0 + ldr r5, [sp, r6, lsr #14] @ Load reg + add r5, r5, r4, lsl #2 + str r5, [sp, r6, lsr #14] @ Save reg + mov pc, r9 +/* + * SVC mode handlers + */ + .align 5 __dabt_svc: sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ save r0 - r12 ldr r2, .LCabt add r0, sp, #S_FRAME_SIZE + ldmia r2, {r2 - r4} @ get pc, cpsr add r5, sp, #S_SP mov r1, lr - ldmia r2, {r2 - r4} @ get pc, cpsr stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro tst r3, #I_BIT mrseq r0, cpsr @ Enable interrupts if they were @@ -619,29 +525,15 @@ msr spsr, r0 ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr -__dabt_invalid: sub sp, sp, #S_FRAME_SIZE - stmia sp, {r0 - lr} @ Save SVC r0 - lr [lr *should* be intact] - mov r7, r0 - ldr r4, .LCabt - ldmia r4, {r5, r6} @ Get SVC pc, cpsr - add r4, sp, #S_PC - stmia r4, {r5, r6, r7} @ Save SVC pc, cpsr, old_r0 - mov r0, sp - mov r1, #BAD_DATA - and r2, r6, #31 - b SYMBOL_NAME(bad_mode) - -/*============================================================================= - * Interrupt (IRQ) handler - *----------------------------------------------------------------------------- - */ -__irq_usr: sub sp, sp, #S_FRAME_SIZE + .align 5 +__irq_svc: sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ save r0 - r12 - add r8, sp, #S_PC - stmdb r8, {sp, lr}^ - ldr r4, .LCirq - ldmia r4, {r5 - r7} @ get saved PC, SPSR - stmia r8, {r5 - r7} @ save pc, psr, old_r0 + ldr r7, .LCirq + add r5, sp, #S_FRAME_SIZE + ldmia r7, {r7 - r9} + add r4, sp, #S_SP + mov r6, lr + stmia r4, {r5, r6, r7, r8, r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro 1: get_irqnr_and_base r0, r6, r5 movne r1, sp @ @@ -649,48 +541,97 @@ @ adrsvc ne, lr, 1b bne do_IRQ - b ret_with_reschedule - - irq_prio_table + ldr r0, [sp, #S_PSR] + msr spsr, r0 + ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr -__irq_svc: sub sp, sp, #S_FRAME_SIZE + .align 5 +__und_svc: sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ save r0 - r12 mov r6, lr - ldr r7, .LCirq + ldr r7, .LCund ldmia r7, {r7 - r9} add r5, sp, #S_FRAME_SIZE add r4, sp, #S_SP - stmia r4, {r5, r6, r7, r8, r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro + stmia r4, {r5 - r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro + + adrsvc al, r9, 1f @ r9 = normal FP return + bl call_fpe @ lr = undefined instr return + + mov r0, r5 @ unsigned long pc + mov r1, sp @ struct pt_regs *regs + bl SYMBOL_NAME(do_undefinstr) + +1: ldr lr, [sp, #S_PSR] @ Get SVC cpsr + msr spsr, lr + ldmia sp, {r0 - pc}^ @ Restore SVC registers + + .align 5 +.LCirq: .word __temp_irq +.LCund: .word __temp_und +.LCabt: .word __temp_abt +.LCprocfns: .word SYMBOL_NAME(processor) +.LCfp: .word SYMBOL_NAME(fp_enter) + + irq_prio_table + +/* + * User mode handlers + */ +#ifdef DEBUG_UNDEF +t: .ascii "Prefetch -> undefined instruction\n\0" + .align +#endif + .align 5 +__dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go + stmia sp, {r0 - r12} @ save r0 - r12 + add r3, sp, #S_PC + stmdb r3, {sp, lr}^ + ldr r4, .LCabt + ldmia r4, {r0 - r2} @ Get USR pc, cpsr + stmia r3, {r0 - r2} @ Save USR pc, cpsr, old_r0 + +#ifdef CONFIG_ALIGNMENT_TRAP + ldr r7, [r4, #OFF_CR_ALIGNMENT(__temp_abt)] + mcr p15, 0, r7, c1, c0 +#endif + + mov fp, #0 + mrs r2, cpsr @ Enable interrupts if they were + bic r2, r2, #I_BIT @ previously + msr cpsr, r2 + ldr r2, .LCprocfns + mov lr, pc + ldr pc, [r2, #8] @ call processor specific code + mov r3, sp + adrsvc al, lr, ret_from_sys_call + b SYMBOL_NAME(do_DataAbort) + + .align 5 +__irq_usr: sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ save r0 - r12 + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ + ldr r4, .LCirq + ldmia r4, {r5 - r7} @ get saved PC, SPSR + stmia r8, {r5 - r7} @ save pc, psr, old_r0 + +#ifdef CONFIG_ALIGNMENT_TRAP + ldr r7, [r4, #OFF_CR_ALIGNMENT(__temp_irq)] + mcr p15, 0, r7, c1, c0 +#endif + 1: get_irqnr_and_base r0, r6, r5 movne r1, sp + adrsvc ne, lr, 1b @ @ routine called with r0 = irq number, r1 = struct pt_regs * @ - adrsvc ne, lr, 1b bne do_IRQ - ldr r0, [sp, #S_PSR] - msr spsr, r0 - ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr - -__irq_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate space on stack for frame - stmfd sp, {r0 - lr} @ Save r0 - lr - mov r7, #-1 - ldr r4, .LCirq - ldmia r4, {r5, r6} @ get saved pc, psr - add r4, sp, #S_PC - stmia r4, {r5, r6, r7} - mov fp, #0 - mov r0, sp - mov r1, #BAD_IRQ - b SYMBOL_NAME(bad_mode) - -/*============================================================================= - * Undefined instruction handler - *----------------------------------------------------------------------------- - * Handles floating point instructions - */ -.LC2: .word SYMBOL_NAME(fp_enter) + mov r4, #0 + b ret_with_reschedule + .align 5 __und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go stmia sp, {r0 - r12} @ Save r0 - r12 add r8, sp, #S_PC @@ -698,99 +639,311 @@ ldr r4, .LCund ldmia r4, {r5 - r7} stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0 + +#ifdef CONFIG_ALIGNMENT_TRAP + ldr r7, [r4, #OFF_CR_ALIGNMENT(__temp_und)] + mcr p15, 0, r7, c1, c0 +#endif + mov fp, #0 - adrsvc al, r9, ret_from_exception @ r9 = normal FP return + adrsvc al, r9, ret_from_sys_call @ r9 = normal FP return adrsvc al, lr, fpundefinstr @ lr = undefined instr return -1: get_current_task r10 +call_fpe: get_current_task r10 mov r8, #1 strb r8, [r10, #TSK_USED_MATH] @ set current->used_math add r10, r10, #TSS_FPESAVE @ r10 = workspace - ldr r4, .LC2 + ldr r4, .LCfp ldr pc, [r4] @ Call FP module USR entry point -__und_svc: sub sp, sp, #S_FRAME_SIZE - stmia sp, {r0 - r12} @ save r0 - r12 - mov r6, lr - ldr r7, .LCund - ldmia r7, {r7 - r9} - add r5, sp, #S_FRAME_SIZE - add r4, sp, #S_SP - stmia r4, {r5 - r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro - - adrsvc al, r9, 3f @ r9 = normal FP return - bl 1b @ lr = undefined instr return - - mov r0, r5 @ unsigned long pc - mov r1, sp @ struct pt_regs *regs - bl SYMBOL_NAME(do_undefinstr) - -3: ldr lr, [sp, #S_PSR] @ Get SVC cpsr - msr spsr, lr - ldmia sp, {r0 - pc}^ @ Restore SVC registers - fpundefinstr: mov r0, lr mov r1, sp mrs r4, cpsr @ Enable interrupts bic r4, r4, #I_BIT msr cpsr, r4 - adrsvc al, lr, ret_from_exception + adrsvc al, lr, ret_from_sys_call b SYMBOL_NAME(do_undefinstr) -__und_invalid: sub sp, sp, #S_FRAME_SIZE - stmia sp, {r0 - lr} - mov r7, r0 - ldr r4, .LCund - ldmia r4, {r5, r6} @ Get UND/IRQ/FIQ/ABT pc, cpsr - add r4, sp, #S_PC - stmia r4, {r5, r6, r7} @ Save UND/IRQ/FIQ/ABT pc, cpsr, old_r0 - mov r0, sp @ struct pt_regs *regs - mov r1, #BAD_UNDEFINSTR @ int reason - and r2, r6, #31 @ int mode - b SYMBOL_NAME(bad_mode) @ Does not ever return... + .align 5 +__pabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go + stmia sp, {r0 - r12} @ Save r0 - r12 + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ @ Save sp_usr lr_usr + ldr r4, .LCabt + ldmia r4, {r5 - r7} @ Get USR pc, cpsr + stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0 -/* We get here if an undefined instruction happens and the floating - * point emulator is not present. If the offending instruction was - * a WFS, we just perform a normal return as if we had emulated the - * operation. This is a hack to allow some basic userland binaries - * to run so that the emulator module proper can be loaded. --philb - */ -fpe_not_present: - adr r10, wfs_mask_data - ldmia r10, {r4, r5, r6, r7, r8} - ldr r10, [sp, #S_PC] @ Load PC - sub r10, r10, #4 - mask_pc r10, r10 - ldrt r10, [r10] @ get instruction - and r5, r10, r5 - teq r5, r4 @ Is it WFS? - moveq pc, r9 - and r5, r10, r8 - teq r5, r6 @ Is it LDF/STF on sp or fp? - teqne r5, r7 - movne pc, lr - tst r10, #0x00200000 @ Does it have WB - moveq pc, r9 - and r4, r10, #255 @ get offset - and r6, r10, #0x000f0000 - tst r10, #0x00800000 @ +/- - rsbeq r4, r4, #0 - ldr r5, [sp, r6, lsr #14] @ Load reg - add r5, r5, r4, lsl #2 - str r5, [sp, r6, lsr #14] @ Save reg - mov pc, r9 +#ifdef CONFIG_ALIGNMENT_TRAP + ldr r7, [r4, #OFF_CR_ALIGNMENT(__temp_abt)] + mcr p15, 0, r7, c1, c0 +#endif -wfs_mask_data: .word 0x0e200110 @ WFS - .word 0x0fff0fff - .word 0x0d0d0100 @ LDF [sp]/STF [sp] - .word 0x0d0b0100 @ LDF [fp]/STF [fp] - .word 0x0f0f0f00 + mrs r7, cpsr @ Enable interrupts if they were + bic r7, r7, #I_BIT @ previously + msr cpsr, r7 + mov r0, r5 @ address (pc) + mov r1, sp @ regs + bl SYMBOL_NAME(do_PrefetchAbort) @ call abort handler + teq r0, #0 @ Does this still apply??? + bne ret_from_sys_call @ Return from exception +#ifdef DEBUG_UNDEF + adr r0, t + bl SYMBOL_NAME(printk) +#endif + mov r0, r5 + mov r1, sp + and r2, r6, #31 + bl SYMBOL_NAME(do_undefinstr) + ldr lr, [sp, #S_PSR] @ Get USR cpsr + msr spsr, lr + ldmia sp, {r0 - pc}^ @ Restore USR registers #include "entry-common.S" + .text + +#ifndef __ARM_ARCH_4__ +.Larm700bug: str lr, [r8] + ldr r0, [sp, #S_PSR] @ Get calling cpsr + msr spsr, r0 + ldmia sp, {r0 - lr}^ @ Get calling r0 - lr + mov r0, r0 + add sp, sp, #S_PC + ldr lr, [sp], #S_FRAME_SIZE - S_PC @ Get PC and jump over PC, PSR, OLD_R0 + movs pc, lr +#endif + + .section ".text.init",#alloc,#execinstr +/* + * Vector stubs. NOTE that we only align 'vector_IRQ' to a cache line boundary, + * and we rely on each stub being exactly 48 (1.5 cache lines) in size. This + * means that we only ever load two cache lines for this code, or one if we're + * lucky. We also copy this code to 0x200 so that we can use branches in the + * vectors, rather than ldr's. + */ + .align 5 +__stubs_start: +/* + * Interrupt dispatcher + * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC + */ +vector_IRQ: @ + @ save mode specific registers + @ + ldr r13, .LCsirq + sub lr, lr, #4 + str lr, [r13] @ save lr_IRQ + mrs lr, spsr + str lr, [r13, #4] @ save spsr_IRQ + @ + @ now branch to the relevent MODE handling routine + @ + bic r13, lr, #63 + orr r13, r13, #0x93 + msr spsr, r13 @ switch to SVC_32 mode + + and lr, lr, #15 + adr r13, .LCtab_irq + ldr lr, [r13, lr, lsl #2] + movs pc, lr @ Changes mode and branches +/* + * Data abort dispatcher - dispatches it to the correct handler for the processor mode + * Enter in ABT mode, spsr = USR CPSR, lr = USR PC + */ +vector_data: @ + @ save mode specific registers + @ + sub lr, lr, #8 + ldr r13, .LCsabt + str lr, [r13] + mrs lr, spsr + str lr, [r13, #4] + @ + @ now branch to the relevent MODE handling routine + @ + bic r13, lr, #63 + orr r13, r13, #0x93 + msr spsr, r13 @ switch to SVC_32 mode + + and lr, lr, #15 + adr r13, .LCtab_dabt + ldr lr, [r13, lr, lsl #2] + movs pc, lr @ Changes mode and branches + +/* + * Prefetch abort dispatcher - dispatches it to the correct handler for the processor mode + * Enter in ABT mode, spsr = USR CPSR, lr = USR PC + */ +vector_prefetch: + @ + @ save mode specific registers + @ + sub lr, lr, #4 + ldr r13, .LCsabt + str lr, [r13] @ save lr_ABT + mrs lr, spsr + str lr, [r13, #4] @ save spsr_ABT + @ + @ now branch to the relevent MODE handling routine + @ + bic r13, lr, #63 + orr r13, r13, #0x93 + msr spsr, r13 @ switch to SVC_32 mode + + ands lr, lr, #15 + ldreq lr, .LCtab_pabt + ldrne lr, .LCtab_pabt + 4 + movs pc, lr + +/* + * Undef instr entry dispatcher - dispatches it to the correct handler for the processor mode + * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC + */ +vector_undefinstr: + @ + @ save mode specific registers + @ + ldr r13, .LCsund + str lr, [r13] @ save lr_UND + mrs lr, spsr + str lr, [r13, #4] @ save spsr_UND + @ + @ now branch to the relevent MODE handling routine + @ + bic r13, lr, #63 + orr r13, r13, #0x93 + msr spsr, r13 @ switch to SVC_32 mode + + and lr, lr, #15 + adr r13, .LCtab_und + ldr lr, [r13, lr, lsl #2] + movs pc, lr @ Changes mode and branches + +/*============================================================================= + * Undefined FIQs + *----------------------------------------------------------------------------- + * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC + * MUST PRESERVE SVC SPSR, but need to switch to SVC mode to show our msg. + * Basically to switch modes, we *HAVE* to clobber one register... brain + * damage alert! I don't think that we can execute any code in here in any + * other mode than FIQ... Ok you can switch to another mode, but you can't + * get out of that mode without clobbering one register. + */ +vector_FIQ: disable_fiq + subs pc, lr, #4 + +/*============================================================================= + * Address exception handler + *----------------------------------------------------------------------------- + * These aren't too critical. + * (they're not supposed to happen, and won't happen in 32-bit data mode). + */ + +vector_addrexcptn: + b vector_addrexcptn + +/* + * We group all the following data together to optimise + * for CPUs with separate I & D caches. + */ + .align 5 + +.LCtab_irq: .word __irq_usr @ 0 (USR_26 / USR_32) + .word __irq_invalid @ 1 (FIQ_26 / FIQ_32) + .word __irq_invalid @ 2 (IRQ_26 / IRQ_32) + .word __irq_svc @ 3 (SVC_26 / SVC_32) + .word __irq_invalid @ 4 + .word __irq_invalid @ 5 + .word __irq_invalid @ 6 + .word __irq_invalid @ 7 + .word __irq_invalid @ 8 + .word __irq_invalid @ 9 + .word __irq_invalid @ a + .word __irq_invalid @ b + .word __irq_invalid @ c + .word __irq_invalid @ d + .word __irq_invalid @ e + .word __irq_invalid @ f + +.LCtab_und: .word __und_usr @ 0 (USR_26 / USR_32) + .word __und_invalid @ 1 (FIQ_26 / FIQ_32) + .word __und_invalid @ 2 (IRQ_26 / IRQ_32) + .word __und_svc @ 3 (SVC_26 / SVC_32) + .word __und_invalid @ 4 + .word __und_invalid @ 5 + .word __und_invalid @ 6 + .word __und_invalid @ 7 + .word __und_invalid @ 8 + .word __und_invalid @ 9 + .word __und_invalid @ a + .word __und_invalid @ b + .word __und_invalid @ c + .word __und_invalid @ d + .word __und_invalid @ e + .word __und_invalid @ f + +.LCtab_dabt: .word __dabt_usr @ 0 (USR_26 / USR_32) + .word __dabt_invalid @ 1 (FIQ_26 / FIQ_32) + .word __dabt_invalid @ 2 (IRQ_26 / IRQ_32) + .word __dabt_svc @ 3 (SVC_26 / SVC_32) + .word __dabt_invalid @ 4 + .word __dabt_invalid @ 5 + .word __dabt_invalid @ 6 + .word __dabt_invalid @ 7 + .word __dabt_invalid @ 8 + .word __dabt_invalid @ 9 + .word __dabt_invalid @ a + .word __dabt_invalid @ b + .word __dabt_invalid @ c + .word __dabt_invalid @ d + .word __dabt_invalid @ e + .word __dabt_invalid @ f + +.LCtab_pabt: .word __pabt_usr + .word __pabt_invalid + +.LCvswi: .word vector_swi + +.LCsirq: .word __temp_irq +.LCsund: .word __temp_und +.LCsabt: .word __temp_abt + +__stubs_end: + + .equ __real_stubs_start, .LCvectors + 0x200 + +.LCvectors: swi SYS_ERROR0 + b __real_stubs_start + (vector_undefinstr - __stubs_start) + ldr pc, __real_stubs_start + (.LCvswi - __stubs_start) + b __real_stubs_start + (vector_prefetch - __stubs_start) + b __real_stubs_start + (vector_data - __stubs_start) + b __real_stubs_start + (vector_addrexcptn - __stubs_start) + b __real_stubs_start + (vector_IRQ - __stubs_start) + b __real_stubs_start + (vector_FIQ - __stubs_start) + +ENTRY(trap_init) + stmfd sp!, {r4 - r6, lr} + adr r0, __stubs_start @ copy stubs to 0x200 + adr r1, __stubs_end + mov r2, #0x200 +1: ldr r3, [r0], #4 + str r3, [r2], #4 + cmp r0, r1 + blt 1b + + adr r1, .LCvectors @ set up the vectors + mov r0, #0 + ldmia r1, {r1, r2, r3, r4, r5, r6, ip, lr} + stmia r0, {r1, r2, r3, r4, r5, r6, ip, lr} + LOADREGS(fd, sp!, {r4 - r6, pc}) + .data +/* + * Do not reorder these, and do not insert extra data between... + */ + __temp_irq: .word 0 @ saved lr_irq .word 0 @ saved spsr_irq .word -1 @ old_r0 @@ -800,3 +953,10 @@ __temp_abt: .word 0 @ Saved lr_abt .word 0 @ Saved spsr_abt .word -1 @ old_r0 + + .globl SYMBOL_NAME(cr_alignment) + .globl SYMBOL_NAME(cr_no_alignment) +SYMBOL_NAME(cr_alignment): + .space 4 +SYMBOL_NAME(cr_no_alignment): + .space 4 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/entry-common.S linux.ac/arch/arm/kernel/entry-common.S --- linux.vanilla/arch/arm/kernel/entry-common.S Tue Dec 22 23:19:26 1998 +++ linux.ac/arch/arm/kernel/entry-common.S Sun Jan 24 21:11:31 1999 @@ -1,51 +1,55 @@ +#include + /*============================================================================ * All exits to user mode from the kernel go through this code. */ - -#include - .globl ret_from_sys_call -ret_from_exception: - adr r0, 1f - ldmia r0, {r0, r1} + .align 5 +fast_syscall_return: + str r0, [sp, #S_R0 + 4] @ returned r0 +slow_syscall_return: + add sp, sp, #4 +ret_from_sys_call: + adr r0, bh_data + ldmia r0, {r0, r4} ldr r0, [r0] - ldr r1, [r1] + ldr r1, [r4] tst r0, r1 blne SYMBOL_NAME(do_bottom_half) -ret_from_intr: ldr r0, [sp, #S_PSR] - tst r0, #3 - beq ret_with_reschedule - b ret_from_all +ret_with_reschedule: + get_current_task r1 @ check for scheduling + ldr r0, [r1, #TSK_NEED_RESCHED] + teq r0, #0 + bne ret_reschedule + ldr r1, [r1, #TSK_SIGPENDING] + teq r1, #0 @ check for signals + bne ret_signal + +ret_from_all: restore_user_regs ret_signal: mov r1, sp adrsvc al, lr, ret_from_all + mov r2, r4 b SYMBOL_NAME(do_signal) -2: bl SYMBOL_NAME(schedule) +ret_reschedule: adrsvc al, lr, ret_with_reschedule + b SYMBOL_NAME(schedule) -ret_from_sys_call: - adr r0, 1f +ret_from_exception: + adr r0, bh_data ldmia r0, {r0, r1} ldr r0, [r0] ldr r1, [r1] tst r0, r1 - adrsvc ne, lr, ret_from_intr - bne SYMBOL_NAME(do_bottom_half) - -ret_with_reschedule: - get_current_task r1 - ldr r0, [r1, #TSK_NEED_RESCHED] - teq r0, #0 - bne 2b - ldr r1, [r1, #TSK_SIGPENDING] - teq r1, #0 - bne ret_signal - -ret_from_all: restore_user_regs + mov r4, #0 + blne SYMBOL_NAME(do_bottom_half) + ldr r0, [sp, #S_PSR] + tst r0, #3 @ returning to user mode? + beq ret_with_reschedule + b ret_from_all -1: .word SYMBOL_NAME(bh_mask) - .word SYMBOL_NAME(bh_active) +#include "calls.S" /*============================================================================= * SWI handler @@ -57,140 +61,67 @@ * too worried. */ -#include "calls.S" - + .align 5 vector_swi: save_user_regs - mov fp, #0 mask_pc lr, lr - ldr r6, [lr, #-4]! @ get SWI instruction + mov fp, #0 + ldr r6, [lr, #-4] @ get SWI instruction arm700_bug_check r6, r7 enable_irqs r7 - + + str r4, [sp, #-4]! @ new style: (r0 = arg1, r4 = arg5) + adrsvc al, lr, fast_syscall_return + bic r6, r6, #0xff000000 @ mask off SWI op-code eor r6, r6, #OS_NUMBER<<20 @ check OS number cmp r6, #NR_syscalls @ check upper syscall limit bcs 2f - get_current_task r5 - ldr ip, [r5, #TSK_FLAGS] @ check for syscall tracing - tst ip, #PF_TRACESYS - bne 1f + adr r5, SYMBOL_NAME(sys_call_table) - adr ip, SYMBOL_NAME(sys_call_table) - str r4, [sp, #-4]! @ new style: (r0 = arg1, r5 = arg5) - mov lr, pc - ldr pc, [ip, r6, lsl #2] @ call sys routine - add sp, sp, #4 - str r0, [sp, #S_R0] @ returned r0 - b ret_from_sys_call + get_current_task r7 + ldr ip, [r7, #TSK_FLAGS] @ check for syscall tracing + tst ip, #PF_TRACESYS + ldreq pc, [r5, r6, lsl #2] @ call sys routine -1: ldr r7, [sp, #S_IP] @ save old IP + ldr r7, [sp, #S_IP + 4] @ save old IP mov r0, #0 - str r0, [sp, #S_IP] @ trace entry [IP = 0] + str r0, [sp, #S_IP + 4] @ trace entry [IP = 0] bl SYMBOL_NAME(syscall_trace) - str r7, [sp, #S_IP] - ldmia sp, {r0 - r3} @ have to reload r0 - r3 - adr ip, SYMBOL_NAME(sys_call_table) - str r4, [sp, #-4]! @ new style: (r0 = arg1, r5 = arg5) + str r7, [sp, #S_IP + 4] + + ldmib sp, {r0 - r3} @ have to reload r0 - r3 mov lr, pc - ldr pc, [ip, r6, lsl #2] @ call sys routine - add sp, sp, #4 - str r0, [sp, #S_R0] @ returned r0 + ldr pc, [r5, r6, lsl #2] @ call sys routine + str r0, [sp, #S_R0 + 4] @ returned r0 + mov r0, #1 - str r0, [sp, #S_IP] @ trace exit [IP = 1] + str r0, [sp, #S_IP + 4] @ trace exit [IP = 1] bl SYMBOL_NAME(syscall_trace) - str r7, [sp, #S_IP] - b ret_from_sys_call + str r7, [sp, #S_IP + 4] + b slow_syscall_return -2: tst r6, #0x00f00000 @ is it a Unix SWI? +2: add r1, sp, #4 + tst r6, #0x00f00000 @ is it a Unix SWI? bne 3f - cmp r6, #(KSWI_SYS_BASE - KSWI_BASE) - bcc 4f @ not private func - bic r0, r6, #0x000f0000 - mov r1, sp - bl SYMBOL_NAME(arm_syscall) - b ret_from_sys_call - -3: eor r0, r6, #OS_NUMBER<<20 @ Put OS number back - mov r1, sp - bl SYMBOL_NAME(deferred) - ldmfd sp, {r0 - r3} - b ret_from_sys_call - -4: bl SYMBOL_NAME(sys_ni_syscall) - str r0, [sp, #0] @ returned r0 - b ret_from_sys_call + subs r0, r6, #(KSWI_SYS_BASE - KSWI_BASE) + bcs SYMBOL_NAME(arm_syscall) + b SYMBOL_NAME(sys_ni_syscall) @ not private func + +3: add sp, sp, #4 + eor r0, r6, #OS_NUMBER <<20 @ Put OS number back + adrsvc al, lr, slow_syscall_return + b SYMBOL_NAME(deferred) -@ r0 = syscall number -@ r1 = syscall r0 -@ r5 = syscall r4 -@ ip = syscall table -SYMBOL_NAME(sys_syscall): - mov r6, r0 - eor r6, r6, #OS_NUMBER << 20 - cmp r6, #NR_syscalls @ check range - movgt r0, #-ENOSYS - movgt pc, lr - add sp, sp, #4 @ take of the save of our r4 - ldmib sp, {r0 - r4} @ get our args - str r4, [sp, #-4]! @ Put our arg on the stack - ldr pc, [ip, r6, lsl #2] + .align 5 + +bh_data: .word SYMBOL_NAME(bh_mask) + .word SYMBOL_NAME(bh_active) ENTRY(sys_call_table) #include "calls.S" -/*============================================================================ - * Special system call wrappers - */ -sys_fork_wrapper: - add r0, sp, #4 - b SYMBOL_NAME(sys_fork) - -sys_execve_wrapper: - add r3, sp, #4 - b SYMBOL_NAME(sys_execve) - -sys_mount_wrapper: - mov r6, lr - add r5, sp, #4 - str r5, [sp] - str r4, [sp, #-4]! - bl SYMBOL_NAME(sys_compat_mount) - add sp, sp, #4 - RETINSTR(mov,pc,r6) - -sys_clone_wapper: - add r2, sp, #4 - b SYMBOL_NAME(sys_clone) - -sys_llseek_wrapper: - mov r6, lr - add r5, sp, #4 - str r5, [sp] - str r4, [sp, #-4]! - bl SYMBOL_NAME(sys_compat_llseek) - add sp, sp, #4 - RETINSTR(mov,pc,r6) - -sys_sigsuspend_wrapper: - add r3, sp, #4 - b SYMBOL_NAME(sys_sigsuspend) - -sys_rt_sigsuspend_wrapper: - add r2, sp, #4 - b SYMBOL_NAME(sys_rt_sigsuspend) - -sys_sigreturn_wrapper: - add r0, sp, #4 - b SYMBOL_NAME(sys_sigreturn) - -sys_rt_sigreturn_wrapper: - add r0, sp, #4 - b SYMBOL_NAME(sys_rt_sigreturn) - -sys_sigaltstack_wrapper: - ldr r2, [sp, #4 + S_SP] - b do_sigaltstack +#if defined(CONFIG_CPU_26) /* *============================================================================= @@ -211,45 +142,6 @@ .section ".text.init",#alloc,#execinstr -#if defined(CONFIG_CPU_32) -/* - * these go into 0x00 - */ -.Lbranches: swi SYS_ERROR0 - ldr pc, .Lbranches + 0xe4 - ldr pc, .Lbranches + 0xe8 - ldr pc, .Lbranches + 0xec - ldr pc, .Lbranches + 0xf0 - ldr pc, .Lbranches + 0xf4 - ldr pc, .Lbranches + 0xf8 - ldr pc, .Lbranches + 0xfc -/* - * this is put into 0xe4 and above - */ -.Ljump_addresses: - .word vector_undefinstr @ 0xe4 - .word vector_swi @ 0xe8 - .word vector_prefetch @ 0xec - .word vector_data @ 0xf0 - .word vector_addrexcptn @ 0xf4 - .word vector_IRQ @ 0xf8 - .word _unexp_fiq @ 0xfc -/* - * initialise the trap system - */ -ENTRY(trap_init) - stmfd sp!, {r4 - r7, lr} - initialise_traps_extra - mov r0, #0xe4 - adr r1, .Ljump_addresses - ldmia r1, {r1 - r7} - stmia r0, {r1 - r7} - mov r0, #0 - adr r1, .Lbranches - ldmia r1, {r1 - r7} - stmia r0, {r1 - r7} - LOADREGS(fd, sp!, {r4 - r7, pc}) -#elif defined(CONFIG_CPU_26) .Ljump_addresses: swi SYS_ERROR0 .word vector_undefinstr - 12 @@ -279,11 +171,75 @@ ldmfd sp!, {r4 - r7, pc}^ #endif - .previous + .text /*============================================================================ - * FP support + * Special system call wrappers */ +@ r0 = syscall number +@ r5 = syscall table +SYMBOL_NAME(sys_syscall): + eor r6, r0, #OS_NUMBER << 20 + cmp r6, #NR_syscalls @ check range + ldmleib sp, {r0 - r4} @ get our args + strle r4, [sp] @ Put our arg on the stack + ldrle pc, [r5, r6, lsl #2] + mov r0, #-ENOSYS + mov pc, lr + +sys_fork_wrapper: + add r0, sp, #4 + b SYMBOL_NAME(sys_fork) + +sys_vfork_wrapper: + add r0, sp, #4 + b SYMBOL_NAME(sys_vfork) + +sys_execve_wrapper: + add r3, sp, #4 + b SYMBOL_NAME(sys_execve) + +sys_mount_wrapper: + mov r6, lr + add r5, sp, #4 + str r5, [sp] + str r4, [sp, #-4]! + bl SYMBOL_NAME(sys_compat_mount) + add sp, sp, #4 + RETINSTR(mov,pc,r6) + +sys_clone_wapper: + add r2, sp, #4 + b SYMBOL_NAME(sys_clone) + +sys_llseek_wrapper: + mov r6, lr + add r5, sp, #4 + str r5, [sp] + str r4, [sp, #-4]! + bl SYMBOL_NAME(sys_compat_llseek) + add sp, sp, #4 + RETINSTR(mov,pc,r6) + +sys_sigsuspend_wrapper: + add r3, sp, #4 + b SYMBOL_NAME(sys_sigsuspend) + +sys_rt_sigsuspend_wrapper: + add r2, sp, #4 + b SYMBOL_NAME(sys_rt_sigsuspend) + +sys_sigreturn_wrapper: + add r0, sp, #4 + b SYMBOL_NAME(sys_sigreturn) + +sys_rt_sigreturn_wrapper: + add r0, sp, #4 + b SYMBOL_NAME(sys_rt_sigreturn) + +sys_sigaltstack_wrapper: + ldr r2, [sp, #4 + S_SP] + b do_sigaltstack .data diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/fiq.c linux.ac/arch/arm/kernel/fiq.c --- linux.vanilla/arch/arm/kernel/fiq.c Tue Dec 22 23:19:26 1998 +++ linux.ac/arch/arm/kernel/fiq.c Sun Jan 24 21:11:31 1999 @@ -113,21 +113,68 @@ void set_fiq_regs(struct pt_regs *regs) { - /* not yet - - * this is temporary to get the floppy working - * again on RiscPC. It *will* become more - * generic. - */ -#ifdef CONFIG_ARCH_ACORN - extern void floppy_fiqsetup(unsigned long len, unsigned long addr, - unsigned long port); - floppy_fiqsetup(regs->ARM_r9, regs->ARM_r10, regs->ARM_fp); + register unsigned long tmp, tmp2; + __asm__ volatile ( +#ifdef CONFIG_CPU_26 + "mov %0, pc + bic %1, %0, #0x0c000003 + orr %1, %1, #1 + teqp %1, #0 @ select FIQ mode + mov r0, r0 + ldmia %2, {r8 - r14} + teqp %0, #0 @ return to SVC mode + mov r0, r0" #endif +#ifdef CONFIG_CPU_32 + "mrs %0, cpsr + bic %1, %0, #0xf + orr %1, %1, #1 + msr cpsr, %1 @ select FIQ mode + mov r0, r0 + ldmia %2, {r8 - r14} + msr cpsr, %0 @ return to SVC mode + mov r0, r0" +#endif + : "=r" (tmp), "=r" (tmp2) + : "r" (®s->ARM_r8) + /* These registers aren't modified by the above code in a way + visible to the compiler, but we mark them as clobbers anyway + so that GCC won't put any of the input or output operands in + them. */ + : "r8", "r9", "r10", "r11", "r12", "r13", "r14"); } void get_fiq_regs(struct pt_regs *regs) { - /* not yet */ + register unsigned long tmp, tmp2; + __asm__ volatile ( +#ifdef CONFIG_CPU_26 + "mov %0, pc + bic %1, %0, #0x0c000003 + orr %1, %1, #1 + teqp %1, #0 @ select FIQ mode + mov r0, r0 + stmia %2, {r8 - r14} + teqp %0, #0 @ return to SVC mode + mov r0, r0" +#endif +#ifdef CONFIG_CPU_32 + "mrs %0, cpsr + bic %1, %0, #0xf + orr %1, %1, #1 + msr cpsr, %1 @ select FIQ mode + mov r0, r0 + stmia %2, {r8 - r14} + msr cpsr, %0 @ return to SVC mode + mov r0, r0" +#endif + : "=r" (tmp), "=r" (tmp2) + : "r" (®s->ARM_r8) + /* These registers aren't modified by the above code in a way + visible to the compiler, but we mark them as clobbers anyway + so that GCC won't put any of the input or output operands in + them. */ + : "r8", "r9", "r10", "r11", "r12", "r13", "r14"); } int claim_fiq(struct fiq_handler *f) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/head-armv.S linux.ac/arch/arm/kernel/head-armv.S --- linux.vanilla/arch/arm/kernel/head-armv.S Tue Dec 22 23:19:26 1998 +++ linux.ac/arch/arm/kernel/head-armv.S Sun Jan 24 21:11:31 1999 @@ -8,12 +8,20 @@ #include #include -#ifndef CONFIG_ARCH_VNC +#define DEBUG + + .globl SYMBOL_NAME(swapper_pg_dir) + .equ SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x4000 + + .section ".text.init",#alloc,#execinstr +ENTRY(stext) +ENTRY(_stext) + #if (TEXTADDR & 0xffff) != 0x8000 #error TEXTADDR must start at 0xXXXX8000 #endif -#else - .text + +#if defined(CONFIG_ARCH_VNC) || defined(CONFIG_ARCH_NETWINDER) mov r0, r0 mov r0, r0 mov r0, r0 @@ -22,16 +30,34 @@ mov r0, r0 mov r0, r0 mov r0, r0 + + adr r2, 1f + ldmdb r2, {r7, r8} + and r3, r2, #0x0000c000 + teq r3, #0x00008000 + beq __entry + bic r3, r2, #0xc000 + orr r3, r3, #0x8000 + mov r0, r3 + mov r4, #32 + sub r5, r8, r7 + b 1f + + .word _stext + .word _end + +1: ldmia r2!, {r6, r7, r8, r9} + stmia r3!, {r6, r7, r8, r9} + subs r4, r4, #16 + bcs 1b + movs r4, r5 + mov r5, #0 + movne pc, r0 + mov r0, #0 mov r1, #5 #endif -#define DEBUG - - .globl SYMBOL_NAME(swapper_pg_dir) - .equ SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x4000 - - .text /* * Entry point and restart point. Entry *must* be called with r0 == 0, * MMU off. Note! These should be unique!!! Please read Documentation/ARM-README @@ -45,16 +71,15 @@ * r1 = 5 -> Corel Netwinder * r1 = 6 -> CATS * r1 = 7 -> tbox + * r1 = 8 -> SA110/21285 as co-processor */ -ENTRY(stext) -ENTRY(_stext) __entry: teq r0, #0 @ check for illegal entry... bne .Lerror @ loop indefinitely cmp r1, #8 @ Unknown machine architecture bge .Lerror -/* First thing to do is to get the page tables set up so that we can call the kernel - * in the correct place. This is relocatable code... +/* First thing to do is to get the page tables set up so that we can call + * the kernel in the correct place. This is relocatable code... * - Read processor ID register (CP#15, CR0). */ mrc p15, 0, r9, c0, c0 @ get Processor ID @@ -111,7 +136,11 @@ add r3, r3, #1 << 20 teq r0, r2 bne 1b -#ifdef CONFIG_ARCH_VNC +#ifdef CONFIG_ARCH_NETWINDER + teq r1, #5 + bne 1f +#endif +#if defined(CONFIG_ARCH_VNC) || defined(CONFIG_ARCH_NETWINDER) add r0, r4, #0x3f00 add r0, r0, #0x00f8 mov r3, #0x7c000000 @@ -120,6 +149,7 @@ add r3, r3, #1 << 20 str r3, [r0], #4 #endif +1: #endif #ifdef CONFIG_ARCH_RPC /* Map in screen at 0x02000000 & SCREEN2_BASE @@ -250,7 +280,11 @@ mcr p15, 0, r4, c2, c0 @ load page table pointer mov r0, #0x1f @ Domains 0, 1 = client mcr p15, 0, r0, c3, c0 @ load domain access register +#ifdef CONFIG_ALIGNMENT_TRAP + mov r0, #0x3f @ ....S..DPWCAM +#else mov r0, #0x3d @ ....S..DPWC.M +#endif orr r0, r0, #0x100 mov pc, lr @@ -261,7 +295,11 @@ mcr p15, 0, r4, c2, c0 @ load page table pointer mov r0, #0x1f @ Domains 0, 1 = client mcr p15, 0, r0, c3, c0 @ load domain access register +#ifdef CONFIG_ALIGNMENT_TRAP + mov r0, #0x7f @ ....S.LDPWCAM +#else mov r0, #0x7d @ ....S.LDPWC.M +#endif orr r0, r0, #0x100 mov pc, lr @@ -276,12 +314,14 @@ mrc p15, 0, r0, c1, c0 @ get control register v4 bic r0, r0, #0x0e00 bic r0, r0, #0x0002 +#ifdef CONFIG_ALIGNMENT_TRAP + orr r0, r0, #0x003f @ I...S..DPWCAM +#else orr r0, r0, #0x003d @ I...S..DPWC.M +#endif orr r0, r0, #0x1100 @ v4 supports separate I cache mov pc, lr - .section ".text.init",#alloc,#execinstr - .Lsa_fastclock: mcr p15, 0, r4, c15, c1, 2 @ Enable clock switching mov pc, lr @@ -290,18 +330,22 @@ .long SYMBOL_NAME(__bss_start) .long SYMBOL_NAME(processor_id) .long SYMBOL_NAME(_end) + .long SYMBOL_NAME(cr_alignment) .long SYMBOL_NAME(init_task_union)+8192 .align .Lalready_done_mmap: adr r4, .LC0 - ldmia r4, {r3, r4, r5, r6, r8, sp} @ Setup stack + ldmia r4, {r3, r4, r5, r6, r7, r8, sp} @ Setup stack add r10, r10, r3 @ Add base back in mov fp, #0 -1: cmp r5, r8 @ Clear BSS +1: cmp r5, r7 @ Clear BSS strcc fp, [r5],#4 bcc 1b + bic r2, r0, #2 @ Clear 'A' bit + stmia r8, {r0, r2} @ Save control register values + str r1, [r4] @ Save machine type str r9, [r6] @ Save processor ID mov lr, pc @@ -363,6 +407,7 @@ .endm #elif defined(CONFIG_ARCH_EBSA285) +#if 1 .macro addruart,rx mov \rx, #0xfe000000 .endm @@ -379,7 +424,30 @@ .macro waituart,rd,rx .endm +#else + .macro addruart,rx + mov \rx, #0xff000000 + orr \rx, \rx, #0x00e00000 + orr \rx, \rx, #0x000003f8 + .endm + .macro senduart,rd,rx + strb \rd, [\rx] + .endm + + .macro busyuart,rd,rx +1002: ldrb \rd, [\rx, #0x5] + and \rd, \rd, #0x60 + teq \rd, #0x60 + bne 1002b + .endm + + .macro waituart,rd,rx +1001: ldrb \rd, [\rx, #0x6] + tst \rd, #0x10 + beq 1001b + .endm +#endif #elif defined(CONFIG_ARCH_NEXUSPCI) .macro addruart,rx ldr \rx, =0xfff00000 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/hw-ebsa285.c linux.ac/arch/arm/kernel/hw-ebsa285.c --- linux.vanilla/arch/arm/kernel/hw-ebsa285.c Mon Dec 28 23:09:40 1998 +++ linux.ac/arch/arm/kernel/hw-ebsa285.c Sun Jan 24 21:11:31 1999 @@ -3,27 +3,37 @@ * * EBSA285 hardware specific functions * - * Copyright (C) 1998 Russell King, Phil Blundel + * Copyright (C) 1998 Russell King, Phil Blundell */ +#include +#include #include #include #include #include #include #include +#include +#include #include +#include +#include #include +#include #include -extern int setup_arm_irq(int, struct irqaction *); +#define ETHER10_IO_BASE 0x301 +#define DEC21143_IO_BASE 0x401 +#define DEC21143_MEM_BASE 0x00800000 +#define CYBER2000_MEM_BASE 0x01000000 +extern int setup_arm_irq(int, struct irqaction *); extern void pci_set_cmd(struct pci_dev *dev, unsigned short clear, unsigned short set); extern void pci_set_base_addr(struct pci_dev *dev, int idx, unsigned int addr); extern void pci_set_irq_line(struct pci_dev *dev, unsigned int irq); -static int irqmap_ebsa[] __initdata = { 9, 8, 18, 11 }; -static int irqmap_cats[] __initdata = { 18, 8, 9, 11 }; +static int irqmap_ebsa[] __initdata = { IRQ_IN1, IRQ_IN0, IRQ_PCI, IRQ_IN3 }; __initfunc(static int ebsa_irqval(struct pci_dev *dev)) { @@ -37,6 +47,9 @@ return irqmap_ebsa[(PCI_SLOT(dev->devfn) + pin) & 3]; } +#ifdef CONFIG_CATS +static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 }; + __initfunc(static int cats_irqval(struct pci_dev *dev)) { if (dev->irq >= 128) @@ -56,77 +69,179 @@ dev->bus->number, dev->devfn, dev->irq); return 0; } +#endif __initfunc(void pcibios_fixup_ebsa285(struct pci_dev *dev)) { - char cmd; + /* Latency timer of 32 */ + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 32); + /* 32-byte cache line size */ + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8); + /* Set SysErr enable, Parity enable */ + pci_set_cmd(dev, PCI_COMMAND_FAST_BACK, PCI_COMMAND_SERR | PCI_COMMAND_PARITY); /* sort out the irq mapping for this device */ switch (machine_type) { case MACH_TYPE_EBSA285: dev->irq = ebsa_irqval(dev); + /* Turn on bus mastering - boot loader doesn't + * - perhaps it should! - dag + */ + pci_set_cmd(dev, 0, PCI_COMMAND_MASTER); break; + +#ifdef CONFIG_CATS case MACH_TYPE_CATS: dev->irq = cats_irqval(dev); + /* Turn on bus mastering - boot loader doesn't + * - perhaps it should! - dag + */ + pci_set_cmd(dev, 0, PCI_COMMAND_MASTER); break; +#endif +#ifdef CONFIG_ARCH_NETWINDER + case MACH_TYPE_NETWINDER: + /* disable ROM */ + pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0); + +#define DEV(v,d) ((v)<<16|(d)) + switch (DEV(dev->vendor, dev->device)) { + /* Ether 100 */ + case DEV(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142): + pci_set_base_addr(dev, 0, DEC21143_IO_BASE); + pci_set_base_addr(dev, 1, DEC21143_MEM_BASE); + pci_set_cmd(dev, 0, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO); + dev->irq = IRQ_NETWINDER_ETHER100; + break; + + /* Ether 10 */ + case DEV(PCI_VENDOR_ID_WINBOND2,0x5a5a): + pci_set_base_addr(dev, 0, ETHER10_IO_BASE); + pci_set_cmd(dev, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY, PCI_COMMAND_IO); + dev->irq = IRQ_NETWINDER_ETHER10; + break; + + /* ISA bridge */ + case DEV(PCI_VENDOR_ID_WINBOND,PCI_DEVICE_ID_WINBOND_83C553): + pci_set_base_addr(dev, 0, 0); + pci_set_cmd(dev, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY, PCI_COMMAND_IO); + /* + * Enable all memory requests from ISA to be channeled to PCI + */ + pci_write_config_byte(dev, 0x48, 255); + /* + * Disable ping-pong (as per errata) + */ + pci_write_config_byte(dev, 0x42, 0); + /* + * Enable PCI packet retry + */ + pci_write_config_byte(dev, 0x40, 0x22); + /* + * Do not use PCI CPU park enable, park on + * last master, disable GAT bit + */ + pci_write_config_byte(dev, 0x83, 0x02); + /* + * Default rotating priorities + */ + pci_write_config_byte(dev, 0x80, 0xe0); + /* + * Rotate bank 4 + */ + pci_write_config_byte(dev, 0x81, 0x01); + break; + + /* IDE */ + case DEV(PCI_VENDOR_ID_WINBOND,PCI_DEVICE_ID_WINBOND_82C105): + pci_set_base_addr(dev, 0, 0x1f1); + pci_set_base_addr(dev, 1, 0x3f5); + pci_set_base_addr(dev, 2, 0x171); + pci_set_base_addr(dev, 3, 0x375); + pci_set_base_addr(dev, 4, 0xe801); + pci_set_cmd(dev, PCI_COMMAND_MEMORY, PCI_COMMAND_MASTER | PCI_COMMAND_IO); + dev->irq = IRQ_NETWINDER_IDE; + break; + + /* VGA */ + case DEV(PCI_VENDOR_ID_INTERG,0x2000): + pci_set_base_addr(dev, 0, CYBER2000_MEM_BASE); + pci_set_cmd(dev, PCI_COMMAND_MASTER, PCI_COMMAND_IO | PCI_COMMAND_MEMORY); + dev->irq = IRQ_NETWINDER_VGA; + break; + } +#endif } - - /* Turn on bus mastering - boot loader doesn't - * - perhaps it should! - dag - */ - pci_read_config_byte(dev, PCI_COMMAND, &cmd); - pci_write_config_byte(dev, PCI_COMMAND, cmd | PCI_COMMAND_MASTER); } -static void irq_pci_err(int irq, void *dev_id, struct pt_regs *regs) +static void +irq_pci_err(int irq, void *dev_id, struct pt_regs *regs) { - const char *err = "unknown"; - unsigned long cmd = *(unsigned long *)0xfe000004 & 0xffff; - unsigned long ctrl = *(unsigned long *)0xfe00013c & 0xffffde07; - static unsigned long next_warn[7]; - int idx = 6; - - switch(irq) { - case IRQ_PCIPARITY: - *(unsigned long *)0xfe000004 = cmd | 1 << 31; - idx = 0; - err = "parity"; - break; + static unsigned long next_warn; + unsigned long cmd = *CSR_PCICMD & 0x0000ffff; + unsigned long ctrl = (*CSR_SA110_CNTL) & 0xffffde07; + unsigned long irqstatus = *CSR_IRQ_RAWSTATUS; + struct pci_dev *dev; + int warn = time_after_eq(jiffies, next_warn); + + if (warn) { + next_warn = jiffies + 3 * HZ / 100; + printk(KERN_DEBUG "PCI: "); + } - case IRQ_PCITARGETABORT: - *(unsigned long *)0xfe000004 = cmd | 1 << 28; - idx = 1; - err = "target abort"; - break; + if (irqstatus & (1 << 31)) { + if (warn) + printk("parity error "); + cmd |= 1 << 31; + } - case IRQ_PCIMASTERABORT: - *(unsigned long *)0xfe000004 = cmd | 1 << 29; - idx = 2; - err = "master abort"; - break; + if (irqstatus & (1 << 30)) { + if (warn) + printk("target abort "); + cmd |= 1 << 28; + } - case IRQ_PCIDATAPARITY: - *(unsigned long *)0xfe000004 = cmd | 1 << 24; - idx = 3; - err = "data parity"; - break; + if (irqstatus & (1 << 29)) { + if (warn) + printk("master abort "); + cmd |= 1 << 29; + } - case IRQ_DISCARDTIMER: - *(unsigned long *)0xfe00013c = ctrl | 1 << 8; - idx = 4; - err = "discard timer"; - break; + if (irqstatus & (1 << 28)) { + if (warn) + printk("data parity error "); + cmd |= 1 << 24; + } - case IRQ_SERR: - *(unsigned long *)0xfe00013c = ctrl | 1 << 3; - idx = 5; - err = "system"; - break; + if (irqstatus & (1 << 27)) { + if (warn) + printk("discard timer expired "); + ctrl |= 1 << 8; } - if (time_after_eq(jiffies, next_warn[idx])) { - next_warn[idx] = jiffies + 3 * HZ / 100; - printk(KERN_ERR "PCI %s error detected\n", err); + + if (irqstatus & (1 << 23)) { + if (warn) + printk("system error "); + ctrl |= 1 << 3; + } + + if (warn) + printk("pc=%08lX\n", instruction_pointer(regs)); + + for (dev = pci_devices; dev; dev = dev->next) { + unsigned short status; + + pci_read_config_word(dev, PCI_STATUS, &status); + if (status & 0xf900) { + printk("PCI: [%04X:%04X] status = %X\n", + dev->vendor, dev->device, status); + + pci_write_config_word(dev, PCI_STATUS, status & 0xf900); + } } + + *CSR_PCICMD = cmd; + *CSR_SA110_CNTL = ctrl; } static struct irqaction irq_pci_error = { @@ -135,12 +250,9 @@ __initfunc(void pcibios_init_ebsa285(void)) { - setup_arm_irq(IRQ_PCIPARITY, &irq_pci_error); - setup_arm_irq(IRQ_PCITARGETABORT, &irq_pci_error); - setup_arm_irq(IRQ_PCIMASTERABORT, &irq_pci_error); - setup_arm_irq(IRQ_PCIDATAPARITY, &irq_pci_error); - setup_arm_irq(IRQ_DISCARDTIMER, &irq_pci_error); - setup_arm_irq(IRQ_SERR, &irq_pci_error); + unsigned int mem_size = (int)high_memory - PAGE_OFFSET; + + setup_arm_irq(IRQ_PCI_ERR, &irq_pci_error); /* * Map our SDRAM at a known address in PCI space, just in case @@ -150,12 +262,374 @@ * * We should really only do this if the central function is enabled. */ - *(unsigned long *)0xfe000010 = 0; - *(unsigned long *)0xfe000018 = 0xe0000000; - *(unsigned long *)0xfe0000f8 = 0; - *(unsigned long *)0xfe0000fc = 0; - *(unsigned long *)0xfe000100 = 0x01fc0000; - *(unsigned long *)0xfe000104 = 0; - *(unsigned long *)0xfe000108 = 0x80000000; - *(unsigned long *)0xfe000004 = 0x17; + *CSR_CSRBASEMASK = 0; + *CSR_CSRBASEOFFSET = 0; + *CSR_SDRAMBASEMASK = (mem_size - 1) & 0x0ffc0000; + *CSR_SDRAMBASEOFFSET = 0; + *CSR_ROMBASEMASK = 0x80000000; + *CSR_PCICACHELINESIZE = 0x00002008; + *CSR_PCICSRBASE = 0; + *CSR_PCICSRIOBASE = 0; + *CSR_PCISDRAMBASE = virt_to_bus((void *)PAGE_OFFSET); + *CSR_PCIROMBASE = 0; + *CSR_PCICMD = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | + PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY; + *CSR_PCIADDR_EXTN = 0; +} + +/* + * Netwinder stuff + */ +#ifdef CONFIG_ARCH_NETWINDER +/* + * This is a lock for accessing ports 0x338 and 0x33a + */ +spinlock_t __netwinder_data gpio_lock = SPIN_LOCK_UNLOCKED; + +static unsigned int __netwinder_data current_gpio_op = 0; +static unsigned int __netwinder_data current_gpio_io = 0; +static unsigned int __netwinder_data current_cpld = 0; + +void __netwinder_text gpio_modify_op(int mask, int set) +{ + unsigned int new_gpio, changed; +unsigned long flags; save_flags_cli(flags); +if ((flags & 128) == 0) {printk("gpio_modify_op called with IRQs enabled from %p\n", __builtin_return_address(0)); __backtrace(); } + + new_gpio = (current_gpio_op & ~mask) | set; + changed = new_gpio ^ current_gpio_op; + current_gpio_op = new_gpio; + + if (changed & 0xff) + outb(new_gpio, 0x338); + if (changed & 0xff00) + outb(new_gpio >> 8, 0x33a); +restore_flags(flags); +} + +static inline void __gpio_modify_io(int mask, int in) +{ + unsigned int new_gpio, changed; + int port; + + new_gpio = (current_gpio_io & ~mask) | in; + changed = new_gpio ^ current_gpio_io; + current_gpio_io = new_gpio; + + changed >>= 1; + new_gpio >>= 1; + + outb(7, 0x370); + outb(7, 0x371); + + for (port = 0xe1; changed && port < 0xe8; changed >>= 1) { + outb(port, 0x370); + outb(new_gpio & 1, 0x371); + + port += 1; + new_gpio >>= 1; + } + + outb(7, 0x370); + outb(8, 0x371); + + for (port = 0xe8; changed && port < 0xec; changed >>= 1) { + outb(port, 0x370); + outb(new_gpio & 1, 0x371); + + port += 1; + new_gpio >>= 1; + } +} + +void __netwinder_text gpio_modify_io(int mask, int in) +{ + /* Open up the SuperIO chip */ + outb(0x87, 0x370); + outb(0x87, 0x370); + + __gpio_modify_io(mask, in); + + /* Close up the EFER gate */ + outb(0xaa, 0x370); +} + +int __netwinder_text gpio_read(void) +{ + return inb(0x338) | inb(0x33a) << 8; +} + +void __netwinder_text cpld_modify(int mask, int set) +{ + int msk; + + current_cpld = (current_cpld & ~mask) | set; + + gpio_modify_io(GPIO_DATA, 0); + gpio_modify_op(GPIO_IOLOAD, 0); + + for (msk = 8; msk; msk >>= 1) { + int bit = current_cpld & msk; + + gpio_modify_op(GPIO_DATA | GPIO_IOCLK, bit ? GPIO_DATA : 0); + gpio_modify_op(GPIO_IOCLK, GPIO_IOCLK); + } + + gpio_modify_op(GPIO_IOCLK|GPIO_DATA, 0); + gpio_modify_op(GPIO_IOLOAD|GPIO_DSCLK, GPIO_IOLOAD|GPIO_DSCLK); + gpio_modify_op(GPIO_IOLOAD, 0); +} + +__initfunc(static void hw_init_cpld(void)) +{ + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + cpld_modify(-1, CPLD_UNMUTE | 4); + spin_unlock_irqrestore(&gpio_lock, flags); } + +__initfunc(static void hw_init_wb553(void)) +{ + unsigned long flags; +#define WRITE_REG(r,v) do { outb((r), 0x370); outb((v), 0x371); } while (0) + + /* Open up the SuperIO chip */ + outb(0x87, 0x370); + outb(0x87, 0x370); + + /* Set the serial interrupt numbers */ + WRITE_REG(7, 5); /* keyboard subsection */ + WRITE_REG(0x72, 5); /* interrupt number for mouse - IRQ5 */ + + WRITE_REG(7, 6); /* Infrared */ + WRITE_REG(0x70, 6); /* IRQ 6 */ + + WRITE_REG(0x2a, 0xc1); /* Enable GP12, GP11, GP10 as I/O, CIRRX, IRRXH */ + + WRITE_REG(0x2b, 0x6b); /* Enable GP23, GP22, GP21, GP20, GP13 as I/O */ + + WRITE_REG(0x2c, 0x55); /* Enable GP17, GP16, GP15, GP14 as I/O */ + + current_gpio_io = -1; + __gpio_modify_io(-1, GPIO_DONE | GPIO_WDTIMER); + + WRITE_REG(7, 7); /* Aux function group 1 (dev 7) */ + WRITE_REG(0x60, 0x03); /* Group controlled by IO port 0x338 */ + WRITE_REG(0x61, 0x38); /* GP 11, 12, 13, 14, 15, 16 */ + + WRITE_REG(0x70, 0x0a); /* IRQ10 for GP10 (Orange button) */ + + WRITE_REG(0xe0, 0x19); /* GP10 control reg set for debounce & input */ + WRITE_REG(0x30, 0x01); /* Turn on section 7 (aux function group 1) */ + + WRITE_REG(7, 8); /* Aux function group 2 (dev 8) */ + WRITE_REG(0x60, 0x03); /* Group controlled by IO port 0x33a */ + WRITE_REG(0x61, 0x3a); + + /* Clear watchdog timer regs */ + WRITE_REG(0xf2, 0x00); /* Watchdog timeout value (disabled) */ + WRITE_REG(0xf3, 0x00); /* Watchdog reg (reset to default) */ + WRITE_REG(0xf4, 0x00); /* Reset if in timed out state (bit 0) */ + + /* T.B.D. set IRDA inputs (touch reg 2A, EC, ED) */ + WRITE_REG(0x30, 0x01); /* Turn on section 8 (aux function group 2) */ + + spin_lock_irqsave(&gpio_lock, flags); + gpio_modify_op(-1, GPIO_RED_LED | GPIO_FAN); + spin_unlock_irqrestore(&gpio_loc, flags); + + /* Close up the EFER gate */ + outb(0xaa, 0x370); +} + +static unsigned char rwa_unlock[] __initdata = +{ 0x00, 0x00, 0x6a, 0xb5, 0xda, 0xed, 0xf6, 0xfb, 0x7d, 0xbe, 0xdf, 0x6f, 0x37, 0x1b, + 0x0d, 0x86, 0xc3, 0x61, 0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, 0xa2, 0xd1, 0xe8, 0x74, + 0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39 }; + +#ifndef DEBUG +#define dprintk if (0) printk +#else +#define dprintk printk +#endif + +__initfunc(static void hw_init_rwa010(void)) +{ + unsigned char si[9]; + int i, j; + +#define WRITE_RWA(r,v) do { outb((r), 0x279); outb((v), 0xa79); } while (0) + + WRITE_RWA(2, 2); + mdelay(10); + + for (i = 0; i < sizeof(rwa_unlock); i++) + outb(rwa_unlock[i], 0x279); + + WRITE_RWA(3, 0); + WRITE_RWA(0, 128); + + outb(1, 0x279); + + mdelay(10); + + dprintk("Identifier: "); + for (i = 0; i < 9; i++) { + si[i] = 0; + for (j = 0; j < 8; j++) { + int bit; + mdelay(1); + inb(0x203); + mdelay(1); + bit = inb(0x203); + dprintk("%02X ", bit); + si[i] |= bit << j; + } + mdelay(10); + dprintk("%02X ", si[i]); + } + dprintk("\n"); + + WRITE_RWA(6, 2); // Assign a card no = 2 + + dprintk("Card no = %d\n", inb(0x203)); + + WRITE_RWA(7, 3); + WRITE_RWA(0x30, 0); + + WRITE_RWA(7, 4); + WRITE_RWA(0x30, 0); + + WRITE_RWA(7, 2); + WRITE_RWA(0x30, 0); + + WRITE_RWA(7, 5); + + dprintk("Slider base: "); + WRITE_RWA(0x61, 1); + i = inb(0x203); + + WRITE_RWA(0x60, 2); + dprintk("%02X%02X (201)\n", inb(0x203), i); + + WRITE_RWA(0x30, 1); + + + WRITE_RWA(7, 0); + + dprintk("WaveArtist base: "); + WRITE_RWA(0x61, 0x50); + i = inb(0x203); + + WRITE_RWA(0x60, 0x02); + dprintk("%02X%02X (250),", inb(0x203), i); + + WRITE_RWA(0x70, 3); + dprintk(" irq: %d (3),", inb(0x203)); + + WRITE_RWA(0x74, 7); + dprintk(" dma: %d (7)\n", inb(0x203)); + + WRITE_RWA(0x30, 1); + + WRITE_RWA(7, 1); + + dprintk("SoundBlaster base: "); + WRITE_RWA(0x61, 0x20); + i = inb(0x203); + + WRITE_RWA(0x60, 0x02); + dprintk("%02X%02X (220),", inb(0x203), i); + + dprintk(" irq: "); + WRITE_RWA(0x70, 3); + dprintk("%d (3),", inb(0x203)); + + dprintk(" 8-bit DMA: "); + WRITE_RWA(0x74, 1); + dprintk("%d (1)\n", inb(0x203)); + + dprintk("AdLib base: "); + WRITE_RWA(0x63, 0x88); + i = inb(0x203); + + WRITE_RWA(0x62, 0x03); + dprintk("%02X%02X (388)\n", inb(0x203), i); + + WRITE_RWA(0x30, 1); + + outb(1, 0x226); + udelay(3); + outb(0, 0x226); + + for (i = 0; i < 5; i++) { + if (inb(0x22e) & 0x80) + break; + mdelay(1); + } + if (i == 5) + printk("SoundBlaster: DSP reset failed\n"); + + dprintk("SoundBlaster DSP reset: %02X (AA)\n", inb(0x22a)); + + for (i = 0; i < 5; i++) { + if ((inb(0x22c) & 0x80) == 0) + break; + mdelay(1); + } + + if (i == 5) + printk("SoundBlaster: DSP not ready\n"); + else { + outb(0xe1, 0x22c); + + dprintk("SoundBlaster DSP id: "); + i = inb(0x22a); + udelay(1); + i |= inb(0x22a) << 8; + dprintk("%04X\n", i); + + for (i = 0; i < 5; i++) { + if ((inb(0x22c) & 0x80) == 0) + break; + mdelay(1); + } + + if (i == 5) + printk("SoundBlaster: could not turn speaker off\n"); + + outb(0xd3, 0x22c); + } +} + +__initfunc(void hw_init(void)) +{ + unsigned long flags; + + hw_init_wb553(); + hw_init_cpld(); + hw_init_rwa010(); +#if 0 + /* does anyone want to have this in? */ + drum(); +#endif + +#ifdef CONFIG_LEDS /* Clear both LEDs and start the LED driver up */ + spin_lock_irqsave(&gpio_lock, flags); + gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, 0); + spin_unlock_irqrestore(&gpio_lock, flags); + leds_event(led_start); +#else /* Set the green LED on and the red LED off */ + spin_lock_irqsave(&gpio_lock, flags); + gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, GPIO_GREEN_LED); + spin_unlock_irqrestore(&gpio_lock, flags); +#endif /* CONFIG_LEDS */ +} + +EXPORT_SYMBOL(gpio_lock); +EXPORT_SYMBOL(gpio_modify_op); +EXPORT_SYMBOL(gpio_modify_io); +EXPORT_SYMBOL(cpld_modify); + +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/iic.c linux.ac/arch/arm/kernel/iic.c --- linux.vanilla/arch/arm/kernel/iic.c Sun Nov 8 15:08:43 1998 +++ linux.ac/arch/arm/kernel/iic.c Sun Jan 24 21:11:31 1999 @@ -9,8 +9,11 @@ #include #include -#include #include +#include +#include + +#define FORCE_ONES 0xdc /* * if delay loop has been calibrated then us that, @@ -42,7 +45,7 @@ { unsigned char out; - out = inb(IOC_CONTROL) | 0xc2; + out = inb(IOC_CONTROL) | FORCE_ONES | 0x02; outb(out, IOC_CONTROL); iic_delay(); @@ -55,7 +58,7 @@ { unsigned char out; - out = inb(IOC_CONTROL) | 0xc3; + out = inb(IOC_CONTROL) | FORCE_ONES | 0x03; iic_delay(); outb(out ^ 1, IOC_CONTROL); @@ -69,7 +72,7 @@ unsigned char out, in; int i; - out = (inb(IOC_CONTROL) & 0xfc) | 0xc0; + out = (inb(IOC_CONTROL) & 0xfc) | FORCE_ONES; outb(out, IOC_CONTROL); for (i = 7; i >= 0; i--) { @@ -110,7 +113,7 @@ unsigned char out, in; int i; - out = (inb(IOC_CONTROL) & 0xfc) | 0xc0; + out = (inb(IOC_CONTROL) & 0xfc) | FORCE_ONES; outb(out, IOC_CONTROL); in = 0; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/init_task.c linux.ac/arch/arm/kernel/init_task.c --- linux.vanilla/arch/arm/kernel/init_task.c Tue Dec 22 23:19:26 1998 +++ linux.ac/arch/arm/kernel/init_task.c Sun Jan 24 21:11:31 1999 @@ -6,6 +6,7 @@ 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/arm/kernel/ioport.c linux.ac/arch/arm/kernel/ioport.c --- linux.vanilla/arch/arm/kernel/ioport.c Sun Nov 8 15:08:43 1998 +++ linux.ac/arch/arm/kernel/ioport.c Thu Jan 1 01:00:00 1970 @@ -1,29 +0,0 @@ -/* - * linux/arch/arm/kernel/ioport.c - * - * Io-port support is not used for ARM - */ - -#include -#include -#include -#include -#include - -/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */ -/*asmlinkage void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value) -{ -}*/ - -asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on) -{ - return -ENOSYS; -} - -asmlinkage int sys_iopl(long ebx,long ecx,long edx, - long esi, long edi, long ebp, long eax, long ds, - long es, long fs, long gs, long orig_eax, - long eip,long cs,long eflags,long esp,long ss) -{ - return -ENOSYS; -} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/irq.c linux.ac/arch/arm/kernel/irq.c --- linux.vanilla/arch/arm/kernel/irq.c Mon Dec 28 23:09:40 1998 +++ linux.ac/arch/arm/kernel/irq.c Sun Jan 24 21:11:31 1999 @@ -49,6 +49,7 @@ unsigned int local_bh_count[NR_CPUS]; unsigned int local_irq_count[NR_CPUS]; spinlock_t irq_controller_lock; +int setup_arm_irq(int, struct irqaction *); extern int get_fiq_list(char *); extern void init_FIQ(void); @@ -71,6 +72,12 @@ static struct irqdesc irq_desc[NR_IRQS]; /* + * Get architecture specific interrupt handlers + * and interrupt initialisation. + */ +#include + +/* * Dummy mask/unmask handler */ static void dummy_mask_unmask_irq(unsigned int irq) @@ -130,10 +137,14 @@ */ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) { - struct irqdesc * desc = irq_desc + irq; + struct irqdesc * desc; struct irqaction * action; int status, cpu; + irq = fixup_irq(irq); + + desc = irq_desc + irq; + spin_lock(&irq_controller_lock); desc->mask_ack(irq); spin_unlock(&irq_controller_lock); @@ -261,10 +272,6 @@ return 0; } -/* - * Using "struct sigaction" is slightly silly, but there - * are historical reasons and it works well, so.. - */ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long irq_flags, const char * devname, void *dev_id) { @@ -405,14 +412,9 @@ irq_found = NO_IRQ; out: spin_unlock_irq(&irq_controller_lock); +printk("probe_irq_off: irq %d\n", irq_found); return irq_found; } - -/* - * Get architecture specific interrupt handlers - * and interrupt initialisation. - */ -#include __initfunc(void init_IRQ(void)) { diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/leds-ebsa285.c linux.ac/arch/arm/kernel/leds-ebsa285.c --- linux.vanilla/arch/arm/kernel/leds-ebsa285.c Sun Nov 8 15:08:44 1998 +++ linux.ac/arch/arm/kernel/leds-ebsa285.c Sun Jan 24 21:11:31 1999 @@ -9,36 +9,72 @@ * - Amber - On if system is not idle * - Red - currently unused */ +#include +#include +#include + #include #include +#include #include -static char led_state = XBUS_LED_RED | XBUS_LED_GREEN; +static int led_state; +static char ebsa_led_state = XBUS_LED_RED | XBUS_LED_GREEN; void leds_event(led_event_t ledevt) { unsigned long flags; + switch (ledevt) { + case led_start: + led_state = !machine_is_cats(); + return; + + case led_stop: + led_state = 0; + return; + + default: + break; + } + + if (!led_state) + return; + save_flags_cli(flags); switch(ledevt) { +#ifdef CONFIG_LEDS_CPU case led_idle_start: - led_state |= XBUS_LED_AMBER; + ebsa_led_state |= XBUS_LED_AMBER; break; case led_idle_end: - led_state &= ~XBUS_LED_AMBER; + ebsa_led_state &= ~XBUS_LED_AMBER; break; - +#endif +#ifdef CONFIG_LEDS_TIMER case led_timer: - led_state ^= XBUS_LED_GREEN; + ebsa_led_state ^= XBUS_LED_GREEN; break; - +#endif default: break; } restore_flags(flags); - *XBUS_LEDS = led_state; + switch (machine_type) { + case MACH_TYPE_EBSA285: + *XBUS_LEDS = led_state; + break; + + case MACH_TYPE_NETWINDER: + spin_lock_irqsave(&gpio_lock, flags); + gpio_modify_op(GPIO_RED_LED | GPIO_GREEN_LED, + (ebsa_led_state & XBUS_LED_AMBER ? GPIO_RED_LED : 0) | + (ebsa_led_state & XBUS_LED_GREEN ? GPIO_GREEN_LED : 0)); + spin_unlock_irqrestore(&gpio_lock, flags); + break; + } } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/process.c linux.ac/arch/arm/kernel/process.c --- linux.vanilla/arch/arm/kernel/process.c Sun Nov 8 15:08:44 1998 +++ linux.ac/arch/arm/kernel/process.c Sun Jan 24 21:11:31 1999 @@ -55,46 +55,37 @@ } /* - * The idle loop on an arm.. + * The idle loop on an ARM... */ asmlinkage int sys_idle(void) { - int ret = -EPERM; - - lock_kernel(); if (current->pid != 0) - goto out; + return -EPERM; + /* endless idle loop with no priority at all */ - current->priority = -100; - for (;;) - { + while (1) { + if (!current->need_resched && !hlt_counter) + proc_idle(); + current->policy = SCHED_YIELD; + schedule(); +#ifndef CONFIG_NO_PGT_CACHE check_pgt_cache(); -#if 0 //def ARCH_IDLE_OK - if (!hlt_counter && !current->need_resched) - proc_idle (); #endif - run_task_queue(&tq_scheduler); - schedule(); } - ret = 0; -out: - unlock_kernel(); - return ret; } +static char reboot_mode = 'h'; + __initfunc(void reboot_setup(char *str, int *ints)) { + reboot_mode = str[0]; } -/* - * This routine reboots the machine by resetting the expansion cards via - * their loaders, turning off the processor cache (if ARM3), copying the - * first instruction of the ROM to 0, and executing it there. - */ void machine_restart(char * __unused) { - proc_hard_reset (); - arch_hard_reset (); + arch_reset(reboot_mode); + panic("Reboot failed\n"); + while (1); } void machine_halt(void) @@ -150,6 +141,67 @@ } /* + * Task structure and kernel stack allocation. + * + * Taken from the i386 version. + */ +#ifdef CONFIG_CPU_32 +#define EXTRA_TASK_STRUCT 8 +static struct task_struct *task_struct_stack[EXTRA_TASK_STRUCT]; +static int task_struct_stack_ptr = -1; +#endif + +struct task_struct *alloc_task_struct(void) +{ + struct task_struct *tsk; + +#ifndef EXTRA_TASK_STRUCT + tsk = ll_alloc_task_struct(); +#else + int index; + + index = task_struct_stack_ptr; + if (index >= EXTRA_TASK_STRUCT/2) + goto use_cache; + + tsk = ll_alloc_task_struct(); + + if (!tsk) { + index = task_struct_stack_ptr; + + if (index >= 0) { +use_cache: tsk = task_struct_stack[index]; + task_struct_stack_ptr = index - 1; + } + } +#endif +#ifdef CONFIG_SYSRQ + /* You need this if you want SYSRQ-T to give sensible stack + * usage information + */ + if (tsk) { + char *p = (char *)tsk; + memzero(p+KERNEL_STACK_SIZE, KERNEL_STACK_SIZE); + } +#endif + + return tsk; +} + +void free_task_struct(struct task_struct *p) +{ +#ifdef EXTRA_TASK_STRUCT + int index = task_struct_stack_ptr + 1; + + if (index < EXTRA_TASK_STRUCT) { + task_struct_stack[index] = p; + task_struct_stack_ptr = index; + } else +#endif + ll_free_task_struct(p); +} + +/* * Free current thread data structures etc.. */ void exit_thread(void) @@ -179,9 +231,10 @@ childregs = ((struct pt_regs *)((unsigned long)p + 8192)) - 1; *childregs = *regs; childregs->ARM_r0 = 0; + childregs->ARM_sp = esp; save = ((struct context_save_struct *)(childregs)) - 1; - copy_thread_css(save); + init_thread_css(save); p->tss.save = save; return 0; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/setup.c linux.ac/arch/arm/kernel/setup.c --- linux.vanilla/arch/arm/kernel/setup.c Tue Dec 22 23:19:27 1998 +++ linux.ac/arch/arm/kernel/setup.c Sun Jan 24 21:11:31 1999 @@ -56,12 +56,16 @@ #define SUPPORT_CPU_SA110 #endif -#ifndef CONFIG_CMDLINE -#define CONFIG_CMDLINE "root=/dev/nfs rw" -#endif #define MEM_SIZE (16*1024*1024) #define COMMAND_LINE_SIZE 256 +#ifndef CONFIG_CMDLINE +#define CONFIG_CMDLINE "" +#endif + +extern void reboot_setup(char *str, int *ints); +extern void disable_hlt(void); + struct drive_info_struct { char dummy[32]; } drive_info; struct screen_info screen_info = { orig_video_lines: 30, @@ -87,20 +91,26 @@ /*-- Match -- --- Mask -- -- Manu -- Processor uname -m --- ELF STUFF --- --- processor asm funcs --- */ #if defined(CONFIG_CPU_26) + /* ARM2 fake ident */ { 0x41560200, 0xfffffff0, "ARM/VLSI", "arm2" , "armv1" , "v1", 0, &arm2_processor_functions }, + /* ARM250 fake ident */ { 0x41560250, 0xfffffff0, "ARM/VLSI", "arm250" , "armv2" , "v2", HWCAP_SWP, &arm250_processor_functions }, + /* ARM3 processors */ { 0x41560300, 0xfffffff0, "ARM/VLSI", "arm3" , "armv2" , "v2", HWCAP_SWP, &arm3_processor_functions }, #elif defined(CONFIG_CPU_32) #ifdef SUPPORT_CPU_ARM6 + /* ARM6 */ { 0x41560600, 0xfffffff0, "ARM/VLSI", "arm6" , "armv3" , "v3", HWCAP_SWP, &arm6_processor_functions }, + /* ARM610 */ { 0x41560610, 0xfffffff0, "ARM/VLSI", "arm610" , "armv3" , "v3", HWCAP_SWP, &arm6_processor_functions }, #endif #ifdef SUPPORT_CPU_ARM7 + /* ARM7's have a strange numbering */ { 0x41007000, 0xffffff00, "ARM/VLSI", "arm7" , "armv3" , "v3", HWCAP_SWP, &arm7_processor_functions }, /* ARM710 IDs are non-standard */ @@ -108,8 +118,14 @@ &arm7_processor_functions }, #endif #ifdef SUPPORT_CPU_SA110 - { 0x4401a100, 0xfffffff0, "DEC", "sa110" , "armv4" , "v3", HWCAP_SWP|HWCAP_HALF, +#ifdef CONFIG_ARCH_RPC + /* Acorn RiscPC's can't handle ARMv4 half-word instructions */ + { 0x4401a100, 0xfffffff0, "DEC", "sa110" , "armv4" , "v4", HWCAP_SWP, &sa110_processor_functions }, +#else + { 0x4401a100, 0xfffffff0, "DEC", "sa110" , "armv4" , "v4", HWCAP_SWP|HWCAP_HALF, + &sa110_processor_functions }, +#endif #endif #endif { 0x00000000, 0x00000000, "***", "unknown", "unknown", "**", 0, NULL } @@ -132,139 +148,10 @@ */ /* - * Risc-PC specific initialisation - */ -#ifdef CONFIG_ARCH_RPC - -#include - -unsigned int vram_half_sam; - -static void -setup_rpc(struct param_struct *params) -{ - extern void init_dram_banks(const struct param_struct *params); - - init_dram_banks(params); - - switch (params->u1.s.pages_in_vram) { - case 256: - vram_half_sam = 1024; - break; - case 512: - default: - vram_half_sam = 2048; - } -} -#else -#define setup_rpc(x) -#endif - -#ifdef PARAMS_BASE - -#ifdef CONFIG_ARCH_ACORN -int memc_ctrl_reg; -int number_ide_drives; -int number_mfm_drives; -#endif - -static struct param_struct *params = (struct param_struct *)PARAMS_BASE; - -__initfunc(static char * -setup_params(unsigned long *mem_end_p)) -{ - ROOT_DEV = to_kdev_t(params->u1.s.rootdev); - ORIG_X = params->u1.s.video_x; - ORIG_Y = params->u1.s.video_y; - ORIG_VIDEO_COLS = params->u1.s.video_num_cols; - ORIG_VIDEO_LINES = params->u1.s.video_num_rows; - -#ifdef CONFIG_ARCH_ACORN -#ifndef CONFIG_FB - { - extern int bytes_per_char_h; - extern int bytes_per_char_v; - - bytes_per_char_h = params->u1.s.bytes_per_char_h; - bytes_per_char_v = params->u1.s.bytes_per_char_v; - } -#endif - memc_ctrl_reg = params->u1.s.memc_control_reg; - number_ide_drives = (params->u1.s.adfsdrives >> 6) & 3; - number_mfm_drives = (params->u1.s.adfsdrives >> 3) & 3; - - setup_rpc(params); - - if (!(params->u1.s.flags & FLAG_READONLY)) - root_mountflags &= ~MS_RDONLY; -#endif -#ifdef CONFIG_BLK_DEV_RAM - { - extern int rd_doload; - extern int rd_prompt; - extern int rd_image_start; - - rd_image_start = params->u1.s.rd_start; - rd_prompt = (params->u1.s.flags & FLAG_RDPROMPT) == 0; - rd_doload = (params->u1.s.flags & FLAG_RDLOAD) == 0; - } -#endif - -#ifdef CONFIG_ARCH_ACORN - *mem_end_p = GET_MEMORY_END(params); -#elif defined(CONFIG_ARCH_EBSA285) - *mem_end_p = PAGE_OFFSET + params->u1.s.page_size * params->u1.s.nr_pages; -#else - *mem_end_p = PAGE_OFFSET + MEM_SIZE; -#endif - - return params->commandline; -} - -#else - -static char default_command_line[] __initdata = CONFIG_CMDLINE; - -__initfunc(static char * -setup_params(unsigned long *mem_end_p)) -{ - ROOT_DEV = 0x00ff; - -#ifdef CONFIG_BLK_DEV_RAM - { - extern int rd_doload; - extern int rd_prompt; - extern int rd_image_start; - - rd_image_start = 0; - rd_prompt = 1; - rd_doload = 1; - } -#endif - - *mem_end_p = PAGE_OFFSET + MEM_SIZE; - - return default_command_line; -} -#endif - -/* * initial ram disk */ #ifdef CONFIG_BLK_DEV_INITRD __initfunc(static void -setup_initrd(const struct param_struct *params)) -{ - if (params->u1.s.initrd_start) { - initrd_start = params->u1.s.initrd_start; - initrd_end = initrd_start + params->u1.s.initrd_size; - } else { - initrd_start = 0; - initrd_end = 0; - } -} - -__initfunc(static void check_initrd(unsigned long mem_start, unsigned long mem_end)) { if (initrd_end > mem_end) { @@ -276,7 +163,6 @@ } #else -#define setup_initrd(p) #define check_initrd(ms,me) #endif @@ -289,48 +175,48 @@ armidlist[armidindex].mask) armidindex += 1; - if (armidlist[armidindex].id == 0) { -#ifdef CONFIG_ARCH_ACORN - int i; - - for (i = 0; i < 3200; i++) - ((unsigned long *)SCREEN2_BASE)[i] = 0x77113322; -#endif + if (armidlist[armidindex].id == 0) while (1); - } processor = *armidlist[armidindex].proc; processor._proc_init(); } +static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; static char command_line[COMMAND_LINE_SIZE] = { 0, }; char saved_command_line[COMMAND_LINE_SIZE]; __initfunc(static void setup_mem(char *cmd_line, unsigned long *mem_start, unsigned long *mem_end)) { - char c, *to = command_line; + char c = ' ', *to = command_line; int len = 0; *mem_start = (unsigned long)&_end; for (;;) { - if (cmd_line[0] == ' ' && - cmd_line[1] == 'm' && - cmd_line[2] == 'e' && - cmd_line[3] == 'm' && - cmd_line[4] == '=') { - *mem_end = simple_strtoul(cmd_line+5, &cmd_line, 0); - switch(*cmd_line) { - case 'M': - case 'm': - *mem_end <<= 10; - case 'K': - case 'k': - *mem_end <<= 10; + if (c == ' ') { + if (cmd_line[0] == 'm' && + cmd_line[1] == 'e' && + cmd_line[2] == 'm' && + cmd_line[3] == '=') { + *mem_end = simple_strtoul(cmd_line+4, &cmd_line, 0); + switch(*cmd_line) { + case 'M': + case 'm': + *mem_end <<= 10; + case 'K': + case 'k': + *mem_end <<= 10; + cmd_line++; + } + *mem_end = *mem_end + PAGE_OFFSET; + } + /* if there are two spaces, remove one */ + if (*cmd_line == ' ') { cmd_line++; + continue; } - *mem_end = *mem_end + PAGE_OFFSET; } c = *cmd_line++; if (!c) @@ -341,8 +227,49 @@ } *to = '\0'; + + /* remove trailing spaces */ + while (*--to == ' ' && to != command_line) + *to = '\0'; +} + +__initfunc(static void +setup_ram(int doload, int prompt, int image_start)) +{ +#ifdef CONFIG_BLK_DEV_RAM + extern int rd_doload; + extern int rd_prompt; + extern int rd_image_start; + + rd_image_start = image_start; + rd_prompt = prompt; + rd_doload = doload; +#endif +} + +/* + * initial ram disk + */ +__initfunc(static void +setup_initrd(unsigned int start, unsigned int size)) +{ +#ifdef CONFIG_BLK_DEV_INITRD + if (start) { + initrd_start = start; + initrd_end = start + size; + } else { + initrd_start = 0; + initrd_end = 0; + } +#endif } +#ifdef CONFIG_ARCH_ACORN +int memc_ctrl_reg; +int number_ide_drives; +int number_mfm_drives; +#endif + __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p)) { @@ -350,6 +277,11 @@ unsigned long memory_end; char endian = 'l'; char *from; +#ifdef PARAMS_BASE + struct param_struct *params = (struct param_struct *)PARAMS_BASE; +#else + struct param_struct *params = NULL; +#endif if (smptrap == 1) return; @@ -357,8 +289,83 @@ setup_processor(); - from = setup_params(&memory_end); - setup_initrd(params); + init_task.mm->start_code = TASK_SIZE; + init_task.mm->end_code = TASK_SIZE + (unsigned long) &_etext; + init_task.mm->end_data = TASK_SIZE + (unsigned long) &_edata; + init_task.mm->brk = TASK_SIZE + (unsigned long) &_end; + + /* + * Add your machine dependencies here + */ + switch (machine_type) { + case MACH_TYPE_EBSA110: + /* EBSA110 locks if we execute 'wait for interrupt' */ + disable_hlt(); + params = NULL; + break; + + case MACH_TYPE_CATS: + /* CATS must use soft-reboot */ + reboot_setup("s", NULL); + break; + + case MACH_TYPE_NETWINDER: + /* to be fixed in NeTTrom 2.0.6 */ + params = NULL; + break; + + default: + break; + } + + if (params) { + memory_end = params->u1.s.page_size * + params->u1.s.nr_pages; + + ROOT_DEV = to_kdev_t(params->u1.s.rootdev); + ORIG_X = params->u1.s.video_x; + ORIG_Y = params->u1.s.video_y; + ORIG_VIDEO_COLS = params->u1.s.video_num_cols; + ORIG_VIDEO_LINES = params->u1.s.video_num_rows; + + setup_ram((params->u1.s.flags & FLAG_RDLOAD) == 0, + (params->u1.s.flags & FLAG_RDPROMPT) == 0, + params->u1.s.rd_start); + + setup_initrd(params->u1.s.initrd_start, + params->u1.s.initrd_size); + + if (!(params->u1.s.flags & FLAG_READONLY)) + root_mountflags &= ~MS_RDONLY; + +#ifdef CONFIG_ARCH_ACORN + memc_ctrl_reg = params->u1.s.memc_control_reg; + number_ide_drives = (params->u1.s.adfsdrives >> 6) & 3; + number_mfm_drives = (params->u1.s.adfsdrives >> 3) & 3; +#ifndef CONFIG_FB + { + extern int bytes_per_char_h; + extern int bytes_per_char_v; + + bytes_per_char_h = params->u1.s.bytes_per_char_h; + bytes_per_char_v = params->u1.s.bytes_per_char_v; + } +#endif + setup_rpc(params); +#endif + + from = params->commandline; + } else { + memory_end = MEM_SIZE; + ROOT_DEV = 0x00ff; + + setup_ram(1, 1, 0); + setup_initrd(0, 0); + + from = default_command_line; + } + + memory_end += PAGE_OFFSET; /* Save unparsed command line copy for /proc/cmdline */ memcpy(saved_command_line, from, COMMAND_LINE_SIZE); @@ -367,14 +374,6 @@ setup_mem(from, memory_start_p, &memory_end); check_initrd(*memory_start_p, memory_end); - init_task.mm->start_code = TASK_SIZE; - init_task.mm->end_code = TASK_SIZE + (unsigned long) &_etext; - init_task.mm->end_data = TASK_SIZE + (unsigned long) &_edata; - init_task.mm->brk = TASK_SIZE + (unsigned long) &_end; - - *cmdline_p = command_line; - *memory_end_p = memory_end; - sprintf(system_utsname.machine, "%s%c", armidlist[armidindex].arch_vsn, endian); sprintf(elf_platform, "%s%c", armidlist[armidindex].elf_vsn, endian); @@ -385,6 +384,9 @@ conswitchp = &dummy_con; #endif #endif + + *cmdline_p = command_line; + *memory_end_p = memory_end; } static const struct { @@ -393,11 +395,12 @@ } machine_desc[] = { { "DEC-EBSA110", "DEC" }, { "Acorn-RiscPC", "Acorn" }, - { "Nexus-NexusPCI", "PCI" }, + { "unknown", "PCI" }, + { "Nexus-FTV/PCI", "PCI" }, { "DEC-EBSA285", "PCI" }, - { "Corel-Netwinder", "PCI/ISA" }, - { "Chalice-CATS", "PCI" }, - { "unknown-TBOX", "PCI" } + { "Corel-NetWinder", "PCI/ISA" }, + { "Chalice-CATS", "PCI/ISA" }, + { "unknown-TBOX", "none" } }; #if defined(CONFIG_ARCH_ARC) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/signal.c linux.ac/arch/arm/kernel/signal.c --- linux.vanilla/arch/arm/kernel/signal.c Sun Nov 8 15:08:43 1998 +++ linux.ac/arch/arm/kernel/signal.c Sun Jan 24 21:11:32 1999 @@ -28,7 +28,7 @@ asmlinkage int sys_wait4(pid_t pid, unsigned long * stat_addr, int options, unsigned long *ru); -asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs); +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall); extern int ptrace_cancel_bpt (struct task_struct *); extern int ptrace_set_bpt (struct task_struct *); @@ -50,7 +50,7 @@ while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(&saveset, regs)) + if (do_signal(&saveset, regs, 0)) return regs->ARM_r0; } } @@ -78,7 +78,7 @@ while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(&saveset, regs)) + if (do_signal(&saveset, regs, 0)) return regs->ARM_r0; } } @@ -260,6 +260,18 @@ return err; } +static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, + unsigned long framesize) +{ + unsigned long sp = regs->ARM_sp; + + /* This is the X/Open sanctioned signal stack switching. */ + if ((ka->sa.sa_flags & SA_ONSTACK) && ! on_sig_stack(sp)) + sp = current->sas_ss_sp + current->sas_ss_size; + + return (void *)(sp - framesize); +} + static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs) { @@ -267,9 +279,9 @@ unsigned long retcode; int err = 0; - frame = (struct sigframe *)regs->ARM_sp - 1; + frame = get_sigframe(ka, regs, sizeof(*frame)); - if (!access_ok(VERIFT_WRITE, frame, sizeof (*frame))) + if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) goto segv_and_exit; err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]); @@ -299,6 +311,11 @@ regs->ARM_sp = (unsigned long)frame; regs->ARM_lr = retcode; regs->ARM_pc = (unsigned long)ka->sa.sa_handler; +#if defined(CONFIG_CPU_32) + /* Maybe we need to deliver a 32-bit signal to a 26-bit task. */ + if (ka->sa.sa_flags & SA_THIRTYTWO) + regs->ARM_cpsr = USR_MODE; +#endif if (valid_user_regs(regs)) return; @@ -315,7 +332,8 @@ unsigned long retcode; int err = 0; - frame = (struct rt_sigframe *)regs->ARM_sp - 1; + frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe)); + if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) goto segv_and_exit; @@ -350,6 +368,11 @@ regs->ARM_sp = (unsigned long)frame; regs->ARM_lr = retcode; regs->ARM_pc = (unsigned long)ka->sa.sa_handler; +#if defined(CONFIG_CPU_32) + /* Maybe we need to deliver a 32-bit signal to a 26-bit task. */ + if (ka->sa.sa_flags & SA_THIRTYTWO) + regs->ARM_cpsr = USR_MODE; +#endif if (valid_user_regs(regs)) return; @@ -393,18 +416,19 @@ * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ -asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) { - unsigned long instr, *pc = (unsigned long *)(instruction_pointer(regs)-4); struct k_sigaction *ka; siginfo_t info; - int single_stepping, swi_instr; + int single_stepping; + + if (!user_mode(regs)) + return 0; if (!oldset) oldset = ¤t->blocked; single_stepping = ptrace_cancel_bpt (current); - swi_instr = (!get_user (instr, pc) && (instr & 0x0f000000) == 0x0f000000); for (;;) { unsigned long signr; @@ -503,7 +527,7 @@ } /* Are we from a system call? */ - if (swi_instr) { + if (syscall) { switch (regs->ARM_r0) { case -ERESTARTNOHAND: regs->ARM_r0 = -EINTR; @@ -527,7 +551,7 @@ return 1; } - if (swi_instr && + if (syscall && (regs->ARM_r0 == -ERESTARTNOHAND || regs->ARM_r0 == -ERESTARTSYS || regs->ARM_r0 == -ERESTARTNOINTR)) { diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/sys_arm.c linux.ac/arch/arm/kernel/sys_arm.c --- linux.vanilla/arch/arm/kernel/sys_arm.c Tue Dec 22 23:19:27 1998 +++ linux.ac/arch/arm/kernel/sys_arm.c Sun Jan 24 21:11:32 1999 @@ -221,13 +221,7 @@ */ asmlinkage int sys_fork(struct pt_regs *regs) { - int ret; - - lock_kernel(); - ret = do_fork(SIGCHLD, regs->ARM_sp, regs); - unlock_kernel(); - - return ret; + return do_fork(SIGCHLD, regs->ARM_sp, regs); } /* Clone a task - this clones the calling program thread. @@ -235,14 +229,23 @@ */ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct pt_regs *regs) { - int ret; - - lock_kernel(); if (!newsp) newsp = regs->ARM_sp; - ret = do_fork(clone_flags, newsp, regs); - unlock_kernel(); - return ret; + return do_fork(clone_flags, newsp, regs); +} + +asmlinkage int sys_vfork(struct pt_regs *regs) +{ + int child; + struct semaphore sem = MUTEX_LOCKED; + + current->vfork_sem = &sem; + child = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs); + + if (child > 0) + down(&sem); + + return child; } /* sys_execve() executes a new program. diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/time.c linux.ac/arch/arm/kernel/time.c --- linux.vanilla/arch/arm/kernel/time.c Sun Jan 24 19:55:30 1999 +++ linux.ac/arch/arm/kernel/time.c Sun Jan 24 21:11:32 1999 @@ -130,27 +130,12 @@ time_state = TIME_ERROR; /* p. 24, (a) */ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; - sti (); + sti(); } -/* - * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "do_timer()" routine every clocktick. - */ -static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - if (reset_timer ()) - do_timer(regs); - - update_rtc (); -} - -static struct irqaction irqtimer = { timer_interrupt, 0, 0, "timer", NULL, NULL}; - __initfunc(void time_init(void)) { - xtime.tv_sec = setup_timer(); xtime.tv_usec = 0; - setup_arm_irq(IRQ_TIMER, &irqtimer); + setup_timer(); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/traps.c linux.ac/arch/arm/kernel/traps.c --- linux.vanilla/arch/arm/kernel/traps.c Tue Dec 22 23:19:27 1998 +++ linux.ac/arch/arm/kernel/traps.c Sun Jan 24 21:11:32 1999 @@ -54,7 +54,7 @@ if (stackptr < PAGE_OFFSET || stackptr + size > (unsigned long)high_memory) return -EFAULT; #endif - return 0; + return 0; } /* @@ -199,9 +199,8 @@ void bad_user_access_alignment (const void *ptr) { - void *pc; - __asm__("mov %0, lr\n": "=r" (pc)); - printk (KERN_ERR "bad_user_access_alignment called: ptr = %p, pc = %p\n", ptr, pc); + printk (KERN_ERR "bad_user_access_alignment called: ptr = %p, pc = %p\n", ptr, + __builtin_return_address(0)); current->tss.error_code = 0; current->tss.trap_no = 11; force_sig (SIGBUS, current); @@ -210,6 +209,10 @@ asmlinkage void do_undefinstr (int address, struct pt_regs *regs, int mode) { +#ifdef CONFIG_DEBUG_USER + printk(KERN_INFO "%s (%d): undefined instruction: pc=%08lx\n", + current->comm, current->pid, instruction_pointer(regs)); +#endif current->tss.error_code = 0; current->tss.trap_no = 6; force_sig (SIGILL, current); @@ -218,6 +221,10 @@ asmlinkage void do_excpt (int address, struct pt_regs *regs, int mode) { +#ifdef CONFIG_DEBUG_USER + printk(KERN_INFO "%s (%d): address exception: pc=%08lx\n", + current->comm, current->pid, instruction_pointer(regs)); +#endif current->tss.error_code = 0; current->tss.trap_no = 11; force_sig (SIGBUS, current); @@ -249,19 +256,14 @@ */ asmlinkage void math_state_restore (void) { - current->used_math = 1; + current->used_math = 1; } -asmlinkage void arm_syscall (int no, struct pt_regs *regs) +asmlinkage int arm_syscall (int no, struct pt_regs *regs) { switch (no) { case 0: /* branch through 0 */ force_sig(SIGSEGV, current); -// if (user_mode(regs)) { -// dump_state("branch through zero", regs, 0); -// if (regs->ARM_fp) -// c_backtrace (regs->ARM_fp, processor_mode(regs)); -// } die_if_kernel ("branch through zero", regs, 0, SIGSEGV); break; @@ -271,21 +273,54 @@ force_sig (SIGTRAP, current); break; + case 2: /* sys_cacheflush */ +#ifdef CONFIG_CPU_32 + /* r0 = start, r1 = length, r2 = flags */ + processor.u.armv3v4._flush_cache_area(regs->ARM_r0, + regs->ARM_r1, + 1); +#endif + break; + default: + /* Calls 9f00xx..9f07ff are defined to return -ENOSYS + if not implemented, rather than raising SIGILL. This + way the calling program can gracefully determine whether + a feature is supported. */ + if (no <= 0x7ff) + return -ENOSYS; +#ifdef CONFIG_DEBUG_USER + /* experiance shows that these seem to indicate that + * something catastrophic has happened + */ printk ("[%d] %s: arm syscall %d\n", current->pid, current->comm, no); - force_sig (SIGILL, current); if (user_mode(regs)) { show_regs (regs); c_backtrace (regs->ARM_fp, processor_mode(regs)); } +#endif + force_sig (SIGILL, current); die_if_kernel ("Oops", regs, no, SIGILL); break; } + return 0; } asmlinkage void deferred(int n, struct pt_regs *regs) { - dump_state("old system call", regs, n); + /* You might think just testing `handler' would be enough, but PER_LINUX + points it to no_lcall7 to catch undercover SVr4 binaries. Gutted. */ + if (current->personality != PER_LINUX && current->exec_domain->handler) { + /* Hand it off to iBCS. The extra parameter and consequent type + forcing is necessary because of the weird ARM calling convention. */ + void (*handler)(int nr, struct pt_regs *regs) = (void *)current->exec_domain->handler; + (*handler)(n, regs); + return; + } +#ifdef CONFIG_DEBUG_USER + printk(KERN_ERR "[%d] %s: old system call.\n", current->pid, + current->comm); +#endif force_sig (SIGILL, current); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/lib/Makefile linux.ac/arch/arm/lib/Makefile --- linux.vanilla/arch/arm/lib/Makefile Tue Dec 22 23:19:27 1998 +++ linux.ac/arch/arm/lib/Makefile Sun Jan 24 21:11:32 1999 @@ -6,7 +6,7 @@ L_TARGET := lib.a L_OBJS := backtrace.o bitops.o checksum.o delay.o io.o memcpy.o \ - system.o string.o uaccess.o + semaphore.o string.o system.o uaccess.o ifeq ($(PROCESSOR),armo) L_OBJS += uaccess-armo.o @@ -24,10 +24,6 @@ ifeq ($(MACHINE),ebsa110) L_OBJS += io-ebsa110.o -endif - -ifeq ($(MACHINE),vnc) - L_OBJS += io-ebsa285.o endif ifeq ($(MACHINE),ebsa285) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/lib/checksum.S linux.ac/arch/arm/lib/checksum.S --- linux.vanilla/arch/arm/lib/checksum.S Sun Nov 8 15:08:44 1998 +++ linux.ac/arch/arm/lib/checksum.S Sun Jan 24 21:11:32 1999 @@ -520,13 +520,13 @@ LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) ldr r4, [r0], #4 tst r2, #2 - beq Lexit + beq Lexit_r4 adcs r3, r3, r4, lsl #16 strb r4, [r1], #1 mov r4, r4, lsr #8 strb r4, [r1], #1 mov r4, r4, lsr #8 - b Lexit + b Lexit_r4 Ltoo_small: teq r2, #0 LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) @@ -538,10 +538,12 @@ adds r3, r3, ip strb ip, [r1], #1 strb r8, [r1], #1 -Lexit: tst r2, #1 -Ltoo_small1: ldrneb ip, [r0], #1 - strneb ip, [r1], #1 - adcnes r3, r3, ip + tst r2, #1 +Ltoo_small1: ldrneb r4, [r0], #1 +Lexit_r4: tst r2, #1 + strneb r4, [r1], #1 + andne r4, r4, #255 + adcnes r3, r3, r4 adcs r0, r3, #0 LOADREGS(ea,fp,{r4 - r8, fp, sp, pc}) @@ -598,13 +600,13 @@ adceq r0, r3, #0 LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) tst r2, #2 - beq Lexit + beq Lexit_r4 adcs r3, r3, r4, lsl #16 strb r4, [r1], #1 mov r4, r4, lsr #8 strb r4, [r1], #1 mov r4, r4, lsr #8 - b Lexit + b Lexit_r4 Lsrc2_aligned: mov r4, r4, lsr #16 adds r3, r3, #0 @@ -650,13 +652,13 @@ adceq r0, r3, #0 LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) tst r2, #2 - beq Lexit + beq Lexit_r4 adcs r3, r3, r4, lsl #16 strb r4, [r1], #1 mov r4, r4, lsr #8 strb r4, [r1], #1 ldrb r4, [r0], #1 - b Lexit + b Lexit_r4 Lsrc3_aligned: mov r4, r4, lsr #24 adds r3, r3, #0 @@ -702,14 +704,14 @@ adceq r0, r3, #0 LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) tst r2, #2 - beq Lexit + beq Lexit_r4 adcs r3, r3, r4, lsl #16 strb r4, [r1], #1 ldr r4, [r0], #4 strb r4, [r1], #1 adcs r3, r3, r4, lsl #24 mov r4, r4, lsr #8 - b Lexit + b Lexit_r4 ENTRY(__csum_ipv6_magic) stmfd sp!, {lr} diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/lib/io-ebsa285.S linux.ac/arch/arm/lib/io-ebsa285.S --- linux.vanilla/arch/arm/lib/io-ebsa285.S Tue Dec 22 23:19:27 1998 +++ linux.ac/arch/arm/lib/io-ebsa285.S Sun Jan 24 21:11:32 1999 @@ -1,8 +1,12 @@ #include + .macro ioaddr, rd,rn + add \rd, \rn, #0xff000000 + add \rd, \rd, #0x00e00000 + .endm + ENTRY(insl) - add r0, r0, #0xff000000 - add r0, r0, #0x00e00000 + ioaddr r0, r0 ands ip, r1, #3 bne 2f @@ -14,49 +18,48 @@ 2: cmp ip, #2 ldr ip, [r0] - blt 3f - bgt 4f + blt 4f + bgt 6f strh ip, [r1], #2 mov ip, ip, lsr #16 -1: subs r2, r2, #1 +3: subs r2, r2, #1 ldrne r3, [r0] orrne ip, ip, r3, lsl #16 strne ip, [r1], #4 movne ip, r3, lsr #16 - bne 1b + bne 3b strh ip, [r1], #2 mov pc, lr -3: strb ip, [r1], #1 +4: strb ip, [r1], #1 mov ip, ip, lsr #8 strh ip, [r1], #2 mov ip, ip, lsr #16 -1: subs r2, r2, #1 +5: subs r2, r2, #1 ldrne r3, [r0] orrne ip, ip, r3, lsl #8 strne ip, [r1], #4 movne ip, r3, lsr #24 - bne 1b + bne 5b strb ip, [r1], #1 mov pc, lr -4: strb ip, [r1], #1 +6: strb ip, [r1], #1 mov ip, ip, lsr #8 -1: subs r2, r2, #1 +7: subs r2, r2, #1 ldrne r3, [r0] orrne ip, ip, r3, lsl #24 strne ip, [r1], #4 movne ip, r3, lsr #8 - bne 1b + bne 7b strb ip, [r1], #1 mov ip, ip, lsr #8 strh ip, [r1], #2 mov pc, lr ENTRY(outsl) - add r0, r0, #0xff000000 - add r0, r0, #0x00e00000 + ioaddr r0, r0 ands ip, r1, #3 bne 2f @@ -70,31 +73,31 @@ cmp ip, #2 ldr ip, [r1], #4 mov ip, ip, lsr #16 - blt 3f - bgt 4f + blt 4f + bgt 5f -1: ldr r3, [r1], #4 +3: ldr r3, [r1], #4 orr ip, ip, r3, lsl #16 str ip, [r0] mov ip, r3, lsr #16 subs r2, r2, #1 - bne 1b + bne 3b mov pc, lr -3: ldr r3, [r1], #4 +4: ldr r3, [r1], #4 orr ip, ip, r3, lsl #8 str ip, [r0] mov ip, r3, lsr #24 subs r2, r2, #1 - bne 3b + bne 4b mov pc, lr -4: ldr r3, [r1], #4 +5: ldr r3, [r1], #4 orr ip, ip, r3, lsl #24 str ip, [r0] mov ip, r3, lsr #8 subs r2, r2, #1 - bne 4b + bne 5b mov pc, lr /* Nobody could say these are optimal, but not to worry. */ @@ -102,8 +105,7 @@ ENTRY(outswb) mov r2, r2, lsr #1 ENTRY(outsw) - add r0, r0, #0xff000000 - add r0, r0, #0x00e00000 + ioaddr r0, r0 1: subs r2, r2, #1 ldrgeh r3, [r1], #2 strgeh r3, [r0] @@ -114,8 +116,7 @@ mov r2, r2, lsr #1 ENTRY(insw) stmfd sp!, {r4, r5, lr} - add r0, r0, #0xff000000 - add r0, r0, #0x00e00000 + ioaddr r0, r0 @ + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 subs ip, r2, #8 blo too_little @@ -176,8 +177,7 @@ ENTRY(insb) - add r0, r0, #0xff000000 - add r0, r0, #0x00e00000 + ioaddr r0, r0 1: teq r2, #0 ldrneb r3, [r0] strneb r3, [r1], #1 @@ -187,8 +187,7 @@ ENTRY(outsb) - add r0, r0, #0xff000000 - add r0, r0, #0x00e00000 + ioaddr r0, r0 1: teq r2, #0 ldrneb r3, [r1], #1 strneb r3, [r0] diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/lib/semaphore.S linux.ac/arch/arm/lib/semaphore.S --- linux.vanilla/arch/arm/lib/semaphore.S Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/arm/lib/semaphore.S Sun Jan 24 21:11:32 1999 @@ -0,0 +1,29 @@ +/* + * linux/arch/arm/lib/semaphore.S + * + * Idea from i386 code, Copyright Linus Torvalds. + * Converted for ARM by Russell King + */ +#include +#include + +/* + * The semaphore operations have a special calling sequence + * that allows us to keep the distruption of the main code + * path to a minimum. These routines save and restore the + * registers that will be touched by __down etc. + */ +ENTRY(__down_failed) + stmfd sp!, {r0 - r3, ip, lr} + bl SYMBOL_NAME(__down) + LOADREGS(fd, sp!, {r0 - r3, ip, pc}) + +ENTRY(__down_interruptible_failed) + stmfd sp!, {r1 - r3, ip, lr} + bl SYMBOL_NAME(__down_interruptible) + LOADREGS(fd, sp!, {r1 - r3, ip, pc}) + +ENTRY(__up_wakeup) + stmfd sp!, {r0 - r3, ip, lr} + bl SYMBOL_NAME(__up) + LOADREGS(fd, sp!, {r0 - r3, ip, pc}) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/mm/Makefile linux.ac/arch/arm/mm/Makefile --- linux.vanilla/arch/arm/mm/Makefile Sun Nov 8 15:08:44 1998 +++ linux.ac/arch/arm/mm/Makefile Sun Jan 24 21:11:32 1999 @@ -22,7 +22,7 @@ endif ifeq ($(PROCESSOR),armv) - O_OBJS += small_page.o proc-arm6,7.o proc-sa110.o + O_OBJS += small_page.o proc-arm6,7.o proc-sa110.o ioremap.o endif include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/mm/fault-armo.c linux.ac/arch/arm/mm/fault-armo.c --- linux.vanilla/arch/arm/mm/fault-armo.c Tue Dec 22 23:19:28 1998 +++ linux.ac/arch/arm/mm/fault-armo.c Sun Jan 24 21:11:32 1999 @@ -157,19 +157,17 @@ bad_area: up(&mm->mmap_sem); if (mode & FAULT_CODE_USER) { -//extern int console_loglevel; -//cli(); tsk->tss.error_code = mode; tsk->tss.trap_no = 14; -//console_loglevel = 9; +#ifdef CONFIG_DEBUG_USER printk ("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n", tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode); -//#ifdef DEBUG +#ifdef DEBUG show_regs (regs); c_backtrace (regs->ARM_fp, 0); -//#endif +#endif +#endif force_sig(SIGSEGV, tsk); -//while (1); goto out; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/mm/fault-armv.c linux.ac/arch/arm/mm/fault-armv.c --- linux.vanilla/arch/arm/mm/fault-armv.c Tue Dec 22 23:19:28 1998 +++ linux.ac/arch/arm/mm/fault-armv.c Sun Jan 24 21:11:32 1999 @@ -5,6 +5,7 @@ * Modifications for ARM processor (c) 1995, 1996 Russell King */ +#include #include #include #include @@ -16,10 +17,13 @@ #include #include #include +#include +#include #include #include #include +#include #define FAULT_CODE_READ 0x02 #define FAULT_CODE_USER 0x01 @@ -48,8 +52,8 @@ if (pgd) { init = pgd_offset(&init_mm, 0); - memzero ((void *)pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR); - memcpy (pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, + memzero((void *)pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR); + memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, (PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR); } return pgd; @@ -62,14 +66,14 @@ pte = (pte_t *) get_small_page(GFP_KERNEL); if (pmd_none(*pmd)) { if (pte) { - memzero (pte, PTRS_PER_PTE * BYTES_PER_PTR); + memzero(pte, PTRS_PER_PTE * BYTES_PER_PTR); set_pmd(pmd, mk_user_pmd(pte)); return pte + offset; } set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE)); return NULL; } - free_small_page ((unsigned long) pte); + free_small_page((unsigned long) pte); if (pmd_bad(*pmd)) { __bad_pmd(pmd); return NULL; @@ -84,14 +88,14 @@ pte = (pte_t *) get_small_page(GFP_KERNEL); if (pmd_none(*pmd)) { if (pte) { - memzero (pte, PTRS_PER_PTE * BYTES_PER_PTR); + memzero(pte, PTRS_PER_PTE * BYTES_PER_PTR); set_pmd(pmd, mk_kernel_pmd(pte)); return pte + offset; } set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE)); return NULL; } - free_small_page ((unsigned long) pte); + free_small_page((unsigned long) pte); if (pmd_bad(*pmd)) { __bad_pmd_kernel(pmd); return NULL; @@ -102,7 +106,7 @@ extern void die_if_kernel(char *msg, struct pt_regs *regs, unsigned int err, unsigned int ret); #ifdef DEBUG -static int sp_valid (unsigned long *sp) +static int sp_valid(unsigned long *sp) { unsigned long addr = (unsigned long) sp; @@ -114,7 +118,7 @@ } #endif -static void kernel_page_fault (unsigned long addr, int mode, struct pt_regs *regs, +static void kernel_page_fault(unsigned long addr, int mode, struct pt_regs *regs, struct task_struct *tsk, struct mm_struct *mm) { /* @@ -123,26 +127,26 @@ */ pgd_t *pgd; if (addr < PAGE_SIZE) - printk (KERN_ALERT "Unable to handle kernel NULL pointer dereference"); + printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); else - printk (KERN_ALERT "Unable to handle kernel paging request"); - printk (" at virtual address %08lx\n", addr); - printk (KERN_ALERT "current->tss.memmap = %08lX\n", tsk->tss.memmap); - pgd = pgd_offset (mm, addr); - printk (KERN_ALERT "*pgd = %08lx", pgd_val (*pgd)); - if (!pgd_none (*pgd)) { + printk(KERN_ALERT "Unable to handle kernel paging request"); + printk(" at virtual address %08lx\n", addr); + printk(KERN_ALERT "current->tss.memmap = %08lX\n", tsk->tss.memmap); + pgd = pgd_offset(mm, addr); + printk(KERN_ALERT "*pgd = %08lx", pgd_val(*pgd)); + if (!pgd_none(*pgd)) { pmd_t *pmd; - pmd = pmd_offset (pgd, addr); - printk (", *pmd = %08lx", pmd_val (*pmd)); - if (!pmd_none (*pmd)) - printk (", *pte = %08lx", pte_val (*pte_offset (pmd, addr))); - } - printk ("\n"); - die_if_kernel ("Oops", regs, mode, SIGKILL); - do_exit (SIGKILL); + pmd = pmd_offset(pgd, addr); + printk(", *pmd = %08lx", pmd_val(*pmd)); + if (!pmd_none(*pmd)) + printk(", *pte = %08lx", pte_val(*pte_offset(pmd, addr))); + } + printk("\n"); + die_if_kernel("Oops", regs, mode, SIGKILL); + do_exit(SIGKILL); } -static void page_fault (unsigned long addr, int mode, struct pt_regs *regs) +static void do_page_fault(unsigned long addr, int mode, struct pt_regs *regs) { struct task_struct *tsk; struct mm_struct *mm; @@ -154,12 +158,12 @@ mm = tsk->mm; down(&mm->mmap_sem); - vma = find_vma (mm, addr); + vma = find_vma(mm, addr); if (!vma) goto bad_area; if (vma->vm_start <= addr) goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN) || expand_stack (vma, addr)) + if (!(vma->vm_flags & VM_GROWSDOWN) || expand_stack(vma, addr)) goto bad_area; /* @@ -174,7 +178,7 @@ if (!(vma->vm_flags & VM_WRITE)) goto bad_area; } - handle_mm_fault (tsk, vma, addr & PAGE_MASK, !(mode & FAULT_CODE_READ)); + handle_mm_fault(tsk, vma, addr & PAGE_MASK, !(mode & FAULT_CODE_READ)); up(&mm->mmap_sem); goto out; @@ -187,21 +191,23 @@ if (mode & FAULT_CODE_USER) { tsk->tss.error_code = mode; tsk->tss.trap_no = 14; - printk ("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n", +#ifdef CONFIG_DEBUG_USER + printk("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n", tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode); #ifdef DEBUG { unsigned int i, j; unsigned long *sp = (unsigned long *) (regs->ARM_sp - 128); - for (j = 0; j < 20 && sp_valid (sp); j++) { - printk ("%p: ", sp); - for (i = 0; i < 8 && sp_valid (sp); i += 1, sp++) - printk ("%08lx ", *sp); - printk ("\n"); + for (j = 0; j < 20 && sp_valid(sp); j++) { + printk("%p: ", sp); + for (i = 0; i < 8 && sp_valid(sp); i += 1, sp++) + printk("%08lx ", *sp); + printk("\n"); } } - show_regs (regs); - c_backtrace (regs->ARM_fp, regs->ARM_cpsr); + show_regs(regs); + c_backtrace(regs->ARM_fp, regs->ARM_cpsr); +#endif #endif force_sig(SIGSEGV, tsk); goto out; @@ -209,92 +215,363 @@ /* Are we prepared to handle this kernel fault? */ if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) { +#ifdef DEBUG printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n", tsk->comm, regs->ARM_pc, addr, fixup); +#endif regs->ARM_pc = fixup; goto out; } - kernel_page_fault (addr, mode, regs, tsk, mm); + kernel_page_fault(addr, mode, regs, tsk, mm); out: unlock_kernel(); } +#ifdef CONFIG_ALIGNMENT_TRAP +/* + * 32-bit misaligned trap handler (c) 1998 San Mehat (CCC) -July 1998 + * /proc/sys/debug/alignment, modified and integrated into + * Linux 2.1 by Russell King + * + * NOTE!!! This is not portable onto the ARM6/ARM7 processors yet. Also, + * it seems to give a severe performance impact (1 abort/ms - NW runs at + * ARM6 speeds) with GCC 2.7.2.2 - needs checking with a later GCC/EGCS. + * + * IMHO, I don't think that the trap handler is advantageous on ARM6,7 + * processors (they'll run like an ARM3). We'll see. + */ +#define CODING_BITS(i) (i & 0x0e000000) + +#define LDST_I_BIT(i) (i & (1 << 26)) /* Immediate constant */ +#define LDST_P_BIT(i) (i & (1 << 24)) /* Preindex */ +#define LDST_U_BIT(i) (i & (1 << 23)) /* Add offset */ +#define LDST_W_BIT(i) (i & (1 << 21)) /* Writeback */ +#define LDST_L_BIT(i) (i & (1 << 20)) /* Load */ + +#define LDSTH_I_BIT(i) (i & (1 << 22)) /* half-word immed */ +#define LDM_S_BIT(i) (i & (1 << 22)) /* write CPSR from SPSR */ + +#define RN_BITS(i) ((i >> 16) & 15) /* Rn */ +#define RD_BITS(i) ((i >> 12) & 15) /* Rd */ +#define RM_BITS(i) (i & 15) /* Rm */ + +#define REGMASK_BITS(i) (i & 0xffff) +#define OFFSET_BITS(i) (i & 0x0fff) + +#define IS_SHIFT(i) (i & 0x0ff0) +#define SHIFT_BITS(i) ((i >> 7) & 0x1f) +#define SHIFT_TYPE(i) (i & 0x60) +#define SHIFT_LSL 0x00 +#define SHIFT_LSR 0x20 +#define SHIFT_ASR 0x40 +#define SHIFT_RORRRX 0x60 + +static unsigned long ai_user; +static unsigned long ai_sys; +static unsigned long ai_skipped; +static unsigned long ai_half; +static unsigned long ai_word; +static unsigned long ai_multi; + +static int proc_alignment_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *p = page; + int len; + + p += sprintf(p, "User:\t\t%li\n", ai_user); + p += sprintf(p, "System:\t\t%li\n", ai_sys); + p += sprintf(p, "Skipped:\t%li\n", ai_skipped); + p += sprintf(p, "Half:\t\t%li\n", ai_half); + p += sprintf(p, "Word:\t\t%li\n", ai_word); + p += sprintf(p, "Multi:\t\t%li\n", ai_multi); + + len = (p - page) - off; + if (len < 0) + len = 0; + + *eof = (len <= count) ? 1 : 0; + *start = page + off; + + return len; +} + /* - * Handle a data abort. Note that we have to handle a range of addresses - * on ARM2/3 for ldm. If both pages are zero-mapped, then we have to force - * a copy-on-write + * This needs to be done after sysctl_init, otherwise sys/ + * will be overwritten. */ +void __init alignment_init(void) +{ + struct proc_dir_entry *e; + + e = create_proc_entry("sys/debug/alignment", S_IFREG | S_IRUGO, NULL); + + if (e) + e->read_proc = proc_alignment_read; +} + +static void +do_alignment_exception(struct pt_regs *regs) +{ + unsigned int instr, rd, rn, correction, nr_regs, regbits; + unsigned long eaddr; + union { unsigned long un; signed long sn; } offset; + + if (user_mode(regs)) { + set_cr(cr_no_alignment); + ai_user += 1; + return; + } + + ai_sys += 1; + + instr = *(unsigned long *)instruction_pointer(regs); + correction = 4; /* sometimes 8 on ARMv3 */ + regs->ARM_pc += correction + 4; + + rd = RD_BITS(instr); + rn = RN_BITS(instr); + eaddr = regs->uregs[rn]; + + switch(CODING_BITS(instr)) { + case 0x00000000: + if ((instr & 0x0ff00ff0) == 0x01000090) { + ai_skipped += 1; + printk(KERN_ERR "Unaligned trap: not handling swp instruction\n"); + break; + } + + if (((instr & 0x0e000090) == 0x00000090) && (instr & 0x60) != 0) { + ai_half += 1; + if (LDSTH_I_BIT(instr)) + offset.un = (instr & 0xf00) >> 4 | (instr & 15); + else + offset.un = regs->uregs[RM_BITS(instr)]; + + if (LDST_P_BIT(instr)) { + if (LDST_U_BIT(instr)) + eaddr += offset.un; + else + eaddr -= offset.un; + } + + if (LDST_L_BIT(instr)) + regs->uregs[rd] = get_unaligned((unsigned short *)eaddr); + else + put_unaligned(regs->uregs[rd], (unsigned short *)eaddr); + + /* signed half-word? */ + if (instr & 0x40) + regs->uregs[rd] = (long)((short) regs->uregs[rd]); + + if (!LDST_P_BIT(instr)) { + if (LDST_U_BIT(instr)) + eaddr += offset.un; + else + eaddr -= offset.un; + regs->uregs[rn] = eaddr; + } else if (LDST_W_BIT(instr)) + regs->uregs[rn] = eaddr; + break; + } + + default: + ai_skipped += 1; + panic("Alignment trap: not handling instruction %08X at %08lX", + instr, regs->ARM_pc - correction - 4); + break; + + case 0x04000000: + offset.un = OFFSET_BITS(instr); + goto ldr_str; + + case 0x06000000: + offset.un = regs->uregs[RM_BITS(instr)]; + + if (IS_SHIFT(instr)) { + unsigned int shiftval = SHIFT_BITS(instr); + + switch(SHIFT_TYPE(instr)) { + case SHIFT_LSL: + offset.un <<= shiftval; + break; + + case SHIFT_LSR: + offset.un >>= shiftval; + break; + + case SHIFT_ASR: + offset.sn >>= shiftval; + break; + + case SHIFT_RORRRX: + if (shiftval == 0) { + offset.un >>= 1; + if (regs->ARM_cpsr & CC_C_BIT) + offset.un |= 1 << 31; + } else + offset.un = offset.un >> shiftval | + offset.un << (32 - shiftval); + break; + } + } + + ldr_str: + ai_word += 1; + if (LDST_P_BIT(instr)) { + if (LDST_U_BIT(instr)) + eaddr += offset.un; + else + eaddr -= offset.un; + } else { + if (LDST_W_BIT(instr)) + printk(KERN_ERR "Not handling ldrt/strt correctly\n"); + } + + if (LDST_L_BIT(instr)) { + regs->uregs[rd] = get_unaligned((unsigned long *)eaddr); + if (rd == 15) + correction = 0; + } else + put_unaligned(regs->uregs[rd], (unsigned long *)eaddr); + + if (!LDST_P_BIT(instr)) { + if (LDST_U_BIT(instr)) + eaddr += offset.un; + else + eaddr -= offset.un; + + regs->uregs[rn] = eaddr; + } else if (LDST_W_BIT(instr)) + regs->uregs[rn] = eaddr; + break; + + case 0x08000000: + if (LDM_S_BIT(instr)) + panic("Alignment trap: not handling LDM with s-bit\n"); + ai_multi += 1; + + for (regbits = REGMASK_BITS(instr), nr_regs = 0; regbits; regbits >>= 1) + nr_regs += 4; + + if (!LDST_U_BIT(instr)) + eaddr -= nr_regs; + + if ((LDST_U_BIT(instr) == 0 && LDST_P_BIT(instr) == 0) || + (LDST_U_BIT(instr) && LDST_P_BIT(instr))) + eaddr += 4; + + for (regbits = REGMASK_BITS(instr), rd = 0; regbits; regbits >>= 1, rd += 1) + if (regbits & 1) { + if (LDST_L_BIT(instr)) { + regs->uregs[rd] = get_unaligned((unsigned long *)eaddr); + if (rd == 15) + correction = 0; + } else + put_unaligned(regs->uregs[rd], (unsigned long *)eaddr); + eaddr += 4; + } + + if (LDST_W_BIT(instr)) { + if (LDST_P_BIT(instr) && !LDST_U_BIT(instr)) + eaddr -= nr_regs; + else if (LDST_P_BIT(instr)) + eaddr -= 4; + else if (!LDST_U_BIT(instr)) + eaddr -= 4 + nr_regs; + regs->uregs[rn] = eaddr; + } + break; + } + + regs->ARM_pc -= correction; +} + +#endif + asmlinkage void -do_DataAbort (unsigned long addr, int fsr, int error_code, struct pt_regs *regs) +do_DataAbort(unsigned long addr, int fsr, int error_code, struct pt_regs *regs) { if (user_mode(regs)) error_code |= FAULT_CODE_USER; + #define DIE(signr,nam)\ force_sig(signr, current);\ die_if_kernel(nam, regs, fsr, signr);\ - break; + break switch (fsr & 15) { case 2: - DIE(SIGKILL, "Terminal exception") + DIE(SIGKILL, "Terminal exception"); case 0: - DIE(SIGSEGV, "Vector exception") + DIE(SIGSEGV, "Vector exception"); case 1: case 3: - DIE(SIGBUS, "Alignment exception") +#ifdef CONFIG_ALIGNMENT_TRAP + do_alignment_exception(regs); +#else + /* this should never happen */ + DIE(SIGBUS, "Alignment exception"); +#endif + break; + case 12: case 14: - DIE(SIGBUS, "External abort on translation") + DIE(SIGBUS, "External abort on translation"); case 9: case 11: - DIE(SIGSEGV, "Domain fault") + DIE(SIGSEGV, "Domain fault"); case 13:/* permission fault on section */ +#ifdef CONFIG_DEBUG_USER + printk("%s: permission fault on section, address=0x%08lx, code %d\n", + current->comm, addr, error_code); #ifdef DEBUG { unsigned int i, j; unsigned long *sp; - printk ("%s: section permission fault (bad address=0x%08lx, code %d)\n", - current->comm, addr, error_code); sp = (unsigned long *) (regs->ARM_sp - 128); - for (j = 0; j < 20 && sp_valid (sp); j++) { - printk ("%p: ", sp); - for (i = 0; i < 8 && sp_valid (sp); i += 1, sp++) - printk ("%08lx ", *sp); - printk ("\n"); + for (j = 0; j < 20 && sp_valid(sp); j++) { + printk("%p: ", sp); + for (i = 0; i < 8 && sp_valid(sp); i += 1, sp++) + printk("%08lx ", *sp); + printk("\n"); } - show_regs (regs); + show_regs(regs); c_backtrace(regs->ARM_fp, regs->ARM_cpsr); } #endif - DIE(SIGSEGV, "Permission fault") +#endif + DIE(SIGSEGV, "Permission fault"); case 15:/* permission fault on page */ case 5: /* page-table entry descriptor fault */ case 7: /* first-level descriptor fault */ - page_fault (addr, error_code, regs); + do_page_fault(addr, error_code, regs); break; case 4: case 6: - DIE(SIGBUS, "External abort on linefetch") + DIE(SIGBUS, "External abort on linefetch"); case 8: case 10: - DIE(SIGBUS, "External abort on non-linefetch") + DIE(SIGBUS, "External abort on non-linefetch"); } } asmlinkage int -do_PrefetchAbort (unsigned long addr, struct pt_regs *regs) +do_PrefetchAbort(unsigned long addr, struct pt_regs *regs) { #if 0 - /* does this still apply ? */ + /* does this still apply? It doesn't seem to happen, so + * I guess not. + */ if (the memc mapping for this page exists - can check now...) { - printk ("Page in, but got abort (undefined instruction?)\n"); + printk("Page in, but got abort (undefined instruction?)\n"); return 0; } #endif - page_fault (addr, FAULT_CODE_USER|FAULT_CODE_READ, regs); + do_page_fault(addr, FAULT_CODE_USER|FAULT_CODE_READ, regs); return 1; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/mm/init.c linux.ac/arch/arm/mm/init.c --- linux.vanilla/arch/arm/mm/init.c Tue Dec 22 23:19:28 1998 +++ linux.ac/arch/arm/mm/init.c Sun Jan 24 21:11:32 1999 @@ -137,6 +137,9 @@ flush_tlb_all(); update_memc_all(); + end_mem &= PAGE_MASK; + high_memory = (void *)end_mem; + return free_area_init(start_mem, end_mem); } @@ -161,19 +164,18 @@ /* mark usable pages in the mem_map[] */ mark_usable_memory_areas(&start_mem, end_mem); +#define BETWEEN(w,min,max) ((w) >= (unsigned long)(min) && \ + (w) < (unsigned long)(max)) + for (tmp = PAGE_OFFSET; tmp < end_mem ; tmp += PAGE_SIZE) { if (PageReserved(mem_map+MAP_NR(tmp))) { - if (tmp >= KERNTOPHYS(_stext) && - tmp < KERNTOPHYS(_edata)) { - if (tmp < KERNTOPHYS(_etext)) - codepages++; - else - datapages++; - } else if (tmp >= KERNTOPHYS(__init_begin) - && tmp < KERNTOPHYS(__init_end)) + if (BETWEEN(tmp, &__init_begin, &__init_end)) initpages++; - else if (tmp >= KERNTOPHYS(__bss_start) - && tmp < (unsigned long) start_mem) + else if (BETWEEN(tmp, &_stext, &_etext)) + codepages++; + else if (BETWEEN(tmp, &_etext, &_edata)) + datapages++; + else if (BETWEEN(tmp, &__bss_start, start_mem)) datapages++; else reservedpages++; @@ -181,13 +183,16 @@ } atomic_set(&mem_map[MAP_NR(tmp)].count, 1); #ifdef CONFIG_BLK_DEV_INITRD - if (!initrd_start || (tmp < initrd_start || tmp >= initrd_end)) + if (!initrd_start || !BETWEEN(tmp, initrd_start, initrd_end)) #endif free_page(tmp); } - printk ("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n", + +#undef BETWEEN + + printk ("Memory: %luk/%luM available (%dk code, %dk reserved, %dk data, %dk init)\n", (unsigned long) nr_free_pages << (PAGE_SHIFT-10), - max_mapnr << (PAGE_SHIFT-10), + max_mapnr >> (20 - PAGE_SHIFT), codepages << (PAGE_SHIFT-10), reservedpages << (PAGE_SHIFT-10), datapages << (PAGE_SHIFT-10), @@ -203,17 +208,45 @@ #endif } -void free_initmem (void) +static void free_area(unsigned long addr, unsigned long end, char *s) { - unsigned long addr; + unsigned int size = (end - addr) >> 10; - addr = (unsigned long)(&__init_begin); - for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { + for (; addr < end; addr += PAGE_SIZE) { mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved); atomic_set(&mem_map[MAP_NR(addr)].count, 1); free_page(addr); } - printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10); + + if (size) + printk(" %dk %s", size, s); +} + +void free_initmem (void) +{ + printk("Freeing unused kernel memory:"); + + free_area((unsigned long)(&__init_begin), + (unsigned long)(&__init_end), + "init"); + +#ifdef CONFIG_FOOTBRIDGE + { + extern int __netwinder_begin, __netwinder_end, __ebsa285_begin, __ebsa285_end; + + if (!machine_is_netwinder()) + free_area((unsigned long)(&__netwinder_begin), + (unsigned long)(&__netwinder_end), + "netwinder"); + + if (!machine_is_ebsa285() && !machine_is_cats()) + free_area((unsigned long)(&__ebsa285_begin), + (unsigned long)(&__ebsa285_end), + "ebsa285/cats"); + } +#endif + + printk("\n"); } void si_meminfo(struct sysinfo *val) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/mm/ioremap.c linux.ac/arch/arm/mm/ioremap.c --- linux.vanilla/arch/arm/mm/ioremap.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/arm/mm/ioremap.c Sun Jan 24 21:11:32 1999 @@ -0,0 +1,153 @@ +/* + * arch/arm/mm/ioremap.c + * + * Re-map IO memory to kernel address space so that we can access it. + * + * (C) Copyright 1995 1996 Linus Torvalds + * + * Hacked for ARM by Phil Blundell + * Hacked to allow all architectures to build, and various cleanups + * by Russell King + */ + +/* + * This allows a driver to remap an arbitrary region of bus memory into + * virtual space. One should *only* use readl, writel, memcpy_toio and + * so on with such remapped areas. + * + * Because the ARM only has a 32-bit address space we can't address the + * whole of the (physical) PCI space at once. PCI huge-mode addressing + * allows us to circumvent this restriction by splitting PCI space into + * two 2GB chunks and mapping only one at a time into processor memory. + * We use MMU protection domains to trap any attempt to access the bank + * that is not currently mapped. (This isn't fully implemented yet.) + * + * DC21285 currently has a bug in that the PCI address extension + * register affects the address of any writes waiting in the outbound + * FIFO. Unfortunately, it is not possible to tell the DC21285 to + * flush this - flushing the area causes the bus to lock. + */ + +#include +#include + +/* + * Only include this if we have valid_ioaddr() is defined + */ +#ifdef valid_ioaddr + +static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, + unsigned long phys_addr, pgprot_t pgprot) +{ + unsigned long end; + + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + do { + if (!pte_none(*pte)) + printk("remap_area_pte: page already exists\n"); + set_pte(pte, mk_pte_phys(phys_addr, pgprot)); + address += PAGE_SIZE; + phys_addr += PAGE_SIZE; + pte++; + } while (address < end); +} + +static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, + unsigned long phys_addr, unsigned long flags) +{ + unsigned long end; + pgprot_t pgprot; + + address &= ~PGDIR_MASK; + end = address + size; + + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + + phys_addr -= address; + pgprot = __pgprot(PTE_TYPE_SMALL | _PTE_WRITE | flags); + do { + pte_t * pte = pte_alloc_kernel(pmd, address); + if (!pte) + return -ENOMEM; + remap_area_pte(pte, address, end - address, address + phys_addr, pgprot); + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } while (address < end); + return 0; +} + +static int remap_area_pages(unsigned long address, unsigned long phys_addr, + unsigned long size, unsigned long flags) +{ + pgd_t * dir; + unsigned long end = address + size; + + phys_addr -= address; + dir = pgd_offset(&init_mm, address); + flush_cache_all(); + while (address < end) { + pmd_t *pmd = pmd_alloc_kernel(dir, address); + if (!pmd) + return -ENOMEM; + if (remap_area_pmd(pmd, address, end - address, + phys_addr + address, flags)) + return -ENOMEM; + set_pgdir(address, *dir); + address = (address + PGDIR_SIZE) & PGDIR_MASK; + dir++; + } + flush_tlb_all(); + return 0; +} + +/* + * Remap an arbitrary physical address space into the kernel virtual + * address space. Needed when the kernel wants to access high addresses + * directly. + * + * NOTE! We need to allow non-page-aligned mappings too: we will obviously + * have to convert them into an offset in a page-aligned mapping, but the + * caller shouldn't need to know that small detail. + */ +void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) +{ + void * addr; + struct vm_struct * area; + unsigned long offset; + + /* + * Mappings have to be page-aligned + */ + offset = phys_addr & ~PAGE_MASK; + size = PAGE_ALIGN(size + offset); + + /* + * Don't allow mappings that wrap.. + */ + if (!size || size > phys_addr + size) + return NULL; + + /* + * Ok, go for it.. + */ + area = get_vm_area(size); + if (!area) + return NULL; + addr = area->addr; + if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) { + vfree(addr); + return NULL; + } + return (void *) (offset + (char *)addr); +} + +void iounmap(void *addr) +{ + return vfree((void *) (PAGE_MASK & (unsigned long) addr)); +} + +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/mm/mm-ebsa285.c linux.ac/arch/arm/mm/mm-ebsa285.c --- linux.vanilla/arch/arm/mm/mm-ebsa285.c Tue Dec 22 23:19:28 1998 +++ linux.ac/arch/arm/mm/mm-ebsa285.c Sun Jan 24 21:11:32 1999 @@ -16,24 +16,23 @@ #include /* - * This is to allow us to fiddle with the EEPROM - * This entry will go away in time, once the fmu - * can mmap() the flash. + * The first entry allows us to fiddle with the EEPROM from user-space. + * This entry will go away in time, once the fmu32 can mmap() the + * flash. It can't at the moment. * - * These ones are so that we can fiddle - * with the various cards (eg VGA) - * until we're happy with them... + * If you want to fiddle with PCI VGA cards from user space, then + * change the '0, 1 }' for the PCI MEM and PCI IO to '1, 1 }' + * You can then access the PCI bus at 0xe0000000 and 0xffe00000. */ #define MAPPING \ { 0xd8000000, DC21285_FLASH, 0x00400000, DOMAIN_USER, 1, 1 }, /* EEPROM */ \ - { 0xdc000000, 0x7c000000, 0x00100000, DOMAIN_USER, 1, 1 }, /* VGA */ \ - { 0xe0000000, DC21285_PCI_MEM, 0x18000000, DOMAIN_USER, 1, 1 }, /* VGA */ \ + { 0xe0000000, DC21285_PCI_MEM, 0x18000000, DOMAIN_IO , 0, 1 }, /* PCI memory */ \ { 0xf8000000, DC21285_PCI_TYPE_0_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 0 Config */ \ { 0xf9000000, DC21285_PCI_TYPE_1_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 1 Config */ \ { PCI_IACK, DC21285_PCI_IACK, 0x01000000, DOMAIN_IO , 0, 1 }, /* PCI IACK */ \ { 0xfd000000, DC21285_OUTBOUND_WRITE_FLUSH, 0x01000000, DOMAIN_IO , 0, 1 }, /* Out wrflsh */ \ - { 0xfe000000, DC21285_ARMCSR_BASE, 0x01000000, DOMAIN_IO , 0, 1 }, /* CSR */ \ - { 0xffe00000, DC21285_PCI_IO, 0x00100000, DOMAIN_IO , 0, 1 }, /* PCI I/O */ \ + { ARMCSR_BASE,DC21285_ARMCSR_BASE, 0x01000000, DOMAIN_IO , 0, 1 }, /* CSR */ \ + { PCIO_BASE, DC21285_PCI_IO, 0x00100000, DOMAIN_IO , 0, 1 }, /* PCI I/O */ \ { 0xfff00000, 0x40000000, 0x00100000, DOMAIN_IO , 0, 1 }, /* X-Bus */ #include "mm-armv.c" diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/mm/mm-vnc.c linux.ac/arch/arm/mm/mm-vnc.c --- linux.vanilla/arch/arm/mm/mm-vnc.c Tue Dec 22 23:19:28 1998 +++ linux.ac/arch/arm/mm/mm-vnc.c Thu Jan 1 01:00:00 1970 @@ -1,31 +0,0 @@ -/* - * arch/arm/mm/mm-vnc.c - * - * Extra MM routines for the Corel VNC architecture - * - * Copyright (C) 1998 Russell King - */ -#include -#include -#include - -#include -#include -#include -#include -#include - -/* Table describing the MMU translation mapping - * mainly used to set up the I/O mappings. - */ -#define MAPPING \ - { 0xd0000000, DC21285_FLASH, 0x00800000, DOMAIN_IO , 0, 1 }, /* Flash */ \ - { 0xe0000000, DC21285_PCI_MEM, 0x18000000, DOMAIN_IO , 0, 1 }, /* PCI Mem */ \ - { 0xf8000000, DC21285_PCI_TYPE_0_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 0 Config */ \ - { 0xf9000000, DC21285_PCI_TYPE_1_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 1 Config */ \ - { PCI_IACK, DC21285_PCI_IACK, 0x01000000, DOMAIN_IO , 0, 1 }, /* PCI IACK */ \ - { 0xfd000000, DC21285_OUTBOUND_WRITE_FLUSH, 0x01000000, DOMAIN_IO , 0, 1 }, /* Out wrflsh */ \ - { 0xfe000000, DC21285_ARMCSR_BASE, 0x01000000, DOMAIN_IO , 0, 1 }, /* CSR */ \ - { 0xffe00000, DC21285_PCI_IO, 0x00100000, DOMAIN_IO , 0, 1 }, /* PCI I/O */ \ - -#include "mm-armv.c" diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/mm/proc-sa110.S linux.ac/arch/arm/mm/proc-sa110.S --- linux.vanilla/arch/arm/mm/proc-sa110.S Tue Dec 22 23:19:28 1998 +++ linux.ac/arch/arm/mm/proc-sa110.S Sun Jan 24 21:11:32 1999 @@ -8,6 +8,7 @@ */ #include #include +#include #include "../lib/constants.h" /* This is the maximum size of an area which will be flushed. If the area @@ -21,7 +22,6 @@ /* * Function: sa110_flush_cache_all (void) - * * Purpose : Flush all cache lines */ .align 5 @@ -33,7 +33,7 @@ ands r1, r1, #1 eor r1, r1, #1 str r1, [r3] - ldr ip, =0xdf000000 + ldr ip, =FLUSH_BASE addne ip, ip, #32768 add r1, ip, #16384 @ only necessary for 16k 1: ldr r3, [ip], #32 @@ -47,11 +47,9 @@ /* * Function: sa110_flush_cache_area (unsigned long address, int end, int flags) - * * Params : address Area start address * : end Area end address * : flags b0 = I cache as well - * * Purpose : clean & flush all cache lines associated with this area of memory */ .align 5 @@ -74,10 +72,8 @@ /* * Function: sa110_cache_wback_area(unsigned long address, unsigned long end) - * * Params : address Area start address * : end Area end address - * * Purpose : ensure all dirty cachelines in the specified area have been * written out to memory (for DMA) */ @@ -99,13 +95,10 @@ /* * Function: sa110_cache_purge_area(unsigned long address, unsigned long end) - * * Params : address Area start address * : end Area end address - * * Purpose : throw away all D-cached data in specified region without * an obligation to write it ack. - * * Note : Must clean the D-cached entries around the boundaries if the * start and/or end address are not cache aligned. */ @@ -124,9 +117,7 @@ /* * Function: sa110_flush_cache_entry (unsigned long address) - * * Params : address Address of cache line to flush - * * Purpose : clean & flush an entry */ .align 5 @@ -139,9 +130,7 @@ /* * Function: sa110_flush_cache_pte (unsigned long address) - * * Params : address Address of cache line to clean - * * Purpose : Ensure that physical memory reflects cache at this location * for page table purposes. */ @@ -151,11 +140,9 @@ /* * Function: sa110_flush_ram_page (unsigned long page) - * * Params : address Area start address * : size size of area * : flags b0 = I cache as well - * * Purpose : clean & flush all cache lines associated with this area of memory */ .align 5 @@ -176,7 +163,6 @@ /* * Function: sa110_flush_tlb_all (void) - * * Purpose : flush all TLB entries in all caches */ .align 5 @@ -188,11 +174,9 @@ /* * Function: sa110_flush_tlb_area (unsigned long address, unsigned long end, int flags) - * * Params : address Area start address * : end Area end address * : flags b0 = I cache as well - * * Purpose : flush a TLB entry */ .align 5 @@ -221,13 +205,10 @@ mov pc, lr /* * Function: sa110_switch_to (struct task_struct *prev, struct task_struct *next) - * * Params : prev Old task structure * : next New task structure for process to run - * * Purpose : Perform a task switch, saving the old processes state, and restoring * the new. - * * Notes : We don't fiddle with the FP registers here - we postpone this until * the new task actually uses FP. This way, we don't swap FP for tasks * that do not require it. @@ -237,6 +218,7 @@ stmfd sp!, {r4 - r9, fp, lr} @ Store most regs on stack mrs ip, cpsr stmfd sp!, {ip} @ Save cpsr_SVC +@ ldr r2, [r0, #TSS_MEMMAP] @ Get old page tables str sp, [r0, #TSS_SAVE] @ Save sp_SVC ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC ldr r0, [r1, #TSK_ADDR_LIMIT] @@ -245,12 +227,21 @@ movne r0, #DOM_USERDOMAIN mcr p15, 0, r0, c3, c0 @ Set segment ldr r0, [r1, #TSS_MEMMAP] @ Page table pointer +/* + * Flushing the cache is nightmarishly slow, so we take any excuse + * to get out of it. If the old page table is the same as the new, + * this is a CLONE_VM relative of the old task and there is no need + * to flush. The overhead of the tests isn't even on the radar + * compared to the cost of the flush itself. + */ + teq r0, r2 + beq 2f ldr r3, =Lclean_switch ldr r2, [r3] ands r2, r2, #1 eor r2, r2, #1 str r2, [r3] - ldr r2, =0xdf000000 + ldr r2, =FLUSH_BASE addne r2, r2, #32768 add r1, r2, #16384 @ only necessary for 16k 1: ldr r3, [r2], #32 @@ -261,17 +252,14 @@ mcr p15, 0, r1, c7, c10, 4 @ drain WB mcr p15, 0, r0, c2, c0, 0 @ load page table pointer mcr p15, 0, r1, c8, c7, 0 @ flush TLBs - ldmfd sp!, {ip} +2: ldmfd sp!, {ip} msr spsr, ip @ Save tasks CPSR into SPSR for this return ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously /* * Function: sa110_data_abort () - * * Params : r0 = address of aborted instruction - * * Purpose : obtain information about current aborted instruction - * * Returns : r0 = address of abort * : r1 = FSR * : r2 != 0 if writing @@ -289,10 +277,8 @@ /* * Function: sa110_set_pmd () - * * Params : r0 = Address to set * : r1 = value to set - * * Purpose : Set a PMD and flush it out of any WB cache */ .align 5 @@ -304,20 +290,19 @@ * Function: sa110_check_bugs (void) * : sa110_proc_init (void) * : sa110_proc_fin (void) - * * Notes : This processor does not require these */ _sa110_check_bugs: mrs ip, cpsr bic ip, ip, #F_BIT msr cpsr, ip + _sa110_proc_init: _sa110_proc_fin: mov pc, lr /* * Function: sa110_reset - * * Notes : This sets up everything for a reset */ _sa110_reset: mrs r1, cpsr diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/vmlinux-armv.lds linux.ac/arch/arm/vmlinux-armv.lds --- linux.vanilla/arch/arm/vmlinux-armv.lds Sun Nov 8 15:08:45 1998 +++ linux.ac/arch/arm/vmlinux-armv.lds Sun Jan 24 21:11:32 1999 @@ -7,50 +7,64 @@ ENTRY(_start) SECTIONS { - _text = .; /* Text and read-only data */ - .text : { + _text = .; /* Text and read-only data */ + .text : { } /* Set text start address */ + + __init_begin = .; /* Init code and data */ + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __ebsa285_begin = .; + .text.ebsa285 : { *(.text.ebsa285) } + .data.ebsa285 : { *(.data.ebsa285) } + . = ALIGN(4096); + __ebsa285_end = .; + + __netwinder_begin = .; + .text.netwinder : { *(.text.netwinder) } + .data.netwinder : { *(.data.netwinder) } + . = ALIGN(4096); + __netwinder_end = .; + + .text.real : { /* Real text segment */ *(.text) *(.fixup) *(.gnu.warning) - } = 0x9090 + } + .text.lock : { *(.text.lock) } /* out-of-line lock text */ .rodata : { *(.rodata) } .kstrtab : { *(.kstrtab) } - . = ALIGN(16); /* Exception table */ + . = ALIGN(16); /* Exception table */ __start___ex_table = .; __ex_table : { *(__ex_table) } __stop___ex_table = .; - __start___ksymtab = .; /* Kernel symbol table */ + __start___ksymtab = .; /* Kernel symbol table */ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; - _etext = .; /* End of text section */ + _etext = .; /* End of text section */ . = ALIGN(8192); - .data : { /* Data */ + .data : { /* Data */ *(.init.task) *(.data) CONSTRUCTORS } - _edata = .; /* End of data section */ - - . = ALIGN(4096); /* Init code and data */ - __init_begin = .; - .text.init : { *(.text.init) } - .data.init : { *(.data.init) } - . = ALIGN(4096); - __init_end = .; + _edata = .; /* End of data section */ - __bss_start = .; /* BSS */ + __bss_start = .; /* BSS */ .bss : { *(.bss) } _end = . ; - /* Stabs debugging sections. */ + /* Stabs debugging sections. */ .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } .stab.excl 0 : { *(.stab.excl) } 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 Dec 4 17:14:23 1998 @@ -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/m68k/kernel/process.c linux.ac/arch/m68k/kernel/process.c --- linux.vanilla/arch/m68k/kernel/process.c Sun Jan 24 19:55:31 1999 +++ linux.ac/arch/m68k/kernel/process.c Sun Jan 24 20:22:53 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; 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 Dec 4 17:14:23 1998 @@ -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/irixioctl.c linux.ac/arch/mips/kernel/irixioctl.c --- linux.vanilla/arch/mips/kernel/irixioctl.c Sun Nov 8 15:08:29 1998 +++ linux.ac/arch/mips/kernel/irixioctl.c Fri Dec 4 17:14:23 1998 @@ -33,7 +33,7 @@ { struct file *filp; - if(fd >= NR_OPEN || !(filp = current->files->fd[fd])) + if(fd >= current->files->max_fds || !(filp = current->files->fd[fd])) return ((struct tty_struct *) 0); if(filp->private_data) { struct tty_struct *ttyp = (struct tty_struct *) filp->private_data; 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 Sun Nov 8 15:10:06 1998 +++ linux.ac/arch/mips/kernel/sysirix.c Fri Dec 4 17:14:23 1998 @@ -788,7 +788,8 @@ error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs)); if (error) goto out; - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) { + if (fd >= current->files->max_fds || + !(file = current->files->fd[fd])) { error = -EBADF; goto out; } @@ -1111,7 +1112,8 @@ lock_kernel(); if(!(flags & MAP_ANONYMOUS)) { - if(fd >= NR_OPEN || !(file = current->files->fd[fd])) { + if(fd >= current->files->max_fds || + !(file = current->files->fd[fd])) { retval = -EBADF; goto out; } @@ -1583,7 +1585,8 @@ error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); if (error) goto out; - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) { + if (fd >= current->files->max_fds || + !(file = current->files->fd[fd])) { error = -EBADF; goto out; } @@ -1727,7 +1730,8 @@ } if(!(flags & MAP_ANONYMOUS)) { - if(fd >= NR_OPEN || !(file = current->files->fd[fd])) { + if(fd >= current->files->max_fds || + !(file = current->files->fd[fd])) { error = -EBADF; goto out; } @@ -1879,7 +1883,8 @@ error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); if (error) goto out; - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) { + if (fd >= current->files->max_fds || + !(file = current->files->fd[fd])) { error = -EBADF; goto out; } @@ -2040,7 +2045,8 @@ current->pid, fd, dirent, count, eob); #endif error = -EBADF; - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) + if (fd >= current->files->max_fds || + !(file = current->files->fd[fd])) goto out; dentry = file->f_dentry; @@ -2151,7 +2157,8 @@ current->pid, fd, dirent, cnt); #endif error = -EBADF; - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) + if (fd >= current->files->max_fds || + !(file = current->files->fd[fd])) goto out; dentry = file->f_dentry; @@ -2212,7 +2219,8 @@ current->pid, fd, dirent, cnt); #endif error = -EBADF; - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) + if (fd >= current->files->max_fds || + !(file = current->files->fd[fd])) goto out; dentry = file->f_dentry; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/kernel/process.c linux.ac/arch/ppc/kernel/process.c --- linux.vanilla/arch/ppc/kernel/process.c Sat Jan 9 21:50:36 1999 +++ linux.ac/arch/ppc/kernel/process.c Sat Jan 9 21:57:09 1999 @@ -67,7 +67,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; 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 Sun Nov 8 15:08:33 1998 +++ linux.ac/arch/ppc/kernel/syscalls.c Fri Dec 4 17:14:34 1998 @@ -205,7 +205,8 @@ lock_kernel(); if (!(flags & MAP_ANONYMOUS)) { - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) + if (fd >= current->files->max_fds || + !(file = current->files->fd[fd])) goto out; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/mbx_defconfig linux.ac/arch/ppc/mbx_defconfig --- linux.vanilla/arch/ppc/mbx_defconfig Mon Dec 28 23:09:41 1998 +++ linux.ac/arch/ppc/mbx_defconfig Tue Dec 22 23:35:52 1998 @@ -14,7 +14,6 @@ # CONFIG_ALL_PPC is not set # CONFIG_APUS is not set CONFIG_MBX=y -CONFIG_SMP=n CONFIG_MACH_SPECIFIC=y CONFIG_SERIAL_CONSOLE=y 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 Dec 4 17:14:35 1998 @@ -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/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 Dec 4 17:14:35 1998 @@ -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/drivers/acorn/block/Config.in linux.ac/drivers/acorn/block/Config.in --- linux.vanilla/drivers/acorn/block/Config.in Sun Nov 8 15:08:19 1998 +++ linux.ac/drivers/acorn/block/Config.in Sun Jan 24 23:54:36 1999 @@ -11,6 +11,7 @@ fi tristate 'MFM harddisk support' CONFIG_BLK_DEV_MFM +tristate 'Old Archimedes floppy (1772) support' CONFIG_BLK_DEV_FD1772 if [ "$CONFIG_BLK_DEV_MFM" != "n" ]; then bool ' Autodetect hard drive geometry' CONFIG_BLK_DEV_MFM_AUTODETECT fi diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/block/Makefile linux.ac/drivers/acorn/block/Makefile --- linux.vanilla/drivers/acorn/block/Makefile Sun Nov 8 15:08:19 1998 +++ linux.ac/drivers/acorn/block/Makefile Sun Jan 24 23:54:36 1999 @@ -14,13 +14,11 @@ M_OBJS := MOD_LIST_NAME := ACORN_BLOCK_MODULES -ifeq ($(CONFIG_ARCH_ARC),y) - ifeq ($(CONFIG_BLK_DEV_FD),y) - L_OBJS += fd1772.o fd1772dma.o - else - ifeq ($(CONFIG_BLK_DEV_FD),m) - M_OBJS += fd1772_mod.o - endif +ifeq ($(CONFIG_BLK_DEV_FD1772),y) + L_OBJS += fd1772.o fd1772dma.o +else + ifeq ($(CONFIG_BLK_DEV_FD1772),m) + M_OBJS += fd1772_mod.o endif endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/block/fd1772.c linux.ac/drivers/acorn/block/fd1772.c --- linux.vanilla/drivers/acorn/block/fd1772.c Sat Jan 9 21:50:36 1999 +++ linux.ac/drivers/acorn/block/fd1772.c Sun Jan 24 23:54:36 1999 @@ -136,6 +136,7 @@ #include #include #include +#include #include #include #include diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/block/ide-ics.c linux.ac/drivers/acorn/block/ide-ics.c --- linux.vanilla/drivers/acorn/block/ide-ics.c Tue Dec 22 23:19:34 1998 +++ linux.ac/drivers/acorn/block/ide-ics.c Sun Jan 24 23:54:36 1999 @@ -81,6 +81,8 @@ icside_irqenable_arcin_v5, icside_irqdisable_arcin_v5, NULL, + NULL, + NULL, NULL }; @@ -106,9 +108,22 @@ inb (ide_base_port + ICS_ARCIN_V6_INTROFFSET_2); } +/* Prototype: icside_irqprobe(struct expansion_card *ec) + * Purpose : detect an active interrupt from card + */ +static int icside_irqpending_arcin_v6(struct expansion_card *ec) +{ + unsigned int ide_base_port = (unsigned int)ec->irq_data; + + return inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 || + inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_2) & 1; +} + static const expansioncard_ops_t icside_ops_arcin_v6 = { icside_irqenable_arcin_v6, icside_irqdisable_arcin_v6, + icside_irqpending_arcin_v6, + NULL, NULL, NULL }; @@ -220,8 +235,6 @@ case ics_if_arcin_v6: port = ecard_address (ec, ECARD_IOC, ECARD_FAST); - ec->irqaddr = ioaddr(port + ICS_ARCIN_V6_INTRSTAT_1); - ec->irqmask = 1; ec->irq_data = (void *)port; ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/block/ide-rapide.c linux.ac/drivers/acorn/block/ide-rapide.c --- linux.vanilla/drivers/acorn/block/ide-rapide.c Sun Nov 8 15:08:19 1998 +++ linux.ac/drivers/acorn/block/ide-rapide.c Sun Jan 24 23:54:36 1999 @@ -13,7 +13,6 @@ #include #include #include -#include #include "../../block/ide.h" @@ -28,14 +27,20 @@ static inline int rapide_register(struct expansion_card *ec) { unsigned long port = ecard_address (ec, ECARD_MEMC, 0); - ide_ioregspec_t spec; + hw_regs_t hw; - spec.base = port; - spec.ctrl = port + 0x206; - spec.offset = 1 << 4; - spec.irq = ec->irq; + int i; - return ide_register_port(&spec); + memset(&hw, 0, sizeof(hw)); + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hw.io_ports[i] = (ide_ioreg_t)port; + port += 1 << 4; + } + hw.io_ports[IDE_CONTROL_OFFSET] = port + 0x206; + hw.irq = ec->irq; + + return ide_register_hw(&hw, NULL); } int rapide_init(void) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/block/mfmhd.c linux.ac/drivers/acorn/block/mfmhd.c --- linux.vanilla/drivers/acorn/block/mfmhd.c Sun Nov 8 15:08:19 1998 +++ linux.ac/drivers/acorn/block/mfmhd.c Sun Jan 24 23:54:36 1999 @@ -123,6 +123,7 @@ #include #include #include +#include /* * This sort of stuff should be in a header file shared with ide.c, hd.c, xd.c etc diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/char/Config.in linux.ac/drivers/acorn/char/Config.in --- linux.vanilla/drivers/acorn/char/Config.in Tue Dec 22 23:19:34 1998 +++ linux.ac/drivers/acorn/char/Config.in Thu Jan 1 01:00:00 1970 @@ -1,15 +0,0 @@ -if [ "$CONFIG_SERIAL" != "n" ]; then - tristate ' Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL - tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL -fi - -if [ "$CONFIG_MOUSE" = "y" ]; then - if [ "$CONFIG_ARCH_ACORN" = "y" ]; then - if [ "$CONFIG_ARCH_RPC" != "y" ]; then - define_bool CONFIG_KBDMOUSE y - else - define_bool CONFIG_RPCMOUSE y - fi - fi -fi - diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/char/keyb_ps2.c linux.ac/drivers/acorn/char/keyb_ps2.c --- linux.vanilla/drivers/acorn/char/keyb_ps2.c Tue Dec 22 23:19:34 1998 +++ linux.ac/drivers/acorn/char/keyb_ps2.c Sun Jan 24 23:54:37 1999 @@ -25,6 +25,7 @@ #include #include #include +#include #include extern void kbd_reset_kdown(void); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/char/mouse_rpc.c linux.ac/drivers/acorn/char/mouse_rpc.c --- linux.vanilla/drivers/acorn/char/mouse_rpc.c Tue Dec 22 23:19:34 1998 +++ linux.ac/drivers/acorn/char/mouse_rpc.c Sun Jan 24 23:54:37 1999 @@ -1,5 +1,5 @@ /* - * linux/drivers/char/rpcmouse.c + * linux/drivers/char/mouse_rpc.c * * Copyright (C) 1996-1998 Russell King * @@ -16,6 +16,7 @@ #include #include #include +#include #include "../../char/mouse.h" diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/net/ether1.c linux.ac/drivers/acorn/net/ether1.c --- linux.vanilla/drivers/acorn/net/ether1.c Mon Dec 28 23:09:41 1998 +++ linux.ac/drivers/acorn/net/ether1.c Sun Jan 24 23:54:37 1999 @@ -128,7 +128,7 @@ { int used; - addr = IO_BASE + (addr << 2); + addr = ioaddr(addr); __asm__ __volatile__( "subs %3, %3, #2 @@ -171,7 +171,7 @@ { int used; - addr = IO_BASE + (addr << 2); + addr = ioaddr(addr); __asm__ __volatile__( "subs %3, %3, #2 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/net/ether3.c linux.ac/drivers/acorn/net/ether3.c --- linux.vanilla/drivers/acorn/net/ether3.c Sun Nov 8 15:08:20 1998 +++ linux.ac/drivers/acorn/net/ether3.c Sun Jan 24 23:54:37 1999 @@ -33,11 +33,13 @@ * packet starts two bytes from the end of the * buffer, it corrupts the receiver chain, and * never updates the transmit status correctly. + * 1.14 RMK 07/01/1998 Added initial code for ETHERB addressing. + * * TODO: * When we detect a fatal error on the interface, we should restart it. */ -static char *version = "ether3 ethernet driver (c) 1995-1998 R.M.King v1.13\n"; +static char *version = "ether3 ethernet driver (c) 1995-1999 R.M.King v1.14\n"; #include #include @@ -471,6 +473,25 @@ return error; } +static void +ether3_get_dev(struct device *dev, struct expansion_card *ec) +{ + ecard_claim(ec); + + dev->base_addr = ecard_address(ec, ECARD_MEMC, 0); + dev->irq = ec->irq; + + if (ec->cid.manufacturer == MANU_ANT && + ec->cid.product == PROD_ANT_ETHERB) { + dev->base_addr += 0x200; + } + + ec->irqaddr = ioaddr(dev->base_addr); + ec->irqmask = 0xf0; + + ether3_addr(dev->dev_addr, ec); +} + #ifndef MODULE __initfunc(int ether3_probe(struct device *dev)) @@ -485,12 +506,8 @@ if ((ec = ecard_find(0, ether3_cids)) == NULL) return ENODEV; - dev->base_addr = ecard_address(ec, ECARD_MEMC, 0); - dev->irq = ec->irq; - - ecard_claim(ec); + ether3_get_dev(dev, ec); - ether3_addr(dev->dev_addr, ec); return ether3_probe1(dev); } #endif @@ -942,17 +959,13 @@ my_ethers[i] = (struct device *)kmalloc(sizeof(struct device), GFP_KERNEL); memset(my_ethers[i], 0, sizeof(struct device)); - my_ethers[i]->irq = ec[i]->irq; - my_ethers[i]->base_addr= ecard_address(ec[i], ECARD_MEMC, 0); my_ethers[i]->init = ether3_probe1; my_ethers[i]->name = ethernames[i]; - ether3_addr(my_ethers[i]->dev_addr, ec[i]); - - ecard_claim(ec[i]); + ether3_get_dev(my_ethers[i], ec[i]); if(register_netdev(my_ethers[i]) != 0) { - for (i = 0; i < 4; i++) { + for (i = 0; i < MAX_ECARDS; i++) { if(my_ethers[i]) { kfree(my_ethers[i]); my_ethers[i] = NULL; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/net/etherh.c linux.ac/drivers/acorn/net/etherh.c --- linux.vanilla/drivers/acorn/net/etherh.c Tue Dec 22 23:19:35 1998 +++ linux.ac/drivers/acorn/net/etherh.c Sun Jan 24 23:54:37 1999 @@ -461,6 +461,8 @@ etherh_irq_enable, etherh_irq_disable, NULL, + NULL, + NULL, NULL }; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/acornscsi.c linux.ac/drivers/acorn/scsi/acornscsi.c --- linux.vanilla/drivers/acorn/scsi/acornscsi.c Mon Dec 28 23:09:41 1998 +++ linux.ac/drivers/acorn/scsi/acornscsi.c Sun Jan 24 23:54:37 1999 @@ -21,6 +21,8 @@ * 12-Oct-1997 RMK Added catch for re-entering interrupt routine. * 15-Oct-1997 RMK Improved handling of commands. * 27-Jun-1998 RMK Changed asm/delay.h to linux/delay.h. + * 13-Dec-1998 RMK Better abort code and command handling. Extra state + * transitions added to allow dodgy devices to work. */ #define DEBUG_NO_WRITE 1 #define DEBUG_QUEUES 2 @@ -35,7 +37,7 @@ #define DEBUG_RESET 1024 #define DEBUG_ALL (DEBUG_RESET|DEBUG_MESSAGES|DEBUG_LINK|DEBUG_WRITE|\ DEBUG_PHASES|DEBUG_CONNECT|DEBUG_DISCON|DEBUG_ABORT|\ - DEBUG_DMA|DEBUG_QUEUES|DEBUG_NO_WRITE) + DEBUG_DMA|DEBUG_QUEUES) /* DRIVER CONFIGURATION * @@ -186,26 +188,7 @@ #define DMAC_BUFFER_SIZE 65536 #endif -/* - * This is used to dump the previous states of the SBIC - */ -static struct status_entry { - unsigned long when; - unsigned char ssr; - unsigned char ph; - unsigned char irq; - unsigned char unused; -} status[9][16]; -static unsigned char status_ptr[9]; - -#define ADD_STATUS(_q,_ssr,_ph,_irq) \ -({ \ - status[(_q)][status_ptr[(_q)]].when = jiffies; \ - status[(_q)][status_ptr[(_q)]].ssr = (_ssr); \ - status[(_q)][status_ptr[(_q)]].ph = (_ph); \ - status[(_q)][status_ptr[(_q)]].irq = (_irq); \ - status_ptr[(_q)] = (status_ptr[(_q)] + 1) & 15; \ -}) +#define STATUS_BUFFER_TO_PRINT 24 unsigned int sdtr_period = SDTR_PERIOD; unsigned int sdtr_size = SDTR_SIZE; @@ -214,31 +197,31 @@ PROC_SCSI_EATA, 9, "acornscsi", S_IFDIR | S_IRUGO | S_IXUGO, 2 }; -static void acornscsi_done (AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result); -static int acornscsi_reconnect_finish (AS_Host *host); -static void acornscsi_dma_cleanup (AS_Host *host); -static void acornscsi_abortcmd (AS_Host *host, unsigned char tag); +static void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result); +static int acornscsi_reconnect_finish(AS_Host *host); +static void acornscsi_dma_cleanup(AS_Host *host); +static void acornscsi_abortcmd(AS_Host *host, unsigned char tag); /* ==================================================================================== * Miscellaneous */ static inline void -sbic_arm_write (unsigned int io_port, int reg, int value) +sbic_arm_write(unsigned int io_port, int reg, int value) { - outb_t (reg, io_port); - outb_t (value, io_port + 4); + outb_t(reg, io_port); + outb_t(value, io_port + 4); } #define sbic_arm_writenext(io,val) \ - outb_t ((val), (io) + 4) + outb_t((val), (io) + 4) static inline -int sbic_arm_read (unsigned int io_port, int reg) +int sbic_arm_read(unsigned int io_port, int reg) { if(reg == ASR) return inl_t(io_port) & 255; - outb_t (reg, io_port); + outb_t(reg, io_port); return inl_t(io_port + 4) & 255; } @@ -247,129 +230,165 @@ #ifdef USE_DMAC #define dmac_read(io_port,reg) \ - inb ((io_port) + (reg)) + inb((io_port) + (reg)) #define dmac_write(io_port,reg,value) \ - ({ outb ((value), (io_port) + (reg)); }) + ({ outb((value), (io_port) + (reg)); }) #define dmac_clearintr(io_port) \ - ({ outb (0, (io_port)); }) + ({ outb(0, (io_port)); }) static inline -unsigned int dmac_address (unsigned int io_port) +unsigned int dmac_address(unsigned int io_port) { - return dmac_read (io_port, TXADRHI) << 16 | - dmac_read (io_port, TXADRMD) << 8 | - dmac_read (io_port, TXADRLO); + return dmac_read(io_port, TXADRHI) << 16 | + dmac_read(io_port, TXADRMD) << 8 | + dmac_read(io_port, TXADRLO); } static -void acornscsi_dumpdma (AS_Host *host, char *where) +void acornscsi_dumpdma(AS_Host *host, char *where) { unsigned int mode, addr, len; - mode = dmac_read (host->dma.io_port, MODECON); - addr = dmac_address (host->dma.io_port); - len = dmac_read (host->dma.io_port, TXCNTHI) << 8 | - dmac_read (host->dma.io_port, TXCNTLO); + mode = dmac_read(host->dma.io_port, MODECON); + addr = dmac_address(host->dma.io_port); + len = dmac_read(host->dma.io_port, TXCNTHI) << 8 | + dmac_read(host->dma.io_port, TXCNTLO); - printk ("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ", + printk("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ", host->host->host_no, where, mode, addr, (len + 1) & 0xffff, - dmac_read (host->dma.io_port, MASKREG)); + dmac_read(host->dma.io_port, MASKREG)); - printk ("DMA @%06x, ", host->dma.start_addr); - printk ("BH @%p +%04x, ", host->scsi.SCp.ptr, + printk("DMA @%06x, ", host->dma.start_addr); + printk("BH @%p +%04x, ", host->scsi.SCp.ptr, host->scsi.SCp.this_residual); - printk ("DT @+%04x ST @+%04x", host->dma.transferred, + printk("DT @+%04x ST @+%04x", host->dma.transferred, host->scsi.SCp.scsi_xferred); - printk ("\n"); + printk("\n"); } #endif static -unsigned long acornscsi_sbic_xfcount (AS_Host *host) +unsigned long acornscsi_sbic_xfcount(AS_Host *host) { unsigned long length; - length = sbic_arm_read (host->scsi.io_port, TRANSCNTH) << 16; - length |= sbic_arm_readnext (host->scsi.io_port) << 8; - length |= sbic_arm_readnext (host->scsi.io_port); + length = sbic_arm_read(host->scsi.io_port, TRANSCNTH) << 16; + length |= sbic_arm_readnext(host->scsi.io_port) << 8; + length |= sbic_arm_readnext(host->scsi.io_port); return length; } -static -int acornscsi_sbic_issuecmd (AS_Host *host, int command) +static int +acornscsi_sbic_wait(AS_Host *host, int stat_mask, int stat, int timeout, char *msg) { - int asr; + int asr; - do { - asr = sbic_arm_read (host->scsi.io_port, ASR); - } while (asr & ASR_CIP); + do { + asr = sbic_arm_read(host->scsi.io_port, ASR); + + if ((asr & stat_mask) == stat) + return 0; + + udelay(1); + } while (--timeout); + + printk("scsi%d: timeout while %s\n", host->host->host_no, msg); + + return -1; +} + +static +int acornscsi_sbic_issuecmd(AS_Host *host, int command) +{ + if (acornscsi_sbic_wait(host, ASR_CIP, 0, 1000, "issuing command")) + return -1; - sbic_arm_write (host->scsi.io_port, CMND, command); + sbic_arm_write(host->scsi.io_port, CMND, command); return 0; } static void -acornscsi_csdelay (unsigned int cs) +acornscsi_csdelay(unsigned int cs) { unsigned long target_jiffies, flags; target_jiffies = jiffies + 1 + cs * HZ / 100; - save_flags (flags); - sti (); + save_flags(flags); + sti(); while (time_before(jiffies, target_jiffies)) barrier(); - restore_flags (flags); + restore_flags(flags); } static -void acornscsi_resetcard (AS_Host *host) +void acornscsi_resetcard(AS_Host *host) { - unsigned int i; + unsigned int i, timeout; /* assert reset line */ host->card.page_reg = 0x80; - outb (host->card.page_reg, host->card.io_page); + outb(host->card.page_reg, host->card.io_page); /* wait 3 cs. SCSI standard says 25ms. */ - acornscsi_csdelay (3); + acornscsi_csdelay(3); host->card.page_reg = 0; - outb (host->card.page_reg, host->card.io_page); + outb(host->card.page_reg, host->card.io_page); /* * Should get a reset from the card */ - while (!(inb (host->card.io_intr) & 8)); - sbic_arm_read (host->scsi.io_port, ASR); - sbic_arm_read (host->scsi.io_port, SSR); + timeout = 1000; + do { + if (inb(host->card.io_intr) & 8) + break; + udelay(1); + } while (--timeout); + + if (timeout == 0) + printk("scsi%d: timeout while resetting card\n", + host->host->host_no); + + sbic_arm_read(host->scsi.io_port, ASR); + sbic_arm_read(host->scsi.io_port, SSR); /* setup sbic - WD33C93A */ - sbic_arm_write (host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id); - sbic_arm_write (host->scsi.io_port, CMND, CMND_RESET); + sbic_arm_write(host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id); + sbic_arm_write(host->scsi.io_port, CMND, CMND_RESET); /* * Command should cause a reset interrupt */ - while (!(inb (host->card.io_intr) & 8)); - sbic_arm_read (host->scsi.io_port, ASR); - if (sbic_arm_read (host->scsi.io_port, SSR) != 0x01) - printk (KERN_CRIT "scsi%d: WD33C93A didn't give enhanced reset interrupt\n", + timeout = 1000; + do { + if (inb(host->card.io_intr) & 8) + break; + udelay(1); + } while (--timeout); + + if (timeout == 0) + printk("scsi%d: timeout while resetting card\n", host->host->host_no); - sbic_arm_write (host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI); - sbic_arm_write (host->scsi.io_port, TIMEOUT, TIMEOUT_TIME); - sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA); - sbic_arm_write (host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP); + sbic_arm_read(host->scsi.io_port, ASR); + if (sbic_arm_read(host->scsi.io_port, SSR) != 0x01) + printk(KERN_CRIT "scsi%d: WD33C93A didn't give enhanced reset interrupt\n", + host->host->host_no); + + sbic_arm_write(host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI); + sbic_arm_write(host->scsi.io_port, TIMEOUT, TIMEOUT_TIME); + sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA); + sbic_arm_write(host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP); host->card.page_reg = 0x40; - outb (host->card.page_reg, host->card.io_page); + outb(host->card.page_reg, host->card.io_page); /* setup dmac - uPC71071 */ dmac_write(host->dma.io_port, INIT, 0); @@ -391,7 +410,7 @@ } /* wait 25 cs. SCSI standard says 250ms. */ - acornscsi_csdelay (25); + acornscsi_csdelay(25); } /*============================================================================================= @@ -461,80 +480,101 @@ }; static -void print_scsi_status (unsigned int ssr) +void print_scsi_status(unsigned int ssr) { if (acornscsi_map[ssr] != -1) - printk ("%s:%s", + printk("%s:%s", acornscsi_interrupttype[(ssr >> 4)], acornscsi_interruptcode[acornscsi_map[ssr]]); else - printk ("%X:%X", ssr >> 4, ssr & 0x0f); + printk("%X:%X", ssr >> 4, ssr & 0x0f); } #endif static -void print_sbic_status (int asr, int ssr, int cmdphase) +void print_sbic_status(int asr, int ssr, int cmdphase) { #ifdef CONFIG_ACORNSCSI_CONSTANTS - printk ("sbic: %c%c%c%c%c%c ", + printk("sbic: %c%c%c%c%c%c ", asr & ASR_INT ? 'I' : 'i', asr & ASR_LCI ? 'L' : 'l', asr & ASR_BSY ? 'B' : 'b', asr & ASR_CIP ? 'C' : 'c', asr & ASR_PE ? 'P' : 'p', asr & ASR_DBR ? 'D' : 'd'); - printk ("scsi: "); - print_scsi_status (ssr); - printk (" ph %02X\n", cmdphase); + printk("scsi: "); + print_scsi_status(ssr); + printk(" ph %02X\n", cmdphase); #else - printk ("sbic: %02X scsi: %X:%X ph: %02X\n", + printk("sbic: %02X scsi: %X:%X ph: %02X\n", asr, (ssr & 0xf0)>>4, ssr & 0x0f, cmdphase); #endif } -static -void acornscsi_dumplog (AS_Host *host, int target) +static void +acornscsi_dumplogline(AS_Host *host, int target, int line) { - unsigned int prev; - do { - signed int statptr; + unsigned long prev; + signed int ptr; - printk ("%c:", target == 8 ? 'H' : ('0' + target)); - statptr = status_ptr[target] - 10; + ptr = host->status_ptr[target] - STATUS_BUFFER_TO_PRINT; + if (ptr < 0) + ptr += STATUS_BUFFER_SIZE; - if (statptr < 0) - statptr += 16; + printk("%c: %3s:", target == 8 ? 'H' : '0' + target, + line == 0 ? "ph" : line == 1 ? "ssr" : "int"); - prev = status[target][statptr].when; + prev = host->status[target][ptr].when; - for (; statptr != status_ptr[target]; statptr = (statptr + 1) & 15) { - if (status[target][statptr].when) { -#ifdef CONFIG_ACORNSCSI_CONSTANTS - printk ("%c%02X:S=", - status[target][statptr].irq ? '-' : ' ', - status[target][statptr].ph); - print_scsi_status (status[target][statptr].ssr); -#else - printk ("%c%02X:%02X", - status[target][statptr].irq ? '-' : ' ', - status[target][statptr].ph, - status[target][statptr].ssr); -#endif - printk ("+%02ld", - (status[target][statptr].when - prev) < 100 ? - (status[target][statptr].when - prev) : 99); - prev = status[target][statptr].when; - } + for (; ptr != host->status_ptr[target]; ptr = (ptr + 1) & (STATUS_BUFFER_SIZE - 1)) { + unsigned long time_diff; + + if (!host->status[target][ptr].when) + continue; + + switch (line) { + case 0: + printk("%c%02X", host->status[target][ptr].irq ? '-' : ' ', + host->status[target][ptr].ph); + break; + + case 1: + printk(" %02X", host->status[target][ptr].ssr); + break; + + case 2: + time_diff = host->status[target][ptr].when - prev; + prev = host->status[target][ptr].when; + if (time_diff == 0) + printk("==^"); + else if (time_diff >= 100) + printk(" "); + else + printk(" %02ld", time_diff); + break; + } } - printk ("\n"); + + printk("\n"); +} + +static +void acornscsi_dumplog(AS_Host *host, int target) +{ + do { + acornscsi_dumplogline(host, target, 0); + acornscsi_dumplogline(host, target, 1); + acornscsi_dumplogline(host, target, 2); + if (target == 8) break; + target = 8; } while (1); } static -char acornscsi_target (AS_Host *host) +char acornscsi_target(AS_Host *host) { if (host->SCpnt) return '0' + host->SCpnt->target; @@ -542,7 +582,7 @@ } /* - * Prototype: cmdtype_t acornscsi_cmdtype (int command) + * Prototype: cmdtype_t acornscsi_cmdtype(int command) * Purpose : differentiate READ from WRITE from other commands * Params : command - command to interpret * Returns : CMD_READ - command reads data, @@ -550,7 +590,7 @@ * CMD_MISC - everything else */ static inline -cmdtype_t acornscsi_cmdtype (int command) +cmdtype_t acornscsi_cmdtype(int command) { switch (command) { case WRITE_6: case WRITE_10: case WRITE_12: @@ -563,7 +603,7 @@ } /* - * Prototype: int acornscsi_datadirection (int command) + * Prototype: int acornscsi_datadirection(int command) * Purpose : differentiate between commands that have a DATA IN phase * and a DATA OUT phase * Params : command - command to interpret @@ -571,7 +611,7 @@ * DATADIR_IN - data in phase expected */ static -datadir_t acornscsi_datadirection (int command) +datadir_t acornscsi_datadirection(int command) { switch (command) { case CHANGE_DEFINITION: case COMPARE: case COPY: @@ -605,13 +645,13 @@ }; /* - * Prototype: int acornscsi_getperiod (unsigned char syncxfer) + * Prototype: int acornscsi_getperiod(unsigned char syncxfer) * Purpose : period for the synchronous transfer setting * Params : syncxfer SYNCXFER register value * Returns : period in ns. */ static -int acornscsi_getperiod (unsigned char syncxfer) +int acornscsi_getperiod(unsigned char syncxfer) { int i; @@ -626,14 +666,14 @@ } /* - * Prototype: int round_period (unsigned int period) + * Prototype: int round_period(unsigned int period) * Purpose : return index into above table for a required REQ period * Params : period - time (ns) for REQ * Returns : table index * Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting */ static inline -int round_period (unsigned int period) +int round_period(unsigned int period) { int i; @@ -646,7 +686,7 @@ } /* - * Prototype: unsigned char calc_sync_xfer (unsigned int period, unsigned int offset) + * Prototype: unsigned char calc_sync_xfer(unsigned int period, unsigned int offset) * Purpose : calculate value for 33c93s SYNC register * Params : period - time (ns) for REQ * offset - offset in bytes between REQ/ACK @@ -654,7 +694,7 @@ * Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting */ static -unsigned char calc_sync_xfer (unsigned int period, unsigned int offset) +unsigned char calc_sync_xfer(unsigned int period, unsigned int offset) { return sync_xfer_table[round_period(period)].reg_value | ((offset < SDTR_SIZE) ? offset : SDTR_SIZE); @@ -664,14 +704,14 @@ * Command functions */ /* - * Function: acornscsi_kick (AS_Host *host) + * Function: acornscsi_kick(AS_Host *host) * Purpose : kick next command to interface * Params : host - host to send command to * Returns : INTR_IDLE if idle, otherwise INTR_PROCESSING * Notes : interrupts are always disabled! */ static -intr_ret_t acornscsi_kick (AS_Host *host) +intr_ret_t acornscsi_kick(AS_Host *host) { int from_queue = 0; Scsi_Cmnd *SCpnt; @@ -682,7 +722,7 @@ /* retrieve next command */ if (!SCpnt) { - SCpnt = queue_remove_exclude (&host->queues.issue, host->busyluns); + SCpnt = queue_remove_exclude(&host->queues.issue, host->busyluns); if (!SCpnt) return INTR_IDLE; @@ -690,11 +730,11 @@ } if (host->scsi.disconnectable && host->SCpnt) { - queue_add_cmd_tail (&host->queues.disconnected, host->SCpnt); + queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt); host->scsi.disconnectable = 0; #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) - DBG(host->SCpnt, printk ("scsi%d.%c: moved command to disconnected queue\n", - host->host->host_no, acornscsi_target (host))); + DBG(host->SCpnt, printk("scsi%d.%c: moved command to disconnected queue\n", + host->host->host_no, acornscsi_target(host))); #endif host->SCpnt = NULL; } @@ -703,9 +743,9 @@ * If we have an interrupt pending, then we may have been reselected. * In this case, we don't want to write to the registers */ - if (!(sbic_arm_read (host->scsi.io_port, ASR) & (ASR_INT|ASR_BSY|ASR_CIP))) { - sbic_arm_write (host->scsi.io_port, DESTID, SCpnt->target); - sbic_arm_write (host->scsi.io_port, CMND, CMND_SELWITHATN); + if (!(sbic_arm_read(host->scsi.io_port, ASR) & (ASR_INT|ASR_BSY|ASR_CIP))) { + sbic_arm_write(host->scsi.io_port, DESTID, SCpnt->target); + sbic_arm_write(host->scsi.io_port, CMND, CMND_SELWITHATN); } /* @@ -717,9 +757,10 @@ host->scsi.SCp = SCpnt->SCp; host->dma.xfer_setup = 0; host->dma.xfer_required = 0; + host->dma.xfer_done = 0; #if (DEBUG & (DEBUG_ABORT|DEBUG_CONNECT)) - DBG(SCpnt,printk ("scsi%d.%c: starting cmd %02X\n", + DBG(SCpnt,printk("scsi%d.%c: starting cmd %02X\n", host->host->host_no, '0' + SCpnt->target, SCpnt->cmnd[0])); #endif @@ -736,11 +777,11 @@ SCpnt->tag = SCpnt->device->current_tag; } else #endif - set_bit (SCpnt->target * 8 + SCpnt->lun, host->busyluns); + set_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns); host->stats.removes += 1; - switch (acornscsi_cmdtype (SCpnt->cmnd[0])) { + switch (acornscsi_cmdtype(SCpnt->cmnd[0])) { case CMD_WRITE: host->stats.writes += 1; break; @@ -757,25 +798,25 @@ } /* - * Function: void acornscsi_done (AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result) + * Function: void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result) * Purpose : complete processing for command * Params : host - interface that completed * result - driver byte of result */ static -void acornscsi_done (AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result) +void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result) { Scsi_Cmnd *SCpnt = *SCpntp; /* clean up */ - sbic_arm_write (host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP); + sbic_arm_write(host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP); host->stats.fins += 1; if (SCpnt) { *SCpntp = NULL; - acornscsi_dma_cleanup (host); + acornscsi_dma_cleanup(host); SCpnt->result = result << 16 | host->scsi.SCp.Message << 8 | host->scsi.SCp.Status; @@ -787,35 +828,63 @@ * It doesn't appear to be set to something meaningful by the higher * levels all the time. */ - if (host->scsi.SCp.ptr && result == DID_OK && - acornscsi_cmdtype (SCpnt->cmnd[0]) != CMD_MISC) { - switch (status_byte (SCpnt->result)) { - case CHECK_CONDITION: - case COMMAND_TERMINATED: - case BUSY: - case QUEUE_FULL: - case RESERVATION_CONFLICT: - break; + if (result == DID_OK) { + int xfer_warn = 0; - default: - printk (KERN_ERR "scsi%d.H: incomplete data transfer detected: result=%08X command=", - host->host->host_no, SCpnt->result); - print_command (SCpnt->cmnd); - acornscsi_dumpdma (host, "done"); - acornscsi_dumplog (host, SCpnt->target); - SCpnt->result &= 0xffff; - SCpnt->result |= DID_ERROR << 16; - } + if (SCpnt->underflow == 0) { + if (host->scsi.SCp.ptr && + acornscsi_cmdtype(SCpnt->cmnd[0]) != CMD_MISC) + xfer_warn = 1; + } else { + if (host->scsi.SCp.scsi_xferred < SCpnt->underflow || + host->scsi.SCp.scsi_xferred != host->dma.transferred) + xfer_warn = 1; + } + + /* ANSI standard says: (SCSI-2 Rev 10c Sect 5.6.6) + * Targets which break data transfers into multiple + * connections shall end each successful connection + * (except possibly the last) with a SAVE DATA + * POINTER - DISCONNECT message sequence. + * + * This makes it difficult to ensure that a transfer has + * completed. If we reach the end of a transfer during + * the command, then we can only have finished the transfer. + * therefore, if we seem to have some data remaining, this + * is not a problem. + */ + if (host->dma.xfer_done) + xfer_warn = 0; + + if (xfer_warn) { + switch (status_byte(SCpnt->result)) { + case CHECK_CONDITION: + case COMMAND_TERMINATED: + case BUSY: + case QUEUE_FULL: + case RESERVATION_CONFLICT: + break; + + default: + printk(KERN_ERR "scsi%d.H: incomplete data transfer detected: result=%08X command=", + host->host->host_no, SCpnt->result); + print_command(SCpnt->cmnd); + acornscsi_dumpdma(host, "done"); + acornscsi_dumplog(host, SCpnt->target); + SCpnt->result &= 0xffff; + SCpnt->result |= DID_ERROR << 16; + } + } } if (!SCpnt->scsi_done) - panic ("scsi%d.H: null scsi_done function in acornscsi_done", host->host->host_no); + panic("scsi%d.H: null scsi_done function in acornscsi_done", host->host->host_no); - clear_bit (SCpnt->target * 8 + SCpnt->lun, host->busyluns); + clear_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns); - SCpnt->scsi_done (SCpnt); + SCpnt->scsi_done(SCpnt); } else - printk ("scsi%d: null command in acornscsi_done", host->host->host_no); + printk("scsi%d: null command in acornscsi_done", host->host->host_no); host->scsi.phase = PHASE_IDLE; } @@ -828,7 +897,7 @@ * Notes : this will only be one SG entry or less */ static -void acornscsi_data_updateptr (AS_Host *host, Scsi_Pointer *SCp, unsigned int length) +void acornscsi_data_updateptr(AS_Host *host, Scsi_Pointer *SCp, unsigned int length) { SCp->ptr += length; SCp->this_residual -= length; @@ -839,13 +908,15 @@ SCp->buffers_residual--; SCp->ptr = (char *)SCp->buffer->address; SCp->this_residual = SCp->buffer->length; - } else + } else { SCp->ptr = NULL; + host->dma.xfer_done = 1; + } } } /* - * Prototype: void acornscsi_data_read (AS_Host *host, char *ptr, + * Prototype: void acornscsi_data_read(AS_Host *host, char *ptr, * unsigned int start_addr, unsigned int length) * Purpose : read data from DMA RAM * Params : host - host to transfer from @@ -855,16 +926,16 @@ * Notes : this will only be one SG entry or less */ static -void acornscsi_data_read (AS_Host *host, char *ptr, +void acornscsi_data_read(AS_Host *host, char *ptr, unsigned int start_addr, unsigned int length) { - extern void __acornscsi_in (int port, char *buf, int len); + extern void __acornscsi_in(int port, char *buf, int len); unsigned int page, offset, len = length; page = (start_addr >> 12); offset = start_addr & ((1 << 12) - 1); - outb ((page & 0x3f) | host->card.page_reg, host->card.io_page); + outb((page & 0x3f) | host->card.page_reg, host->card.io_page); while (len > 0) { unsigned int this_len; @@ -874,7 +945,7 @@ else this_len = len; - __acornscsi_in (host->card.io_ram + (offset << 1), ptr, this_len); + __acornscsi_in(host->card.io_ram + (offset << 1), ptr, this_len); offset += this_len; ptr += this_len; @@ -883,14 +954,14 @@ if (offset == (1 << 12)) { offset = 0; page ++; - outb ((page & 0x3f) | host->card.page_reg, host->card.io_page); + outb((page & 0x3f) | host->card.page_reg, host->card.io_page); } } - outb (host->card.page_reg, host->card.io_page); + outb(host->card.page_reg, host->card.io_page); } /* - * Prototype: void acornscsi_data_write (AS_Host *host, char *ptr, + * Prototype: void acornscsi_data_write(AS_Host *host, char *ptr, * unsigned int start_addr, unsigned int length) * Purpose : write data to DMA RAM * Params : host - host to transfer from @@ -900,16 +971,16 @@ * Notes : this will only be one SG entry or less */ static -void acornscsi_data_write (AS_Host *host, char *ptr, +void acornscsi_data_write(AS_Host *host, char *ptr, unsigned int start_addr, unsigned int length) { - extern void __acornscsi_out (int port, char *buf, int len); + extern void __acornscsi_out(int port, char *buf, int len); unsigned int page, offset, len = length; page = (start_addr >> 12); offset = start_addr & ((1 << 12) - 1); - outb ((page & 0x3f) | host->card.page_reg, host->card.io_page); + outb((page & 0x3f) | host->card.page_reg, host->card.io_page); while (len > 0) { unsigned int this_len; @@ -919,7 +990,7 @@ else this_len = len; - __acornscsi_out (host->card.io_ram + (offset << 1), ptr, this_len); + __acornscsi_out(host->card.io_ram + (offset << 1), ptr, this_len); offset += this_len; ptr += this_len; @@ -928,10 +999,10 @@ if (offset == (1 << 12)) { offset = 0; page ++; - outb ((page & 0x3f) | host->card.page_reg, host->card.io_page); + outb((page & 0x3f) | host->card.page_reg, host->card.io_page); } } - outb (host->card.page_reg, host->card.io_page); + outb(host->card.page_reg, host->card.io_page); } /* ========================================================================================= @@ -939,25 +1010,25 @@ */ #ifdef USE_DMAC /* - * Prototype: void acornscsi_dmastop (AS_Host *host) + * Prototype: void acornscsi_dmastop(AS_Host *host) * Purpose : stop all DMA * Params : host - host on which to stop DMA * Notes : This is called when leaving DATA IN/OUT phase, * or when interface is RESET */ static inline -void acornscsi_dma_stop (AS_Host *host) +void acornscsi_dma_stop(AS_Host *host) { - dmac_write (host->dma.io_port, MASKREG, MASK_ON); - dmac_clearintr (host->dma.io_intr_clear); + dmac_write(host->dma.io_port, MASKREG, MASK_ON); + dmac_clearintr(host->dma.io_intr_clear); #if (DEBUG & DEBUG_DMA) - DBG(host->SCpnt, acornscsi_dumpdma (host, "stop")); + DBG(host->SCpnt, acornscsi_dumpdma(host, "stop")); #endif } /* - * Function: void acornscsi_dma_setup (AS_Host *host, dmadir_t direction) + * Function: void acornscsi_dma_setup(AS_Host *host, dmadir_t direction) * Purpose : setup DMA controller for data transfer * Params : host - host to setup * direction - data transfer direction @@ -965,19 +1036,19 @@ * while we're in a DATA I/O phase */ static -void acornscsi_dma_setup (AS_Host *host, dmadir_t direction) +void acornscsi_dma_setup(AS_Host *host, dmadir_t direction) { unsigned int address, length, mode; host->dma.direction = direction; - dmac_write (host->dma.io_port, MASKREG, MASK_ON); + dmac_write(host->dma.io_port, MASKREG, MASK_ON); if (direction == DMA_OUT) { #if (DEBUG & DEBUG_NO_WRITE) if (NO_WRITE & (1 << host->SCpnt->target)) { - printk (KERN_CRIT "scsi%d.%c: I can't handle DMA_OUT!\n", - host->host->host_no, acornscsi_target (host)); + printk(KERN_CRIT "scsi%d.%c: I can't handle DMA_OUT!\n", + host->host->host_no, acornscsi_target(host)); return; } #endif @@ -988,7 +1059,7 @@ /* * Allocate some buffer space, limited to half the buffer size */ - length = min (host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2); + length = min(host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2); if (length) { host->dma.start_addr = address = host->dma.free_addr; host->dma.free_addr = (host->dma.free_addr + length) & @@ -998,27 +1069,27 @@ * Transfer data to DMA memory */ if (direction == DMA_OUT) - acornscsi_data_write (host, host->scsi.SCp.ptr, host->dma.start_addr, + acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr, length); length -= 1; - dmac_write (host->dma.io_port, TXCNTLO, length); - dmac_write (host->dma.io_port, TXCNTHI, length >> 8); - dmac_write (host->dma.io_port, TXADRLO, address); - dmac_write (host->dma.io_port, TXADRMD, address >> 8); - dmac_write (host->dma.io_port, TXADRHI, 0); - dmac_write (host->dma.io_port, MODECON, mode); - dmac_write (host->dma.io_port, MASKREG, MASK_OFF); + dmac_write(host->dma.io_port, TXCNTLO, length); + dmac_write(host->dma.io_port, TXCNTHI, length >> 8); + dmac_write(host->dma.io_port, TXADRLO, address); + dmac_write(host->dma.io_port, TXADRMD, address >> 8); + dmac_write(host->dma.io_port, TXADRHI, 0); + dmac_write(host->dma.io_port, MODECON, mode); + dmac_write(host->dma.io_port, MASKREG, MASK_OFF); #if (DEBUG & DEBUG_DMA) - DBG(host->SCpnt, acornscsi_dumpdma (host, "strt")); + DBG(host->SCpnt, acornscsi_dumpdma(host, "strt")); #endif host->dma.xfer_setup = 1; } } /* - * Function: void acornscsi_dma_cleanup (AS_Host *host) + * Function: void acornscsi_dma_cleanup(AS_Host *host) * Purpose : ensure that all DMA transfers are up-to-date & host->scsi.SCp is correct * Params : host - host to finish * Notes : This is called when a command is: @@ -1026,10 +1097,10 @@ * : This must not return until all transfers are completed. */ static -void acornscsi_dma_cleanup (AS_Host *host) +void acornscsi_dma_cleanup(AS_Host *host) { - dmac_write (host->dma.io_port, MASKREG, MASK_ON); - dmac_clearintr (host->dma.io_intr_clear); + dmac_write(host->dma.io_port, MASKREG, MASK_ON); + dmac_clearintr(host->dma.io_intr_clear); /* * Check for a pending transfer @@ -1037,7 +1108,7 @@ if (host->dma.xfer_required) { host->dma.xfer_required = 0; if (host->dma.direction == DMA_IN) - acornscsi_data_read (host, host->dma.xfer_ptr, + acornscsi_data_read(host, host->dma.xfer_ptr, host->dma.xfer_start, host->dma.xfer_length); } @@ -1056,17 +1127,17 @@ /* * Calculate number of bytes transferred from DMA. */ - transferred = dmac_address (host->dma.io_port) - host->dma.start_addr; + transferred = dmac_address(host->dma.io_port) - host->dma.start_addr; host->dma.transferred += transferred; if (host->dma.direction == DMA_IN) - acornscsi_data_read (host, host->scsi.SCp.ptr, + acornscsi_data_read(host, host->scsi.SCp.ptr, host->dma.start_addr, transferred); /* * Update SCSI pointers */ - acornscsi_data_updateptr (host, &host->scsi.SCp, transferred); + acornscsi_data_updateptr(host, &host->scsi.SCp, transferred); #if (DEBUG & DEBUG_DMA) DBG(host->SCpnt, acornscsi_dumpdma(host, "cupo")); #endif @@ -1074,7 +1145,7 @@ } /* - * Function: void acornscsi_dmacintr (AS_Host *host) + * Function: void acornscsi_dmacintr(AS_Host *host) * Purpose : handle interrupts from DMAC device * Params : host - host to process * Notes : If reading, we schedule the read to main memory & @@ -1084,21 +1155,21 @@ * : Called whenever DMAC finished it's current transfer. */ static -void acornscsi_dma_intr (AS_Host *host) +void acornscsi_dma_intr(AS_Host *host) { unsigned int address, length, transferred; #if (DEBUG & DEBUG_DMA) - DBG(host->SCpnt, acornscsi_dumpdma (host, "inti")); + DBG(host->SCpnt, acornscsi_dumpdma(host, "inti")); #endif - dmac_write (host->dma.io_port, MASKREG, MASK_ON); - dmac_clearintr (host->dma.io_intr_clear); + dmac_write(host->dma.io_port, MASKREG, MASK_ON); + dmac_clearintr(host->dma.io_intr_clear); /* * Calculate amount transferred via DMA */ - transferred = dmac_address (host->dma.io_port) - host->dma.start_addr; + transferred = dmac_address(host->dma.io_port) - host->dma.start_addr; host->dma.transferred += transferred; /* @@ -1111,12 +1182,12 @@ host->dma.xfer_required = 1; } - acornscsi_data_updateptr (host, &host->scsi.SCp, transferred); + acornscsi_data_updateptr(host, &host->scsi.SCp, transferred); /* * Allocate some buffer space, limited to half the on-board RAM size */ - length = min (host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2); + length = min(host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2); if (length) { host->dma.start_addr = address = host->dma.free_addr; host->dma.free_addr = (host->dma.free_addr + length) & @@ -1126,19 +1197,19 @@ * Transfer data to DMA memory */ if (host->dma.direction == DMA_OUT) - acornscsi_data_write (host, host->scsi.SCp.ptr, host->dma.start_addr, + acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr, length); length -= 1; - dmac_write (host->dma.io_port, TXCNTLO, length); - dmac_write (host->dma.io_port, TXCNTHI, length >> 8); - dmac_write (host->dma.io_port, TXADRLO, address); - dmac_write (host->dma.io_port, TXADRMD, address >> 8); - dmac_write (host->dma.io_port, TXADRHI, 0); - dmac_write (host->dma.io_port, MASKREG, MASK_OFF); + dmac_write(host->dma.io_port, TXCNTLO, length); + dmac_write(host->dma.io_port, TXCNTHI, length >> 8); + dmac_write(host->dma.io_port, TXADRLO, address); + dmac_write(host->dma.io_port, TXADRMD, address >> 8); + dmac_write(host->dma.io_port, TXADRHI, 0); + dmac_write(host->dma.io_port, MASKREG, MASK_OFF); #if (DEBUG & DEBUG_DMA) - DBG(host->SCpnt, acornscsi_dumpdma (host, "into")); + DBG(host->SCpnt, acornscsi_dumpdma(host, "into")); #endif } else { host->dma.xfer_setup = 0; @@ -1149,48 +1220,48 @@ * attention condition. We continue giving one byte until * the device recognises the attention. */ - if (dmac_read (host->dma.io_port, STATUS) & STATUS_RQ0) { - acornscsi_abortcmd (host, host->SCpnt->tag); + if (dmac_read(host->dma.io_port, STATUS) & STATUS_RQ0) { + acornscsi_abortcmd(host, host->SCpnt->tag); - dmac_write (host->dma.io_port, TXCNTLO, 0); - dmac_write (host->dma.io_port, TXCNTHI, 0); - dmac_write (host->dma.io_port, TXADRLO, 0); - dmac_write (host->dma.io_port, TXADRMD, 0); - dmac_write (host->dma.io_port, TXADRHI, 0); - dmac_write (host->dma.io_port, MASKREG, MASK_OFF); + dmac_write(host->dma.io_port, TXCNTLO, 0); + dmac_write(host->dma.io_port, TXCNTHI, 0); + dmac_write(host->dma.io_port, TXADRLO, 0); + dmac_write(host->dma.io_port, TXADRMD, 0); + dmac_write(host->dma.io_port, TXADRHI, 0); + dmac_write(host->dma.io_port, MASKREG, MASK_OFF); } #endif } } /* - * Function: void acornscsi_dma_xfer (AS_Host *host) + * Function: void acornscsi_dma_xfer(AS_Host *host) * Purpose : transfer data between AcornSCSI and memory * Params : host - host to process */ static -void acornscsi_dma_xfer (AS_Host *host) +void acornscsi_dma_xfer(AS_Host *host) { host->dma.xfer_required = 0; if (host->dma.direction == DMA_IN) - acornscsi_data_read (host, host->dma.xfer_ptr, + acornscsi_data_read(host, host->dma.xfer_ptr, host->dma.xfer_start, host->dma.xfer_length); } /* - * Function: void acornscsi_dma_adjust (AS_Host *host) + * Function: void acornscsi_dma_adjust(AS_Host *host) * Purpose : adjust DMA pointers & count for bytes transfered to * SBIC but not SCSI bus. * Params : host - host to adjust DMA count for */ static -void acornscsi_dma_adjust (AS_Host *host) +void acornscsi_dma_adjust(AS_Host *host) { if (host->dma.xfer_setup) { signed long transferred; #if (DEBUG & (DEBUG_DMA|DEBUG_WRITE)) - DBG(host->SCpnt, acornscsi_dumpdma (host, "adji")); + DBG(host->SCpnt, acornscsi_dumpdma(host, "adji")); #endif /* * Calculate correct DMA address - DMA is ahead of SCSI bus while @@ -1205,17 +1276,17 @@ */ transferred = host->scsi.SCp.scsi_xferred - host->dma.transferred; if (transferred < 0) - printk ("scsi%d.%c: Ack! DMA write correction %ld < 0!\n", - host->host->host_no, acornscsi_target (host), transferred); + printk("scsi%d.%c: Ack! DMA write correction %ld < 0!\n", + host->host->host_no, acornscsi_target(host), transferred); else if (transferred == 0) host->dma.xfer_setup = 0; else { transferred += host->dma.start_addr; - dmac_write (host->dma.io_port, TXADRLO, transferred); - dmac_write (host->dma.io_port, TXADRMD, transferred >> 8); - dmac_write (host->dma.io_port, TXADRHI, transferred >> 16); + dmac_write(host->dma.io_port, TXADRLO, transferred); + dmac_write(host->dma.io_port, TXADRMD, transferred >> 8); + dmac_write(host->dma.io_port, TXADRHI, transferred >> 16); #if (DEBUG & (DEBUG_DMA|DEBUG_WRITE)) - DBG(host->SCpnt, acornscsi_dumpdma (host, "adjo")); + DBG(host->SCpnt, acornscsi_dumpdma(host, "adjo")); #endif } } @@ -1225,66 +1296,88 @@ /* ========================================================================================= * Data I/O */ +static int +acornscsi_write_pio(AS_Host *host, char *bytes, int *ptr, int len, unsigned int max_timeout) +{ + unsigned int asr, timeout = max_timeout; + int my_ptr = *ptr; + + while (my_ptr < len) { + asr = sbic_arm_read(host->scsi.io_port, ASR); + + if (asr & ASR_DBR) { + timeout = max_timeout; + + sbic_arm_write(host->scsi.io_port, DATA, bytes[my_ptr++]); + } else if (asr & ASR_INT) + break; + else if (--timeout == 0) + break; + udelay(1); + } + + *ptr = my_ptr; + + return (timeout == 0) ? -1 : 0; +} + /* - * Function: void acornscsi_sendcommand (AS_Host *host) + * Function: void acornscsi_sendcommand(AS_Host *host) * Purpose : send a command to a target * Params : host - host which is connected to target */ -static -void acornscsi_sendcommand (AS_Host *host) +static void +acornscsi_sendcommand(AS_Host *host) { Scsi_Cmnd *SCpnt = host->SCpnt; - unsigned int asr; - unsigned char *cmdptr, *cmdend; - sbic_arm_write (host->scsi.io_port, TRANSCNTH, 0); - sbic_arm_writenext (host->scsi.io_port, 0); - sbic_arm_writenext (host->scsi.io_port, SCpnt->cmd_len - host->scsi.SCp.sent_command); - acornscsi_sbic_issuecmd (host, CMND_XFERINFO); - - cmdptr = SCpnt->cmnd + host->scsi.SCp.sent_command; - cmdend = SCpnt->cmnd + SCpnt->cmd_len; - - while (cmdptr < cmdend) { - asr = sbic_arm_read (host->scsi.io_port, ASR); - if (asr & ASR_DBR) - sbic_arm_write (host->scsi.io_port, DATA, *cmdptr++); - else if (asr & ASR_INT) - break; - } - if (cmdptr >= cmdend) - host->scsi.SCp.sent_command = cmdptr - SCpnt->cmnd; + sbic_arm_write(host->scsi.io_port, TRANSCNTH, 0); + sbic_arm_writenext(host->scsi.io_port, 0); + sbic_arm_writenext(host->scsi.io_port, SCpnt->cmd_len - host->scsi.SCp.sent_command); + + acornscsi_sbic_issuecmd(host, CMND_XFERINFO); + + if (acornscsi_write_pio(host, SCpnt->cmnd, + (int *)&host->scsi.SCp.sent_command, SCpnt->cmd_len, 1000000)) + printk("scsi%d: timeout while sending command\n", host->host->host_no); + host->scsi.phase = PHASE_COMMAND; } static -void acornscsi_sendmessage (AS_Host *host) +void acornscsi_sendmessage(AS_Host *host) { - unsigned int message_length = msgqueue_msglength (&host->scsi.msgs); - int msgnr; + unsigned int message_length = msgqueue_msglength(&host->scsi.msgs); + unsigned int msgnr; struct message *msg; #if (DEBUG & DEBUG_MESSAGES) - printk ("scsi%d.%c: sending message ", - host->host->host_no, acornscsi_target (host)); + printk("scsi%d.%c: sending message ", + host->host->host_no, acornscsi_target(host)); #endif switch (message_length) { case 0: - acornscsi_sbic_issuecmd (host, CMND_XFERINFO | CMND_SBT); - while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_DBR) == 0); - sbic_arm_write (host->scsi.io_port, DATA, NOP); + acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT); + + acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 1"); + + sbic_arm_write(host->scsi.io_port, DATA, NOP); + host->scsi.last_message = NOP; #if (DEBUG & DEBUG_MESSAGES) - printk ("NOP"); + printk("NOP"); #endif break; case 1: - acornscsi_sbic_issuecmd (host, CMND_XFERINFO | CMND_SBT); + acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT); msg = msgqueue_getmsg(&host->scsi.msgs, 0); - while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_DBR) == 0); - sbic_arm_write (host->scsi.io_port, DATA, msg->msg[0]); + + acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 2"); + + sbic_arm_write(host->scsi.io_port, DATA, msg->msg[0]); + host->scsi.last_message = msg->msg[0]; #if (DEBUG & DEBUG_MESSAGES) print_msg(msg->msg); @@ -1300,86 +1393,85 @@ * initiator. This provides an interlock so that the * initiator can determine which message byte is rejected. */ - sbic_arm_write (host->scsi.io_port, TRANSCNTH, 0); - sbic_arm_writenext (host->scsi.io_port, 0); - sbic_arm_writenext (host->scsi.io_port, message_length); - acornscsi_sbic_issuecmd (host, CMND_XFERINFO); + sbic_arm_write(host->scsi.io_port, TRANSCNTH, 0); + sbic_arm_writenext(host->scsi.io_port, 0); + sbic_arm_writenext(host->scsi.io_port, message_length); + acornscsi_sbic_issuecmd(host, CMND_XFERINFO); msgnr = 0; while ((msg = msgqueue_getmsg(&host->scsi.msgs, msgnr++)) != NULL) { - unsigned int asr, i; + unsigned int i; #if (DEBUG & DEBUG_MESSAGES) - print_msg (msg); + print_msg(msg); #endif - for (i = 0; i < msg->length;) { - asr = sbic_arm_read (host->scsi.io_port, ASR); - if (asr & ASR_DBR) - sbic_arm_write (host->scsi.io_port, DATA, msg->msg[i++]); - if (asr & ASR_INT) - break; - } + i = 0; + if (acornscsi_write_pio(host, msg->msg, &i, msg->length, 1000000)) + printk("scsi%d: timeout while sending message\n", host->host->host_no); + host->scsi.last_message = msg->msg[0]; if (msg->msg[0] == EXTENDED_MESSAGE) host->scsi.last_message |= msg->msg[2] << 8; - if (asr & ASR_INT) + + if (i != msg->length) break; } break; } #if (DEBUG & DEBUG_MESSAGES) - printk ("\n"); + printk("\n"); #endif } /* - * Function: void acornscsi_readstatusbyte (AS_Host *host) + * Function: void acornscsi_readstatusbyte(AS_Host *host) * Purpose : Read status byte from connected target * Params : host - host connected to target */ static -void acornscsi_readstatusbyte (AS_Host *host) +void acornscsi_readstatusbyte(AS_Host *host) { - acornscsi_sbic_issuecmd (host, CMND_XFERINFO|CMND_SBT); - while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_DBR) == 0); - - host->scsi.SCp.Status = sbic_arm_read (host->scsi.io_port, DATA); + acornscsi_sbic_issuecmd(host, CMND_XFERINFO|CMND_SBT); + acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "reading status byte"); + host->scsi.SCp.Status = sbic_arm_read(host->scsi.io_port, DATA); } /* - * Function: unsigned char acornscsi_readmessagebyte (AS_Host *host) + * Function: unsigned char acornscsi_readmessagebyte(AS_Host *host) * Purpose : Read one message byte from connected target * Params : host - host connected to target */ static -unsigned char acornscsi_readmessagebyte (AS_Host *host) +unsigned char acornscsi_readmessagebyte(AS_Host *host) { unsigned char message; - acornscsi_sbic_issuecmd (host, CMND_XFERINFO | CMND_SBT); - while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_DBR) == 0); + acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT); - message = sbic_arm_read (host->scsi.io_port, DATA); + acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "for message byte"); + + message = sbic_arm_read(host->scsi.io_port, DATA); /* wait for MSGIN-XFER-PAUSED */ - while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_INT) == 0); - sbic_arm_read (host->scsi.io_port, SSR); + acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after message byte"); + + sbic_arm_read(host->scsi.io_port, SSR); return message; } /* - * Function: void acornscsi_message (AS_Host *host) + * Function: void acornscsi_message(AS_Host *host) * Purpose : Read complete message from connected target & action message * Params : host - host connected to target */ static -void acornscsi_message (AS_Host *host) +void acornscsi_message(AS_Host *host) { unsigned char message[16]; unsigned int msgidx = 0, msglen = 1; do { - message[msgidx] = acornscsi_readmessagebyte (host); + message[msgidx] = acornscsi_readmessagebyte(host); switch (msgidx) { case 0: @@ -1395,17 +1487,17 @@ } msgidx += 1; if (msgidx < msglen) { - acornscsi_sbic_issuecmd (host, CMND_NEGATEACK); + acornscsi_sbic_issuecmd(host, CMND_NEGATEACK); /* wait for next msg-in */ - while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_INT) == 0); - sbic_arm_read (host->scsi.io_port, SSR); + acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after negate ack"); + sbic_arm_read(host->scsi.io_port, SSR); } } while (msgidx < msglen); #if (DEBUG & DEBUG_MESSAGES) printk("scsi%d.%c: message in: ", - host->host->host_no, acornscsi_target (host)); + host->host->host_no, acornscsi_target(host)); print_msg(message); printk("\n"); #endif @@ -1419,7 +1511,7 @@ */ if (message[0] == SIMPLE_QUEUE_TAG) host->scsi.reconnected.tag = message[1]; - if (acornscsi_reconnect_finish (host)) + if (acornscsi_reconnect_finish(host)) host->scsi.phase = PHASE_MSGIN; } @@ -1429,7 +1521,7 @@ case COMMAND_COMPLETE: if (host->scsi.phase != PHASE_STATUSIN) { printk(KERN_ERR "scsi%d.%c: command complete following non-status in phase?\n", - host->host->host_no, acornscsi_target (host)); + host->host->host_no, acornscsi_target(host)); acornscsi_dumplog(host, host->SCpnt->target); } host->scsi.phase = PHASE_DONE; @@ -1443,7 +1535,7 @@ * direct the initiator to copy the active data pointer to * the saved data pointer for the current I/O process. */ - acornscsi_dma_cleanup (host); + acornscsi_dma_cleanup(host); host->SCpnt->SCp = host->scsi.SCp; host->SCpnt->SCp.sent_command = 0; host->scsi.phase = PHASE_MSGIN; @@ -1459,7 +1551,7 @@ * status pointers shall be restored to the beginning of * the present command and status areas.' */ - acornscsi_dma_cleanup (host); + acornscsi_dma_cleanup(host); host->scsi.SCp = host->SCpnt->SCp; host->scsi.phase = PHASE_MSGIN; break; @@ -1474,7 +1566,7 @@ * message. When reconnection is completed, the most recent * saved pointer values are restored.' */ - acornscsi_dma_cleanup (host); + acornscsi_dma_cleanup(host); host->scsi.phase = PHASE_DISCONNECT; break; @@ -1493,8 +1585,8 @@ /* * If we have any messages waiting to go out, then assert ATN now */ - if (msgqueue_msglength (&host->scsi.msgs)) - acornscsi_sbic_issuecmd (host, CMND_ASSERTATN); + if (msgqueue_msglength(&host->scsi.msgs)) + acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); switch (host->scsi.last_message) { #ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE @@ -1507,21 +1599,21 @@ * message is received, it shall respond with a MESSAGE REJECT * message and accept the I/O process as if it were untagged. */ - printk (KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n", - host->host->host_no, acornscsi_target (host)); + printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n", + host->host->host_no, acornscsi_target(host)); host->SCpnt->device->tagged_queue = 0; - set_bit (host->SCpnt->target * 8 + host->SCpnt->lun, &host->busyluns); + set_bit(host->SCpnt->target * 8 + host->SCpnt->lun, &host->busyluns); break; #endif case EXTENDED_MESSAGE | (EXTENDED_SDTR << 8): /* * Target can't handle synchronous transfers */ - printk (KERN_NOTICE "scsi%d.%c: Using asynchronous transfer\n", - host->host->host_no, acornscsi_target (host)); + printk(KERN_NOTICE "scsi%d.%c: Using asynchronous transfer\n", + host->host->host_no, acornscsi_target(host)); host->device[host->SCpnt->target].sync_xfer = SYNCHTRANSFER_2DBA; host->device[host->SCpnt->target].sync_state = SYNC_ASYNCHRONOUS; - sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer); + sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer); break; default: @@ -1535,8 +1627,8 @@ case SIMPLE_QUEUE_TAG: /* tag queue reconnect... message[1] = queue tag. Print something to indicate something happened! */ - printk ("scsi%d.%c: reconnect queue tag %02X\n", - host->host->host_no, acornscsi_target (host), + printk("scsi%d.%c: reconnect queue tag %02X\n", + host->host->host_no, acornscsi_target(host), message[1]); break; @@ -1552,26 +1644,26 @@ * and the target retries fail, then we fallback to asynchronous mode */ host->device[host->SCpnt->target].sync_state = SYNC_COMPLETED; - printk (KERN_NOTICE "scsi%d.%c: Using synchronous transfer, offset %d, %d ns\n", + printk(KERN_NOTICE "scsi%d.%c: Using synchronous transfer, offset %d, %d ns\n", host->host->host_no, acornscsi_target(host), message[4], message[3] * 4); host->device[host->SCpnt->target].sync_xfer = - calc_sync_xfer (message[3] * 4, message[4]); + calc_sync_xfer(message[3] * 4, message[4]); } else { unsigned char period, length; /* * Target requested synchronous transfers. The agreement is only * to be in operation AFTER the target leaves message out phase. */ - acornscsi_sbic_issuecmd (host, CMND_ASSERTATN); - period = max (message[3], sdtr_period / 4); - length = min (message[4], sdtr_size); - msgqueue_addmsg (&host->scsi.msgs, 5, EXTENDED_MESSAGE, 3, + acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); + period = max(message[3], sdtr_period / 4); + length = min(message[4], sdtr_size); + msgqueue_addmsg(&host->scsi.msgs, 5, EXTENDED_MESSAGE, 3, EXTENDED_SDTR, period, length); host->device[host->SCpnt->target].sync_xfer = - calc_sync_xfer (period * 4, length); + calc_sync_xfer(period * 4, length); } - sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer); + sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer); break; #else /* We do not accept synchronous transfers. Respond with a @@ -1584,9 +1676,9 @@ * to a wide data transfer request. */ default: - acornscsi_sbic_issuecmd (host, CMND_ASSERTATN); - msgqueue_flush (&host->scsi.msgs); - msgqueue_addmsg (&host->scsi.msgs, 1, MESSAGE_REJECT); + acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); + msgqueue_flush(&host->scsi.msgs); + msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT); break; } break; @@ -1607,19 +1699,19 @@ * if there are more linked commands available. */ if (!host->SCpnt->next_link) { - printk (KERN_WARNING "scsi%d.%c: lun %d tag %d linked command complete, but no next_link\n", - instance->host_no, acornscsi_target (host), host->SCpnt->tag); - acornscsi_sbic_issuecmd (host, CMND_ASSERTATN); - msgqueue_addmsg (&host->scsi.msgs, 1, ABORT); + printk(KERN_WARNING "scsi%d.%c: lun %d tag %d linked command complete, but no next_link\n", + instance->host_no, acornscsi_target(host), host->SCpnt->tag); + acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); + msgqueue_addmsg(&host->scsi.msgs, 1, ABORT); } else { Scsi_Cmnd *SCpnt = host->SCpnt; - acornscsi_dma_cleanup (host); + acornscsi_dma_cleanup(host); host->SCpnt = host->SCpnt->next_link; host->SCpnt->tag = SCpnt->tag; SCpnt->result = DID_OK | host->scsi.SCp.Message << 8 | host->Scsi.SCp.Status; - SCpnt->done (SCpnt); + SCpnt->done(SCpnt); /* initialise host->SCpnt->SCp */ } @@ -1628,42 +1720,42 @@ #endif default: /* reject message */ - printk (KERN_ERR "scsi%d.%c: unrecognised message %02X, rejecting\n", - host->host->host_no, acornscsi_target (host), + printk(KERN_ERR "scsi%d.%c: unrecognised message %02X, rejecting\n", + host->host->host_no, acornscsi_target(host), message[0]); - acornscsi_sbic_issuecmd (host, CMND_ASSERTATN); - msgqueue_flush (&host->scsi.msgs); - msgqueue_addmsg (&host->scsi.msgs, 1, MESSAGE_REJECT); + acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); + msgqueue_flush(&host->scsi.msgs); + msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT); host->scsi.phase = PHASE_MSGIN; break; } - acornscsi_sbic_issuecmd (host, CMND_NEGATEACK); + acornscsi_sbic_issuecmd(host, CMND_NEGATEACK); } /* - * Function: int acornscsi_buildmessages (AS_Host *host) + * Function: int acornscsi_buildmessages(AS_Host *host) * Purpose : build the connection messages for a host * Params : host - host to add messages to */ static -void acornscsi_buildmessages (AS_Host *host) +void acornscsi_buildmessages(AS_Host *host) { #if 0 /* does the device need resetting? */ if (cmd_reset) { - msgqueue_addmsg (&host->scsi.msgs, 1, BUS_DEVICE_RESET); + msgqueue_addmsg(&host->scsi.msgs, 1, BUS_DEVICE_RESET); return; } #endif - msgqueue_addmsg (&host->scsi.msgs, 1, + msgqueue_addmsg(&host->scsi.msgs, 1, IDENTIFY(host->device[host->SCpnt->target].disconnect_ok, host->SCpnt->lun)); #if 0 /* does the device need the current command aborted */ if (cmd_aborted) { - acornscsi_abortcmd (host->SCpnt->tag); + acornscsi_abortcmd(host->SCpnt->tag); return; } #endif @@ -1678,14 +1770,14 @@ tag_type = HEAD_OF_QUEUE_TAG; else tag_type = SIMPLE_QUEUE_TAG; - msgqueue_addmsg (&host->scsi.msgs, 2, tag_type, host->SCpnt->tag); + msgqueue_addmsg(&host->scsi.msgs, 2, tag_type, host->SCpnt->tag); } #endif #ifdef CONFIG_SCSI_ACORNSCSI_SYNC if (host->device[host->SCpnt->target].sync_state == SYNC_NEGOCIATE) { host->device[host->SCpnt->target].sync_state = SYNC_SENT_REQUEST; - msgqueue_addmsg (&host->scsi.msgs, 5, + msgqueue_addmsg(&host->scsi.msgs, 5, EXTENDED_MESSAGE, 3, EXTENDED_SDTR, sdtr_period / 4, sdtr_size); } @@ -1693,29 +1785,29 @@ } /* - * Function: int acornscsi_starttransfer (AS_Host *host) + * Function: int acornscsi_starttransfer(AS_Host *host) * Purpose : transfer data to/from connected target * Params : host - host to which target is connected * Returns : 0 if failure */ static -int acornscsi_starttransfer (AS_Host *host) +int acornscsi_starttransfer(AS_Host *host) { int residual; if (!host->scsi.SCp.ptr /*&& host->scsi.SCp.this_residual*/) { - printk (KERN_ERR "scsi%d.%c: null buffer passed to acornscsi_starttransfer\n", - host->host->host_no, acornscsi_target (host)); + printk(KERN_ERR "scsi%d.%c: null buffer passed to acornscsi_starttransfer\n", + host->host->host_no, acornscsi_target(host)); return 0; } residual = host->SCpnt->request_bufflen - host->scsi.SCp.scsi_xferred; - sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer); - sbic_arm_writenext (host->scsi.io_port, residual >> 16); - sbic_arm_writenext (host->scsi.io_port, residual >> 8); - sbic_arm_writenext (host->scsi.io_port, residual); - acornscsi_sbic_issuecmd (host, CMND_XFERINFO); + sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer); + sbic_arm_writenext(host->scsi.io_port, residual >> 16); + sbic_arm_writenext(host->scsi.io_port, residual >> 8); + sbic_arm_writenext(host->scsi.io_port, residual); + acornscsi_sbic_issuecmd(host, CMND_XFERINFO); return 1; } @@ -1723,7 +1815,7 @@ * Connection & Disconnection */ /* - * Function : acornscsi_reconnect (AS_Host *host) + * Function : acornscsi_reconnect(AS_Host *host) * Purpose : reconnect a previously disconnected command * Params : host - host specific data * Remarks : SCSI spec says: @@ -1731,27 +1823,27 @@ * of saved pointers upon reconnection of the I/O process' */ static -int acornscsi_reconnect (AS_Host *host) +int acornscsi_reconnect(AS_Host *host) { unsigned int target, lun, ok = 0; - target = sbic_arm_read (host->scsi.io_port, SOURCEID); + target = sbic_arm_read(host->scsi.io_port, SOURCEID); if (!(target & 8)) - printk (KERN_ERR "scsi%d: invalid source id after reselection " + printk(KERN_ERR "scsi%d: invalid source id after reselection " "- device fault?\n", host->host->host_no); target &= 7; if (host->SCpnt && !host->scsi.disconnectable) { - printk (KERN_ERR "scsi%d.%d: reconnected while command in " + printk(KERN_ERR "scsi%d.%d: reconnected while command in " "progress to target %d?\n", host->host->host_no, target, host->SCpnt->target); host->SCpnt = NULL; } - lun = sbic_arm_read (host->scsi.io_port, DATA) & 7; + lun = sbic_arm_read(host->scsi.io_port, DATA) & 7; host->scsi.reconnected.target = target; host->scsi.reconnected.lun = lun; @@ -1761,7 +1853,7 @@ host->SCpnt->target == target && host->SCpnt->lun == lun) ok = 1; - if (!ok && queue_probetgtlun (&host->queues.disconnected, target, lun)) + if (!ok && queue_probetgtlun(&host->queues.disconnected, target, lun)) ok = 1; ADD_STATUS(target, 0x81, host->scsi.phase, 0); @@ -1770,26 +1862,28 @@ host->scsi.phase = PHASE_RECONNECTED; } else { /* this doesn't seem to work */ - printk (KERN_ERR "scsi%d.%c: reselected with no command " + printk(KERN_ERR "scsi%d.%c: reselected with no command " "to reconnect with\n", host->host->host_no, '0' + target); - acornscsi_dumplog (host, target); - acornscsi_sbic_issuecmd (host, CMND_ASSERTATN); - msgqueue_addmsg (&host->scsi.msgs, 1, ABORT); - host->scsi.phase = PHASE_ABORTED; + acornscsi_dumplog(host, target); + acornscsi_abortcmd(host, 0); + if (host->SCpnt) { + queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt); + host->SCpnt = NULL; + } } - acornscsi_sbic_issuecmd (host, CMND_NEGATEACK); + acornscsi_sbic_issuecmd(host, CMND_NEGATEACK); return !ok; } /* - * Function: int acornscsi_reconect_finish (AS_Host *host) + * Function: int acornscsi_reconect_finish(AS_Host *host) * Purpose : finish reconnecting a command * Params : host - host to complete * Returns : 0 if failed */ static -int acornscsi_reconnect_finish (AS_Host *host) +int acornscsi_reconnect_finish(AS_Host *host) { if (host->scsi.disconnectable && host->SCpnt) { host->scsi.disconnectable = 0; @@ -1797,45 +1891,44 @@ host->SCpnt->lun == host->scsi.reconnected.lun && host->SCpnt->tag == host->scsi.reconnected.tag) { #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) - DBG(host->SCpnt, printk ("scsi%d.%c: reconnected", - host->host->host_no, acornscsi_target (host))); + DBG(host->SCpnt, printk("scsi%d.%c: reconnected", + host->host->host_no, acornscsi_target(host))); #endif } else { - queue_add_cmd_tail (&host->queues.disconnected, host->SCpnt); + queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt); #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) - DBG(host->SCpnt, printk ("scsi%d.%c: had to move command " + DBG(host->SCpnt, printk("scsi%d.%c: had to move command " "to disconnected queue\n", - host->host->host_no, acornscsi_target (host))); + host->host->host_no, acornscsi_target(host))); #endif host->SCpnt = NULL; } } if (!host->SCpnt) { - host->SCpnt = queue_remove_tgtluntag (&host->queues.disconnected, + host->SCpnt = queue_remove_tgtluntag(&host->queues.disconnected, host->scsi.reconnected.target, host->scsi.reconnected.lun, host->scsi.reconnected.tag); #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) - DBG(host->SCpnt, printk ("scsi%d.%c: had to get command", - host->host->host_no, acornscsi_target (host))); + DBG(host->SCpnt, printk("scsi%d.%c: had to get command", + host->host->host_no, acornscsi_target(host))); #endif } - if (!host->SCpnt) { - acornscsi_abortcmd (host, host->scsi.reconnected.tag); - host->scsi.phase = PHASE_ABORTED; - } else { + if (!host->SCpnt) + acornscsi_abortcmd(host, host->scsi.reconnected.tag); + else { /* * Restore data pointer from SAVED pointers. */ host->scsi.SCp = host->SCpnt->SCp; #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) - printk (", data pointers: [%p, %X]", + printk(", data pointers: [%p, %X]", host->scsi.SCp.ptr, host->scsi.SCp.this_residual); #endif } #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) - printk ("\n"); + printk("\n"); #endif host->dma.transferred = host->scsi.SCp.scsi_xferred; @@ -1844,47 +1937,48 @@ } /* - * Function: void acornscsi_disconnect_unexpected (AS_Host *host) + * Function: void acornscsi_disconnect_unexpected(AS_Host *host) * Purpose : handle an unexpected disconnect * Params : host - host on which disconnect occurred */ static -void acornscsi_disconnect_unexpected (AS_Host *host) +void acornscsi_disconnect_unexpected(AS_Host *host) { - printk (KERN_ERR "scsi%d.%c: unexpected disconnect\n", - host->host->host_no, acornscsi_target (host)); + printk(KERN_ERR "scsi%d.%c: unexpected disconnect\n", + host->host->host_no, acornscsi_target(host)); #if (DEBUG & DEBUG_ABORT) - acornscsi_dumplog (host, 8); + acornscsi_dumplog(host, 8); #endif - acornscsi_done (host, &host->SCpnt, DID_ABORT); + acornscsi_done(host, &host->SCpnt, DID_ERROR); } /* - * Function: void acornscsi_abortcmd (AS_host *host, unsigned char tag) + * Function: void acornscsi_abortcmd(AS_host *host, unsigned char tag) * Purpose : abort a currently executing command * Params : host - host with connected command to abort * tag - tag to abort */ static -void acornscsi_abortcmd (AS_Host *host, unsigned char tag) +void acornscsi_abortcmd(AS_Host *host, unsigned char tag) { - sbic_arm_write (host->scsi.io_port, CMND, CMND_ASSERTATN); + host->scsi.phase = PHASE_ABORTED; + sbic_arm_write(host->scsi.io_port, CMND, CMND_ASSERTATN); - msgqueue_flush (&host->scsi.msgs); + msgqueue_flush(&host->scsi.msgs); #ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE if (tag) - msgqueue_addmsg (&host->scsi.msgs, 2, ABORT_TAG, tag); + msgqueue_addmsg(&host->scsi.msgs, 2, ABORT_TAG, tag); else #endif - msgqueue_addmsg (&host->scsi.msgs, 1, ABORT); + msgqueue_addmsg(&host->scsi.msgs, 1, ABORT); } /* ========================================================================================== * Interrupt routines. */ /* - * Function: int acornscsi_sbicintr (AS_Host *host) + * Function: int acornscsi_sbicintr(AS_Host *host) * Purpose : handle interrupts from SCSI device * Params : host - host to process * Returns : INTR_PROCESS if expecting another SBIC interrupt @@ -1892,15 +1986,15 @@ * INTR_NEXT_COMMAND if we have finished processing the command */ static -intr_ret_t acornscsi_sbicintr (AS_Host *host, int in_irq) +intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq) { unsigned int asr, ssr; - asr = sbic_arm_read (host->scsi.io_port, ASR); + asr = sbic_arm_read(host->scsi.io_port, ASR); if (!(asr & ASR_INT)) return INTR_IDLE; - ssr = sbic_arm_read (host->scsi.io_port, SSR); + ssr = sbic_arm_read(host->scsi.io_port, SSR); #if (DEBUG & DEBUG_PHASES) print_sbic_status(asr, ssr, host->scsi.phase); @@ -1913,23 +2007,23 @@ switch (ssr) { case 0x00: /* reset state - not advanced */ - printk (KERN_ERR "scsi%d: reset in standard mode but wanted advanced mode.\n", + printk(KERN_ERR "scsi%d: reset in standard mode but wanted advanced mode.\n", host->host->host_no); /* setup sbic - WD33C93A */ - sbic_arm_write (host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id); - sbic_arm_write (host->scsi.io_port, CMND, CMND_RESET); + sbic_arm_write(host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id); + sbic_arm_write(host->scsi.io_port, CMND, CMND_RESET); return INTR_IDLE; case 0x01: /* reset state - advanced */ - sbic_arm_write (host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI); - sbic_arm_write (host->scsi.io_port, TIMEOUT, TIMEOUT_TIME); - sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA); - sbic_arm_write (host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP); - msgqueue_flush (&host->scsi.msgs); + sbic_arm_write(host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI); + sbic_arm_write(host->scsi.io_port, TIMEOUT, TIMEOUT_TIME); + sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA); + sbic_arm_write(host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP); + msgqueue_flush(&host->scsi.msgs); return INTR_IDLE; case 0x41: /* unexpected disconnect aborted command */ - acornscsi_disconnect_unexpected (host); + acornscsi_disconnect_unexpected(host); return INTR_NEXT_COMMAND; } @@ -1939,35 +2033,35 @@ case 0x11: /* -> PHASE_CONNECTED */ /* BUS FREE -> SELECTION */ host->scsi.phase = PHASE_CONNECTED; - msgqueue_flush (&host->scsi.msgs); + msgqueue_flush(&host->scsi.msgs); host->dma.transferred = host->scsi.SCp.scsi_xferred; /* 33C93 gives next interrupt indicating bus phase */ - asr = sbic_arm_read (host->scsi.io_port, ASR); + asr = sbic_arm_read(host->scsi.io_port, ASR); if (!(asr & ASR_INT)) break; - ssr = sbic_arm_read (host->scsi.io_port, SSR); + ssr = sbic_arm_read(host->scsi.io_port, SSR); ADD_STATUS(8, ssr, host->scsi.phase, 1); ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, 1); goto connected; case 0x42: /* select timed out */ /* -> PHASE_IDLE */ - acornscsi_done (host, &host->SCpnt, DID_NO_CONNECT); + acornscsi_done(host, &host->SCpnt, DID_NO_CONNECT); return INTR_NEXT_COMMAND; case 0x81: /* -> PHASE_RECONNECTED or PHASE_ABORTED */ /* BUS FREE -> RESELECTION */ host->origSCpnt = host->SCpnt; host->SCpnt = NULL; - msgqueue_flush (&host->scsi.msgs); - acornscsi_reconnect (host); + msgqueue_flush(&host->scsi.msgs); + acornscsi_reconnect(host); break; default: - printk (KERN_ERR "scsi%d.%c: PHASE_CONNECTING, SSR %02X?\n", - host->host->host_no, acornscsi_target (host), ssr); - acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8); - acornscsi_abortcmd (host, host->SCpnt->tag); + printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTING, SSR %02X?\n", + host->host->host_no, acornscsi_target(host), ssr); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_abortcmd(host, host->SCpnt->tag); } return INTR_PROCESSING; @@ -1977,12 +2071,12 @@ #ifdef NONSTANDARD case 0x8a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */ /* SELECTION -> COMMAND */ - acornscsi_sendcommand (host); + acornscsi_sendcommand(host); break; case 0x8b: /* -> PHASE_STATUS */ /* SELECTION -> STATUS */ - acornscsi_readstatusbyte (host); + acornscsi_readstatusbyte(host); host->scsi.phase = PHASE_STATUSIN; break; #endif @@ -1990,55 +2084,57 @@ case 0x8e: /* -> PHASE_MSGOUT */ /* SELECTION ->MESSAGE OUT */ host->scsi.phase = PHASE_MSGOUT; - acornscsi_buildmessages (host); - acornscsi_sendmessage (host); + acornscsi_buildmessages(host); + acornscsi_sendmessage(host); break; /* these should not happen */ case 0x85: /* target disconnected */ - acornscsi_done (host, &host->SCpnt, DID_ERROR); + acornscsi_done(host, &host->SCpnt, DID_ERROR); break; default: - printk (KERN_ERR "scsi%d.%c: PHASE_CONNECTED, SSR %02X?\n", - host->host->host_no, acornscsi_target (host), ssr); - acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8); - acornscsi_abortcmd (host, host->SCpnt->tag); + printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTED, SSR %02X?\n", + host->host->host_no, acornscsi_target(host), ssr); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_abortcmd(host, host->SCpnt->tag); } return INTR_PROCESSING; case PHASE_MSGOUT: /* STATE: connected & sent IDENTIFY message */ /* - * SCSI standard says th at a MESSAGE OUT phases can be followed by a DATA phase + * SCSI standard says that MESSAGE OUT phases can be followed by a + * DATA phase, STATUS phase, MESSAGE IN phase or COMMAND phase */ switch (ssr) { - case 0x8a: + case 0x8a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */ case 0x1a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */ /* MESSAGE OUT -> COMMAND */ - acornscsi_sendcommand (host); + acornscsi_sendcommand(host); break; + case 0x8b: /* -> PHASE_STATUS */ case 0x1b: /* -> PHASE_STATUS */ /* MESSAGE OUT -> STATUS */ - acornscsi_readstatusbyte (host); + acornscsi_readstatusbyte(host); host->scsi.phase = PHASE_STATUSIN; break; case 0x8e: /* -> PHASE_MSGOUT */ /* MESSAGE_OUT(MESSAGE_IN) ->MESSAGE OUT */ - acornscsi_sendmessage (host); + acornscsi_sendmessage(host); break; - case 0x4f: + case 0x4f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */ case 0x1f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */ /* MESSAGE OUT -> MESSAGE IN */ - acornscsi_message (host); + acornscsi_message(host); break; default: - printk (KERN_ERR "scsi%d.%c: PHASE_MSGOUT, SSR %02X?\n", - host->host->host_no, acornscsi_target (host), ssr); - acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8); + printk(KERN_ERR "scsi%d.%c: PHASE_MSGOUT, SSR %02X?\n", + host->host->host_no, acornscsi_target(host), ssr); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); } return INTR_PROCESSING; @@ -2047,43 +2143,43 @@ case 0x18: /* -> PHASE_DATAOUT */ /* COMMAND -> DATA OUT */ if (host->scsi.SCp.sent_command != host->SCpnt->cmd_len) - acornscsi_abortcmd (host, host->SCpnt->tag); - acornscsi_dma_setup (host, DMA_OUT); - if (!acornscsi_starttransfer (host)) - acornscsi_abortcmd (host, host->SCpnt->tag); + acornscsi_abortcmd(host, host->SCpnt->tag); + acornscsi_dma_setup(host, DMA_OUT); + if (!acornscsi_starttransfer(host)) + acornscsi_abortcmd(host, host->SCpnt->tag); host->scsi.phase = PHASE_DATAOUT; return INTR_IDLE; case 0x19: /* -> PHASE_DATAIN */ /* COMMAND -> DATA IN */ if (host->scsi.SCp.sent_command != host->SCpnt->cmd_len) - acornscsi_abortcmd (host, host->SCpnt->tag); - acornscsi_dma_setup (host, DMA_IN); - if (!acornscsi_starttransfer (host)) - acornscsi_abortcmd (host, host->SCpnt->tag); + acornscsi_abortcmd(host, host->SCpnt->tag); + acornscsi_dma_setup(host, DMA_IN); + if (!acornscsi_starttransfer(host)) + acornscsi_abortcmd(host, host->SCpnt->tag); host->scsi.phase = PHASE_DATAIN; return INTR_IDLE; case 0x1b: /* -> PHASE_STATUS */ /* COMMAND -> STATUS */ - acornscsi_readstatusbyte (host); + acornscsi_readstatusbyte(host); host->scsi.phase = PHASE_STATUSIN; break; case 0x1e: /* -> PHASE_MSGOUT */ /* COMMAND -> MESSAGE OUT */ - acornscsi_sendmessage (host); + acornscsi_sendmessage(host); break; case 0x1f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */ /* COMMAND -> MESSAGE IN */ - acornscsi_message (host); + acornscsi_message(host); break; default: - printk (KERN_ERR "scsi%d.%c: PHASE_COMMAND, SSR %02X?\n", - host->host->host_no, acornscsi_target (host), ssr); - acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8); + printk(KERN_ERR "scsi%d.%c: PHASE_COMMAND, SSR %02X?\n", + host->host->host_no, acornscsi_target(host), ssr); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); } return INTR_PROCESSING; @@ -2094,19 +2190,19 @@ host->scsi.phase = PHASE_IDLE; host->stats.disconnects += 1; } else { - printk (KERN_ERR "scsi%d.%c: PHASE_DISCONNECT, SSR %02X instead of disconnect?\n", - host->host->host_no, acornscsi_target (host), ssr); - acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8); + printk(KERN_ERR "scsi%d.%c: PHASE_DISCONNECT, SSR %02X instead of disconnect?\n", + host->host->host_no, acornscsi_target(host), ssr); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); } return INTR_NEXT_COMMAND; case PHASE_IDLE: /* STATE: disconnected */ if (ssr == 0x81) /* -> PHASE_RECONNECTED or PHASE_ABORTED */ - acornscsi_reconnect (host); + acornscsi_reconnect(host); else { - printk (KERN_ERR "scsi%d.%c: PHASE_IDLE, SSR %02X while idle?\n", - host->host->host_no, acornscsi_target (host), ssr); - acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8); + printk(KERN_ERR "scsi%d.%c: PHASE_IDLE, SSR %02X while idle?\n", + host->host->host_no, acornscsi_target(host), ssr); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); } return INTR_PROCESSING; @@ -2119,54 +2215,54 @@ * If we reconnected and we're not in MESSAGE IN phase after IDENTIFY, * reconnect I_T_L command */ - if (ssr != 0x8f && !acornscsi_reconnect_finish (host)) + if (ssr != 0x8f && !acornscsi_reconnect_finish(host)) return INTR_IDLE; ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, in_irq); switch (ssr) { case 0x88: /* data out phase */ /* -> PHASE_DATAOUT */ /* MESSAGE IN -> DATA OUT */ - acornscsi_dma_setup (host, DMA_OUT); - if (!acornscsi_starttransfer (host)) - acornscsi_abortcmd (host, host->SCpnt->tag); + acornscsi_dma_setup(host, DMA_OUT); + if (!acornscsi_starttransfer(host)) + acornscsi_abortcmd(host, host->SCpnt->tag); host->scsi.phase = PHASE_DATAOUT; return INTR_IDLE; case 0x89: /* data in phase */ /* -> PHASE_DATAIN */ /* MESSAGE IN -> DATA IN */ - acornscsi_dma_setup (host, DMA_IN); - if (!acornscsi_starttransfer (host)) - acornscsi_abortcmd (host, host->SCpnt->tag); + acornscsi_dma_setup(host, DMA_IN); + if (!acornscsi_starttransfer(host)) + acornscsi_abortcmd(host, host->SCpnt->tag); host->scsi.phase = PHASE_DATAIN; return INTR_IDLE; case 0x8a: /* command out */ /* MESSAGE IN -> COMMAND */ - acornscsi_sendcommand (host);/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */ + acornscsi_sendcommand(host);/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */ break; case 0x8b: /* status in */ /* -> PHASE_STATUSIN */ /* MESSAGE IN -> STATUS */ - acornscsi_readstatusbyte (host); + acornscsi_readstatusbyte(host); host->scsi.phase = PHASE_STATUSIN; break; case 0x8e: /* message out */ /* -> PHASE_MSGOUT */ /* MESSAGE IN -> MESSAGE OUT */ - acornscsi_sendmessage (host); + acornscsi_sendmessage(host); break; case 0x8f: /* message in */ - acornscsi_message (host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ + acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ break; default: - printk (KERN_ERR "scsi%d.%c: PHASE_RECONNECTED, SSR %02X after reconnect?\n", - host->host->host_no, acornscsi_target (host), ssr); - acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8); + printk(KERN_ERR "scsi%d.%c: PHASE_RECONNECTED, SSR %02X after reconnect?\n", + host->host->host_no, acornscsi_target(host), ssr); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); } return INTR_PROCESSING; @@ -2177,41 +2273,45 @@ */ switch (ssr) { case 0x19: /* -> PHASE_DATAIN */ - acornscsi_abortcmd (host, host->SCpnt->tag); + case 0x89: /* -> PHASE_DATAIN */ + acornscsi_abortcmd(host, host->SCpnt->tag); return INTR_IDLE; - case 0x4b: /* -> PHASE_STATUSIN */ case 0x1b: /* -> PHASE_STATUSIN */ + case 0x4b: /* -> PHASE_STATUSIN */ + case 0x8b: /* -> PHASE_STATUSIN */ /* DATA IN -> STATUS */ host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - - acornscsi_sbic_xfcount (host); - acornscsi_dma_stop (host); - acornscsi_readstatusbyte (host); + acornscsi_sbic_xfcount(host); + acornscsi_dma_stop(host); + acornscsi_readstatusbyte(host); host->scsi.phase = PHASE_STATUSIN; break; case 0x1e: /* -> PHASE_MSGOUT */ case 0x4e: /* -> PHASE_MSGOUT */ + case 0x8e: /* -> PHASE_MSGOUT */ /* DATA IN -> MESSAGE OUT */ host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - - acornscsi_sbic_xfcount (host); - acornscsi_dma_stop (host); - acornscsi_sendmessage (host); + acornscsi_sbic_xfcount(host); + acornscsi_dma_stop(host); + acornscsi_sendmessage(host); break; case 0x1f: /* message in */ case 0x4f: /* message in */ + case 0x8f: /* message in */ /* DATA IN -> MESSAGE IN */ host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - - acornscsi_sbic_xfcount (host); - acornscsi_dma_stop (host); - acornscsi_message (host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ + acornscsi_sbic_xfcount(host); + acornscsi_dma_stop(host); + acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ break; default: - printk (KERN_ERR "scsi%d.%c: PHASE_DATAIN, SSR %02X?\n", - host->host->host_no, acornscsi_target (host), ssr); - acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8); + printk(KERN_ERR "scsi%d.%c: PHASE_DATAIN, SSR %02X?\n", + host->host->host_no, acornscsi_target(host), ssr); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); } return INTR_PROCESSING; @@ -2222,58 +2322,69 @@ */ switch (ssr) { case 0x18: /* -> PHASE_DATAOUT */ - acornscsi_abortcmd (host, host->SCpnt->tag); + case 0x88: /* -> PHASE_DATAOUT */ + acornscsi_abortcmd(host, host->SCpnt->tag); return INTR_IDLE; - case 0x4b: /* -> PHASE_STATUSIN */ case 0x1b: /* -> PHASE_STATUSIN */ + case 0x4b: /* -> PHASE_STATUSIN */ + case 0x8b: /* -> PHASE_STATUSIN */ /* DATA OUT -> STATUS */ host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - - acornscsi_sbic_xfcount (host); - acornscsi_dma_stop (host); - acornscsi_dma_adjust (host); - acornscsi_readstatusbyte (host); + acornscsi_sbic_xfcount(host); + acornscsi_dma_stop(host); + acornscsi_dma_adjust(host); + acornscsi_readstatusbyte(host); host->scsi.phase = PHASE_STATUSIN; break; case 0x1e: /* -> PHASE_MSGOUT */ case 0x4e: /* -> PHASE_MSGOUT */ + case 0x8e: /* -> PHASE_MSGOUT */ /* DATA OUT -> MESSAGE OUT */ host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - - acornscsi_sbic_xfcount (host); - acornscsi_dma_stop (host); - acornscsi_dma_adjust (host); - acornscsi_sendmessage (host); + acornscsi_sbic_xfcount(host); + acornscsi_dma_stop(host); + acornscsi_dma_adjust(host); + acornscsi_sendmessage(host); break; case 0x1f: /* message in */ case 0x4f: /* message in */ + case 0x8f: /* message in */ /* DATA OUT -> MESSAGE IN */ host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - - acornscsi_sbic_xfcount (host); - acornscsi_dma_stop (host); - acornscsi_dma_adjust (host); - acornscsi_message (host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ + acornscsi_sbic_xfcount(host); + acornscsi_dma_stop(host); + acornscsi_dma_adjust(host); + acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ break; default: - printk (KERN_ERR "scsi%d.%c: PHASE_DATAOUT, SSR %02X?\n", - host->host->host_no, acornscsi_target (host), ssr); - acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8); + printk(KERN_ERR "scsi%d.%c: PHASE_DATAOUT, SSR %02X?\n", + host->host->host_no, acornscsi_target(host), ssr); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); } return INTR_PROCESSING; case PHASE_STATUSIN: /* STATE: status in complete */ - if (ssr == 0x1f) /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */ + switch (ssr) { + case 0x1f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */ + case 0x8f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */ /* STATUS -> MESSAGE IN */ - acornscsi_message (host); - else if (ssr == 0x1e) /* -> PHASE_MSGOUT */ + acornscsi_message(host); + break; + + case 0x1e: /* -> PHASE_MSGOUT */ + case 0x8e: /* -> PHASE_MSGOUT */ /* STATUS -> MESSAGE OUT */ - acornscsi_sendmessage (host); - else { - printk (KERN_ERR "scsi%d.%c: PHASE_STATUSIN, SSR %02X instead of MESSAGE_IN?\n", - host->host->host_no, acornscsi_target (host), ssr); - acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_sendmessage(host); + break; + + default: + printk(KERN_ERR "scsi%d.%c: PHASE_STATUSIN, SSR %02X instead of MESSAGE_IN?\n", + host->host->host_no, acornscsi_target(host), ssr); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); } return INTR_PROCESSING; @@ -2281,78 +2392,93 @@ switch (ssr) { case 0x1e: /* -> PHASE_MSGOUT */ case 0x4e: /* -> PHASE_MSGOUT */ + case 0x8e: /* -> PHASE_MSGOUT */ /* MESSAGE IN -> MESSAGE OUT */ - acornscsi_sendmessage (host); + acornscsi_sendmessage(host); break; case 0x1f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */ case 0x2f: case 0x4f: case 0x8f: - acornscsi_message (host); + acornscsi_message(host); + break; + + case 0x85: + printk("scsi%d.%c: strange message in disconnection\n", + host->host->host_no, acornscsi_target(host)); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); + acornscsi_done(host, &host->SCpnt, DID_ERROR); break; default: - printk (KERN_ERR "scsi%d.%c: PHASE_MSGIN, SSR %02X after message in?\n", - host->host->host_no, acornscsi_target (host), ssr); - acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8); + printk(KERN_ERR "scsi%d.%c: PHASE_MSGIN, SSR %02X after message in?\n", + host->host->host_no, acornscsi_target(host), ssr); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); } return INTR_PROCESSING; case PHASE_DONE: /* STATE: received status & message */ switch (ssr) { case 0x85: /* -> PHASE_IDLE */ - acornscsi_done (host, &host->SCpnt, DID_OK); + acornscsi_done(host, &host->SCpnt, DID_OK); return INTR_NEXT_COMMAND; + case 0x1e: case 0x8e: - acornscsi_sendmessage (host); + acornscsi_sendmessage(host); break; default: - printk (KERN_ERR "scsi%d.%c: PHASE_DONE, SSR %02X instead of disconnect?\n", - host->host->host_no, acornscsi_target (host), ssr); - acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8); + printk(KERN_ERR "scsi%d.%c: PHASE_DONE, SSR %02X instead of disconnect?\n", + host->host->host_no, acornscsi_target(host), ssr); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); } return INTR_PROCESSING; case PHASE_ABORTED: switch (ssr) { case 0x85: - acornscsi_done (host, &host->SCpnt, DID_ABORT); + if (host->SCpnt) + acornscsi_done(host, &host->SCpnt, DID_ABORT); + else { + clear_bit(host->scsi.reconnected.target * 8 + host->scsi.reconnected.lun, + host->busyluns); + host->scsi.phase = PHASE_IDLE; + } return INTR_NEXT_COMMAND; case 0x1e: case 0x2e: case 0x4e: case 0x8e: - acornscsi_sendmessage (host); + acornscsi_sendmessage(host); break; default: - printk (KERN_ERR "scsi%d.%c: PHASE_ABORTED, SSR %02X?\n", - host->host->host_no, acornscsi_target (host), ssr); - acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8); + printk(KERN_ERR "scsi%d.%c: PHASE_ABORTED, SSR %02X?\n", + host->host->host_no, acornscsi_target(host), ssr); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); } return INTR_PROCESSING; default: - printk (KERN_ERR "scsi%d.%c: unknown driver phase %d\n", - host->host->host_no, acornscsi_target (host), ssr); - acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8); + printk(KERN_ERR "scsi%d.%c: unknown driver phase %d\n", + host->host->host_no, acornscsi_target(host), ssr); + acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); } return INTR_PROCESSING; } /* - * Prototype: void acornscsi_intr (int irq, void *dev_id, struct pt_regs *regs) + * Prototype: void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs) * Purpose : handle interrupts from Acorn SCSI card * Params : irq - interrupt number * dev_id - device specific data (AS_Host structure) * regs - processor registers when interrupt occurred */ static -void acornscsi_intr (int irq, void *dev_id, struct pt_regs *regs) +void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs) { AS_Host *host = (AS_Host *)dev_id; intr_ret_t ret; @@ -2360,21 +2486,21 @@ int in_irq = 0; if (host->scsi.interrupt) - printk ("scsi%d: interrupt re-entered\n", host->host->host_no); + printk("scsi%d: interrupt re-entered\n", host->host->host_no); host->scsi.interrupt = 1; do { ret = INTR_IDLE; - iostatus = inb (host->card.io_intr); + iostatus = inb(host->card.io_intr); if (iostatus & 2) { - acornscsi_dma_intr (host); - iostatus = inb (host->card.io_intr); + acornscsi_dma_intr(host); + iostatus = inb(host->card.io_intr); } if (iostatus & 8) - ret = acornscsi_sbicintr (host, in_irq); + ret = acornscsi_sbicintr(host, in_irq); /* * If we have a transfer pending, start it. @@ -2382,10 +2508,10 @@ * it's data */ if (host->dma.xfer_required) - acornscsi_dma_xfer (host); + acornscsi_dma_xfer(host); if (ret == INTR_NEXT_COMMAND) - ret = acornscsi_kick (host); + ret = acornscsi_kick(host); in_irq = 1; } while (ret != INTR_IDLE); @@ -2398,29 +2524,29 @@ */ /* - * Function : acornscsi_queuecmd (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) + * Function : acornscsi_queuecmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) * Purpose : queues a SCSI command * Params : cmd - SCSI command * done - function called on completion, with pointer to command descriptor * Returns : 0, or < 0 on error. */ -int acornscsi_queuecmd (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) +int acornscsi_queuecmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { AS_Host *host = (AS_Host *)SCpnt->host->hostdata; if (!done) { /* there should be some way of rejecting errors like this without panicing... */ - panic ("scsi%d: queuecommand called with NULL done function [cmd=%p]", + panic("scsi%d: queuecommand called with NULL done function [cmd=%p]", SCpnt->host->host_no, SCpnt); return -EINVAL; } #if (DEBUG & DEBUG_NO_WRITE) - if (acornscsi_cmdtype (SCpnt->cmnd[0]) == CMD_WRITE && (NO_WRITE & (1 << SCpnt->target))) { - printk (KERN_CRIT "scsi%d.%c: WRITE attempted with NO_WRITE flag set\n", + if (acornscsi_cmdtype(SCpnt->cmnd[0]) == CMD_WRITE && (NO_WRITE & (1 << SCpnt->target))) { + printk(KERN_CRIT "scsi%d.%c: WRITE attempted with NO_WRITE flag set\n", SCpnt->host->host_no, '0' + SCpnt->target); SCpnt->result = DID_NO_CONNECT << 16; - done (SCpnt); + done(SCpnt); return 0; } #endif @@ -2429,7 +2555,7 @@ SCpnt->host_scribble = NULL; SCpnt->result = 0; SCpnt->tag = 0; - SCpnt->SCp.phase = (int)acornscsi_datadirection (SCpnt->cmnd[0]); + SCpnt->SCp.phase = (int)acornscsi_datadirection(SCpnt->cmnd[0]); SCpnt->SCp.sent_command = 0; SCpnt->SCp.scsi_xferred = 0; SCpnt->SCp.Status = 0; @@ -2452,21 +2578,21 @@ { unsigned long flags; - if (!queue_add_cmd_ordered (&host->queues.issue, SCpnt)) { + if (!queue_add_cmd_ordered(&host->queues.issue, SCpnt)) { SCpnt->result = DID_ERROR << 16; - done (SCpnt); + done(SCpnt); return 0; } - save_flags_cli (flags); + save_flags_cli(flags); if (host->scsi.phase == PHASE_IDLE) - acornscsi_kick (host); - restore_flags (flags); + acornscsi_kick(host); + restore_flags(flags); } return 0; } /* - * Prototype: void acornscsi_reportstatus (Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result) + * Prototype: void acornscsi_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result) * Purpose : pass a result to *SCpntp1, and check if *SCpntp1 = *SCpntp2 * Params : SCpntp1 - pointer to command to return * SCpntp2 - pointer to command to check @@ -2474,7 +2600,7 @@ * Returns : *SCpntp2 = NULL if *SCpntp1 is the same command structure as *SCpntp2. */ static inline -void acornscsi_reportstatus (Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result) +void acornscsi_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result) { Scsi_Cmnd *SCpnt = *SCpntp1; @@ -2482,80 +2608,203 @@ *SCpntp1 = NULL; SCpnt->result = result; - SCpnt->scsi_done (SCpnt); + SCpnt->scsi_done(SCpnt); } if (SCpnt == *SCpntp2) *SCpntp2 = NULL; } +enum res_abort { res_not_running, res_success, res_success_clear, res_snooze }; + /* - * Prototype: int acornscsi_abort (Scsi_Cmnd *SCpnt) + * Prototype: enum res acornscsi_do_abort(Scsi_Cmnd *SCpnt) + * Purpose : abort a command on this host + * Params : SCpnt - command to abort + * Returns : our abort status + */ +static enum res_abort +acornscsi_do_abort(AS_Host *host, Scsi_Cmnd *SCpnt) +{ + enum res_abort res = res_not_running; + + if (queue_removecmd(&host->queues.issue, SCpnt)) { + /* + * The command was on the issue queue, and has not been + * issued yet. We can remove the command from the queue, + * and acknowledge the abort. Neither the devices nor the + * interface know about the command. + */ +//#if (DEBUG & DEBUG_ABORT) + printk("on issue queue "); +//#endif + res = res_success; + } else if (queue_removecmd(&host->queues.disconnected, SCpnt)) { + /* + * The command was on the disconnected queue. Simply + * acknowledge the abort condition, and when the target + * reconnects, we will give it an ABORT message. The + * target should then disconnect, and we will clear + * the busylun bit. + */ +//#if (DEBUG & DEBUG_ABORT) + printk("on disconnected queue "); +//#endif + res = res_success; + } else if (host->SCpnt == SCpnt) { + unsigned long flags; + +//#if (DEBUG & DEBUG_ABORT) + printk("executing "); +//#endif + + save_flags(flags); + cli(); + switch (host->scsi.phase) { + /* + * If the interface is idle, and the command is 'disconnectable', + * then it is the same as on the disconnected queue. We simply + * remove all traces of the command. When the target reconnects, + * we will give it an ABORT message since the command could not + * be found. When the target finally disconnects, we will clear + * the busylun bit. + */ + case PHASE_IDLE: + if (host->scsi.disconnectable) { + host->scsi.disconnectable = 0; + host->SCpnt = NULL; + res = res_success; + } + break; + + /* + * If the command has connected and done nothing further, + * simply force a disconnect. We also need to clear the + * busylun bit. + */ + case PHASE_CONNECTED: + sbic_arm_write(host->scsi.io_port, CMND, CMND_DISCONNECT); + host->SCpnt = NULL; + res = res_success_clear; + break; + + default: + acornscsi_abortcmd(host, host->SCpnt->tag); + res = res_snooze; + } + restore_flags(flags); + } else if (host->origSCpnt == SCpnt) { + /* + * The command will be executed next, but a command + * is currently using the interface. This is similar to + * being on the issue queue, except the busylun bit has + * been set. + */ + host->origSCpnt = NULL; +//#if (DEBUG & DEBUG_ABORT) + printk("waiting for execution "); +//#endif + res = res_success_clear; + } else + printk("unknown "); + + return res; +} + +/* + * Prototype: int acornscsi_abort(Scsi_Cmnd *SCpnt) * Purpose : abort a command on this host * Params : SCpnt - command to abort * Returns : one of SCSI_ABORT_ macros */ -int acornscsi_abort (Scsi_Cmnd *SCpnt) +int acornscsi_abort(Scsi_Cmnd *SCpnt) { - AS_Host *host = (AS_Host *) SCpnt->host->hostdata; - int result = SCSI_ABORT_NOT_RUNNING; + AS_Host *host = (AS_Host *) SCpnt->host->hostdata; + int result; - host->stats.aborts += 1; + host->stats.aborts += 1; #if (DEBUG & DEBUG_ABORT) - { - int asr, ssr; - asr = sbic_arm_read (host->scsi.io_port, ASR); - ssr = sbic_arm_read (host->scsi.io_port, SSR); + { + int asr, ssr; + asr = sbic_arm_read(host->scsi.io_port, ASR); + ssr = sbic_arm_read(host->scsi.io_port, SSR); - printk (KERN_WARNING "acornscsi_abort: "); - print_sbic_status(asr, ssr, host->scsi.phase); - acornscsi_dumplog (host, SCpnt->target); - } + printk(KERN_WARNING "acornscsi_abort: "); + print_sbic_status(asr, ssr, host->scsi.phase); + acornscsi_dumplog(host, SCpnt->target); + } #endif - if (queue_removecmd (&host->queues.issue, SCpnt)) { - SCpnt->result = DID_ABORT << 16; - SCpnt->scsi_done (SCpnt); -#if (DEBUG & DEBUG_ABORT) - printk ("scsi%d: command on issue queue\n", host->host->host_no); -#endif - result = SCSI_ABORT_SUCCESS; - } else if (queue_cmdonqueue (&host->queues.disconnected, SCpnt)) { - printk ("scsi%d: command on disconnected queue\n", host->host->host_no); - result = SCSI_ABORT_SNOOZE; - } else if (host->SCpnt == SCpnt) { - acornscsi_abortcmd (host, host->SCpnt->tag); - printk ("scsi%d: command executing\n", host->host->host_no); - result = SCSI_ABORT_SNOOZE; - } else if (host->origSCpnt == SCpnt) { - host->origSCpnt = NULL; - SCpnt->result = DID_ABORT << 16; - SCpnt->scsi_done (SCpnt); -#if (DEBUG & DEBUG_ABORT) - printk ("scsi%d: command waiting for execution\n", host->host->host_no); -#endif - result = SCSI_ABORT_SUCCESS; - } + printk("scsi%d: ", host->host->host_no); + + switch (acornscsi_do_abort(host, SCpnt)) { + /* + * We managed to find the command and cleared it out. + * We do not expect the command to be executing on the + * target, but we have set the busylun bit. + */ + case res_success_clear: +//#if (DEBUG & DEBUG_ABORT) + printk("clear "); +//#endif + clear_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns); + + /* + * We found the command, and cleared it out. Either + * the command is still known to be executing on the + * target, or the busylun bit is not set. + */ + case res_success: +//#if (DEBUG & DEBUG_ABORT) + printk("success\n"); +//#endif + SCpnt->result = DID_ABORT << 16; + SCpnt->scsi_done(SCpnt); + result = SCSI_ABORT_SUCCESS; + break; - if (result == SCSI_ABORT_NOT_RUNNING) { - printk ("scsi%d: abort(): command not running\n", host->host->host_no); - acornscsi_dumplog (host, SCpnt->target); + /* + * We did find the command, but unfortunately we couldn't + * unhook it from ourselves. Wait some more, and if it + * still doesn't complete, reset the interface. + */ + case res_snooze: +//#if (DEBUG & DEBUG_ABORT) + printk("snooze\n"); +//#endif + result = SCSI_ABORT_SNOOZE; + break; + + /* + * The command could not be found (either because it completed, + * or it got dropped. + */ + default: + case res_not_running: + acornscsi_dumplog(host, SCpnt->target); #if (DEBUG & DEBUG_ABORT) - result = SCSI_ABORT_SNOOZE; + result = SCSI_ABORT_SNOOZE; +#else + result = SCSI_ABORT_NOT_RUNNING; #endif - } - return result; +//#if (DEBUG & DEBUG_ABORT) + printk("not running\n"); +//#endif + break; + } + + return result; } /* - * Prototype: int acornscsi_reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags) + * Prototype: int acornscsi_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) * Purpose : reset a command on this host/reset this host * Params : SCpnt - command causing reset * result - what type of reset to perform * Returns : one of SCSI_RESET_ macros */ -int acornscsi_reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags) +int acornscsi_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) { AS_Host *host = (AS_Host *)SCpnt->host->hostdata; Scsi_Cmnd *SCptr; @@ -2566,16 +2815,16 @@ { int asr, ssr; - asr = sbic_arm_read (host->scsi.io_port, ASR); - ssr = sbic_arm_read (host->scsi.io_port, SSR); + asr = sbic_arm_read(host->scsi.io_port, ASR); + ssr = sbic_arm_read(host->scsi.io_port, SSR); - printk (KERN_WARNING "acornscsi_reset: "); + printk(KERN_WARNING "acornscsi_reset: "); print_sbic_status(asr, ssr, host->scsi.phase); - acornscsi_dumplog (host, SCpnt->target); + acornscsi_dumplog(host, SCpnt->target); } #endif - acornscsi_dma_stop (host); + acornscsi_dma_stop(host); SCptr = host->SCpnt; @@ -2583,19 +2832,19 @@ * do hard reset. This resets all devices on this host, and so we * must set the reset status on all commands. */ - acornscsi_resetcard (host); + acornscsi_resetcard(host); /* * report reset on commands current connected/disconnected */ - acornscsi_reportstatus (&host->SCpnt, &SCptr, DID_RESET); + acornscsi_reportstatus(&host->SCpnt, &SCptr, DID_RESET); - while ((SCptr = queue_remove (&host->queues.disconnected)) != NULL) - acornscsi_reportstatus (&SCptr, &SCpnt, DID_RESET); + while ((SCptr = queue_remove(&host->queues.disconnected)) != NULL) + acornscsi_reportstatus(&SCptr, &SCpnt, DID_RESET); if (SCpnt) { SCpnt->result = DID_RESET << 16; - SCpnt->scsi_done (SCpnt); + SCpnt->scsi_done(SCpnt); } return SCSI_RESET_BUS_RESET | SCSI_RESET_HOST_RESET | SCSI_RESET_SUCCESS; @@ -2607,19 +2856,19 @@ static struct expansion_card *ecs[MAX_ECARDS]; /* - * Prototype: void acornscsi_init (AS_Host *host) + * Prototype: void acornscsi_init(AS_Host *host) * Purpose : initialise the AS_Host structure for one interface & setup hardware * Params : host - host to setup */ static -void acornscsi_init (AS_Host *host) +void acornscsi_init(AS_Host *host) { - memset (&host->stats, 0, sizeof (host->stats)); - queue_initialise (&host->queues.issue); - queue_initialise (&host->queues.disconnected); - msgqueue_initialise (&host->scsi.msgs); + memset(&host->stats, 0, sizeof (host->stats)); + queue_initialise(&host->queues.issue); + queue_initialise(&host->queues.disconnected); + msgqueue_initialise(&host->scsi.msgs); - acornscsi_resetcard (host); + acornscsi_resetcard(host); } int acornscsi_detect(Scsi_Host_Template * tpnt) @@ -2634,7 +2883,7 @@ for (i = 0; i < MAX_ECARDS; i++) ecs[i] = NULL; - ecard_startfind (); + ecard_startfind(); while(1) { ecs[count] = ecard_find(0, acornscsi_cids); @@ -2642,37 +2891,37 @@ break; if (ecs[count]->irq == 0xff) { - printk ("scsi: WD33C93 does not have IRQ enabled - ignoring\n"); + printk("scsi: WD33C93 does not have IRQ enabled - ignoring\n"); continue; } ecard_claim(ecs[count]); /* Must claim here - card produces irq on reset */ - instance = scsi_register (tpnt, sizeof(AS_Host)); + instance = scsi_register(tpnt, sizeof(AS_Host)); host = (AS_Host *)instance->hostdata; - instance->io_port = ecard_address (ecs[count], ECARD_MEMC, 0); + instance->io_port = ecard_address(ecs[count], ECARD_MEMC, 0); instance->irq = ecs[count]->irq; host->host = instance; - host->scsi.io_port = ioaddr (instance->io_port + 0x800); + host->scsi.io_port = ioaddr(instance->io_port + 0x800); host->scsi.irq = instance->irq; host->card.io_intr = POD_SPACE(instance->io_port) + 0x800; host->card.io_page = POD_SPACE(instance->io_port) + 0xc00; - host->card.io_ram = ioaddr (instance->io_port); + host->card.io_ram = ioaddr(instance->io_port); host->dma.io_port = instance->io_port + 0xc00; host->dma.io_intr_clear = POD_SPACE(instance->io_port) + 0x800; ecs[count]->irqaddr = (char *)ioaddr(host->card.io_intr); ecs[count]->irqmask = 0x0a; - request_region (instance->io_port + 0x800, 2, "acornscsi(sbic)"); - request_region (host->card.io_intr, 1, "acornscsi(intr)"); - request_region (host->card.io_page, 1, "acornscsi(page)"); + request_region(instance->io_port + 0x800, 2, "acornscsi(sbic)"); + request_region(host->card.io_intr, 1, "acornscsi(intr)"); + request_region(host->card.io_page, 1, "acornscsi(page)"); #ifdef USE_DMAC - request_region (host->dma.io_port, 256, "acornscsi(dmac)"); + request_region(host->dma.io_port, 256, "acornscsi(dmac)"); #endif - request_region (instance->io_port, 2048, "acornscsi(ram)"); + request_region(instance->io_port, 2048, "acornscsi(ram)"); if (request_irq(host->scsi.irq, acornscsi_intr, SA_INTERRUPT, "acornscsi", host)) { printk(KERN_CRIT "scsi%d: IRQ%d not free, interrupts disabled\n", @@ -2680,7 +2929,7 @@ host->scsi.irq = NO_IRQ; } - acornscsi_init (host); + acornscsi_init(host); ++count; } @@ -2688,12 +2937,12 @@ } /* - * Function: int acornscsi_release (struct Scsi_Host *host) + * Function: int acornscsi_release(struct Scsi_Host *host) * Purpose : release all resources used by this adapter * Params : host - driver structure to release * Returns : nothing of any consequence */ -int acornscsi_release (struct Scsi_Host *instance) +int acornscsi_release(struct Scsi_Host *instance) { AS_Host *host = (AS_Host *)instance->hostdata; int i; @@ -2701,30 +2950,30 @@ /* * Put card into RESET state */ - outb (0x80, host->card.io_page); + outb(0x80, host->card.io_page); if (host->scsi.irq != NO_IRQ) - free_irq (host->scsi.irq, host); + free_irq(host->scsi.irq, host); - release_region (instance->io_port + 0x800, 2); - release_region (host->card.io_intr, 1); - release_region (host->card.io_page, 1); - release_region (host->dma.io_port, 256); - release_region (instance->io_port, 2048); + release_region(instance->io_port + 0x800, 2); + release_region(host->card.io_intr, 1); + release_region(host->card.io_page, 1); + release_region(host->dma.io_port, 256); + release_region(instance->io_port, 2048); for (i = 0; i < MAX_ECARDS; i++) - if (ecs[i] && instance->io_port == ecard_address (ecs[i], ECARD_MEMC, 0)) - ecard_release (ecs[i]); + if (ecs[i] && instance->io_port == ecard_address(ecs[i], ECARD_MEMC, 0)) + ecard_release(ecs[i]); - msgqueue_free (&host->scsi.msgs); - queue_free (&host->queues.disconnected); - queue_free (&host->queues.issue); + msgqueue_free(&host->scsi.msgs); + queue_free(&host->queues.disconnected); + queue_free(&host->queues.issue); return 0; } /* - * Function: char *acornscsi_info (struct Scsi_Host *host) + * Function: char *acornscsi_info(struct Scsi_Host *host) * Purpose : return a string describing this interface * Params : host - host to give information on * Returns : a constant string @@ -2736,7 +2985,7 @@ p = string; - p += sprintf (string, "%s at port %lX irq %d v%d.%d.%d" + p += sprintf(string, "%s at port %X irq %d v%d.%d.%d" #ifdef CONFIG_SCSI_ACORNSCSI_SYNC " SYNC" #endif @@ -2772,7 +3021,7 @@ host = (AS_Host *)instance->hostdata; - p += sprintf (p, "AcornSCSI driver v%d.%d.%d" + p += sprintf(p, "AcornSCSI driver v%d.%d.%d" #ifdef CONFIG_SCSI_ACORNSCSI_SYNC " SYNC" #endif @@ -2787,14 +3036,14 @@ #endif "\n\n", VER_MAJOR, VER_MINOR, VER_PATCH); - p += sprintf (p, "SBIC: WD33C93A Address: %08X IRQ : %d\n", + p += sprintf(p, "SBIC: WD33C93A Address: %08X IRQ : %d\n", host->scsi.io_port, host->scsi.irq); #ifdef USE_DMAC - p += sprintf (p, "DMAC: uPC71071 Address: %08X IRQ : %d\n\n", + p += sprintf(p, "DMAC: uPC71071 Address: %08X IRQ : %d\n\n", host->dma.io_port, host->scsi.irq); #endif - p += sprintf (p, "Statistics:\n" + p += sprintf(p, "Statistics:\n" "Queued commands: %-10u Issued commands: %-10u\n" "Done commands : %-10u Reads : %-10u\n" "Writes : %-10u Others : %-10u\n" @@ -2809,47 +3058,47 @@ for (devidx = 0; devidx < 9; devidx ++) { unsigned int statptr, prev; - p += sprintf (p, "\n%c:", devidx == 8 ? 'H' : ('0' + devidx)); - statptr = status_ptr[devidx] - 10; + p += sprintf(p, "\n%c:", devidx == 8 ? 'H' : ('0' + devidx)); + statptr = host->status_ptr[devidx] - 10; if ((signed int)statptr < 0) - statptr += 16; + statptr += STATUS_BUFFER_SIZE; - prev = status[devidx][statptr].when; + prev = host->status[devidx][statptr].when; - for (; statptr != status_ptr[devidx]; statptr = (statptr + 1) & 15) { - if (status[devidx][statptr].when) { - p += sprintf (p, "%c%02X:%02X+%2ld", - status[devidx][statptr].irq ? '-' : ' ', - status[devidx][statptr].ph, - status[devidx][statptr].ssr, - (status[devidx][statptr].when - prev) < 100 ? - (status[devidx][statptr].when - prev) : 99); - prev = status[devidx][statptr].when; + for (; statptr != host->status_ptr[devidx]; statptr = (statptr + 1) & (STATUS_BUFFER_SIZE - 1)) { + if (host->status[devidx][statptr].when) { + p += sprintf(p, "%c%02X:%02X+%2ld", + host->status[devidx][statptr].irq ? '-' : ' ', + host->status[devidx][statptr].ph, + host->status[devidx][statptr].ssr, + (host->status[devidx][statptr].when - prev) < 100 ? + (host->status[devidx][statptr].when - prev) : 99); + prev = host->status[devidx][statptr].when; } } } - p += sprintf (p, "\nAttached devices:%s\n", instance->host_queue ? "" : " none"); + p += sprintf(p, "\nAttached devices:%s\n", instance->host_queue ? "" : " none"); for (scd = instance->host_queue; scd; scd = scd->next) { int len; - proc_print_scsidevice (scd, p, &len, 0); + proc_print_scsidevice(scd, p, &len, 0); p += len; - p += sprintf (p, "Extensions: "); + p += sprintf(p, "Extensions: "); if (scd->tagged_supported) - p += sprintf (p, "TAG %sabled [%d] ", + p += sprintf(p, "TAG %sabled [%d] ", scd->tagged_queue ? "en" : "dis", scd->current_tag); - p += sprintf (p, "\nTransfers: "); + p += sprintf(p, "\nTransfers: "); if (host->device[scd->id].sync_xfer & 15) - p += sprintf (p, "sync, offset %d, %d ns\n", + p += sprintf(p, "sync, offset %d, %d ns\n", host->device[scd->id].sync_xfer & 15, - acornscsi_getperiod (host->device[scd->id].sync_xfer)); + acornscsi_getperiod(host->device[scd->id].sync_xfer)); else - p += sprintf (p, "async\n"); + p += sprintf(p, "async\n"); pos = p - buffer; if (pos + begin < offset) { diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/acornscsi.h linux.ac/drivers/acorn/scsi/acornscsi.h --- linux.vanilla/drivers/acorn/scsi/acornscsi.h Sun Nov 8 15:08:18 1998 +++ linux.ac/drivers/acorn/scsi/acornscsi.h Sun Jan 24 23:54:37 1999 @@ -291,6 +291,27 @@ #include "queue.h" #include "msgqueue.h" +#define STATUS_BUFFER_SIZE 32 +/* + * This is used to dump the previous states of the SBIC + */ +struct status_entry { + unsigned long when; + unsigned char ssr; + unsigned char ph; + unsigned char irq; + unsigned char unused; +}; + +#define ADD_STATUS(_q,_ssr,_ph,_irq) \ +({ \ + host->status[(_q)][host->status_ptr[(_q)]].when = jiffies; \ + host->status[(_q)][host->status_ptr[(_q)]].ssr = (_ssr); \ + host->status[(_q)][host->status_ptr[(_q)]].ph = (_ph); \ + host->status[(_q)][host->status_ptr[(_q)]].irq = (_irq); \ + host->status_ptr[(_q)] = (host->status_ptr[(_q)] + 1) & (STATUS_BUFFER_SIZE - 1); \ +}) + /* * AcornSCSI host specific data */ @@ -361,6 +382,7 @@ char *xfer_ptr; /* pointer to area */ unsigned char xfer_required:1; /* set if we need to transfer something */ unsigned char xfer_setup:1; /* set if DMA is setup */ + unsigned char xfer_done:1; /* set if DMA reached end of BH list */ } dma; /* card info */ @@ -370,6 +392,9 @@ unsigned int io_ram; /* base address of RAM access */ unsigned char page_reg; /* current setting of page reg */ } card; + + unsigned char status_ptr[9]; + struct status_entry status[9][STATUS_BUFFER_SIZE]; } AS_Host; #endif /* ndef HOSTS_C */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/cumana_2.c linux.ac/drivers/acorn/scsi/cumana_2.c --- linux.vanilla/drivers/acorn/scsi/cumana_2.c Tue Dec 22 23:19:35 1998 +++ linux.ac/drivers/acorn/scsi/cumana_2.c Sun Jan 24 23:54:37 1999 @@ -4,12 +4,12 @@ * Copyright (C) 1997-1998 Russell King * * Changelog: - * 30-08-1997 RMK 0.0.0 Created, READONLY version - * 22-01-1998 RMK 0.0.1 Updated to 2.1.80 + * 30-08-1997 RMK 0.0.0 Created, READONLY version. + * 22-01-1998 RMK 0.0.1 Updated to 2.1.80. * 15-04-1998 RMK 0.0.1 Only do PIO if FAS216 will allow it. - * 02-05-1998 RMK 0.0.2 Updated & added DMA support + * 02-05-1998 RMK 0.0.2 Updated & added DMA support. * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h - * 18-08-1998 RMK 0.0.3 Fixed synchronous transfer depth + * 18-08-1998 RMK 0.0.3 Fixed synchronous transfer depth. */ #include @@ -117,6 +117,8 @@ cumanascsi_2_irqenable, cumanascsi_2_irqdisable, NULL, + NULL, + NULL, NULL }; @@ -364,6 +366,7 @@ info->info.ifcfg.sync_max_depth = CUMANASCSI2_SYNC_DEPTH; info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; info->info.ifcfg.disconnect_ok = 1; + info->info.ifcfg.wide_max_size = 0; info->info.dma.setup = cumanascsi_2_dma_setup; info->info.dma.pseudo = cumanascsi_2_dma_pseudo; info->info.dma.stop = cumanascsi_2_dma_stop; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/eesox.c linux.ac/drivers/acorn/scsi/eesox.c --- linux.vanilla/drivers/acorn/scsi/eesox.c Tue Dec 22 23:19:35 1998 +++ linux.ac/drivers/acorn/scsi/eesox.c Sun Jan 24 23:54:37 1999 @@ -123,6 +123,8 @@ eesoxscsi_irqenable, eesoxscsi_irqdisable, NULL, + NULL, + NULL, NULL }; @@ -379,6 +381,7 @@ info->info.ifcfg.sync_max_depth = EESOX_SYNC_DEPTH; info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; info->info.ifcfg.disconnect_ok = 1; + info->info.ifcfg.wide_max_size = 0; info->info.dma.setup = eesoxscsi_dma_setup; info->info.dma.pseudo = eesoxscsi_dma_pseudo; info->info.dma.stop = eesoxscsi_dma_stop; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/fas216.c linux.ac/drivers/acorn/scsi/fas216.c --- linux.vanilla/drivers/acorn/scsi/fas216.c Mon Dec 28 23:09:41 1998 +++ linux.ac/drivers/acorn/scsi/fas216.c Sun Jan 24 23:54:37 1999 @@ -24,9 +24,9 @@ * 02-05-1998 RMK Added extra checks in fas216_reset * 24-05-1998 RMK Fixed synchronous transfers with period >= 200ns * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h + * 26-08-1998 RMK Improved message support wrt MESSAGE_REJECT * * Todo: - * - tighten up the MESSAGE_REJECT support. * - allow individual devices to enable sync xfers. */ @@ -57,7 +57,7 @@ #define VER_MAJOR 0 #define VER_MINOR 0 -#define VER_PATCH 4 +#define VER_PATCH 5 #define SCSI2_TAG @@ -86,6 +86,8 @@ */ #define SCSI2_SYNC +#define SCSI2_WIDE + #undef DEBUG_CONNECT #undef DEBUG_BUSSERVICE #undef DEBUG_FUNCTIONDONE @@ -132,8 +134,8 @@ printk(" SCp={ ptr=%p this_residual=%X buffer=%p buffers_residual=%X }\n", info->scsi.SCp.ptr, info->scsi.SCp.this_residual, info->scsi.SCp.buffer, info->scsi.SCp.buffers_residual); - printk(" msgs async_stp=%X last_message=%X disconnectable=%d aborting=%d }\n", - info->scsi.async_stp, info->scsi.last_message, + printk(" msgs async_stp=%X disconnectable=%d aborting=%d }\n", + info->scsi.async_stp, info->scsi.disconnectable, info->scsi.aborting); printk(" stats={ queues=%X removes=%X fins=%X reads=%X writes=%X miscs=%X\n" " disconnects=%X aborts=%X resets=%X }\n", @@ -144,10 +146,10 @@ info->ifcfg.clockrate, info->ifcfg.select_timeout, info->ifcfg.asyncperiod, info->ifcfg.sync_max_depth); for (i = 0; i < 8; i++) { - printk(" busyluns[%d]=%X dev[%d]={ disconnect_ok=%d stp=%X sof=%X negstate=%X }\n", + printk(" busyluns[%d]=%X dev[%d]={ disconnect_ok=%d stp=%X sof=%X sync_state=%X }\n", i, info->busyluns[i], i, info->device[i].disconnect_ok, info->device[i].stp, - info->device[i].sof, info->device[i].negstate); + info->device[i].sof, info->device[i].sync_state); } printk(" dma={ transfer_type=%X setup=%p pseudo=%p stop=%p }\n", info->dma.transfer_type, info->dma.setup, @@ -192,19 +194,19 @@ static const char *fas216_drv_phase(FAS216_Info *info) { switch (info->scsi.phase) { - case PHASE_IDLE: return "idle"; - case PHASE_SELECTION: return "selection"; - case PHASE_MESSAGESENT: return "message sent"; - case PHASE_RECONNECTED: return "reconnected"; - case PHASE_DATAOUT: return "data out"; - case PHASE_DATAIN: return "data in"; - case PHASE_MSGOUT: return "message out"; - case PHASE_MSGIN: return "message in"; - case PHASE_AFTERMSGOUT: return "after message out"; - case PHASE_STATUS: return "status"; - case PHASE_DISCONNECT: return "disconnect"; - case PHASE_DONE: return "done"; - default: return "???"; + case PHASE_IDLE: return "idle"; + case PHASE_SELECTION: return "selection"; + case PHASE_COMMAND: return "command"; + case PHASE_RECONNECTED: return "reconnected"; + case PHASE_DATAOUT: return "data out"; + case PHASE_DATAIN: return "data in"; + case PHASE_MSGIN: return "message in"; + case PHASE_MSGIN_DISCONNECT: return "disconnect"; + case PHASE_MSGOUT_EXPECT: return "expect message out"; + case PHASE_MSGOUT: return "message out"; + case PHASE_STATUS: return "status"; + case PHASE_DONE: return "done"; + default: return "???"; } } @@ -262,6 +264,37 @@ return clock; } +/* Function: unsigned short fas216_get_last_msg(FAS216_Info *info, int pos) + * Purpose : retrieve a last message from the list, using position in fifo + * Params : info - interface to search + * : pos - current fifo position + */ +static inline unsigned short +fas216_get_last_msg(FAS216_Info *info, int pos) +{ + unsigned short packed_msg = NOP; + struct message *msg; + int msgnr = 0; + + while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) { + if (pos >= msg->fifo) + break; + } + + if (msg) { + if (msg->msg[0] == EXTENDED_MESSAGE) + packed_msg = EXTENDED_MESSAGE | msg->msg[2] << 8; + else + packed_msg = msg->msg[0]; + } + +#ifdef DEBUG_MESSAGES + printk("Message: %04X found at position %02X\n", + packed_msg, pos); +#endif + return packed_msg; +} + /* Function: int fas216_syncperiod(FAS216_Info *info, int ns) * Purpose : Calculate value to be loaded into the STP register * for a given period in ns @@ -303,6 +336,240 @@ outb(info->scsi.cfg[2], REG_CNTL3(info)); } +/* Synchronous transfer support + * + * Note: The SCSI II r10 spec says (5.6.12): + * + * (2) Due to historical problems with early host adapters that could + * not accept an SDTR message, some targets may not initiate synchronous + * negotiation after a power cycle as required by this standard. Host + * adapters that support synchronous mode may avoid the ensuing failure + * modes when the target is independently power cycled by initiating a + * synchronous negotiation on each REQUEST SENSE and INQUIRY command. + * This approach increases the SCSI bus overhead and is not recommended + * for new implementations. The correct method is to respond to an + * SDTR message with a MESSAGE REJECT message if the either the + * initiator or target devices does not support synchronous transfers + * or does not want to negotiate for synchronous transfers at the time. + * Using the correct method assures compatibility with wide data + * transfers and future enhancements. + * + * We will always initiate a synchronous transfer negociation request on + * every INQUIRY or REQUEST SENSE message, unless the target itself has + * at some point performed a synchronous transfer negociation request, or + * we have synchronous transfers disabled for this device. + */ + +/* Function: void fas216_handlesync(FAS216_Info *info, char *msg) + * Purpose : Handle a synchronous transfer message from the target + * Params : info - state structure for interface + * : msg - message from target + */ +static void +fas216_handlesync(FAS216_Info *info, char *msg) +{ + struct fas216_device *dev = &info->device[info->SCpnt->target]; + enum { sync, async, none, reject } res = none; + +#ifdef SCSI2_SYNC + switch (msg[0]) { + case MESSAGE_REJECT: + /* Synchronous transfer request failed. + * Note: SCSI II r10: + * + * SCSI devices that are capable of synchronous + * data transfers shall not respond to an SDTR + * message with a MESSAGE REJECT message. + * + * Hence, if we get this condition, we disable + * negociation for this device. + */ + if (dev->sync_state == neg_inprogress) { + dev->sync_state = neg_invalid; + res = async; + } + break; + + case EXTENDED_MESSAGE: + switch (dev->sync_state) { + /* We don't accept synchronous transfer requests. + * Respond with a MESSAGE_REJECT to prevent a + * synchronous transfer agreement from being reached. + */ + case neg_invalid: + res = reject; + break; + + /* We were not negociating a synchronous transfer, + * but the device sent us a negociation request. + * Honour the request by sending back a SDTR + * message containing our capability, limited by + * the targets capability. + */ + default: + outb(CMD_SETATN, REG_CMD(info)); + if (msg[4] > info->ifcfg.sync_max_depth) + msg[4] = info->ifcfg.sync_max_depth; + if (msg[3] < 1000 / info->ifcfg.clockrate) + msg[3] = 1000 / info->ifcfg.clockrate; + + msgqueue_flush(&info->scsi.msgs); + msgqueue_addmsg(&info->scsi.msgs, 5, + EXTENDED_MESSAGE, 3, EXTENDED_SDTR, + msg[3], msg[4]); + info->scsi.phase = PHASE_MSGOUT_EXPECT; + + /* This is wrong. The agreement is not in effect + * until this message is accepted by the device + */ + dev->sync_state = neg_targcomplete; + res = sync; + break; + + /* We initiated the synchronous transfer negociation, + * and have successfully received a response from the + * target. The synchronous transfer agreement has been + * reached. Note: if the values returned are out of our + * bounds, we must reject the message. + */ + case neg_inprogress: + res = reject; + if (msg[4] <= info->ifcfg.sync_max_depth && + msg[3] >= 1000 / info->ifcfg.clockrate) { + dev->sync_state = neg_complete; + res = sync; + } + break; + } + } +#else + res = reject; +#endif + + switch (res) { + case sync: + dev->period = msg[3]; + dev->sof = msg[4]; + dev->stp = fas216_syncperiod(info, msg[3] * 4); + fas216_set_sync(info, info->SCpnt->target); + break; + + case reject: + outb(CMD_SETATN, REG_CMD(info)); + msgqueue_flush(&info->scsi.msgs); + msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); + info->scsi.phase = PHASE_MSGOUT_EXPECT; + + case async: + dev->period = info->ifcfg.asyncperiod / 4; + dev->sof = 0; + dev->stp = info->scsi.async_stp; + fas216_set_sync(info, info->SCpnt->target); + break; + + case none: + break; + } +} + +/* Function: void fas216_handlewide(FAS216_Info *info, char *msg) + * Purpose : Handle a wide transfer message from the target + * Params : info - state structure for interface + * : msg - message from target + */ +static void +fas216_handlewide(FAS216_Info *info, char *msg) +{ + struct fas216_device *dev = &info->device[info->SCpnt->target]; + enum { wide, bit8, none, reject } res = none; + +#ifdef SCSI2_WIDE + switch (msg[0]) { + case MESSAGE_REJECT: + /* Wide transfer request failed. + * Note: SCSI II r10: + * + * SCSI devices that are capable of wide + * data transfers shall not respond to a + * WDTR message with a MESSAGE REJECT message. + * + * Hence, if we get this condition, we never + * reattempt negociation for this device. + */ + if (dev->wide_state == neg_inprogress) { + dev->wide_state = neg_invalid; + res = bit8; + } + break; + + case EXTENDED_MESSAGE: + switch (dev->wide_state) { + /* We don't accept wide data transfer requests. + * Respond with a MESSAGE REJECT to prevent a + * wide data transfer agreement from being reached. + */ + case neg_invalid: + res = reject; + break; + + /* We were not negociating a wide data transfer, + * but the device sent is a negociation request. + * Honour the request by sending back a WDTR + * message containing our capability, limited by + * the targets capability. + */ + default: + outb(CMD_SETATN, REG_CMD(info)); + if (msg[3] > info->ifcfg.wide_max_size) + msg[3] = info->ifcfg.wide_max_size; + + msgqueue_flush(&info->scsi.msgs); + msgqueue_addmsg(&info->scsi.msgs, 4, + EXTENDED_MESSAGE, 2, EXTENDED_WDTR, + msg[3]); + info->scsi.phase = PHASE_MSGOUT_EXPECT; + res = wide; + break; + + /* We initiated the wide data transfer negociation, + * and have successfully received a response from the + * target. The synchronous transfer agreement has been + * reached. Note: if the values returned are out of our + * bounds, we must reject the message. + */ + case neg_inprogress: + res = reject; + if (msg[3] <= info->ifcfg.wide_max_size) { + dev->wide_state = neg_complete; + res = wide; + } + break; + } + } +#else + res = reject; +#endif + + switch (res) { + case wide: + dev->wide_xfer = msg[3]; + break; + + case reject: + outb(CMD_SETATN, REG_CMD(info)); + msgqueue_flush(&info->scsi.msgs); + msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); + info->scsi.phase = PHASE_MSGOUT_EXPECT; + + case bit8: + dev->wide_xfer = 0; + break; + + case none: + break; + } +} + /* Function: void fas216_updateptrs(FAS216_Info *info, int bytes_transferred) * Purpose : update data pointers after transfer suspended/paused * Params : info - interface's local pointer to update @@ -338,6 +605,9 @@ residual -= bytes_transferred; ptr += bytes_transferred; + if (residual == 0) + ptr = NULL; + info->scsi.SCp.ptr = ptr; info->scsi.SCp.this_residual = residual; } @@ -353,7 +623,7 @@ { unsigned int residual; char *ptr; - int correction; + int correction = 0; fas216_checkmagic(info, "fas216_pio"); @@ -361,23 +631,24 @@ ptr = info->scsi.SCp.ptr; if (direction == DMA_OUT) { - while (residual > 0) { - if ((inb(REG_CFIS(info)) & CFIS_CF) < 8) { +// while (residual > 0) { +// if ((inb(REG_CFIS(info)) & CFIS_CF) < 8) { outb(*ptr++, REG_FF(info)); residual -= 1; - } else if (inb(REG_STAT(info)) & STAT_INT) - break; - } - correction = inb(REG_CFIS(info)) & CFIS_CF; +// } +// if (inb(REG_STAT(info)) & STAT_INT) +// break; +// } +// correction = inb(REG_CFIS(info)) & CFIS_CF; } else { - while (residual > 0) { - if ((inb(REG_CFIS(info)) & CFIS_CF) != 0) { +// while (residual > 0) { +// if ((inb(REG_CFIS(info)) & CFIS_CF) != 0) { *ptr++ = inb(REG_FF(info)); residual -= 1; - } else if (inb(REG_STAT(info)) & STAT_INT) - break; - } - correction = 0; +// } +// if (inb(REG_STAT(info)) & STAT_INT) +// break; +// } } ptr -= correction; @@ -549,10 +820,11 @@ switch (info->scsi.phase) { case PHASE_SELECTION: /* while selecting - no target */ + case PHASE_SELSTEPS: fas216_done(info, DID_NO_CONNECT); break; - case PHASE_DISCONNECT: /* message in - disconnecting */ + case PHASE_MSGIN_DISCONNECT: /* message in - disconnecting */ outb(CMD_ENABLESEL, REG_CMD(info)); info->scsi.disconnectable = 1; info->scsi.reconnected.tag = 0; @@ -564,8 +836,8 @@ fas216_done(info, DID_OK); break; - case PHASE_AFTERMSGOUT: /* message out - possible ABORT message */ - if (info->scsi.last_message == ABORT) { + case PHASE_MSGOUT: /* message out - possible ABORT message */ + if (fas216_get_last_msg(info, info->scsi.msgin_fifo) == ABORT) { info->scsi.aborting = 0; fas216_done(info, DID_ABORT); break; @@ -592,14 +864,17 @@ fas216_checkmagic(info, "fas216_reselected_intr"); - if (info->scsi.phase == PHASE_SELECTION && info->SCpnt) { + if ((info->scsi.phase == PHASE_SELECTION || + info->scsi.phase == PHASE_SELSTEPS) && info->SCpnt) { Scsi_Cmnd *SCpnt = info->SCpnt; info->origSCpnt = SCpnt; info->SCpnt = NULL; - if (info->device[SCpnt->target].negstate == syncneg_sent) - info->device[SCpnt->target].negstate = syncneg_start; + if (info->device[SCpnt->target].wide_state == neg_inprogress) + info->device[SCpnt->target].wide_state = neg_wait; + if (info->device[SCpnt->target].sync_state == neg_inprogress) + info->device[SCpnt->target].sync_state = neg_wait; } #ifdef DEBUG_CONNECT @@ -607,15 +882,14 @@ fas216_target(info), info->scsi.phase); #endif - msgqueue_flush(&info->scsi.msgs); - if ((inb(REG_CFIS(info)) & CFIS_CF) != 2) { printk(KERN_ERR "scsi%d.H: incorrect number of bytes after reselect\n", info->host->host_no); outb(CMD_SETATN, REG_CMD(info)); - msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); - info->scsi.phase = PHASE_MSGOUT; outb(CMD_MSGACCEPTED, REG_CMD(info)); + msgqueue_flush(&info->scsi.msgs); + msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); + info->scsi.phase = PHASE_MSGOUT_EXPECT; return; } @@ -636,13 +910,14 @@ if (!ok) { /* - * Something went wrong - abort the command on - * the target. Should this be INITIATOR_ERROR ? + * Something went wrong - send an initiator error to + * the target. */ outb(CMD_SETATN, REG_CMD(info)); - msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); - info->scsi.phase = PHASE_MSGOUT; outb(CMD_MSGACCEPTED, REG_CMD(info)); + msgqueue_flush(&info->scsi.msgs); + msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); + info->scsi.phase = PHASE_MSGOUT_EXPECT; return; } @@ -672,17 +947,20 @@ if (!ok && queue_probetgtlun(&info->queues.disconnected, target, identify_msg)) ok = 1; + msgqueue_flush(&info->scsi.msgs); if (ok) { info->scsi.phase = PHASE_RECONNECTED; outb(target, REG_SDID(info)); } else { /* - * Our command structure not found - abort the command on the target - * Should this be INITIATOR_ERROR ? + * Our command structure not found - abort the + * command on the target. Since we have no + * record of this command, we can't send + * an INITIATOR DETECTED ERROR message. */ outb(CMD_SETATN, REG_CMD(info)); msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); - info->scsi.phase = PHASE_MSGOUT; + info->scsi.phase = PHASE_MSGOUT_EXPECT; } outb(CMD_MSGACCEPTED, REG_CMD(info)); } @@ -733,8 +1011,14 @@ } if (!info->SCpnt) { outb(CMD_SETATN, REG_CMD(info)); - msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); - info->scsi.phase = PHASE_MSGOUT; + msgqueue_flush(&info->scsi.msgs); +#if 0 + if (info->scsi.reconnected.tag) + msgqueue_addmsg(&info->scsi.msgs, 2, ABORT_TAG, info->scsi.reconnected.tag); + else +#endif + msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); + info->scsi.phase = PHASE_MSGOUT_EXPECT; info->scsi.aborting = 1; } else { /* @@ -751,6 +1035,28 @@ #endif } +static unsigned char fas216_get_msg_byte(FAS216_Info *info) +{ + int tout; + + outb(CMD_MSGACCEPTED, REG_CMD(info)); + for (tout = 1000000; tout; tout --) + if (inb(REG_STAT(info)) & STAT_INT) + break; + + inb(REG_INST(info)); + + outb(CMD_TRANSFERINFO, REG_CMD(info)); + + for (tout = 1000000; tout; tout --) + if (inb(REG_STAT(info)) & STAT_INT) + break; + + inb(REG_INST(info)); + + return inb(REG_FF(info)); +} + /* Function: void fas216_message(FAS216_Info *info) * Purpose : handle a function done interrupt from FAS216 chip * Params : info - interface which caused function done interrupt @@ -765,34 +1071,10 @@ message[0] = inb(REG_FF(info)); if (message[0] == EXTENDED_MESSAGE) { - int tout; - outb(CMD_MSGACCEPTED, REG_CMD(info)); - for (tout = 1000000; tout; tout--) - if (inb(REG_STAT(info)) & STAT_INT) - break; - inb(REG_INST(info)); - outb(CMD_TRANSFERINFO, REG_CMD(info)); - for (tout = 1000000; tout; tout--) - if (inb(REG_STAT(info)) & STAT_INT) - break; - inb(REG_INST(info)); - - message[1] = inb(REG_FF(info)); - - for (msglen = 2; msglen < message[1] + 2; msglen++) { - outb(CMD_MSGACCEPTED, REG_CMD(info)); - for (tout = 1000000; tout; tout--) - if (inb(REG_STAT(info)) & STAT_INT) - break; - inb(REG_INST(info)); - outb(CMD_TRANSFERINFO, REG_CMD(info)); - for (tout = 1000000; tout; tout--) - if (inb(REG_STAT(info)) & STAT_INT) - break; - inb(REG_INST(info)); + message[1] = fas216_get_msg_byte(info); - message[msglen] = inb(REG_FF(info)); - } + for (msglen = 2; msglen < message[1] + 2; msglen++) + message[msglen] = fas216_get_msg_byte(info); } #ifdef DEBUG_MESSAGES @@ -806,6 +1088,7 @@ printk("\n"); } #endif + if (info->scsi.phase == PHASE_RECONNECTED) { if (message[0] == SIMPLE_QUEUE_TAG) info->scsi.reconnected.tag = message[1]; @@ -815,14 +1098,22 @@ switch (message[0]) { case COMMAND_COMPLETE: - printk("fas216: command complete with no status in MESSAGE_IN?\n"); + printk(KERN_ERR "scsi%d.%c: command complete with no " + "status in MESSAGE_IN?\n", + info->host->host_no, fas216_target(info)); break; case SAVE_POINTERS: /* * Save current data pointer to SAVED data pointer + * SCSI II standard says that we must not acknowledge + * this until we have really saved pointers. + * NOTE: we DO NOT save the command nor status pointers + * as required by the SCSI II standard. These always + * point to the start of their respective areas. */ info->SCpnt->SCp = info->scsi.SCp; + info->SCpnt->SCp.sent_command = 0; #if defined (DEBUG_MESSAGES) || defined (DEBUG_CONNECT) printk("scsi%d.%c: save data pointers: [%p, %X]\n", info->host->host_no, fas216_target(info), @@ -843,13 +1134,27 @@ break; case DISCONNECT: - info->scsi.phase = PHASE_DISCONNECT; + info->scsi.phase = PHASE_MSGIN_DISCONNECT; break; case MESSAGE_REJECT: - printk("scsi%d.%c: reject, last message %04X\n", - info->host->host_no, fas216_target(info), - info->scsi.last_message); + switch (fas216_get_last_msg(info, info->scsi.msgin_fifo)) { + case EXTENDED_MESSAGE | EXTENDED_SDTR << 8: + fas216_handlesync(info, message); + break; + + case EXTENDED_MESSAGE | EXTENDED_WDTR << 8: + fas216_handlewide(info, message); + break; + + default: + printk("scsi%d.%c: reject, last message %04X\n", + info->host->host_no, fas216_target(info), + fas216_get_last_msg(info, info->scsi.msgin_fifo)); + } + break; + + case NOP: break; case SIMPLE_QUEUE_TAG: @@ -862,49 +1167,18 @@ case EXTENDED_MESSAGE: switch (message[2]) { case EXTENDED_SDTR: /* Sync transfer negociation request/reply */ - switch (info->device[info->SCpnt->target].negstate) { - case syncneg_invalid: - msgqueue_flush(&info->scsi.msgs); - outb(CMD_SETATN, REG_CMD(info)); - msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); - info->scsi.phase = PHASE_MSGOUT; - break; - - default: - if (message[4] > info->ifcfg.sync_max_depth) - message[4] = info->ifcfg.sync_max_depth; - if (message[3] < 1000 / info->ifcfg.clockrate) - message[3] = 1000 / info->ifcfg.clockrate; - - outb(CMD_SETATN, REG_CMD(info)); - msgqueue_addmsg(&info->scsi.msgs, 5, - EXTENDED_MESSAGE, 3, EXTENDED_SDTR, - message[3], message[4]); - info->scsi.phase = PHASE_MSGOUT; - case syncneg_sent: - info->device[info->SCpnt->target].negstate = syncneg_complete; - info->device[info->SCpnt->target].period = message[3]; - info->device[info->SCpnt->target].sof = message[4]; - info->device[info->SCpnt->target].stp = - fas216_syncperiod(info, message[3] * 4); - printk(KERN_NOTICE "scsi%d.%c: using synchronous transfer, offset %d, %d ns\n", - info->host->host_no, fas216_target(info), message[4], message[3] * 4); - fas216_set_sync(info, info->SCpnt->target); - break; - } + fas216_handlesync(info, message); break; case EXTENDED_WDTR: /* Wide transfer negociation request/reply */ - /* We don't do wide transfers - reject message */ + fas216_handlewide(info, message); + break; + default: printk("scsi%d.%c: unrecognised extended message %02X, rejecting\n", info->host->host_no, fas216_target(info), message[2]); - msgqueue_flush(&info->scsi.msgs); - outb(CMD_SETATN, REG_CMD(info)); - msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); - info->scsi.phase = PHASE_MSGOUT; - break; + goto reject_message; } break; @@ -912,13 +1186,17 @@ printk("scsi%d.%c: unrecognised message %02X, rejecting\n", info->host->host_no, fas216_target(info), message[0]); - msgqueue_flush(&info->scsi.msgs); - outb(CMD_SETATN, REG_CMD(info)); - msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); - info->scsi.phase = PHASE_MSGOUT; - break; + goto reject_message; } outb(CMD_MSGACCEPTED, REG_CMD(info)); + return; + +reject_message: + outb(CMD_SETATN, REG_CMD(info)); + outb(CMD_MSGACCEPTED, REG_CMD(info)); + msgqueue_flush(&info->scsi.msgs); + msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); + info->scsi.phase = PHASE_MSGOUT_EXPECT; } /* Function: void fas216_send_command(FAS216_Info *info) @@ -935,201 +1213,46 @@ outb(CMD_FLUSHFIFO, REG_CMD(info)); /* load command */ - for (i = 0; i < info->SCpnt->cmd_len; i++) + for (i = info->scsi.SCp.sent_command; i < info->SCpnt->cmd_len; i++) outb(info->SCpnt->cmnd[i], REG_FF(info)); outb(CMD_TRANSFERINFO, REG_CMD(info)); -} - -/* Function: int fas216_busservice_selection(FAS216_Info *info, unsigned int stat) - * Purpose : handle bus service in selection phase - * Params : info - interface which caused bus service - * Returns : 0 if unable to service this interrupt - */ -static int fas216_busservice_selection(FAS216_Info *info, unsigned int stat) -{ - fas216_checkmagic(info, "fas216_busservice_selection"); - - switch (stat & STAT_BUSMASK) { - case STAT_DATAOUT: /* data out phase */ - fas216_starttransfer(info, DMA_OUT, 1); - return 1; - - case STAT_DATAIN: /* data in phase */ - fas216_starttransfer(info, DMA_IN, 0); - return 1; - - case STAT_STATUS: /* status phase */ - info->scsi.phase = PHASE_STATUS; - outb(CMD_INITCMDCOMPLETE, REG_CMD(info)); - return 1; - case STAT_MESGIN: /* message in phase */ - info->scsi.phase = PHASE_MSGIN; - outb(CMD_TRANSFERINFO, REG_CMD(info)); - return 1; - - case STAT_MESGOUT:{ /* message out phase */ - char *msg; - int start = 1, msglen; - - /* load message bytes, but don't forget to miss the first - * byte! - */ - while ((msg = msgqueue_getnextmsg(&info->scsi.msgs, &msglen)) != NULL) { - int i; - - for (i = start; i < msglen; i++) - outb(msg[i], REG_FF(info)); - start = 0; - } - outb(CMD_TRANSFERINFO, REG_CMD(info)); - info->scsi.phase = PHASE_MESSAGESENT; - return 1; - } - default: - return 0; - } + info->scsi.phase = PHASE_COMMAND; } -/* Function: int fas216_busservice_messagesent(FAS216_Info *info, unsigned int stat) - * Purpose : handle bus service after the IDENTIFY message has been sent - * Params : info - interface which caused bus service - * Returns : 0 if unable to service this interrupt - */ -static int fas216_busservice_messagesent(FAS216_Info *info, unsigned int stat) -{ - fas216_checkmagic(info, "fas216_busservice_messagesent"); - - switch (stat & STAT_BUSMASK) { - case STAT_MESGIN: /* message in phase */ - info->scsi.phase = PHASE_MSGIN; - outb(CMD_FLUSHFIFO, REG_CMD(info)); - outb(CMD_TRANSFERINFO, REG_CMD(info)); - return 1; - - case STAT_COMMAND: /* command phase */ - fas216_send_command(info); - return 1; - - default: - return 0; - } -} - -/* Function: int fas216_busservice_dataphase(FAS216_Info *info, unsigned int stat) - * Purpose : handle bus service in a data in/out phase. - * Params : info - interface which caused bus service - * Returns : 0 if unable to service this interrupt - * Note : We do not allow the device to change the data direction! - */ -static int fas216_busservice_dataphase(FAS216_Info *info, unsigned int stat) -{ - fas216_checkmagic(info, "fas216_busservice_dataphase"); - - switch (stat & STAT_BUSMASK) { - case STAT_DATAIN: /* continue data in phase */ - if (info->scsi.phase == PHASE_DATAIN) { - fas216_starttransfer(info, DMA_IN, 0); - return 1; - } else - return 0; - - case STAT_DATAOUT: /* continue data out phase */ - if (info->scsi.phase == PHASE_DATAOUT) { - fas216_starttransfer(info, DMA_OUT, 0); - return 1; - } else - return 0; - - case STAT_STATUS: /* status in phase */ - fas216_stoptransfer(info); - info->scsi.phase = PHASE_STATUS; - outb(CMD_INITCMDCOMPLETE, REG_CMD(info)); - return 1; - - case STAT_MESGIN: /* message in phase */ - fas216_stoptransfer(info); - info->scsi.phase = PHASE_MSGIN; - outb(CMD_TRANSFERINFO, REG_CMD(info)); - return 1; - - default: - return 0; - } -} - -/* Function: int fas216_busservice_reconnected(FAS216_Info *info, unsigned int stat) - * Purpose : handle bus service in after a reconnection +/* Function: void fas216_send_messageout(FAS216_Info *info, int start) + * Purpose : handle bus service to send a message * Params : info - interface which caused bus service - * Returns : 0 if unable to service this interrupt * Note : We do not allow the device to change the data direction! */ -static int fas216_busservice_reconnected(FAS216_Info *info, unsigned int stat) +static void fas216_send_messageout(FAS216_Info *info, int start) { - fas216_checkmagic(info, "fas216_busservice_reconnected"); - - switch (stat & STAT_BUSMASK) { - case STAT_MESGIN: - outb(CMD_TRANSFERINFO, REG_CMD(info)); - return 1; + unsigned int tot_msglen = msgqueue_msglength(&info->scsi.msgs); - case STAT_STATUS: - fas216_finish_reconnect(info); - info->scsi.phase = PHASE_STATUS; - outb(CMD_INITCMDCOMPLETE, REG_CMD(info)); - return 1; - - case STAT_DATAOUT: /* data out phase */ - fas216_finish_reconnect(info); - fas216_starttransfer(info, DMA_OUT, 1); - return 1; + fas216_checkmagic(info, "fas216_send_messageout"); - case STAT_DATAIN: /* data in phase */ - fas216_finish_reconnect(info); - fas216_starttransfer(info, DMA_IN, 0); - return 1; + outb(CMD_FLUSHFIFO, REG_CMD(info)); - default: - return 0; - } -} + if (tot_msglen) { + struct message *msg; + int msgnr = 0; -/* Function: int fas216_busservice_messageout(FAS216_Info *info, unsigned int stat) - * Purpose : handle bus service to send a message - * Params : info - interface which caused bus service - * Returns : 0 if unable to service this interrupt - * Note : We do not allow the device to change the data direction! - */ -static int fas216_busservice_messageout(FAS216_Info *info, unsigned int stat) -{ - fas216_checkmagic(info, "fas216_busservice_messageout"); - - if ((stat & STAT_BUSMASK) != STAT_MESGOUT) { - printk("scsi%d.%c: didn't manage MESSAGE OUT phase\n", - info->host->host_no, fas216_target(info)); - return 0; - } else { - unsigned int msglen = msgqueue_msglength(&info->scsi.msgs); + while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) { + int i; - outb(CMD_FLUSHFIFO, REG_CMD(info)); + for (i = start; i < msg->length; i++) + outb(msg->msg[i], REG_FF(info)); - if (msglen == 0) - outb(NOP, REG_FF(info)); - else { - char *msg; + msg->fifo = tot_msglen - (inb(REG_CFIS(info)) & CFIS_CF); + start = 0; + } + } else + outb(NOP, REG_FF(info)); - while ((msg = msgqueue_getnextmsg(&info->scsi.msgs, &msglen)) != NULL) { - int i; + outb(CMD_TRANSFERINFO, REG_CMD(info)); - for (i = 0; i < msglen; i++) - outb(msg[i], REG_FF(info)); - } - } - outb(CMD_TRANSFERINFO, REG_CMD(info)); - info->scsi.phase = PHASE_AFTERMSGOUT; - return 1; - } + info->scsi.phase = PHASE_MSGOUT; } /* Function: void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr) @@ -1151,91 +1274,150 @@ case IS_COMPLETE: /* last action completed */ outb(CMD_NOP, REG_CMD(info)); - switch (info->scsi.phase) { - case PHASE_SELECTION: /* while selecting - selected target */ - if (!fas216_busservice_selection(info, stat)) - printk("scsi%d.%c: bus phase %s after connect?\n", - info->host->host_no, fas216_target(info), - fas216_bus_phase(stat)); - break; - - case PHASE_MESSAGESENT: - if (!fas216_busservice_messagesent(info, stat)) - printk("scsi%d.%c: bus phase %s after message sent?\n", - info->host->host_no, fas216_target(info), - fas216_bus_phase(stat)); - break; +#define STATE(st,ph) ((ph) << 3 | (st)) + /* This table describes the legal SCSI state transitions, + * as described by the SCSI II spec. + */ + switch (STATE(stat & STAT_BUSMASK, info->scsi.phase)) { + /* Reselmsgin -> Data In */ + case STATE(STAT_DATAIN, PHASE_RECONNECTED): + fas216_finish_reconnect(info); + case STATE(STAT_DATAIN, PHASE_SELSTEPS):/* Sel w/ steps -> Data In */ + case STATE(STAT_DATAIN, PHASE_DATAIN): /* Data In -> Data In */ + case STATE(STAT_DATAIN, PHASE_MSGOUT): /* Message Out -> Data In */ + case STATE(STAT_DATAIN, PHASE_COMMAND): /* Command -> Data In */ + case STATE(STAT_DATAIN, PHASE_MSGIN): /* Message In -> Data In */ + fas216_starttransfer(info, DMA_IN, 0); + return; - case PHASE_DATAIN: /* while transfering data in */ - case PHASE_DATAOUT: /* while transfering data out */ - if (!fas216_busservice_dataphase(info, stat)) - printk("scsi%d.%c: bus phase %s after %s?\n", - info->host->host_no, fas216_target(info), - fas216_bus_phase(stat), fas216_drv_phase(info)); - break; + case STATE(STAT_DATAOUT, PHASE_DATAOUT):/* Data Out -> Data Out */ + fas216_starttransfer(info, DMA_OUT, 0); + return; - case PHASE_RECONNECTED: /* newly reconnected device */ - /* - * Command reconnected - if MESGIN, get message - it may be - * the tag. If not, get command out of the disconnected queue - */ - if (!fas216_busservice_reconnected(info, stat)) - printk("scsi%d.%c: bus phase %s after reconnect?\n", - info->host->host_no, fas216_target(info), - fas216_bus_phase(stat)); - break; + /* Reselmsgin -> Data Out */ + case STATE(STAT_DATAOUT, PHASE_RECONNECTED): + fas216_finish_reconnect(info); + case STATE(STAT_DATAOUT, PHASE_SELSTEPS):/* Sel w/ steps-> Data Out */ + case STATE(STAT_DATAOUT, PHASE_MSGOUT): /* Message Out -> Data Out */ + case STATE(STAT_DATAOUT, PHASE_COMMAND):/* Command -> Data Out */ + case STATE(STAT_DATAOUT, PHASE_MSGIN): /* Message In -> Data Out */ + fas216_starttransfer(info, DMA_OUT, 1); + return; + + /* Reselmsgin -> Status */ + case STATE(STAT_STATUS, PHASE_RECONNECTED): + fas216_finish_reconnect(info); + goto status; + case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out -> Status */ + case STATE(STAT_STATUS, PHASE_DATAIN): /* Data In -> Status */ + fas216_stoptransfer(info); + case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps -> Status */ + case STATE(STAT_STATUS, PHASE_MSGOUT): /* Message Out -> Status */ + case STATE(STAT_STATUS, PHASE_COMMAND): /* Command -> Status */ + case STATE(STAT_STATUS, PHASE_MSGIN): /* Message In -> Status */ + status: + outb(CMD_INITCMDCOMPLETE, REG_CMD(info)); + info->scsi.phase = PHASE_STATUS; + return; + + case STATE(STAT_MESGIN, PHASE_DATAOUT): /* Data Out -> Message In */ + case STATE(STAT_MESGIN, PHASE_DATAIN): /* Data In -> Message In */ + fas216_stoptransfer(info); + case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In */ + case STATE(STAT_MESGIN, PHASE_MSGOUT): /* Message Out -> Message In */ + info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF; + outb(CMD_TRANSFERINFO, REG_CMD(info)); + info->scsi.phase = PHASE_MSGIN; + return; - case PHASE_MSGIN: - case PHASE_AFTERMSGOUT: - switch (stat & STAT_BUSMASK) { - case STAT_MESGIN: - info->scsi.phase = PHASE_MSGIN; - outb(CMD_TRANSFERINFO, REG_CMD(info)); - break; + /* Reselmsgin -> Message In */ + case STATE(STAT_MESGIN, PHASE_RECONNECTED): + case STATE(STAT_MESGIN, PHASE_MSGIN): + info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF; + outb(CMD_TRANSFERINFO, REG_CMD(info)); + return; - case STAT_COMMAND: /* command phase */ - fas216_send_command(info); - info->scsi.phase = PHASE_SELECTION; - break; + /* Reselmsgin -> Command */ + case STATE(STAT_COMMAND, PHASE_RECONNECTED): + fas216_finish_reconnect(info); + case STATE(STAT_COMMAND, PHASE_MSGOUT): /* Message Out -> Command */ + case STATE(STAT_COMMAND, PHASE_MSGIN): /* Message In -> Command */ + fas216_send_command(info); + info->scsi.phase = PHASE_COMMAND; + return; + /* Selection -> Message Out */ + case STATE(STAT_MESGOUT, PHASE_SELECTION): + fas216_send_messageout(info, 1); + return; + /* Any -> Message Out */ + case STATE(STAT_MESGOUT, PHASE_MSGOUT_EXPECT): + fas216_send_messageout(info, 0); + return; + + /* Error recovery rules. + * These either attempt to abort or retry the operation. + * TODO: we need more of these + */ + case STATE(STAT_COMMAND, PHASE_COMMAND):/* Command -> Command */ + /* error - we've sent out all the command bytes + * we have. + * NOTE: we need SAVE DATA POINTERS/RESTORE DATA POINTERS + * to include the command bytes sent for this to work + * correctly. + */ + printk(KERN_ERR "scsi%d.%c: " + "target trying to receive more command bytes\n", + info->host->host_no, fas216_target(info)); + outb(CMD_SETATN, REG_CMD(info)); + outb(15, REG_STCL(info)); + outb(0, REG_STCM(info)); + outb(0, REG_STCH(info)); + outb(CMD_PADBYTES | CMD_WITHDMA, REG_CMD(info)); + msgqueue_flush(&info->scsi.msgs); + msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); + info->scsi.phase = PHASE_MSGOUT_EXPECT; + return; - default: - printk("scsi%d.%c: bus phase %s after %s?\n", - info->host->host_no, fas216_target(info), - fas216_bus_phase(stat), - fas216_drv_phase(info)); - } - break; + /* Selection -> Message Out */ + case STATE(STAT_MESGOUT, PHASE_SELSTEPS): + case STATE(STAT_MESGOUT, PHASE_MSGOUT): /* Message Out -> Message Out */ + /* If we get another message out phase, this + * usually means some parity error occurred. + * Resend complete set of messages. If we have + * more than 1 byte to send, we need to assert + * ATN again. + */ + if (msgqueue_msglength(&info->scsi.msgs) > 1) + outb(CMD_SETATN, REG_CMD(info)); - case PHASE_MSGOUT: - if (!fas216_busservice_messageout(info, stat)) - printk("scsi%d.%c: bus phase %s instead of message out?\n", - info->host->host_no, fas216_target(info), - fas216_bus_phase(stat)); - break; + fas216_send_messageout(info, 0); + return; + } - case PHASE_DISCONNECT: - printk("scsi%d.%c: disconnect message received, but bus service %s?\n", + if (info->scsi.phase == PHASE_MSGIN_DISCONNECT) { + printk(KERN_ERR "scsi%d.%c: disconnect message received, but bus service %s?\n", info->host->host_no, fas216_target(info), fas216_bus_phase(stat)); + msgqueue_flush(&info->scsi.msgs); outb(CMD_SETATN, REG_CMD(info)); msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); - info->scsi.phase = PHASE_MSGOUT; + info->scsi.phase = PHASE_MSGOUT_EXPECT; info->scsi.aborting = 1; outb(CMD_TRANSFERINFO, REG_CMD(info)); - break; - - default: - printk("scsi%d.%c: internal phase %s for bus service?" - " What do I do with this?\n", - info->host->host_no, fas216_target(info), - fas216_drv_phase(info)); + return; } - break; + printk(KERN_ERR "scsi%d.%c: bus phase %s after %s?\n", + info->host->host_no, fas216_target(info), + fas216_bus_phase(stat), + fas216_drv_phase(info)); + print_debug_list(); + return; default: printk("scsi%d.%c: bus service at step %d?\n", info->host->host_no, fas216_target(info), ssr & IS_BITS); + print_debug_list(); } } @@ -1269,6 +1451,7 @@ case PHASE_MSGIN: /* message in phase */ case PHASE_RECONNECTED: /* reconnected command */ if ((stat & STAT_BUSMASK) == STAT_MESGIN) { + info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF; fas216_message(info); break; } @@ -1300,10 +1483,11 @@ if (stat & STAT_INT) { if (isr & INST_BUSRESET) - printk("scsi%d.H: fas216: bus reset detected\n", instance->host_no); - else if (isr & INST_ILLEGALCMD) + printk("scsi%d.H: bus reset detected\n", instance->host_no); + else if (isr & INST_ILLEGALCMD) { printk(KERN_CRIT "scsi%d.H: illegal command given\n", instance->host_no); - else if (isr & INST_DISCONNECT) + fas216_dumpstate(info); + } else if (isr & INST_DISCONNECT) fas216_disconnect_intr(info); else if (isr & INST_RESELECTED) /* reselected */ fas216_reselected_intr(info); @@ -1327,7 +1511,7 @@ static void fas216_kick(FAS216_Info *info) { Scsi_Cmnd *SCpnt; - int i, msglen, from_queue = 0; + int tot_msglen, from_queue = 0; fas216_checkmagic(info, "fas216_kick"); @@ -1380,7 +1564,8 @@ if (from_queue) { #ifdef SCSI2_TAG - if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE) { + if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE && + SCpnt->cmnd[0] != INQUIRY) { SCpnt->device->current_tag += 1; if (SCpnt->device->current_tag == 0) SCpnt->device->current_tag = 1; @@ -1409,6 +1594,7 @@ /* build outgoing message bytes */ msgqueue_flush(&info->scsi.msgs); + if (info->device[SCpnt->target].disconnect_ok) msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(1, SCpnt->lun)); else @@ -1418,15 +1604,29 @@ if (SCpnt->tag) msgqueue_addmsg(&info->scsi.msgs, 2, SIMPLE_QUEUE_TAG, SCpnt->tag); - /* add synchronous negociation */ - if (SCpnt->cmnd[0] == REQUEST_SENSE && - info->device[SCpnt->target].negstate == syncneg_start) { - info->device[SCpnt->target].negstate = syncneg_sent; +#ifdef SCSI2_WIDE + if (info->device[SCpnt->target].wide_state == neg_wait) { + info->device[SCpnt->target].wide_state = neg_inprogress; + msgqueue_addmsg(&info->scsi.msgs, 4, + EXTENDED_MESSAGE, 2, EXTENDED_WDTR, + info->ifcfg.wide_max_size); + } +#ifdef SCSI2_SYNC + else +#endif +#endif +#ifdef SCSI2_SYNC + if ((info->device[SCpnt->target].sync_state == neg_wait || + info->device[SCpnt->target].sync_state == neg_complete) && + (SCpnt->cmnd[0] == REQUEST_SENSE || + SCpnt->cmnd[0] == INQUIRY)) { + info->device[SCpnt->target].sync_state = neg_inprogress; msgqueue_addmsg(&info->scsi.msgs, 5, EXTENDED_MESSAGE, 3, EXTENDED_SDTR, 1000 / info->ifcfg.clockrate, info->ifcfg.sync_max_depth); } +#endif /* following what the ESP driver says */ outb(0, REG_STCL(info)); @@ -1444,25 +1644,29 @@ /* synchronous transfers */ fas216_set_sync(info, SCpnt->target); - msglen = msgqueue_msglength(&info->scsi.msgs); + tot_msglen = msgqueue_msglength(&info->scsi.msgs); - if (msglen == 1 || msglen == 3) { + if (tot_msglen == 1 || tot_msglen == 3) { /* * We have an easy message length to send... */ - char *msg; + struct message *msg; + int msgnr = 0, i; + + info->scsi.phase = PHASE_SELSTEPS; /* load message bytes */ - while ((msg = msgqueue_getnextmsg(&info->scsi.msgs, &msglen)) != NULL) { - for (i = 0; i < msglen; i++) - outb(msg[i], REG_FF(info)); + while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) { + for (i = 0; i < msg->length; i++) + outb(msg->msg[i], REG_FF(info)); + msg->fifo = tot_msglen - (inb(REG_CFIS(info)) & CFIS_CF); } /* load command */ for (i = 0; i < SCpnt->cmd_len; i++) outb(SCpnt->cmnd[i], REG_FF(info)); - if (msglen == 1) + if (tot_msglen == 1) outb(CMD_SELECTATN, REG_CMD(info)); else outb(CMD_SELECTATN3, REG_CMD(info)); @@ -1471,17 +1675,11 @@ * We have an unusual number of message bytes to send. * Load first byte into fifo, and issue SELECT with ATN and * stop steps. - * Note: we only peek at t his message - we need the rest - * later on! */ - int thismsg; - char *msg = msgqueue_peeknextmsg(&info->scsi.msgs, &thismsg); + struct message *msg = msgqueue_getmsg(&info->scsi.msgs, 0); - if (!msg || thismsg < 1) - printk(KERN_CRIT "scsi%d.%c: no message to send, but %d bytes\n", - info->host->host_no, fas216_target(info), msglen); - else - outb(msg[0], REG_FF(info)); + outb(msg->msg[0], REG_FF(info)); + msg->fifo = 1; outb(CMD_SELECTATNSTOP, REG_CMD(info)); } @@ -1525,11 +1723,15 @@ /* * In theory, this should not happen, but just in case it does. */ - if (info->scsi.SCp.ptr && result == DID_OK) { + if (info->scsi.SCp.ptr && + info->scsi.SCp.this_residual && + result == DID_OK) { switch (SCpnt->cmnd[0]) { case INQUIRY: case START_STOP: case READ_CAPACITY: + case TEST_UNIT_READY: + case MODE_SENSE: break; default: @@ -1819,7 +2021,7 @@ */ static void fas216_reset_state(FAS216_Info *info) { - syncneg_t negstate; + neg_t sync_state, wide_state; int i; fas216_checkmagic(info, "fas216_reset_state"); @@ -1833,26 +2035,37 @@ info->scsi.reconnected.lun = 0; info->scsi.reconnected.tag = 0; info->scsi.disconnectable = 0; - info->scsi.last_message = 0; info->scsi.aborting = 0; info->scsi.phase = PHASE_IDLE; - info->scsi.async_stp = fas216_syncperiod(info, info->ifcfg.asyncperiod); + info->scsi.async_stp = + fas216_syncperiod(info, info->ifcfg.asyncperiod); + + if (info->ifcfg.wide_max_size == 0) + wide_state = neg_invalid; + else +#ifdef SCSI2_WIDE + wide_state = neg_wait; +#else + wide_state = neg_invalid; +#endif if (info->host->dma_channel == NO_DMA || !info->dma.setup) - negstate = syncneg_invalid; + sync_state = neg_invalid; else #ifdef SCSI2_SYNC - negstate = syncneg_start; + sync_state = neg_wait; #else - negstate = syncneg_invalid; + sync_state = neg_invalid; #endif for (i = 0; i < 8; i++) { - info->device[i].disconnect_ok = info->ifcfg.disconnect_ok; - info->device[i].negstate = negstate; - info->device[i].period = info->ifcfg.asyncperiod / 4; - info->device[i].stp = info->scsi.async_stp; - info->device[i].sof = 0; + info->device[i].disconnect_ok = info->ifcfg.disconnect_ok; + info->device[i].sync_state = sync_state; + info->device[i].wide_state = wide_state; + info->device[i].period = info->ifcfg.asyncperiod / 4; + info->device[i].stp = info->scsi.async_stp; + info->device[i].sof = 0; + info->device[i].wide_xfer = 0; } } @@ -2083,6 +2296,49 @@ return 0; } +int fas216_print_stats(FAS216_Info *info, char *buffer) +{ + return sprintf(buffer, + "Queued commands: %-10u Issued commands: %-10u\n" + "Done commands : %-10u Reads : %-10u\n" + "Writes : %-10u Others : %-10u\n" + "Disconnects : %-10u Aborts : %-10u\n" + "Resets : %-10u\n", + info->stats.queues, info->stats.removes, + info->stats.fins, info->stats.reads, + info->stats.writes, info->stats.miscs, + info->stats.disconnects, info->stats.aborts, + info->stats.resets); +} + +int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer) +{ + struct fas216_device *dev = &info->device[scd->id]; + int len = 0; + char *p; + + proc_print_scsidevice(scd, buffer, &len, 0); + p = buffer + len; + + p += sprintf(p, " Extensions: "); + + if (scd->tagged_supported) + p += sprintf(p, "TAG %sabled [%d] ", + scd->tagged_queue ? "en" : "dis", + scd->current_tag); + + p += sprintf(p, "\n Transfers : %d-bit ", + 8 << dev->wide_xfer); + + if (dev->sof) + p += sprintf(p, "sync offset %d, %d ns\n", + dev->sof, dev->period * 4); + else + p += sprintf(p, "async\n"); + + return p - buffer; +} + EXPORT_SYMBOL(fas216_init); EXPORT_SYMBOL(fas216_abort); EXPORT_SYMBOL(fas216_reset); @@ -2094,7 +2350,8 @@ EXPORT_SYMBOL(fas216_eh_device_reset); EXPORT_SYMBOL(fas216_eh_bus_reset); EXPORT_SYMBOL(fas216_eh_host_reset); - +EXPORT_SYMBOL(fas216_print_stats); +EXPORT_SYMBOL(fas216_print_device); #ifdef MODULE int init_module(void) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/fas216.h linux.ac/drivers/acorn/scsi/fas216.h --- linux.vanilla/drivers/acorn/scsi/fas216.h Sun Nov 8 15:08:19 1998 +++ linux.ac/drivers/acorn/scsi/fas216.h Sun Jan 24 23:54:37 1999 @@ -40,6 +40,7 @@ #define CMD_TRANSFERINFO 0x10 #define CMD_INITCMDCOMPLETE 0x11 #define CMD_MSGACCEPTED 0x12 +#define CMD_PADBYTES 0x18 #define CMD_SETATN 0x1a #define CMD_RSETATN 0x1b @@ -171,15 +172,17 @@ typedef enum { PHASE_IDLE, /* we're not planning on doing anything */ PHASE_SELECTION, /* selecting a device */ + PHASE_SELSTEPS, /* selection with command steps */ + PHASE_COMMAND, /* command sent */ PHASE_MESSAGESENT, /* selected, and we're sending cmd */ PHASE_RECONNECTED, /* reconnected */ PHASE_DATAOUT, /* data out to device */ PHASE_DATAIN, /* data in from device */ PHASE_MSGIN, /* message in from device */ - PHASE_MSGOUT, /* message out to device */ - PHASE_AFTERMSGOUT, /* after message out phase */ + PHASE_MSGIN_DISCONNECT, /* disconnecting from bus */ + PHASE_MSGOUT, /* after message out phase */ + PHASE_MSGOUT_EXPECT, /* expecting message out */ PHASE_STATUS, /* status from device */ - PHASE_DISCONNECT, /* disconnecting from bus */ PHASE_DONE /* Command complete */ } phase_t; @@ -197,13 +200,15 @@ } fasdmatype_t; typedef enum { - syncneg_start, /* Negociate with device for Sync xfers */ - syncneg_sent, /* Sync Xfer negociation sent */ - syncneg_complete, /* Sync Xfer complete */ - syncneg_invalid /* Sync Xfer not supported */ -} syncneg_t; + neg_wait, /* Negociate with device */ + neg_inprogress, /* Negociation sent */ + neg_complete, /* Negociation complete */ + neg_targcomplete, /* Target completed negociation */ + neg_invalid /* Negociation not supported */ +} neg_t; #define MAGIC 0x441296bdUL +#define NR_MSGS 8 typedef struct { unsigned long magic_start; @@ -231,7 +236,7 @@ MsgQueue_t msgs; /* message queue for connected device */ unsigned int async_stp; /* Async transfer STP value */ - unsigned short last_message; /* last message to be sent */ + unsigned char msgin_fifo; /* bytes in fifo at time of message in */ unsigned char disconnectable:1; /* this command can be disconnected */ unsigned char aborting:1; /* aborting command */ @@ -255,6 +260,7 @@ unsigned char clockrate; /* clock rate of FAS device (MHz) */ unsigned char select_timeout; /* timeout (R5) */ unsigned char sync_max_depth; /* Synchronous xfer max fifo depth */ + unsigned char wide_max_size; /* Maximum wide transfer size */ unsigned char cntl3; /* Control Reg 3 */ unsigned int asyncperiod; /* Async transfer period (ns) */ unsigned int disconnect_ok:1; /* Disconnects allowed? */ @@ -267,12 +273,14 @@ } queues; /* per-device info */ - struct { + struct fas216_device { unsigned char disconnect_ok:1; /* device can disconnect */ - unsigned int period; /* sync xfer period (*4ns) */ + unsigned char period; /* sync xfer period in (*4ns) */ unsigned char stp; /* synchronous transfer period */ unsigned char sof; /* synchronous offset register */ - syncneg_t negstate; /* synchronous transfer mode */ + unsigned char wide_xfer; /* currently negociated wide transfer */ + neg_t sync_state; /* synchronous transfer mode */ + neg_t wide_state; /* wide transfer mode */ } device[8]; unsigned char busyluns[8]; /* array of bits indicating LUNs busy */ @@ -339,6 +347,9 @@ * Returns : 0 on success */ extern int fas216_release (struct Scsi_Host *instance); + +extern int fas216_print_stats(FAS216_Info *info, char *buffer); +extern int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer); /* Function: int fas216_eh_abort(Scsi_Cmnd *SCpnt) * Purpose : abort this command diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/msgqueue.c linux.ac/drivers/acorn/scsi/msgqueue.c --- linux.vanilla/drivers/acorn/scsi/msgqueue.c Sun Nov 8 15:08:19 1998 +++ linux.ac/drivers/acorn/scsi/msgqueue.c Sun Jan 24 23:54:37 1999 @@ -83,45 +83,25 @@ int length = 0; for (mq = msgq->qe; mq; mq = mq->next) - length += mq->length; + length += mq->msg.length; return length; } /* - * Function: char *msgqueue_getnextmsg(MsgQueue_t *msgq, int *length) - * Purpose : return a message & its length + * Function: struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno) + * Purpose : return a message * Params : msgq - queue to obtain message from - * length - pointer to int for message length + * : msgno - message number * Returns : pointer to message string, or NULL */ -char *msgqueue_getnextmsg(MsgQueue_t *msgq, int *length) +struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno) { struct msgqueue_entry *mq; - if ((mq = msgq->qe) != NULL) { - msgq->qe = mq->next; - mqe_free(msgq, mq); - *length = mq->length; - } - - return mq ? mq->msg : NULL; -} - -/* - * Function: char *msgqueue_peeknextmsg(MsgQueue_t *msgq, int *length) - * Purpose : return next message & length without removing it from the list - * Params : msgq - queue to obtain message from - * : length - pointer to int for message length - * Returns : pointer to message string, or NULL - */ -char *msgqueue_peeknextmsg(MsgQueue_t *msgq, int *length) -{ - struct msgqueue_entry *mq = msgq->qe; - - *length = mq ? mq->length : 0; + for (mq = msgq->qe; mq && msgno; mq = mq->next, msgno--); - return mq ? mq->msg : NULL; + return mq ? &mq->msg : NULL; } /* @@ -143,10 +123,11 @@ va_start(ap, length); for (i = 0; i < length; i++) - mq->msg[i] = va_arg(ap, unsigned char); + mq->msg.msg[i] = va_arg(ap, unsigned char); va_end(ap); - mq->length = length; + mq->msg.length = length; + mq->msg.fifo = 0; mq->next = NULL; mqp = &msgq->qe; @@ -178,8 +159,7 @@ EXPORT_SYMBOL(msgqueue_initialise); EXPORT_SYMBOL(msgqueue_free); EXPORT_SYMBOL(msgqueue_msglength); -EXPORT_SYMBOL(msgqueue_getnextmsg); -EXPORT_SYMBOL(msgqueue_peeknextmsg); +EXPORT_SYMBOL(msgqueue_getmsg); EXPORT_SYMBOL(msgqueue_addmsg); EXPORT_SYMBOL(msgqueue_flush); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/msgqueue.h linux.ac/drivers/acorn/scsi/msgqueue.h --- linux.vanilla/drivers/acorn/scsi/msgqueue.h Sun Nov 8 15:08:19 1998 +++ linux.ac/drivers/acorn/scsi/msgqueue.h Sun Jan 24 23:54:37 1999 @@ -6,9 +6,14 @@ #ifndef MSGQUEUE_H #define MSGQUEUE_H -struct msgqueue_entry { +struct message { char msg[8]; int length; + int fifo; +}; + +struct msgqueue_entry { + struct message msg; struct msgqueue_entry *next; }; @@ -21,60 +26,51 @@ } MsgQueue_t; /* - * Function: void msgqueue_initialise (MsgQueue_t *msgq) + * Function: void msgqueue_initialise(MsgQueue_t *msgq) * Purpose : initialise a message queue * Params : msgq - queue to initialise */ -extern void msgqueue_initialise (MsgQueue_t *msgq); +extern void msgqueue_initialise(MsgQueue_t *msgq); /* - * Function: void msgqueue_free (MsgQueue_t *msgq) + * Function: void msgqueue_free(MsgQueue_t *msgq) * Purpose : free a queue * Params : msgq - queue to free */ -extern void msgqueue_free (MsgQueue_t *msgq); +extern void msgqueue_free(MsgQueue_t *msgq); /* - * Function: int msgqueue_msglength (MsgQueue_t *msgq) + * Function: int msgqueue_msglength(MsgQueue_t *msgq) * Purpose : calculate the total length of all messages on the message queue * Params : msgq - queue to examine * Returns : number of bytes of messages in queue */ -extern int msgqueue_msglength (MsgQueue_t *msgq); +extern int msgqueue_msglength(MsgQueue_t *msgq); /* - * Function: char *msgqueue_getnextmsg (MsgQueue_t *msgq, int *length) + * Function: struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno) * Purpose : return a message & its length * Params : msgq - queue to obtain message from - * length - pointer to int for message length - * Returns : pointer to message string, or NULL - */ -extern char *msgqueue_getnextmsg (MsgQueue_t *msgq, int *length); - -/* - * Function: char *msgqueue_peeknextmsg(MsgQueue_t *msgq, int *length) - * Purpose : return next message & length without removing it from the list - * Params : msgq - queue to obtain message from - * : length - pointer to int for message length + * : msgno - message number * Returns : pointer to message string, or NULL */ -extern char *msgqueue_peeknextmsg(MsgQueue_t *msgq, int *length); +extern struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno); /* - * Function: int msgqueue_addmsg (MsgQueue_t *msgq, int length, ...) + * Function: int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...) * Purpose : add a message onto a message queue * Params : msgq - queue to add message on * length - length of message * ... - message bytes * Returns : != 0 if successful */ -extern int msgqueue_addmsg (MsgQueue_t *msgq, int length, ...); +extern int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...); /* - * Function: void msgqueue_flush (MsgQueue_t *msgq) + * Function: void msgqueue_flush(MsgQueue_t *msgq) * Purpose : flush all messages from message queue * Params : msgq - queue to flush */ -extern void msgqueue_flush (MsgQueue_t *msgq); +extern void msgqueue_flush(MsgQueue_t *msgq); #endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/powertec.c linux.ac/drivers/acorn/scsi/powertec.c --- linux.vanilla/drivers/acorn/scsi/powertec.c Tue Dec 22 23:19:35 1998 +++ linux.ac/drivers/acorn/scsi/powertec.c Sun Jan 24 23:54:37 1999 @@ -114,6 +114,8 @@ powertecscsi_irqenable, powertecscsi_irqdisable, NULL, + NULL, + NULL, NULL }; @@ -271,8 +273,9 @@ info->info.ifcfg.select_timeout = 255; info->info.ifcfg.asyncperiod = POWERTEC_ASYNC_PERIOD; info->info.ifcfg.sync_max_depth = POWERTEC_SYNC_DEPTH; - info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; + info->info.ifcfg.cntl3 = /*CNTL3_BS8 |*/ CNTL3_FASTSCSI | CNTL3_FASTCLK; info->info.ifcfg.disconnect_ok = 1; + info->info.ifcfg.wide_max_size = 0; info->info.dma.setup = powertecscsi_dma_setup; info->info.dma.pseudo = NULL; info->info.dma.stop = powertecscsi_dma_stop; @@ -443,31 +446,12 @@ host->io_port, host->irq, host->dma_channel, info->info.scsi.type, info->control.terms ? "on" : "off"); - pos += sprintf(buffer+pos, - "Queued commands: %-10u Issued commands: %-10u\n" - "Done commands : %-10u Reads : %-10u\n" - "Writes : %-10u Others : %-10u\n" - "Disconnects : %-10u Aborts : %-10u\n" - "Resets : %-10u\n", - info->info.stats.queues, info->info.stats.removes, - info->info.stats.fins, info->info.stats.reads, - info->info.stats.writes, info->info.stats.miscs, - info->info.stats.disconnects, info->info.stats.aborts, - info->info.stats.resets); + pos += fas216_print_stats(&info->info, buffer + pos); - pos += sprintf (buffer+pos, "\nAttached devices:%s\n", host->host_queue ? "" : " none"); + pos += sprintf (buffer+pos, "\nAttached devices:\n"); for (scd = host->host_queue; scd; scd = scd->next) { - int len; - - proc_print_scsidevice (scd, buffer, &len, pos); - pos += len; - pos += sprintf (buffer+pos, "Extensions: "); - if (scd->tagged_supported) - pos += sprintf (buffer+pos, "TAG %sabled [%d] ", - scd->tagged_queue ? "en" : "dis", - scd->current_tag); - pos += sprintf (buffer+pos, "\n"); + pos += fas216_print_device(&info->info, scd, buffer + pos); if (pos + begin < offset) { begin += pos; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/queue.c linux.ac/drivers/acorn/scsi/queue.c --- linux.vanilla/drivers/acorn/scsi/queue.c Sun Nov 8 15:08:19 1998 +++ linux.ac/drivers/acorn/scsi/queue.c Sun Jan 24 23:54:37 1999 @@ -55,6 +55,7 @@ q->magic = QUEUE_MAGIC_FREE; q->SCpnt = NULL; } + q -= 1; q->next = NULL; } 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 Thu Jan 14 01:25:21 1999 +++ linux.ac/drivers/block/genhd.c Mon Feb 1 22:06:27 1999 @@ -130,6 +130,14 @@ SYS_IND(p) == LINUX_EXTENDED_PARTITION); } +static int sector_partition_scale(kdev_t dev) +{ + if (hardsect_size[MAJOR(dev)] != NULL) + return (hardsect_size[MAJOR(dev)][MINOR(dev)]/512); + else + return (1); +} + static unsigned int get_ptable_blocksize(kdev_t dev) { int ret = 1024; @@ -149,6 +157,7 @@ * 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: @@ -196,6 +205,7 @@ struct partition *p; unsigned long first_sector, first_size, this_sector, this_size; int mask = (1 << hd->minor_shift) - 1; + int sector_size = sector_partition_scale(dev); int i; first_sector = hd->part[MINOR(dev)].start_sect; @@ -233,22 +243,22 @@ * First process the data partition(s) */ for (i=0; i<4; i++, p++) { - if (!NR_SECTS(p) || is_extended_partition(p)) - continue; + if (!NR_SECTS(p) || is_extended_partition(p)) + continue; - /* Check the 3rd and 4th entries - - these sometimes contain random garbage */ - if (i >= 2 - && START_SECT(p) + NR_SECTS(p) > this_size - && (this_sector + START_SECT(p) < first_sector || - this_sector + START_SECT(p) + NR_SECTS(p) > - first_sector + first_size)) - continue; - - add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p)); - current_minor++; - if ((current_minor & mask) == 0) - goto done; + /* Check the 3rd and 4th entries - + these sometimes contain random garbage */ + if (i >= 2 + && START_SECT(p) + NR_SECTS(p) > this_size + && (this_sector + START_SECT(p) < first_sector || + this_sector + START_SECT(p) + NR_SECTS(p) > + first_sector + first_size)) + continue; + + add_partition(hd, current_minor, this_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size); + current_minor++; + if ((current_minor & mask) == 0) + goto done; } /* * Next, process the (first) extended partition, if present. @@ -262,20 +272,21 @@ */ p -= 4; for (i=0; i<4; i++, p++) - if(NR_SECTS(p) && is_extended_partition(p)) - break; + if(NR_SECTS(p) && is_extended_partition(p)) + break; if (i == 4) - goto done; /* nothing left to do */ + goto done; /* nothing left to do */ - hd->part[current_minor].nr_sects = NR_SECTS(p); - hd->part[current_minor].start_sect = first_sector + START_SECT(p); - this_sector = first_sector + START_SECT(p); + hd->part[current_minor].nr_sects = NR_SECTS(p) * sector_size; /* JSt */ + hd->part[current_minor].start_sect = first_sector + START_SECT(p) * sector_size; + this_sector = first_sector + START_SECT(p) * sector_size; dev = MKDEV(hd->major, current_minor); brelse(bh); } done: brelse(bh); } + #ifdef CONFIG_SOLARIS_X86_PARTITION static void solaris_x86_partition(struct gendisk *hd, kdev_t dev, long offset) { @@ -317,11 +328,13 @@ #endif #ifdef CONFIG_BSD_DISKLABEL -static void check_and_add_bsd_partition(struct gendisk *hd, struct bsd_partition *bsd_p) +static void check_and_add_bsd_partition(struct gendisk *hd, + struct bsd_partition *bsd_p, kdev_t dev) { struct hd_struct *lin_p; /* check relative position of partitions. */ - for (lin_p = hd->part + 1; lin_p - hd->part < current_minor; lin_p++) { + for (lin_p = hd->part + 1 + MINOR(dev); + lin_p - hd->part - MINOR(dev) < current_minor; lin_p++) { /* no relationship -> try again */ if (lin_p->start_sect + lin_p->nr_sects <= bsd_p->p_offset || lin_p->start_sect >= bsd_p->p_offset + bsd_p->p_size) @@ -383,7 +396,7 @@ break; if (p->p_fstype != BSD_FS_UNUSED) - check_and_add_bsd_partition(hd, p); + check_and_add_bsd_partition(hd, p, dev); } brelse(bh); @@ -436,6 +449,7 @@ struct partition *p; unsigned char *data; int mask = (1 << hd->minor_shift) - 1; + int sector_size = sector_partition_scale(dev); #ifdef CONFIG_BSD_DISKLABEL /* no bsd disklabel as a default */ kdev_t bsd_kdev = 0; @@ -538,7 +552,7 @@ for (i=1 ; i<=4 ; minor++,i++,p++) { if (!NR_SECTS(p)) continue; - add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p)); + add_partition(hd, minor, first_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size); if (is_extended_partition(p)) { printk(" <"); /* @@ -790,7 +804,7 @@ struct sgi_partition *p; #define SGI_LABEL_MAGIC 0x0be5a941 - if(!(bh = bread(dev, 0, 1024))) { + if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) { printk("Dev %s: unable to read partition table\n", kdevname(dev)); return -1; } @@ -854,11 +868,18 @@ int blk; int part, res; + /* + * Don't bother touching M/O 2K media. + */ + + if (get_ptable_blocksize(dev) != 1024) + return 0; + set_blocksize(dev,512); res = 0; for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) { - if(!(bh = bread(dev,blk,512))) { + if(!(bh = bread(dev,blk,get_ptable_blocksize(dev)))) { printk("Dev %s: unable to read RDB block %d\n", kdevname(dev),blk); goto rdb_done; @@ -875,7 +896,7 @@ blk = htonl(rdb->rdb_PartitionList); brelse(bh); for (part = 1; blk > 0 && part <= 16; part++) { - if (!(bh = bread(dev,blk,512))) { + if (!(bh = bread(dev,blk, get_ptable_blocksize(dev)))) { printk("Dev %s: unable to read partition block %d\n", kdevname(dev),blk); goto rdb_done; @@ -908,6 +929,10 @@ } rdb_done: + /* + * FIXME: should restore the original size. Then we could clean + * up the M/O skip. Amiga people ? + */ set_blocksize(dev,BLOCK_SIZE); return res; } @@ -1089,7 +1114,7 @@ partsect = extensect = pi->st; while (1) { - xbh = bread (dev, partsect / 2, 1024); + xbh = bread (dev, partsect / 2, get_ptable_blocksize(dev)); if (!xbh) { printk (" block %ld read failed\n", partsect); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ide-disk.c linux.ac/drivers/block/ide-disk.c --- linux.vanilla/drivers/block/ide-disk.c Tue Jan 19 02:57:24 1999 +++ linux.ac/drivers/block/ide-disk.c Sat Jan 30 18:38:10 1999 @@ -101,20 +101,6 @@ id->cyls = lba_sects / (16 * 63); /* correct cyls */ return 1; /* lba_capacity is our only option */ } - /* - * This is a split test for drives less than 8 Gig only. - * Drives less than 8GB sometimes declare that they have 15 heads. - * This is an accounting trick (0-15) == (1-16), just an initial - * zero point difference. - */ - if ((id->lba_capacity < 16514064) && (lba_sects > chs_sects) && - ((id->heads == 15) || (id->heads == 16)) && (id->sectors == 63)) { - if (id->heads == 15) - id->cyls = lba_sects / (15 * 63); /* correct cyls */ - if (id->heads == 16) - id->cyls = lba_sects / (16 * 63); /* correct cyls */ - return 1; /* lba_capacity is our only option */ - } /* perform a rough sanity check on lba_sects: within 10% is "okay" */ if ((lba_sects - chs_sects) < _10_percent) { return 1; /* lba_capacity is good */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ide-probe.c linux.ac/drivers/block/ide-probe.c --- linux.vanilla/drivers/block/ide-probe.c Wed Jan 6 23:02:18 1999 +++ linux.ac/drivers/block/ide-probe.c Sat Jan 30 17:45:45 1999 @@ -720,17 +720,39 @@ } if (register_blkdev (hwif->major, hwif->name, ide_fops)) { printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major); - } else if (init_irq (hwif)) { - printk("%s: UNABLE TO GET IRQ %d\n", hwif->name, hwif->irq); - (void) unregister_blkdev (hwif->major, hwif->name); - } else { - init_gendisk(hwif); - blk_dev[hwif->major].data = hwif; - blk_dev[hwif->major].request_fn = rfn; - blk_dev[hwif->major].queue = ide_get_queue; - read_ahead[hwif->major] = 8; /* (4kB) */ - hwif->present = 1; /* success */ + return (hwif->present = 0); } + + if (init_irq (hwif)) { + int i = hwif->irq; + /* + * It failed to initialise. Find the default IRQ for + * this port and try that. + */ + if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) + { + printk("%s: Disabled unable to get IRQ %d.\n", hwif->name, i); + (void) unregister_blkdev (hwif->major, hwif->name); + return (hwif->present = 0); + } + if(init_irq (hwif)) + { + printk("%s: probed IRQ %d and default IRQ %d failed.\n", + hwif->name, i, hwif->irq); + (void) unregister_blkdev (hwif->major, hwif->name); + return (hwif->present = 0); + } + printk("%s: probed IRQ %d failed, using default.\n", + hwif->name, hwif->irq); + } + + init_gendisk(hwif); + blk_dev[hwif->major].data = hwif; + blk_dev[hwif->major].request_fn = rfn; + blk_dev[hwif->major].queue = ide_get_queue; + read_ahead[hwif->major] = 8; /* (4kB) */ + hwif->present = 1; /* success */ + #if (DEBUG_SPINLOCK > 0) { static int done = 0; 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 Jan 19 02:57:24 1999 +++ linux.ac/drivers/block/ide.c Mon Feb 1 00:37:11 1999 @@ -2068,6 +2068,12 @@ (unsigned long *) &loc->start)) return -EFAULT; return 0; } + case BLKSSZGET: + /* Block size of media */ + return put_user(blksize_size[HWIF(drive)->major] + [minor&PARTN_MASK], + (int *)arg); + case BLKFLSBUF: if (!capable(CAP_SYS_ADMIN)) return -EACCES; fsync_dev(inode->i_rdev); 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 Sun Nov 8 15:07:36 1998 +++ linux.ac/drivers/block/rd.c Mon Feb 1 00:39:15 1999 @@ -170,14 +170,12 @@ break; case BLKGETSIZE: /* Return device size */ if (!arg) return -EINVAL; - err = verify_area(VERIFY_WRITE, (long *) arg, - sizeof(long)); - if (err) - return err; - put_user(rd_length[MINOR(inode->i_rdev)] / 512, + return put_user(rd_length[MINOR(inode->i_rdev)] / 512, (long *) arg); - return 0; - + case BLKSSZGET: + /* Block size of media */ + return put_user(rd_blocksizes[MINOR(inode->i_rdev)], + (int *)arg); default: break; }; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/Makefile linux.ac/drivers/char/Makefile --- linux.vanilla/drivers/char/Makefile Mon Dec 28 23:09:42 1998 +++ linux.ac/drivers/char/Makefile Thu Jan 14 06:27:08 1999 @@ -44,12 +44,17 @@ ifdef CONFIG_VT L_OBJS += keyboard.o endif -ifneq ($(ARCH),m68k) -L_OBJS += pc_keyb.o defkeymap.o + ifneq ($(ARCH),m68k) + L_OBJS += pc_keyb.o defkeymap.o + endif +else +ifdef CONFIG_PCI +L_OBJS += defkeymap.o keyboard.o endif -ifdef CONFIG_MAGIC_SYSRQ -L_OBJS += sysrq.o endif + +ifdef CONFIG_MAGIC_SYSRQ +LX_OBJS += sysrq.o endif ifeq ($(CONFIG_ATARI_DSP56K),y) 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 Jan 26 09:44:20 1999 +++ linux.ac/drivers/char/bttv.c Mon Feb 1 21:38:35 1999 @@ -537,6 +537,8 @@ { 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0}, 0}, /* 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}}, }; #define TVCARDS (sizeof(tvcards)/sizeof(tvcard)) @@ -2880,9 +2882,6 @@ } else if (I2CRead(&(btv->i2c), I2C_STBEE)>=0) { btv->type=BTTV_STB; - } else - if (I2CRead(&(btv->i2c), I2C_VHX)>=0) { - btv->type=BTTV_VHX; } else { if (I2CRead(&(btv->i2c), 0x80)>=0) /* check for msp34xx */ btv->type = BTTV_MIROPRO; @@ -2907,8 +2906,8 @@ } if(btv->type==BTTV_AVERMEDIA98) { - btv->pll.pll_ifreq=28636363; - btv->pll.pll_crystal=BT848_IFORM_XT0; + btv->pll.pll_ifreq=28636363; + btv->pll.pll_crystal=BT848_IFORM_XT0; } if (btv->have_tuner && btv->tuner_type != -1) 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 Jan 26 09:44:20 1999 +++ linux.ac/drivers/char/bttv.h Mon Feb 1 22:46:11 1999 @@ -206,7 +206,8 @@ #define BTTV_MIROPRO 0x0b #define BTTV_ADSTECH_TV 0x0c #define BTTV_AVERMEDIA98 0x0d -#define BTTV_VHX 0x0e +#define BTTV_VHX 0x0e +#define BTTV_ZOLTRIX 0x0f #define AUDIO_TUNER 0x00 #define AUDIO_RADIO 0x01 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 Sun Nov 8 15:10:11 1998 +++ linux.ac/drivers/char/bw-qcam.c Sun Jan 24 21:15:01 1999 @@ -5,6 +5,28 @@ * * Video4Linux conversion work by Alan Cox. * Parport compatibility by Phil Blundell. + * Busy loop avoidance by Mark Cooke. + * + * Module parameters: + * + * maxpoll=<1 - 5000> + * + * When polling the QuickCam for a response, busy-wait for a + * maximum of this many loops. The default of 250 gives little + * impact on interactive response. + * + * NOTE: If this parameter is set too high, the processor + * will busy wait until this loop times out, and then + * slowly poll for a further 5 seconds before failing + * the transaction. You have been warned. + * + * yieldlines=<1 - 250> + * + * When acquiring a frame from the camera, the data gathering + * loop will yield back to the scheduler after completing + * this many lines. The default of 4 provides a trade-off + * between increased frame acquisition time and impact on + * interactive response. */ /* qcam-lib.c -- Library for programming with the Connectix QuickCam. @@ -58,6 +80,14 @@ #include "bw-qcam.h" +#if LINUX_VERSION_CODE >= 0x020117 +MODULE_PARM(maxpoll,"i"); +MODULE_PARM(yieldlines,"i"); +#endif + +static unsigned int maxpoll=250; /* Maximum busy-loop count for qcam I/O */ +static unsigned int yieldlines=4; /* Yield after this many during capture */ + extern __inline__ int read_lpstatus(struct qcam_device *q) { return parport_read_status(q->pport); @@ -154,6 +184,7 @@ q->top = 1; q->left = 14; q->mode = -1; + q->status = QC_PARAM_CHANGE; return q; } @@ -209,14 +240,17 @@ { /* 1000 is enough spins on the I/O for all normal cases, at that point we start to poll slowly - until the camera wakes up */ + until the camera wakes up. However, we are + busy blocked until the camera responds, so + setting it lower is much better for interactive + response. */ - if(runs++>1000) + if(runs++>maxpoll) { current->state=TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); + schedule_timeout(HZ/200); } - if(runs>1050) + if(runs>(maxpoll+1000)) /* 5 seconds */ return -1; } } @@ -226,14 +260,17 @@ { /* 1000 is enough spins on the I/O for all normal cases, at that point we start to poll slowly - until the camera wakes up */ + until the camera wakes up. However, we are + busy blocked until the camera responds, so + setting it lower is much better for interactive + response. */ - if(runs++>1000) + if(runs++>maxpoll) { current->state=TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); + schedule_timeout(HZ/200); } - if(runs++>1050) /* 5 seconds */ + if(runs++>(maxpoll+1000)) /* 5 seconds */ return -1; } } @@ -256,14 +293,17 @@ status = read_lpdata(q); /* 1000 is enough spins on the I/O for all normal cases, at that point we start to poll slowly - until the camera wakes up */ + until the camera wakes up. However, we are + busy blocked until the camera responds, so + setting it lower is much better for interactive + response. */ - if(runs++>1000) + if(runs++>maxpoll) { current->state=TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); + schedule_timeout(HZ/200); } - if(runs++>1050) /* 5 seconds */ + if(runs++>(maxpoll+1000)) /* 5 seconds */ return 0; } while ((status & 1) != val); @@ -287,7 +327,7 @@ lastreg = reg = read_lpstatus(q) & 0xf0; - for (i = 0; i < 300; i++) + for (i = 0; i < 500; i++) { reg = read_lpstatus(q) & 0xf0; if (reg != lastreg) @@ -296,9 +336,20 @@ mdelay(2); } - /* Be liberal in what you accept... */ - if (count > 30 && count < 200) +#if 0 + /* Force camera detection during testing. Sometimes the camera + won't be flashing these bits. Possibly unloading the module + in the middle of a grab? Or some timeout condition? + I've seen this parameter as low as 19 on my 450Mhz box - mpc */ + printk("Debugging: QCam detection counter <30-200 counts as detected>: %d\n", count); + return 1; +#endif + + /* Be (even more) liberal in what you accept... */ + +/* if (count > 30 && count < 200) */ + if (count > 20 && count < 300) return 1; /* found */ else return 0; /* not found */ @@ -352,6 +403,8 @@ static int qc_setscanmode(struct qcam_device *q) { + int old_mode = q->mode; + switch (q->transfer_scale) { case 1: @@ -383,6 +436,10 @@ case QC_UNIDIR: break; } + + if (q->mode != old_mode) + q->status |= QC_PARAM_CHANGE; + return 0; } @@ -434,8 +491,11 @@ qc_command(q, q->contrast); qc_command(q, 0x1f); qc_command(q, q->whitebal); -} + /* Clear flag that we must update the grabbing parameters on the camera + before we grab the next frame */ + q->status &= (~QC_PARAM_CHANGE); +} /* Qc_readbytes reads some bytes from the QC and puts them in the supplied buffer. It returns the number of bytes read, @@ -539,7 +599,7 @@ long qc_capture(struct qcam_device * q, char *buf, unsigned long len) { - int i, j, k; + int i, j, k, yield; int bytes; int linestotrans, transperline; int divisor; @@ -575,7 +635,7 @@ q->transfer_scale; transperline = (transperline + divisor - 1) / divisor; - for (i = 0; i < linestotrans; i++) + for (i = 0, yield = yieldlines; i < linestotrans; i++) { for (pixels_read = j = 0; j < transperline; j++) { @@ -599,6 +659,18 @@ pixels_read += bytes; } (void) qc_readbytes(q, 0); /* reset state machine */ + + /* Grabbing an entire frame from the quickcam is a lengthy + process. We don't (usually) want to busy-block the + processor for the entire frame. yieldlines is a module + parameter. If we yield every line, the minimum frame + time will be 240 / 200 = 1.2 seconds. The compile-time + default is to yield every 4 lines. */ + if (i >= yield) { + current->state=TASK_INTERRUPTIBLE; + schedule_timeout(HZ/200); + yield = i + yieldlines; + } } if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) @@ -745,9 +817,12 @@ qcam->bpp = p.depth; qc_setscanmode(qcam); - parport_claim_or_block(qcam->pdev); + qcam->status |= QC_PARAM_CHANGE; + +/* parport_claim_or_block(qcam->pdev); qc_set(qcam); parport_release(qcam->pdev); +*/ return 0; } case VIDIOCSWIN: @@ -779,6 +854,11 @@ qcam->transfer_scale = 1; } qc_setscanmode(qcam); + + /* We must update the camera before we grab. We could + just have changed the grab size */ + qcam->status |= QC_PARAM_CHANGE; + /* Ok we figured out what to use from our wide choice */ return 0; } @@ -824,11 +904,15 @@ parport_claim_or_block(qcam->pdev); /* Probably should have a semaphore against multiple users */ qc_reset(qcam); + + /* Update the camera parameters if we need to */ + if (qcam->status & QC_PARAM_CHANGE) + qc_set(qcam); + len=qc_capture(qcam, buf,count); parport_release(qcam->pdev); return len; } - static struct video_device qcam_template= { @@ -909,6 +993,17 @@ for (port = parport_enumerate(); port; port=port->next) init_bwqcam(port); + + /* Do some sanity checks on the module parameters. */ + if (maxpoll > 5000) { + printk("Connectix Quickcam max-poll was above 5000. Using 5000.\n"); + maxpoll = 5000; + } + + if (yieldlines < 1) { + printk("Connectix Quickcam yieldlines was less than 1. Using 1.\n"); + yieldlines = 1; + } return (num_cams)?0:-ENODEV; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/bw-qcam.h linux.ac/drivers/char/bw-qcam.h --- linux.vanilla/drivers/char/bw-qcam.h Sun Nov 8 15:07:44 1998 +++ linux.ac/drivers/char/bw-qcam.h Sun Jan 24 21:15:01 1999 @@ -48,6 +48,9 @@ #define MAX_HEIGHT 243 #define MAX_WIDTH 336 +/* Bit fields for status flags */ +#define QC_PARAM_CHANGE 0x01 /* Camera status change has occurred */ + struct qcam_device { struct video_device vdev; struct pardevice *pdev; @@ -59,6 +62,6 @@ int port_mode; int transfer_scale; int top, left; + int status; unsigned int saved_bits; }; - diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/console.c linux.ac/drivers/char/console.c --- linux.vanilla/drivers/char/console.c Sun Jan 24 19:55:33 1999 +++ linux.ac/drivers/char/console.c Wed Jan 27 18:58:10 1999 @@ -2778,7 +2778,7 @@ set_cursor(currcons); } -u16 vcs_scr_readw(int currcons, u16 *org) +u16 vcs_scr_readw(int currcons, const u16 *org) { if ((unsigned long)org == pos && softcursor_original != -1) return softcursor_original; 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 Sun Nov 8 14:58:21 1998 @@ -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/hfmodem/tables.h linux.ac/drivers/char/hfmodem/tables.h --- linux.vanilla/drivers/char/hfmodem/tables.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/char/hfmodem/tables.h Mon Dec 21 21:08:45 1998 @@ -0,0 +1,90 @@ +/* + * This file is automatically generated by ./gentbl, DO NOT EDIT! +*/ + +#define SINTABBITS 9 +#define SINTABSIZE (1< 1998-10-08. * + * Code fixes to handle mouse ACKs properly. + * C. Scott Ananian 1999-01-29. + * */ #include @@ -74,6 +77,8 @@ static struct aux_queue *queue; /* Mouse data buffer. */ static int aux_count = 0; +/* used when we send commands to the mouse that expect an ACK. */ +static volatile unsigned char mouse_reply_expected = 0; #define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT) #define AUX_INTS_ON (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT) @@ -419,7 +424,10 @@ if (status & KBD_STAT_MOUSE_OBF) { #ifdef CONFIG_PSMOUSE /* Mouse data. */ - if (aux_count) { + /* Add data to queue unless it's an ACK we were + * expecting. */ + if (aux_count && + (!mouse_reply_expected || scancode!=AUX_ACK)) { int head = queue->head; queue->buf[head] = scancode; add_mouse_randomness(scancode); @@ -430,7 +438,12 @@ kill_fasync(queue->fasync, SIGIO); wake_up_interruptible(&queue->proc_list); } - } + /* if we were expecting an ACK but found + * something else, forget about the ACK. */ + mouse_reply_expected=0; + } else if (mouse_reply_expected) + /* we found the ACK we were expecting. */ + mouse_reply_expected--; #endif } else { if (do_acknowledge(scancode)) @@ -770,6 +783,24 @@ spin_unlock_irqrestore(&kbd_controller_lock, flags); } +/* + * Send a byte to the mouse & handle returned ack + */ +static void aux_write_ack(int val) +{ + unsigned long flags; + + spin_lock_irqsave(&kbd_controller_lock, flags); + kb_wait(); + outb(KBD_CCMD_WRITE_MOUSE, KBD_CNTL_REG); + kb_wait(); + outb(val, KBD_DATA_REG); + /* we expect an ACK in response. */ + mouse_reply_expected++; + kb_wait(); + spin_unlock_irqrestore(&kbd_controller_lock, flags); +} + static unsigned int get_from_queue(void) { unsigned int result; @@ -834,7 +865,7 @@ kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_ENABLE); /* Enable the auxiliary port on controller. */ - aux_write_dev(AUX_ENABLE_DEV); /* Enable aux device */ + aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */ kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */ return 0; @@ -951,11 +982,11 @@ #ifdef INITIALIZE_MOUSE kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_ENABLE); /* Enable Aux. */ - aux_write_dev(AUX_SET_SAMPLE); - aux_write_dev(100); /* 100 samples/sec */ - aux_write_dev(AUX_SET_RES); - aux_write_dev(3); /* 8 counts per mm */ - aux_write_dev(AUX_SET_SCALE21); /* 2:1 scaling */ + 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_cmd(AUX_INTS_OFF); /* Disable controller ints. */ 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 Jan 19 02:57:26 1999 +++ linux.ac/drivers/char/pc_keyb.h Sat Jan 30 18:32:27 1999 @@ -114,8 +114,12 @@ #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 +#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; 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 Sun Jan 24 19:55:35 1999 +++ linux.ac/drivers/net/Config.in Tue Jan 26 11:47:13 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 @@ -53,6 +62,7 @@ tristate '3c507 support' CONFIG_EL16 if [ "$CONFIG_MCA" = "y" ]; then tristate '3c523 support' CONFIG_ELMC + #tristate '3c527 support' CONFIG_ELMC_II fi fi tristate '3c509/3c579 support' CONFIG_EL3 @@ -81,11 +91,10 @@ 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 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 @@ -113,6 +122,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 Gigabit support' CONFIG_ACENIC tristate 'Ansel Communications EISA 3200 support (EXPERIMENTAL)' CONFIG_AC3200 fi @@ -143,6 +153,8 @@ fi fi +endmenu + bool 'FDDI driver support' CONFIG_FDDI if [ "$CONFIG_FDDI" = "y" ]; then bool 'Digital DEFEA and DEFPA adapter support' CONFIG_DEFXX @@ -151,7 +163,6 @@ 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 if [ "$CONFIG_ROADRUNNER" != "n" ]; then bool ' Use large TX/RX rings' CONFIG_ROADRUNNER_LARGE_RINGS @@ -159,16 +170,13 @@ 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 # + +mainmenu_option next_comment +comment 'Appletalk devices' + if [ "$CONFIG_ATALK" != "n" ]; then dep_tristate 'Apple/Farallon LocalTalk PC support' CONFIG_LTPC $CONFIG_ATALK dep_tristate 'COPS LocalTalk PC support' CONFIG_COPS $CONFIG_ATALK @@ -183,6 +191,8 @@ fi fi +endmenu + if [ ! "$CONFIG_PARPORT" = "n" ]; then dep_tristate 'PLIP (parallel port) support' CONFIG_PLIP $CONFIG_PARPORT fi @@ -201,10 +211,13 @@ 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 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 @@ -212,12 +225,21 @@ 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 @@ -225,8 +247,19 @@ # 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 # + +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 @@ -239,11 +272,14 @@ 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 Jan 19 02:57:28 1999 +++ linux.ac/drivers/net/Makefile Wed Jan 27 19:06:11 1999 @@ -143,14 +143,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 +163,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 @@ -430,6 +414,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 @@ -478,6 +470,14 @@ endif endif +ifeq ($(CONFIG_ELMC_II),y) +L_OBJS += 3c527.o +else + ifeq ($(CONFIG_ELMC_II),m) + M_OBJS += 3c527.o + endif +endif + ifeq ($(CONFIG_EL3),y) L_OBJS += 3c509.o else @@ -1046,6 +1046,7 @@ ifeq ($(CONFIG_IRDA),y) SUB_DIRS += irda +MOD_SUB_DIRS += irda else ifeq ($(CONFIG_IRDA),m) MOD_SUB_DIRS += irda 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 Jan 19 02:57:28 1999 +++ linux.ac/drivers/net/Space.c Tue Jan 26 11:33:18 1999 @@ -518,7 +518,7 @@ && dfx_probe(dev) #endif #ifdef CONFIG_APFDDI - && apfddi_init(dev); + && apfddi_init(dev) #endif && 1 ) { return 1; /* -ENODEV or -EAGAIN would be more accurate. */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/hamradio/baycom_epp.c linux.ac/drivers/net/hamradio/baycom_epp.c --- linux.vanilla/drivers/net/hamradio/baycom_epp.c Thu Dec 3 13:48:35 1998 +++ linux.ac/drivers/net/hamradio/baycom_epp.c Wed Jan 27 19:08:52 1999 @@ -1075,6 +1075,7 @@ if (!(pp->modes & (PARPORT_MODE_PCECPEPP|PARPORT_MODE_PCEPP))) { printk(KERN_ERR "%s: parport at 0x%lx does not support any EPP mode\n", bc_drvname, pp->base); + parport_release(bc->pdev); parport_unregister_device(bc->pdev); return -EIO; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/ibmtr.c linux.ac/drivers/net/ibmtr.c --- linux.vanilla/drivers/net/ibmtr.c Tue Jan 26 09:44:20 1999 +++ linux.ac/drivers/net/ibmtr.c Thu Jan 28 13:22:37 1999 @@ -1353,12 +1353,23 @@ static void tr_tx(struct device *dev) { struct tok_info *ti=(struct tok_info *) dev->priv; - struct trh_hdr *trhdr=(struct trh_hdr *)ti->current_skb->data; + struct trh_hdr *trhdr; unsigned int hdr_len; __u32 dhb; unsigned char xmit_command; int i; struct trllc *llc; + + if(ti->current_skb==NULL) + { + printk(KERN_ERR "%s: tx request but no packet!\n", + dev->name); + dev->tbusy=0; + mark_bh(NET_BH); + return; + } + + trhdr=(struct trh_hdr *)ti->current_skb->data; if (readb(ti->asb + offsetof(struct asb_xmit_resp, ret_code))!=0xFF) DPRINTK("ASB not free !!!\n"); @@ -1603,6 +1614,7 @@ writeb(XMIT_UI_FRAME, ti->srb + offsetof(struct srb_xmit, command)); writew(ti->exsap_station_id, ti->srb +offsetof(struct srb_xmit, station_id)); + wmb(); /* This must be written before the IRQ hits */ writeb(CMD_IN_SRB, (ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD)); dev->trans_start=jiffies; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/irda/irport.c linux.ac/drivers/net/irda/irport.c --- linux.vanilla/drivers/net/irda/irport.c Tue Jan 26 09:44:20 1999 +++ linux.ac/drivers/net/irda/irport.c Wed Jan 27 19:06:11 1999 @@ -96,7 +96,7 @@ #ifdef MODULE static void irport_cleanup(void) { - int i; +/* int i; */ DEBUG( 4, __FUNCTION__ "()\n"); @@ -303,7 +303,6 @@ int irport_hard_xmit( struct sk_buff *skb, struct device *dev) { struct irda_device *idev; - int xbofs; int actual; DEBUG( 4, __FUNCTION__ "()\n"); diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/irda/pc87108.c linux.ac/drivers/net/irda/pc87108.c --- linux.vanilla/drivers/net/irda/pc87108.c Sun Jan 24 19:55:35 1999 +++ linux.ac/drivers/net/irda/pc87108.c Wed Jan 27 19:06:11 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sat Nov 7 21:43:15 1998 - * Modified at: Mon Dec 28 08:46:16 1998 + * Modified at: Fri Jan 22 20:20:09 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli @@ -100,7 +100,9 @@ /* Some prototypes */ static int pc87108_open( int i, unsigned int iobase, unsigned int board_addr, unsigned int irq, unsigned int dma); +#ifdef MODULE static int pc87108_close( struct irda_device *idev); +#endif /* MODULE */ static int pc87108_probe( int iobase, int board_addr, int irq, int dma); static void pc87108_pio_receive( struct irda_device *idev); static int pc87108_dma_receive( struct irda_device *idev); @@ -250,6 +252,7 @@ return 0; } +#ifdef MODULE /* * Function pc87108_close (idev) * @@ -276,6 +279,7 @@ return 0; } +#endif /* MODULE */ /* * Function pc87108_probe (iobase, board_addr, irq, dma) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/myri_sbus.c linux.ac/drivers/net/myri_sbus.c --- linux.vanilla/drivers/net/myri_sbus.c Sun Nov 8 15:07:29 1998 +++ linux.ac/drivers/net/myri_sbus.c Thu Jan 14 06:23:57 1999 @@ -278,7 +278,7 @@ mp->rx_skbs[i] = skb; skb->dev = dev; skb_put(skb, RX_ALLOC_SIZE); - rxd[i].myri_scatters[0].addr = (u32) ((unsigned long)skb->data); + rxd[i].myri_scatters[0].addr = sbus_dvma_addr(skb->data); rxd[i].myri_scatters[0].len = RX_ALLOC_SIZE; rxd[i].ctx = i; rxd[i].num_sg = 1; @@ -340,12 +340,6 @@ dev_kfree_skb(skb); mp->tx_skbs[entry] = NULL; mp->enet_stats.tx_packets++; - -#ifdef NEED_DMA_SYNCHRONIZATION - mmu_sync_dma(((u32)((unsigned long)skb->data)), - skb->len, mp->myri_sbus_dev->my_bus); -#endif - entry = NEXT_TX(entry); } mp->tx_old = entry; @@ -437,8 +431,7 @@ drops++; DRX(("DROP ")); mp->enet_stats.rx_dropped++; - rxd->myri_scatters[0].addr = - (u32) ((unsigned long)skb->data); + rxd->myri_scatters[0].addr = sbus_dvma_addr(skb->data); rxd->myri_scatters[0].len = RX_ALLOC_SIZE; rxd->ctx = index; rxd->num_sg = 1; @@ -447,7 +440,7 @@ } #ifdef NEED_DMA_SYNCHRONIZATION - mmu_sync_dma(((u32)((unsigned long)skb->data)), + mmu_sync_dma(sbus_dvma_addr(skb->data), skb->len, mp->myri_sbus_dev->my_bus); #endif @@ -464,8 +457,7 @@ mp->rx_skbs[index] = new_skb; new_skb->dev = dev; skb_put(new_skb, RX_ALLOC_SIZE); - rxd->myri_scatters[0].addr = - (u32) ((unsigned long)new_skb->data); + rxd->myri_scatters[0].addr = sbus_dvma_addr(new_skb->data); rxd->myri_scatters[0].len = RX_ALLOC_SIZE; rxd->ctx = index; rxd->num_sg = 1; @@ -489,8 +481,7 @@ /* Reuse original ring buffer. */ DRX(("reuse ")); - rxd->myri_scatters[0].addr = - (u32) ((unsigned long)skb->data); + rxd->myri_scatters[0].addr = sbus_dvma_addr(skb->data); rxd->myri_scatters[0].len = RX_ALLOC_SIZE; rxd->ctx = index; rxd->num_sg = 1; @@ -600,6 +591,12 @@ return 1; } + +#ifdef NEED_DMA_SYNCHRONIZATION + mmu_sync_dma(sbus_dvma_addr(skb->data), + skb->len, mp->myri_sbus_dev->my_bus); +#endif + /* This is just to prevent multiple PIO reads for TX_BUFFS_AVAIL. */ head = sq->head; tail = sq->tail; @@ -628,8 +625,7 @@ txd = &sq->myri_txd[entry]; mp->tx_skbs[entry] = skb; - txd->myri_gathers[0].addr = - (unsigned int) ((unsigned long)skb->data); + txd->myri_gathers[0].addr = sbus_dvma_addr(skb->data); txd->myri_gathers[0].len = len; txd->num_sg = 1; txd->chan = KERNEL_CHANNEL; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/smc-ultra.c linux.ac/drivers/net/smc-ultra.c --- linux.vanilla/drivers/net/smc-ultra.c Tue Dec 22 23:19:47 1998 +++ linux.ac/drivers/net/smc-ultra.c Mon Feb 1 22:16:01 1999 @@ -440,6 +440,8 @@ MODULE_PARM(io, "1-" __MODULE_STRING(MAX_ULTRA_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ULTRA_CARDS) "i"); +EXPORT_NO_SYMBOLS; + /* This is set up so that only a single autoprobe takes place per call. ISA device autoprobes on a running machine are not recommended. */ int 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 Sun Nov 8 14:35:40 1998 @@ -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 Thu Dec 17 01:56:08 1998 @@ -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/Config.in linux.ac/drivers/scsi/Config.in --- linux.vanilla/drivers/scsi/Config.in Sun Jan 3 03:52:01 1999 +++ linux.ac/drivers/scsi/Config.in Sat Jan 30 18:29:12 1999 @@ -66,6 +66,7 @@ fi if [ "$CONFIG_PCI" = "y" ]; then dep_tristate 'Initio 9100U(W) support' CONFIG_SCSI_INITIO $CONFIG_SCSI + dep_tristate 'Initio INI-A100U2W support' CONFIG_SCSI_INIA100 $CONFIG_SCSI fi if [ "$CONFIG_PARPORT" != "n" ]; then dep_tristate 'IOMEGA parallel port (ppa - older drives)' CONFIG_SCSI_PPA $CONFIG_SCSI $CONFIG_PARPORT @@ -76,6 +77,7 @@ fi fi dep_tristate 'NCR53c406a SCSI support' CONFIG_SCSI_NCR53C406A $CONFIG_SCSI +dep_tristate 'symbios 53c416 SCSI support' CONFIG_SCSI_SYM53C416 $CONFIG_SCSI if [ "$CONFIG_PCI" = "y" ]; then dep_tristate 'NCR53c7,8xx SCSI support' CONFIG_SCSI_NCR53C7xx $CONFIG_SCSI if [ "$CONFIG_SCSI_NCR53C7xx" != "n" ]; then @@ -117,7 +119,7 @@ dep_tristate 'Qlogic FAS SCSI support' CONFIG_SCSI_QLOGIC_FAS $CONFIG_SCSI if [ "$CONFIG_PCI" = "y" ]; then dep_tristate 'Qlogic ISP SCSI support' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI -# dep_tristate 'Qlogic ISP FC SCSI support' CONFIG_SCSI_QLOGIC_FC $CONFIG_SCSI + dep_tristate 'Qlogic ISP FC SCSI support' CONFIG_SCSI_QLOGIC_FC $CONFIG_SCSI fi dep_tristate 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE $CONFIG_SCSI if [ "$CONFIG_PCI" = "y" ]; then diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/Makefile linux.ac/drivers/scsi/Makefile --- linux.vanilla/drivers/scsi/Makefile Sun Jan 3 03:52:01 1999 +++ linux.ac/drivers/scsi/Makefile Sat Jan 30 18:29:12 1999 @@ -298,6 +298,14 @@ endif endif +ifeq ($(CONFIG_SCSI_INIA100),y) +L_OBJS += a100u2w.o +else + ifeq ($(CONFIG_SCSI_INIA100),m) + M_OBJS += a100u2w.o + endif +endif + ifeq ($(CONFIG_SCSI_QLOGIC_FC),y) L_OBJS += qlogicfc.o else @@ -576,6 +584,14 @@ endif endif +ifeq ($(CONFIG_SCSI_SYM53C416),y) +L_OBJS += sym53c416.o +else + ifeq ($(CONFIG_SCSI_SYM53C416),m) + M_OBJS += sym53c416.o + endif +endif + ifeq ($(CONFIG_BLK_DEV_IDESCSI),y) L_OBJS += ide-scsi.o else @@ -616,6 +632,9 @@ $(CC) $(CFLAGS) -c i91uscsi.c -o i91uscsi.o $(LD) -r -o initio.o ini9100u.o i91uscsi.o rm -f ini9100u.o i91uscsi.o + +a100u2w.o: inia100.o i60uscsi.o + $(LD) -r -o a100u2w.o inia100.o i60uscsi.o megaraid.o: megaraid.c $(CC) $(CFLAGS) -c megaraid.c 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 Thu Dec 17 01:56:25 1998 @@ -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 Sun Nov 8 14:35:42 1998 @@ -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 Thu Dec 17 01:56:31 1998 @@ -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/gdth_proc.c linux.ac/drivers/scsi/gdth_proc.c --- linux.vanilla/drivers/scsi/gdth_proc.c Thu Jan 14 01:25:25 1999 +++ linux.ac/drivers/scsi/gdth_proc.c Sat Jan 16 21:35:28 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/hosts.c linux.ac/drivers/scsi/hosts.c --- linux.vanilla/drivers/scsi/hosts.c Tue Jan 19 02:57:31 1999 +++ linux.ac/drivers/scsi/hosts.c Sat Jan 30 18:29:12 1999 @@ -223,6 +223,10 @@ #include "NCR53c406a.h" #endif +#ifdef CONFIG_SCSI_SYM53C416 +#include "sym53c416.h" +#endif + #ifdef CONFIG_SCSI_DC390T #include "dc390.h" #endif @@ -283,6 +287,10 @@ #include "ini9100u.h" #endif +#ifdef CONFIG_SCSI_INIA100 +#include "inia100.h" +#endif + #ifdef CONFIG_SCSI_DEBUG #include "scsi_debug.h" #endif @@ -467,6 +475,9 @@ #ifdef CONFIG_SCSI_NCR53C406A /* 53C406A should come before QLOGIC */ NCR53c406a, #endif +#ifdef CONFIG_SCSI_SYM53C416 + SYM53C416, +#endif #ifdef CONFIG_SCSI_QLOGIC_FAS QLOGICFAS, #endif @@ -532,6 +543,9 @@ #endif #ifdef CONFIG_SCSI_INITIO INI9100U, +#endif +#ifdef CONFIG_SCSI_INIA100 + INIA100, #endif #ifdef CONFIG_SCSI_QLOGICPTI QLOGICPTI, diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/i60uscsi.c linux.ac/drivers/scsi/i60uscsi.c --- linux.vanilla/drivers/scsi/i60uscsi.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/scsi/i60uscsi.c Sat Jan 30 18:29:12 1999 @@ -0,0 +1,956 @@ +/************************************************************************** + * Initio A100 device driver for Linux. + * + * Copyright (c) 1994-1998 Initio Corporation + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ************************************************************************* + * + * module: i60uscsi.c + * DESCRIPTION: + * This is the Linux low-level SCSI driver for Initio INIA100 SCSI host + * adapters + * + * 07/02/98 hl - v.91n Initial drivers. + * 09/14/98 hl - v1.01 Support new Kernel. + * 09/22/98 hl - v1.01a Support reset. + * 09/24/98 hl - v1.01b Fixed reset. + * 10/05/98 hl - v1.02 split the source code and release. + * 12/19/98 bv - v1.02a Use spinlocks for 2.1.95 and up + **************************************************************************/ + +#ifndef CVT_LINUX_VERSION +#define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S) +#endif + +#include +#include +#include "i60uscsi.h" + + +/* ---- INTERNAL FUNCTIONS ---- */ +static UCHAR waitChipReady(ORC_HCS * hcsp); +static UCHAR waitFWReady(ORC_HCS * hcsp); +static UCHAR waitFWReady(ORC_HCS * hcsp); +static UCHAR waitSCSIRSTdone(ORC_HCS * hcsp); +static UCHAR waitHDOoff(ORC_HCS * hcsp); +static UCHAR waitHDIset(ORC_HCS * hcsp, UCHAR * pData); +static unsigned short get_FW_version(ORC_HCS * hcsp); +static UCHAR set_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char value); +static UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn); +static int se2_rd_all(ORC_HCS * hcsp); +static void se2_update_all(ORC_HCS * hcsp); /* setup default pattern */ +static void read_eeprom(ORC_HCS * hcsp); +static UCHAR load_FW(ORC_HCS * hcsp); +static void setup_SCBs(ORC_HCS * hcsp); +static void initAFlag(ORC_HCS * hcsp); +ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp); + +/* ---- EXTERNAL FUNCTIONS ---- */ +extern void inia100SCBPost(BYTE * pHcb, BYTE * pScb); + +/* ---- INTERNAL VARIABLES ---- */ +ORC_HCS orc_hcs[MAX_SUPPORTED_ADAPTERS]; +static INIA100_ADPT_STRUCT inia100_adpt[MAX_SUPPORTED_ADAPTERS]; +/* set by inia100_setup according to the command line */ +int orc_num_scb; + +NVRAM nvram, *nvramp = &nvram; +static UCHAR dftNvRam[64] = +{ +/*----------header -------------*/ + 0x01, /* 0x00: Sub System Vendor ID 0 */ + 0x11, /* 0x01: Sub System Vendor ID 1 */ + 0x60, /* 0x02: Sub System ID 0 */ + 0x10, /* 0x03: Sub System ID 1 */ + 0x00, /* 0x04: SubClass */ + 0x01, /* 0x05: Vendor ID 0 */ + 0x11, /* 0x06: Vendor ID 1 */ + 0x60, /* 0x07: Device ID 0 */ + 0x10, /* 0x08: Device ID 1 */ + 0x00, /* 0x09: Reserved */ + 0x00, /* 0x0A: Reserved */ + 0x01, /* 0x0B: Revision of Data Structure */ + /* -- Host Adapter Structure --- */ + 0x01, /* 0x0C: Number Of SCSI Channel */ + 0x01, /* 0x0D: BIOS Configuration 1 */ + 0x00, /* 0x0E: BIOS Configuration 2 */ + 0x00, /* 0x0F: BIOS Configuration 3 */ + /* --- SCSI Channel 0 Configuration --- */ + 0x07, /* 0x10: H/A ID */ + 0x83, /* 0x11: Channel Configuration */ + 0x20, /* 0x12: MAX TAG per target */ + 0x0A, /* 0x13: SCSI Reset Recovering time */ + 0x00, /* 0x14: Channel Configuration4 */ + 0x00, /* 0x15: Channel Configuration5 */ + /* SCSI Channel 0 Target Configuration */ + /* 0x16-0x25 */ + 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, + 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, + /* --- SCSI Channel 1 Configuration --- */ + 0x07, /* 0x26: H/A ID */ + 0x83, /* 0x27: Channel Configuration */ + 0x20, /* 0x28: MAX TAG per target */ + 0x0A, /* 0x29: SCSI Reset Recovering time */ + 0x00, /* 0x2A: Channel Configuration4 */ + 0x00, /* 0x2B: Channel Configuration5 */ + /* SCSI Channel 1 Target Configuration */ + /* 0x2C-0x3B */ + 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, + 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, + 0x00, /* 0x3C: Reserved */ + 0x00, /* 0x3D: Reserved */ + 0x00, /* 0x3E: Reserved */ + 0x00 /* 0x3F: Checksum */ +}; + + +/***************************************************************************/ +static void waitForPause(unsigned amount) +{ + ULONG the_time = jiffies + amount; /* 0.01 seconds per jiffy */ + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + while (time_before_eq(jiffies, the_time)); +#else + while (jiffies < the_time); +#endif +} + +/***************************************************************************/ +UCHAR waitChipReady(ORC_HCS * hcsp) +{ + int i; + + for (i = 0; i < 2000; i++) { /* Wait 1 second for report timeout */ + if (ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HOSTSTOP) /* Wait HOSTSTOP set */ + return (TRUE); + waitForPause(5); /* wait 500ms before try again */ + } + return (FALSE); +} + +/***************************************************************************/ +UCHAR waitFWReady(ORC_HCS * hcsp) +{ + int i; + + for (i = 0; i < 2000; i++) { /* Wait 1 second for report timeout */ + if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY) /* Wait READY set */ + return (TRUE); + waitForPause(5); /* wait 500ms before try again */ + } + return (FALSE); +} + +/***************************************************************************/ +UCHAR waitSCSIRSTdone(ORC_HCS * hcsp) +{ + int i; + + for (i = 0; i < 2000; i++) { /* Wait 1 second for report timeout */ + if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & SCSIRST)) /* Wait SCSIRST done */ + return (TRUE); + waitForPause(5); /* wait 500ms before try again */ + } + return (FALSE); +} + +/***************************************************************************/ +UCHAR waitHDOoff(ORC_HCS * hcsp) +{ + int i; + + for (i = 0; i < 2000; i++) { /* Wait 1 second for report timeout */ + if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HDO)) /* Wait HDO off */ + return (TRUE); + waitForPause(5); /* wait 500ms before try again */ + } + return (FALSE); +} + +/***************************************************************************/ +UCHAR waitHDIset(ORC_HCS * hcsp, UCHAR * pData) +{ + int i; + + for (i = 0; i < 2000; i++) { /* Wait 1 second for report timeout */ + if ((*pData = ORC_RD(hcsp->HCS_Base, ORC_HSTUS)) & HDI) + return (TRUE); /* Wait HDI set */ + waitForPause(5); /* wait 500ms before try again */ + } + return (FALSE); +} + +/***************************************************************************/ +unsigned short get_FW_version(ORC_HCS * hcsp) +{ + UCHAR bData; + union { + unsigned short sVersion; + unsigned char cVersion[2]; + } Version; + + ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_VERSION); + ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); + if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */ + return (FALSE); + + if (waitHDIset(hcsp, &bData) == FALSE) /* Wait HDI set */ + return (FALSE); + Version.cVersion[0] = ORC_RD(hcsp->HCS_Base, ORC_HDATA); + ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData); /* Clear HDI */ + + if (waitHDIset(hcsp, &bData) == FALSE) /* Wait HDI set */ + return (FALSE); + Version.cVersion[1] = ORC_RD(hcsp->HCS_Base, ORC_HDATA); + ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData); /* Clear HDI */ + + return (Version.sVersion); +} + +/***************************************************************************/ +UCHAR set_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char value) +{ + ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_SET_NVM); /* Write command */ + ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); + if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */ + return (FALSE); + + ORC_WR(hcsp->HCS_Base + ORC_HDATA, address); /* Write address */ + ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); + if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */ + return (FALSE); + + ORC_WR(hcsp->HCS_Base + ORC_HDATA, value); /* Write value */ + ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); + if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */ + return (FALSE); + + return (TRUE); +} + +/***************************************************************************/ +UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn) +{ + unsigned char bData; + + ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_GET_NVM); /* Write command */ + ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); + if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */ + return (FALSE); + + ORC_WR(hcsp->HCS_Base + ORC_HDATA, address); /* Write address */ + ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); + if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */ + return (FALSE); + + if (waitHDIset(hcsp, &bData) == FALSE) /* Wait HDI set */ + return (FALSE); + *pDataIn = ORC_RD(hcsp->HCS_Base, ORC_HDATA); + ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData); /* Clear HDI */ + + return (TRUE); +} + +/***************************************************************************/ +void orc_exec_scb(ORC_HCS * hcsp, ORC_SCB * scbp) +{ + scbp->SCB_Status = SCB_POST; + ORC_WR(hcsp->HCS_Base + ORC_PQUEUE, scbp->SCB_ScbIdx); + return; +} + + +/*********************************************************************** + Read SCSI H/A configuration parameters from serial EEPROM +************************************************************************/ +int se2_rd_all(ORC_HCS * hcsp) +{ + int i; + UCHAR *np, chksum = 0; + + np = (UCHAR *) nvramp; + for (i = 0; i < 64; i++, np++) { /* <01> */ + if (get_NVRAM(hcsp, (unsigned char) i, np) == FALSE) + return -1; +// *np++ = get_NVRAM(hcsp, (unsigned char ) i); + } + +/*------ Is ckecksum ok ? ------*/ + np = (UCHAR *) nvramp; + for (i = 0; i < 63; i++) + chksum += *np++; + + if (nvramp->CheckSum != (UCHAR) chksum) + return -1; + return 1; +} + +/************************************************************************ + Update SCSI H/A configuration parameters from serial EEPROM +*************************************************************************/ +void se2_update_all(ORC_HCS * hcsp) +{ /* setup default pattern */ + int i; + UCHAR *np, *np1, chksum = 0; + + /* Calculate checksum first */ + np = (UCHAR *) dftNvRam; + for (i = 0; i < 63; i++) + chksum += *np++; + *np = chksum; + + np = (UCHAR *) dftNvRam; + np1 = (UCHAR *) nvramp; + for (i = 0; i < 64; i++, np++, np1++) { + if (*np != *np1) { + set_NVRAM(hcsp, (unsigned char) i, *np); + } + } + return; +} + +/************************************************************************* + Function name : read_eeprom +**************************************************************************/ +void read_eeprom(ORC_HCS * hcsp) +{ + if (se2_rd_all(hcsp) != 1) { + se2_update_all(hcsp); /* setup default pattern */ + se2_rd_all(hcsp); /* load again */ + } +} + + +/***************************************************************************/ +UCHAR load_FW(ORC_HCS * hcsp) +{ + U32 dData; + USHORT wBIOSAddress; + USHORT i; + UCHAR *pData, bData; + + + bData = ORC_RD(hcsp->HCS_Base, ORC_GCFG); + ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData | EEPRG); /* Enable EEPROM programming */ + ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, 0x00); + ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x00); + if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0x55) { + ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData); /* Disable EEPROM programming */ + return (FALSE); + } + ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x01); + if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0xAA) { + ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData); /* Disable EEPROM programming */ + return (FALSE); + } + ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD); /* Enable SRAM programming */ + pData = (UCHAR *) & dData; + dData = 0; /* Initial FW address to 0 */ + ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x10); + *pData = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */ + ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x11); + *(pData + 1) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */ + ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x12); + *(pData + 2) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */ + ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, *(pData + 2)); + ORC_WRLONG(hcsp->HCS_Base + ORC_FWBASEADR, dData); /* Write FW address */ + + wBIOSAddress = (USHORT) dData; /* FW code locate at BIOS address + ? */ + for (i = 0, pData = (UCHAR *) & dData; /* Download the code */ + i < 0x1000; /* Firmware code size = 4K */ + i++, wBIOSAddress++) { + ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress); + *pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */ + if ((i % 4) == 3) { + ORC_WRLONG(hcsp->HCS_Base + ORC_RISCRAM, dData); /* Write every 4 bytes */ + pData = (UCHAR *) & dData; + } + } + + ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD); /* Reset program count 0 */ + wBIOSAddress -= 0x1000; /* Reset the BIOS adddress */ + for (i = 0, pData = (UCHAR *) & dData; /* Check the code */ + i < 0x1000; /* Firmware code size = 4K */ + i++, wBIOSAddress++) { + ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress); + *pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */ + if ((i % 4) == 3) { + if (ORC_RDLONG(hcsp->HCS_Base, ORC_RISCRAM) != dData) { + ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST); /* Reset program to 0 */ + ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData); /*Disable EEPROM programming */ + return (FALSE); + } + pData = (UCHAR *) & dData; + } + } + ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST); /* Reset program to 0 */ + ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData); /* Disable EEPROM programming */ + return (TRUE); +} + +/***************************************************************************/ +void setup_SCBs(ORC_HCS * hcsp) +{ + ORC_SCB *pVirScb; + int i; + UCHAR j; + ESCB *pVirEscb; + PVOID pPhysEscb; + PVOID tPhysEscb; + + j = 0; + pVirScb = NULL; + tPhysEscb = (PVOID) NULL; + pPhysEscb = (PVOID) NULL; + /* Setup SCB HCS_Base and SCB Size registers */ + ORC_WR(hcsp->HCS_Base + ORC_SCBSIZE, orc_num_scb); /* Total number of SCBs */ + /* SCB HCS_Base address 0 */ + ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE0, hcsp->HCS_physScbArray); + /* SCB HCS_Base address 1 */ + ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE1, hcsp->HCS_physScbArray); + + /* setup scatter list address with one buffer */ + pVirScb = (ORC_SCB *) hcsp->HCS_virScbArray; + pVirEscb = (ESCB *) hcsp->HCS_virEscbArray; + + for (i = 0; i < orc_num_scb; i++) { +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) + pPhysEscb = (PVOID) ((ULONG) hcsp->HCS_virEscbArray + (sizeof(ESCB) * i)); + pVirScb->SCB_SGPAddr = (U32) VIRT_TO_BUS(pPhysEscb); + pVirScb->SCB_SensePAddr = (U32) VIRT_TO_BUS(pPhysEscb); +#else + pPhysEscb = (PVOID) (hcsp->HCS_physEscbArray + (sizeof(ESCB) * i)); + pVirScb->SCB_SGPAddr = (U32) pPhysEscb; + pVirScb->SCB_SensePAddr = (U32) pPhysEscb; +#endif + pVirScb->SCB_EScb = pVirEscb; + pVirScb->SCB_ScbIdx = i; + pVirScb++; + pVirEscb++; + } + + return; +} + +/***************************************************************************/ +static void initAFlag(ORC_HCS * hcsp) +{ + UCHAR i, j; + + for (i = 0; i < MAX_CHANNELS; i++) { + for (j = 0; j < 8; j++) { + hcsp->BitAllocFlag[i][j] = 0xffffffff; + } + } +} + +/***************************************************************************/ +int init_orchid(ORC_HCS * hcsp) +{ + UBYTE *readBytep; + USHORT revision; + UCHAR i; + + initAFlag(hcsp); + ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFF); /* Disable all interrupt */ + if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY) { /* Orchid is ready */ + revision = get_FW_version(hcsp); + if (revision == 0xFFFF) { + ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST); /* Reset Host Adapter */ + if (waitChipReady(hcsp) == FALSE) + return (-1); + load_FW(hcsp); /* Download FW */ + setup_SCBs(hcsp); /* Setup SCB HCS_Base and SCB Size registers */ + ORC_WR(hcsp->HCS_Base + ORC_HCTRL, 0); /* clear HOSTSTOP */ + if (waitFWReady(hcsp) == FALSE) + return (-1); + /* Wait for firmware ready */ + } else { + setup_SCBs(hcsp); /* Setup SCB HCS_Base and SCB Size registers */ + } + } else { /* Orchid is not Ready */ + ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST); /* Reset Host Adapter */ + if (waitChipReady(hcsp) == FALSE) + return (-1); + load_FW(hcsp); /* Download FW */ + setup_SCBs(hcsp); /* Setup SCB HCS_Base and SCB Size registers */ + ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); /* Do Hardware Reset & */ + + /* clear HOSTSTOP */ + if (waitFWReady(hcsp) == FALSE) /* Wait for firmware ready */ + return (-1); + } + +/*------------- get serial EEProm settting -------*/ + + read_eeprom(hcsp); + + if (nvramp->Revision != 1) + return (-1); + + hcsp->HCS_SCSI_ID = nvramp->SCSI0Id; + hcsp->HCS_BIOS = nvramp->BIOSConfig1; + hcsp->HCS_MaxTar = MAX_TARGETS; + readBytep = (UCHAR *) & (nvramp->Target00Config); + for (i = 0; i < 16; readBytep++, i++) { + hcsp->TargetFlag[i] = *readBytep; + hcsp->MaximumTags[i] = orc_num_scb; + } /* for */ + + if (nvramp->SCSI0Config & NCC_BUSRESET) { /* Reset SCSI bus */ + hcsp->HCS_Flags |= HCF_SCSI_RESET; + } + ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFB); /* enable RP FIFO interrupt */ + return (0); +} + +/***************************************************************************** + Function name : orc_reset_scsi_bus + Description : Reset registers, reset a hanging bus and + kill active and disconnected commands for target w/o soft reset + Input : pHCB - Pointer to host adapter structure + Output : None. + Return : pSRB - Pointer to SCSI request block. +*****************************************************************************/ +int orc_reset_scsi_bus(ORC_HCS * pHCB) +{ /* I need Host Control Block Information */ + ULONG flags; + +#if 0 + printk("inia100: enter inia100_reset\n"); +#endif + +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95) + save_flags(flags); + cli(); +#else + spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags); +#endif + + initAFlag(pHCB); + /* reset scsi bus */ + ORC_WR(pHCB->HCS_Base + ORC_HCTRL, SCSIRST); + if (waitSCSIRSTdone(pHCB) == FALSE) { +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95) + restore_flags(flags); +#else + spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); +#endif + return (SCSI_RESET_ERROR); + } else { +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95) + restore_flags(flags); +#else + spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); +#endif + return (SCSI_RESET_SUCCESS); + } +} + +/***************************************************************************** + Function name : orc_device_reset + Description : Reset registers, reset a hanging bus and + kill active and disconnected commands for target w/o soft reset + Input : pHCB - Pointer to host adapter structure + Output : None. + Return : pSRB - Pointer to SCSI request block. +*****************************************************************************/ +int orc_device_reset(ORC_HCS * pHCB, ULONG SCpnt, unsigned int target, unsigned int ResetFlags) +{ /* I need Host Control Block Information */ + ORC_SCB *pScb; + ESCB *pVirEscb; + ORC_SCB *pVirScb; + UCHAR i; + ULONG flags; + +#if 0 + printk("inia100: enter inia100_reset\n"); +#endif + +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95) + save_flags(flags); + cli(); +#else + spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags); +#endif + pScb = (ORC_SCB *) NULL; + pVirEscb = (ESCB *) NULL; + + /* setup scatter list address with one buffer */ + pVirScb = (ORC_SCB *) pHCB->HCS_virScbArray; + + initAFlag(pHCB); + /* device reset */ + for (i = 0; i < orc_num_scb; i++) { + pVirEscb = pVirScb->SCB_EScb; + if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == (unsigned char *) SCpnt)) + break; + pVirScb++; + } + + if (i == orc_num_scb) { + printk("Unable to Reset - No SCB Found\n"); +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95) + restore_flags(flags); +#else + spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); +#endif + return (SCSI_RESET_NOT_RUNNING); + } + if ((pScb = orc_alloc_scb(pHCB)) == NULL) { +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95) + restore_flags(flags); +#else + spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); +#endif + return (SCSI_RESET_NOT_RUNNING); + } + pScb->SCB_Opcode = ORC_BUSDEVRST; + pScb->SCB_Target = target; + pScb->SCB_HaStat = 0; + pScb->SCB_TaStat = 0; + pScb->SCB_Status = 0x0; + pScb->SCB_Link = 0xFF; + pScb->SCB_Reserved0 = 0; + pScb->SCB_Reserved1 = 0; + pScb->SCB_XferLen = 0; + pScb->SCB_SGLen = 0; + + pVirEscb->SCB_Srb = 0; + if (ResetFlags & SCSI_RESET_SYNCHRONOUS) { + pVirEscb->SCB_Srb = (unsigned char *) SCpnt; + } + orc_exec_scb(pHCB, pScb); /* Start execute SCB */ +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95) + restore_flags(flags); +#else + spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); +#endif + return SCSI_RESET_PENDING; +} + + +/***************************************************************************/ +ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp) +{ + ORC_SCB *pTmpScb; + UCHAR Ch; + ULONG idx; + UCHAR index; + UCHAR i; + ULONG flags; + +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95) + save_flags(flags); + cli(); +#else + spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags); +#endif + Ch = hcsp->HCS_Index; + for (i = 0; i < 8; i++) { + for (index = 0; index < 32; index++) { + if ((hcsp->BitAllocFlag[Ch][i] >> index) & 0x01) { + hcsp->BitAllocFlag[Ch][i] &= ~(1 << index); + break; + } + } + idx = index + 32 * i; + pTmpScb = (PVOID) ((ULONG) hcsp->HCS_virScbArray + (idx * sizeof(ORC_SCB))); +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95) + restore_flags(flags); +#else + spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); +#endif + return (pTmpScb); + } +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95) + restore_flags(flags); +#else + spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); +#endif + return (NULL); +} + + +/***************************************************************************/ +void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp) +{ + ULONG flags; + UCHAR Index; + UCHAR i; + UCHAR Ch; + +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95) + save_flags(flags); + cli(); +#else + spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags); +#endif + Ch = hcsp->HCS_Index; + Index = scbp->SCB_ScbIdx; + i = Index / 32; + Index %= 32; + hcsp->BitAllocFlag[Ch][i] |= (1 << Index); +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95) + restore_flags(flags); +#else + spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); +#endif +} + + +/***************************************************************************** + Function name : Addinia100_into_Adapter_table + Description : This function will scan PCI bus to get all Orchid card + Input : None. + Output : None. + Return : SUCCESSFUL - Successful scan + ohterwise - No drives founded +*****************************************************************************/ +int Addinia100_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt, + BYTE bBus, BYTE bDevice) +{ + unsigned int i, j; + + for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) { + if (inia100_adpt[i].ADPT_BIOS < wBIOS) + continue; + if (inia100_adpt[i].ADPT_BIOS == wBIOS) { + if (inia100_adpt[i].ADPT_BASE == wBASE) + if (inia100_adpt[i].ADPT_Bus != 0xFF) + return (FAILURE); + else if (inia100_adpt[i].ADPT_BASE < wBASE) + continue; + } + for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) { + inia100_adpt[j].ADPT_BASE = inia100_adpt[j - 1].ADPT_BASE; + inia100_adpt[j].ADPT_INTR = inia100_adpt[j - 1].ADPT_INTR; + inia100_adpt[j].ADPT_BIOS = inia100_adpt[j - 1].ADPT_BIOS; + inia100_adpt[j].ADPT_Bus = inia100_adpt[j - 1].ADPT_Bus; + inia100_adpt[j].ADPT_Device = inia100_adpt[j - 1].ADPT_Device; + } + inia100_adpt[i].ADPT_BASE = wBASE; + inia100_adpt[i].ADPT_INTR = bInterrupt; + inia100_adpt[i].ADPT_BIOS = wBIOS; + inia100_adpt[i].ADPT_Bus = bBus; + inia100_adpt[i].ADPT_Device = bDevice; + return (SUCCESSFUL); + } + return (FAILURE); +} + + +/***************************************************************************** + Function name : init_inia100Adapter_table + Description : This function will scan PCI bus to get all Orchid card + Input : None. + Output : None. + Return : SUCCESSFUL - Successful scan + ohterwise - No drives founded +*****************************************************************************/ +void init_inia100Adapter_table(void) +{ + int i; + + for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) { /* Initialize adapter structure */ + inia100_adpt[i].ADPT_BIOS = 0xffff; + inia100_adpt[i].ADPT_BASE = 0xffff; + inia100_adpt[i].ADPT_INTR = 0xff; + inia100_adpt[i].ADPT_Bus = 0xff; + inia100_adpt[i].ADPT_Device = 0xff; + } +} + +/***************************************************************************** + Function name : get_orcPCIConfig + Description : + Input : pHCB - Pointer to host adapter structure + Output : None. + Return : pSRB - Pointer to SCSI request block. +*****************************************************************************/ +void get_orcPCIConfig(ORC_HCS * pCurHcb, int ch_idx) +{ + pCurHcb->HCS_Base = inia100_adpt[ch_idx].ADPT_BASE; /* Supply base address */ + pCurHcb->HCS_BIOS = inia100_adpt[ch_idx].ADPT_BIOS; /* Supply BIOS address */ + pCurHcb->HCS_Intr = inia100_adpt[ch_idx].ADPT_INTR; /* Supply interrupt line */ + return; +} + + +/***************************************************************************** + Function name : abort_SCB + Description : Abort a queued command. + (commands that are on the bus can't be aborted easily) + Input : pHCB - Pointer to host adapter structure + Output : None. + Return : pSRB - Pointer to SCSI request block. +*****************************************************************************/ +int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb) +{ + unsigned char bData, bStatus; + + ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_ABORT_SCB); /* Write command */ + ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); + if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */ + return (FALSE); + + ORC_WR(hcsp->HCS_Base + ORC_HDATA, pScb->SCB_ScbIdx); /* Write address */ + ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); + if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */ + return (FALSE); + + if (waitHDIset(hcsp, &bData) == FALSE) /* Wait HDI set */ + return (FALSE); + bStatus = ORC_RD(hcsp->HCS_Base, ORC_HDATA); + ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData); /* Clear HDI */ + + if (bStatus == 1) /* 0 - Successfully */ + return (FALSE); /* 1 - Fail */ + return (TRUE); +} + +/***************************************************************************** + Function name : inia100_abort + Description : Abort a queued command. + (commands that are on the bus can't be aborted easily) + Input : pHCB - Pointer to host adapter structure + Output : None. + Return : pSRB - Pointer to SCSI request block. +*****************************************************************************/ +int orc_abort_srb(ORC_HCS * hcsp, ULONG SCpnt) +{ + ESCB *pVirEscb; + ORC_SCB *pVirScb; + UCHAR i; + ULONG flags; + +#if 0 + printk("inia100: abort SRB \n"); +#endif +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95) + save_flags(flags); + cli(); +#else + spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags); +#endif + + pVirScb = (ORC_SCB *) hcsp->HCS_virScbArray; + + for (i = 0; i < orc_num_scb; i++, pVirScb++) { + pVirEscb = pVirScb->SCB_EScb; + if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == (unsigned char *) SCpnt)) { + if (pVirScb->SCB_TagMsg == 0) { +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95) + restore_flags(flags); +#else + spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); +#endif + return (SCSI_ABORT_BUSY); + } else { + if (abort_SCB(hcsp, pVirScb)) { + pVirEscb->SCB_Srb = NULL; +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95) + restore_flags(flags); +#else + spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); +#endif + return (SCSI_ABORT_SUCCESS); + } else { +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95) + restore_flags(flags); +#else + spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); +#endif + return (SCSI_ABORT_NOT_RUNNING); + } + } + } + } +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95) + restore_flags(flags); +#else + spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); +#endif + return (SCSI_ABORT_NOT_RUNNING); +} + +/*********************************************************************** + Routine Description: + This is the interrupt service routine for the Orchid SCSI adapter. + It reads the interrupt register to determine if the adapter is indeed + the source of the interrupt and clears the interrupt at the device. + Arguments: + HwDeviceExtension - HBA miniport driver's adapter data storage + Return Value: +***********************************************************************/ +void orc_interrupt( + ORC_HCS * hcsp +) +{ + BYTE bScbIdx; + ORC_SCB *pScb; + + if (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT) == 0) { + return; // (FALSE); + + } + do { + bScbIdx = ORC_RD(hcsp->HCS_Base, ORC_RQUEUE); + + pScb = (ORC_SCB *) ((ULONG) hcsp->HCS_virScbArray + (ULONG) (sizeof(ORC_SCB) * bScbIdx)); + pScb->SCB_Status = 0x0; + + inia100SCBPost((BYTE *) hcsp, (BYTE *) pScb); + } while (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT)); + return; //(TRUE); + +} /* End of I1060Interrupt() */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/i60uscsi.h linux.ac/drivers/scsi/i60uscsi.h --- linux.vanilla/drivers/scsi/i60uscsi.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/scsi/i60uscsi.h Sat Jan 30 18:29:12 1999 @@ -0,0 +1,572 @@ +/************************************************************************** + * Initio A100 device driver for Linux. + * + * Copyright (c) 1994-1998 Initio Corporation + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ************************************************************************** + * + * Module: inia100.h + * Description: INI-A100U2W LINUX device driver header + * Revision History: + * 06/18/98 HL, Initial Version 1.02 + * 12/19/98 bv, v1.02a Use spinlocks for 2.1.95 and up. + **************************************************************************/ + +#define ULONG unsigned long +#define PVOID void * +#define USHORT unsigned short +#define UCHAR unsigned char +#define BYTE unsigned char +#define WORD unsigned short +#define DWORD unsigned long +#define UBYTE unsigned char +#define UWORD unsigned short +#define UDWORD unsigned long +#ifdef ALPHA +#define U32 unsigned int +#else +#define U32 unsigned long +#endif + +#ifndef NULL +#define NULL 0 /* zero */ +#endif +#ifndef TRUE +#define TRUE (1) /* boolean true */ +#endif +#ifndef FALSE +#define FALSE (0) /* boolean false */ +#endif +#ifndef FAILURE +#define FAILURE (-1) +#endif +#if 1 +#define ORC_MAXQUEUE 245 +#else +#define ORC_MAXQUEUE 25 +#endif + +#define TOTAL_SG_ENTRY 32 +#define MAX_TARGETS 16 +#define IMAX_CDB 15 +#define SENSE_SIZE 14 +#define MAX_SUPPORTED_ADAPTERS 4 +#define SUCCESSFUL 0x00 + +#define I920_DEVICE_ID 0x0002 /* Initio's inic-950 product ID */ + +/************************************************************************/ +/* Scatter-Gather Element Structure */ +/************************************************************************/ +typedef struct ORC_SG_Struc { + U32 SG_Ptr; /* Data Pointer */ + U32 SG_Len; /* Data Length */ +} ORC_SG; + +typedef struct inia100_Adpt_Struc { + UWORD ADPT_BIOS; /* 0 */ + UWORD ADPT_BASE; /* 1 */ + UBYTE ADPT_Bus; /* 2 */ + UBYTE ADPT_Device; /* 3 */ + UBYTE ADPT_INTR; /* 4 */ +} INIA100_ADPT_STRUCT; + + +/* SCSI related definition */ +#define DISC_NOT_ALLOW 0x80 /* Disconnect is not allowed */ +#define DISC_ALLOW 0xC0 /* Disconnect is allowed */ + + +#define ORC_OFFSET_SCB 16 +#define ORC_MAX_SCBS 250 +#define MAX_CHANNELS 2 +#define MAX_ESCB_ELE 64 +#define TCF_DRV_255_63 0x0400 + +/********************************************************/ +/* Orchid Configuration Register Set */ +/********************************************************/ +#define ORC_PVID 0x00 /* Vendor ID */ +#define ORC_VENDOR_ID 0x1101 /* Orchid vendor ID */ +#define ORC_PDID 0x02 /* Device ID */ +#define ORC_DEVICE_ID 0x1060 /* Orchid device ID */ +#define ORC_COMMAND 0x04 /* Command */ +#define BUSMS 0x04 /* BUS MASTER Enable */ +#define IOSPA 0x01 /* IO Space Enable */ +#define ORC_STATUS 0x06 /* Status register */ +#define ORC_REVISION 0x08 /* Revision number */ +#define ORC_BASE 0x10 /* Base address */ +#define ORC_BIOS 0x50 /* Expansion ROM base address */ +#define ORC_INT_NUM 0x3C /* Interrupt line */ +#define ORC_INT_PIN 0x3D /* Interrupt pin */ + + +/********************************************************/ +/* Orchid Host Command Set */ +/********************************************************/ +#define ORC_CMD_NOP 0x00 /* Host command - NOP */ +#define ORC_CMD_VERSION 0x01 /* Host command - Get F/W version */ +#define ORC_CMD_ECHO 0x02 /* Host command - ECHO */ +#define ORC_CMD_SET_NVM 0x03 /* Host command - Set NVRAM */ +#define ORC_CMD_GET_NVM 0x04 /* Host command - Get NVRAM */ +#define ORC_CMD_GET_BUS_STATUS 0x05 /* Host command - Get SCSI bus status */ +#define ORC_CMD_ABORT_SCB 0x06 /* Host command - Abort SCB */ +#define ORC_CMD_ISSUE_SCB 0x07 /* Host command - Issue SCB */ + +/********************************************************/ +/* Orchid Register Set */ +/********************************************************/ +#define ORC_GINTS 0xA0 /* Global Interrupt Status */ +#define QINT 0x04 /* Reply Queue Interrupt */ +#define ORC_GIMSK 0xA1 /* Global Interrupt MASK */ +#define MQINT 0x04 /* Mask Reply Queue Interrupt */ +#define ORC_GCFG 0xA2 /* Global Configure */ +#define EEPRG 0x01 /* Enable EEPROM programming */ +#define ORC_GSTAT 0xA3 /* Global status */ +#define WIDEBUS 0x10 /* Wide SCSI Devices connected */ +#define ORC_HDATA 0xA4 /* Host Data */ +#define ORC_HCTRL 0xA5 /* Host Control */ +#define SCSIRST 0x80 /* SCSI bus reset */ +#define HDO 0x40 /* Host data out */ +#define HOSTSTOP 0x02 /* Host stop RISC engine */ +#define DEVRST 0x01 /* Device reset */ +#define ORC_HSTUS 0xA6 /* Host Status */ +#define HDI 0x02 /* Host data in */ +#define RREADY 0x01 /* RISC engine is ready to receive */ +#define ORC_NVRAM 0xA7 /* Nvram port address */ +#define SE2CS 0x008 +#define SE2CLK 0x004 +#define SE2DO 0x002 +#define SE2DI 0x001 +#define ORC_PQUEUE 0xA8 /* Posting queue FIFO */ +#define ORC_PQCNT 0xA9 /* Posting queue FIFO Cnt */ +#define ORC_RQUEUE 0xAA /* Reply queue FIFO */ +#define ORC_RQUEUECNT 0xAB /* Reply queue FIFO Cnt */ +#define ORC_FWBASEADR 0xAC /* Firmware base address */ + +#define ORC_EBIOSADR0 0xB0 /* External Bios address */ +#define ORC_EBIOSADR1 0xB1 /* External Bios address */ +#define ORC_EBIOSADR2 0xB2 /* External Bios address */ +#define ORC_EBIOSDATA 0xB3 /* External Bios address */ + +#define ORC_SCBSIZE 0xB7 /* SCB size register */ +#define ORC_SCBBASE0 0xB8 /* SCB base address 0 */ +#define ORC_SCBBASE1 0xBC /* SCB base address 1 */ + +#define ORC_RISCCTL 0xE0 /* RISC Control */ +#define PRGMRST 0x002 +#define DOWNLOAD 0x001 +#define ORC_PRGMCTR0 0xE2 /* RISC program counter */ +#define ORC_PRGMCTR1 0xE3 /* RISC program counter */ +#define ORC_RISCRAM 0xEC /* RISC RAM data port 4 bytes */ + +typedef struct orc_extended_scb { /* Extended SCB */ + ORC_SG ESCB_SGList[TOTAL_SG_ENTRY]; /*0 Start of SG list */ + unsigned char *SCB_Srb; /*50 SRB Pointer */ +// Scsi_Cmnd *SCB_Srb; /*50 SRB Pointer */ +} ESCB; + +/*********************************************************************** + SCSI Control Block +************************************************************************/ +typedef struct orc_scb { /* Scsi_Ctrl_Blk */ + UBYTE SCB_Opcode; /*00 SCB command code&residual */ + UBYTE SCB_Flags; /*01 SCB Flags */ + UBYTE SCB_Target; /*02 Target Id */ + UBYTE SCB_Lun; /*03 Lun */ + U32 SCB_Reserved0; /*04 Reserved for ORCHID must 0 */ + U32 SCB_XferLen; /*08 Data Transfer Length */ + U32 SCB_Reserved1; /*0C Reserved for ORCHID must 0 */ + U32 SCB_SGLen; /*10 SG list # * 8 */ + U32 SCB_SGPAddr; /*14 SG List Buf physical Addr */ + U32 SCB_SGPAddrHigh; /*18 SG Buffer high physical Addr */ + UBYTE SCB_HaStat; /*1C Host Status */ + UBYTE SCB_TaStat; /*1D Target Status */ + UBYTE SCB_Status; /*1E SCB status */ + UBYTE SCB_Link; /*1F Link pointer, default 0xFF */ + UBYTE SCB_SenseLen; /*20 Sense Allocation Length */ + UBYTE SCB_CDBLen; /*21 CDB Length */ + UBYTE SCB_Ident; /*22 Identify */ + UBYTE SCB_TagMsg; /*23 Tag Message */ + UBYTE SCB_CDB[IMAX_CDB]; /*24 SCSI CDBs */ + UBYTE SCB_ScbIdx; /*3C Index for this ORCSCB */ + U32 SCB_SensePAddr; /*34 Sense Buffer physical Addr */ + + ESCB *SCB_EScb; /*38 Extended SCB Pointer */ +#ifndef ALPHA + UBYTE SCB_Reserved2[4]; /*3E Reserved for Driver use */ +#endif +} ORC_SCB; + +/* Opcodes of ORCSCB_Opcode */ +#define ORC_EXECSCSI 0x00 /* SCSI initiator command with residual */ +#define ORC_BUSDEVRST 0x01 /* SCSI Bus Device Reset */ + +/* Status of ORCSCB_Status */ +#define SCB_COMPLETE 0x00 /* SCB request completed */ +#define SCB_POST 0x01 /* SCB is posted by the HOST */ + +/* Bit Definition for ORCSCB_Flags */ +#define SCF_DISINT 0x01 /* Disable HOST interrupt */ +#define SCF_DIR 0x18 /* Direction bits */ +#define SCF_NO_DCHK 0x00 /* Direction determined by SCSI */ +#define SCF_DIN 0x08 /* From Target to Initiator */ +#define SCF_DOUT 0x10 /* From Initiator to Target */ +#define SCF_NO_XF 0x18 /* No data transfer */ +#define SCF_POLL 0x40 + +/* Error Codes for ORCSCB_HaStat */ +#define HOST_SEL_TOUT 0x11 +#define HOST_DO_DU 0x12 +#define HOST_BUS_FREE 0x13 +#define HOST_BAD_PHAS 0x14 +#define HOST_INV_CMD 0x16 +#define HOST_SCSI_RST 0x1B +#define HOST_DEV_RST 0x1C + + +/* Error Codes for ORCSCB_TaStat */ +#define TARGET_CHK_COND 0x02 +#define TARGET_BUSY 0x08 +#define TARGET_TAG_FULL 0x28 + + +/* Queue tag msg: Simple_quque_tag, Head_of_queue_tag, Ordered_queue_tag */ +#define MSG_STAG 0x20 +#define MSG_HTAG 0x21 +#define MSG_OTAG 0x22 + +#define MSG_IGNOREWIDE 0x23 + +#define MSG_IDENT 0x80 +#define MSG_DISC 0x40 /* Disconnect allowed */ + + +/* SCSI MESSAGE */ +#define MSG_EXTEND 0x01 +#define MSG_SDP 0x02 +#define MSG_ABORT 0x06 +#define MSG_REJ 0x07 +#define MSG_NOP 0x08 +#define MSG_PARITY 0x09 +#define MSG_DEVRST 0x0C +#define MSG_STAG 0x20 + +/*********************************************************************** + Target Device Control Structure +**********************************************************************/ + +typedef struct ORC_Tar_Ctrl_Struc { + UBYTE TCS_DrvDASD; /* 6 */ + UBYTE TCS_DrvSCSI; /* 7 */ + UBYTE TCS_DrvHead; /* 8 */ + UWORD TCS_DrvFlags; /* 4 */ + UBYTE TCS_DrvSector; /* 7 */ +} ORC_TCS, *PORC_TCS; + +/* Bit Definition for TCF_DrvFlags */ +#define TCS_DF_NODASD_SUPT 0x20 /* Suppress OS/2 DASD Mgr support */ +#define TCS_DF_NOSCSI_SUPT 0x40 /* Suppress OS/2 SCSI Mgr support */ + + +/*********************************************************************** + Host Adapter Control Structure +************************************************************************/ +typedef struct ORC_Ha_Ctrl_Struc { + USHORT HCS_Base; /* 00 */ + UBYTE HCS_Index; /* 02 */ + UBYTE HCS_Intr; /* 04 */ + UBYTE HCS_SCSI_ID; /* 06 H/A SCSI ID */ + UBYTE HCS_BIOS; /* 07 BIOS configuration */ + + UBYTE HCS_Flags; /* 0B */ + UBYTE HCS_HAConfig1; /* 1B SCSI0MAXTags */ + UBYTE HCS_MaxTar; /* 1B SCSI0MAXTags */ + + USHORT HCS_Units; /* Number of units this adapter */ + USHORT HCS_AFlags; /* Adapter info. defined flags */ + ULONG HCS_Timeout; /* Adapter timeout value */ + PVOID HCS_virScbArray; /* 28 Virtual Pointer to SCB array */ + U32 HCS_physScbArray; /* Scb Physical address */ + PVOID HCS_virEscbArray; /* Virtual pointer to ESCB Scatter list */ + U32 HCS_physEscbArray; /* scatter list Physical address */ + UBYTE TargetFlag[16]; /* 30 target configuration, TCF_EN_TAG */ + UBYTE MaximumTags[16]; /* 40 ORC_MAX_SCBS */ + UBYTE ActiveTags[16][16]; /* 50 */ + ORC_TCS HCS_Tcs[16]; /* 28 */ + U32 BitAllocFlag[MAX_CHANNELS][8]; /* Max STB is 256, So 256/32 */ +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spinlock_t BitAllocFlagLock; +#endif + ULONG pSRB_head; + ULONG pSRB_tail; +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spinlock_t pSRB_lock; +#endif +} ORC_HCS; + +/* Bit Definition for HCS_Flags */ + +#define HCF_SCSI_RESET 0x01 /* SCSI BUS RESET */ +#define HCF_PARITY 0x02 /* parity card */ +#define HCF_LVDS 0x10 /* parity card */ + +/* Bit Definition for TargetFlag */ + +#define TCF_EN_255 0x08 +#define TCF_EN_TAG 0x10 +#define TCF_BUSY 0x20 +#define TCF_DISCONNECT 0x40 +#define TCF_SPIN_UP 0x80 + +/* Bit Definition for HCS_AFlags */ +#define HCS_AF_IGNORE 0x01 /* Adapter ignore */ +#define HCS_AF_DISABLE_RESET 0x10 /* Adapter disable reset */ +#define HCS_AF_DISABLE_ADPT 0x80 /* Adapter disable */ + + +/*---------------------------------------*/ +/* TimeOut for RESET to complete (30s) */ +/* */ +/* After a RESET the drive is checked */ +/* every 200ms. */ +/*---------------------------------------*/ +#define DELAYED_RESET_MAX (30*1000L) +#define DELAYED_RESET_INTERVAL 200L + +/*----------------------------------------------*/ +/* TimeOut for IRQ from last interrupt (5s) */ +/*----------------------------------------------*/ +#define IRQ_TIMEOUT_INTERVAL (5*1000L) + +/*----------------------------------------------*/ +/* Retry Delay interval (200ms) */ +/*----------------------------------------------*/ +#define DELAYED_RETRY_INTERVAL 200L + +#define INQUIRY_SIZE 36 +#define CAPACITY_SIZE 8 +#define DEFAULT_SENSE_LEN 14 + +#define DEVICE_NOT_FOUND 0x86 + +/*----------------------------------------------*/ +/* Definition for PCI device */ +/*----------------------------------------------*/ +#define MAX_PCI_DEVICES 21 +#define MAX_PCI_BUSES 8 + +typedef struct Adpt_Struc { + USHORT ADPT_BIOS; /* 0 */ + UBYTE ADPT_BASE; /* 1 */ + UBYTE ADPT_Bus; /* 2 */ + UBYTE ADPT_Device; /* 3 */ + UBYTE ADPT_Reserved[3]; +} JACS, *PJACS; + +typedef struct _NVRAM { +/*----------header ---------------*/ + UCHAR SubVendorID0; /* 00 - Sub Vendor ID */ + UCHAR SubVendorID1; /* 00 - Sub Vendor ID */ + UCHAR SubSysID0; /* 02 - Sub System ID */ + UCHAR SubSysID1; /* 02 - Sub System ID */ + UCHAR SubClass; /* 04 - Sub Class */ + UCHAR VendorID0; /* 05 - Vendor ID */ + UCHAR VendorID1; /* 05 - Vendor ID */ + UCHAR DeviceID0; /* 07 - Device ID */ + UCHAR DeviceID1; /* 07 - Device ID */ + UCHAR Reserved0[2]; /* 09 - Reserved */ + UCHAR Revision; /* 0B - Revision of data structure */ + /* ----Host Adapter Structure ---- */ + UCHAR NumOfCh; /* 0C - Number of SCSI channel */ + UCHAR BIOSConfig1; /* 0D - BIOS configuration 1 */ + UCHAR BIOSConfig2; /* 0E - BIOS boot channel&target ID */ + UCHAR BIOSConfig3; /* 0F - BIOS configuration 3 */ + /* ----SCSI channel Structure ---- */ + /* from "CTRL-I SCSI Host Adapter SetUp menu " */ + UCHAR SCSI0Id; /* 10 - Channel 0 SCSI ID */ + UCHAR SCSI0Config; /* 11 - Channel 0 SCSI configuration */ + UCHAR SCSI0MaxTags; /* 12 - Channel 0 Maximum tags */ + UCHAR SCSI0ResetTime; /* 13 - Channel 0 Reset recovering time */ + UCHAR ReservedforChannel0[2]; /* 14 - Reserved */ + + /* ----SCSI target Structure ---- */ + /* from "CTRL-I SCSI device SetUp menu " */ + UCHAR Target00Config; /* 16 - Channel 0 Target 0 config */ + UCHAR Target01Config; /* 17 - Channel 0 Target 1 config */ + UCHAR Target02Config; /* 18 - Channel 0 Target 2 config */ + UCHAR Target03Config; /* 19 - Channel 0 Target 3 config */ + UCHAR Target04Config; /* 1A - Channel 0 Target 4 config */ + UCHAR Target05Config; /* 1B - Channel 0 Target 5 config */ + UCHAR Target06Config; /* 1C - Channel 0 Target 6 config */ + UCHAR Target07Config; /* 1D - Channel 0 Target 7 config */ + UCHAR Target08Config; /* 1E - Channel 0 Target 8 config */ + UCHAR Target09Config; /* 1F - Channel 0 Target 9 config */ + UCHAR Target0AConfig; /* 20 - Channel 0 Target A config */ + UCHAR Target0BConfig; /* 21 - Channel 0 Target B config */ + UCHAR Target0CConfig; /* 22 - Channel 0 Target C config */ + UCHAR Target0DConfig; /* 23 - Channel 0 Target D config */ + UCHAR Target0EConfig; /* 24 - Channel 0 Target E config */ + UCHAR Target0FConfig; /* 25 - Channel 0 Target F config */ + + UCHAR SCSI1Id; /* 26 - Channel 1 SCSI ID */ + UCHAR SCSI1Config; /* 27 - Channel 1 SCSI configuration */ + UCHAR SCSI1MaxTags; /* 28 - Channel 1 Maximum tags */ + UCHAR SCSI1ResetTime; /* 29 - Channel 1 Reset recovering time */ + UCHAR ReservedforChannel1[2]; /* 2A - Reserved */ + + /* ----SCSI target Structure ---- */ + /* from "CTRL-I SCSI device SetUp menu " */ + UCHAR Target10Config; /* 2C - Channel 1 Target 0 config */ + UCHAR Target11Config; /* 2D - Channel 1 Target 1 config */ + UCHAR Target12Config; /* 2E - Channel 1 Target 2 config */ + UCHAR Target13Config; /* 2F - Channel 1 Target 3 config */ + UCHAR Target14Config; /* 30 - Channel 1 Target 4 config */ + UCHAR Target15Config; /* 31 - Channel 1 Target 5 config */ + UCHAR Target16Config; /* 32 - Channel 1 Target 6 config */ + UCHAR Target17Config; /* 33 - Channel 1 Target 7 config */ + UCHAR Target18Config; /* 34 - Channel 1 Target 8 config */ + UCHAR Target19Config; /* 35 - Channel 1 Target 9 config */ + UCHAR Target1AConfig; /* 36 - Channel 1 Target A config */ + UCHAR Target1BConfig; /* 37 - Channel 1 Target B config */ + UCHAR Target1CConfig; /* 38 - Channel 1 Target C config */ + UCHAR Target1DConfig; /* 39 - Channel 1 Target D config */ + UCHAR Target1EConfig; /* 3A - Channel 1 Target E config */ + UCHAR Target1FConfig; /* 3B - Channel 1 Target F config */ + UCHAR reserved[3]; /* 3C - Reserved */ + /* ---------- CheckSum ---------- */ + UCHAR CheckSum; /* 3F - Checksum of NVRam */ +} NVRAM, *PNVRAM; + +/* Bios Configuration for nvram->BIOSConfig1 */ +#define NBC_BIOSENABLE 0x01 /* BIOS enable */ +#define NBC_CDROM 0x02 /* Support bootable CDROM */ +#define NBC_REMOVABLE 0x04 /* Support removable drive */ + +/* Bios Configuration for nvram->BIOSConfig2 */ +#define NBB_TARGET_MASK 0x0F /* Boot SCSI target ID number */ +#define NBB_CHANL_MASK 0xF0 /* Boot SCSI channel number */ + +/* Bit definition for nvram->SCSIConfig */ +#define NCC_BUSRESET 0x01 /* Reset SCSI bus at power up */ +#define NCC_PARITYCHK 0x02 /* SCSI parity enable */ +#define NCC_LVDS 0x10 /* Enable LVDS */ +#define NCC_ACTTERM1 0x20 /* Enable active terminator 1 */ +#define NCC_ACTTERM2 0x40 /* Enable active terminator 2 */ +#define NCC_AUTOTERM 0x80 /* Enable auto termination */ + +/* Bit definition for nvram->TargetxConfig */ +#define NTC_PERIOD 0x07 /* Maximum Sync. Speed */ +#define NTC_1GIGA 0x08 /* 255 head / 63 sectors (64/32) */ +#define NTC_NO_SYNC 0x10 /* NO SYNC. NEGO */ +#define NTC_NO_WIDESYNC 0x20 /* NO WIDE SYNC. NEGO */ +#define NTC_DISC_ENABLE 0x40 /* Enable SCSI disconnect */ +#define NTC_SPINUP 0x80 /* Start disk drive */ + +/* Default NVRam values */ +#define NBC_DEFAULT (NBC_ENABLE) +#define NCC_DEFAULT (NCC_BUSRESET | NCC_AUTOTERM | NCC_PARITYCHK) +#define NCC_MAX_TAGS 0x20 /* Maximum tags per target */ +#define NCC_RESET_TIME 0x0A /* SCSI RESET recovering time */ +#define NTC_DEFAULT (NTC_1GIGA | NTC_NO_WIDESYNC | NTC_DISC_ENABLE) + +typedef union { /* Union define for mechanism 1 */ + struct { + unsigned char RegNum; + unsigned char FcnNum:3; + unsigned char DeviceNum:5; + unsigned char BusNum; + unsigned char Reserved:7; + unsigned char Enable:1; + } sConfigAdr; + unsigned long lConfigAdr; +} CONFIG_ADR; + +typedef union { /* Union define for mechanism 2 */ + struct { + unsigned char RegNum; + unsigned char DeviceNum; + unsigned short Reserved; + } sHostAdr; + unsigned long lHostAdr; +} HOST_ADR; + +#define ORC_RD(x,y) (UCHAR)(inb( (int)((ULONG)((ULONG)x+(UCHAR)y)) )) +#define ORC_RDLONG(x,y) (long)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) )) + +#define ORC_WR( adr,data) outb( (UCHAR)(data), (int)(adr)) +#define ORC_WRSHORT(adr,data) outw( (UWORD)(data), (int)(adr)) +#define ORC_WRLONG( adr,data) outl( (ULONG)(data), (int)(adr)) + + +#define SCSI_ABORT_SNOOZE 0 +#define SCSI_ABORT_SUCCESS 1 +#define SCSI_ABORT_PENDING 2 +#define SCSI_ABORT_BUSY 3 +#define SCSI_ABORT_NOT_RUNNING 4 +#define SCSI_ABORT_ERROR 5 + +#define SCSI_RESET_SNOOZE 0 +#define SCSI_RESET_PUNT 1 +#define SCSI_RESET_SUCCESS 2 +#define SCSI_RESET_PENDING 3 +#define SCSI_RESET_WAKEUP 4 +#define SCSI_RESET_NOT_RUNNING 5 +#define SCSI_RESET_ERROR 6 + +#define SCSI_RESET_SYNCHRONOUS 0x01 +#define SCSI_RESET_ASYNCHRONOUS 0x02 +#define SCSI_RESET_SUGGEST_BUS_RESET 0x04 +#define SCSI_RESET_SUGGEST_HOST_RESET 0x08 + +#define SCSI_RESET_BUS_RESET 0x100 +#define SCSI_RESET_HOST_RESET 0x200 +#define SCSI_RESET_ACTION 0xff diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/inia100.c linux.ac/drivers/scsi/inia100.c --- linux.vanilla/drivers/scsi/inia100.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/scsi/inia100.c Sat Jan 30 18:29:12 1999 @@ -0,0 +1,953 @@ +/************************************************************************** + * Initio A100 device driver for Linux. + * + * Copyright (c) 1994-1998 Initio Corporation + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ************************************************************************** + * + * module: inia100.c + * DESCRIPTION: + * This is the Linux low-level SCSI driver for Initio INIA100 SCSI host + * adapters + * 09/24/98 hl - v1.02 initial production release. + * 12/19/98 bv - v1.02a Use spinlocks for 2.1.95 and up. + **************************************************************************/ + +#define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S) + +#ifndef LINUX_VERSION_CODE +#include +#endif + +#ifdef MODULE +#include +#endif + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE <= CVT_LINUX_VERSION(2,1,92) +#include +#endif +#include +#include +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,23) +#include +#endif +#include +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) +#include +#endif +#include "sd.h" +#include "scsi.h" +#include "hosts.h" +#include "inia100.h" +#include +#include +#include + + +#else + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "../block/blk.h" +#include "scsi.h" +#include "sd.h" +#include "hosts.h" +#include +#include "inia100.h" +#endif + +#ifdef MODULE +Scsi_Host_Template driver_template = INIA100; +#include "scsi_module.c" +#endif + +#define ORC_RDWORD(x,y) (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) )) + +char *inia100_Copyright = "Copyright (C) 1998-99"; +char *inia100_InitioName = "by Initio Corporation"; +char *inia100_ProductName = "INI-A100U2W"; +char *inia100_Version = "v1.02a"; + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) +struct proc_dir_entry proc_scsi_inia100 = +{ + PROC_SCSI_INIA100, 7, "INIA100", + S_IFDIR | S_IRUGO | S_IXUGO, 2, + 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; +#endif + +/* set by inia100_setup according to the command line */ +static int setup_called = 0; +static int orc_num_ch = MAX_SUPPORTED_ADAPTERS; /* Maximum 4 adapters */ + +/* ---- INTERNAL VARIABLES ---- */ +#define NUMBER(arr) (sizeof(arr) / sizeof(arr[0])) +static char *setup_str = (char *) NULL; + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) +static void inia100_intr0(int irq, void *dev_id, struct pt_regs *); +static void inia100_intr1(int irq, void *dev_id, struct pt_regs *); +static void inia100_intr2(int irq, void *dev_id, struct pt_regs *); +static void inia100_intr3(int irq, void *dev_id, struct pt_regs *); +static void inia100_intr4(int irq, void *dev_id, struct pt_regs *); +static void inia100_intr5(int irq, void *dev_id, struct pt_regs *); +static void inia100_intr6(int irq, void *dev_id, struct pt_regs *); +static void inia100_intr7(int irq, void *dev_id, struct pt_regs *); +#else +static void inia100_intr0(int irq, struct pt_regs *); +static void inia100_intr1(int irq, struct pt_regs *); +static void inia100_intr2(int irq, struct pt_regs *); +static void inia100_intr3(int irq, struct pt_regs *); +static void inia100_intr4(int irq, struct pt_regs *); +static void inia100_intr5(int irq, struct pt_regs *); +static void inia100_intr6(int irq, struct pt_regs *); +static void inia100_intr7(int irq, struct pt_regs *); +#endif + +static void inia100_panic(char *msg); +void inia100SCBPost(BYTE * pHcb, BYTE * pScb); + +/* ---- EXTERNAL VARIABLES ---- */ +extern int Addinia100_into_Adapter_table(WORD, WORD, BYTE, BYTE, BYTE); +extern void init_inia100Adapter_table(void); +extern ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp); +extern void orc_exec_scb(ORC_HCS * hcsp, ORC_SCB * scbp); +extern void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp); +extern void orc_interrupt(ORC_HCS * hcsp); +extern int orc_device_reset(ORC_HCS * pHCB, ULONG SCpnt, unsigned int target, unsigned int ResetFlags); +extern int orc_reset_scsi_bus(ORC_HCS * pHCB); +extern int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb); +extern int orc_abort_srb(ORC_HCS * hcsp, ULONG SCpnt); +extern void get_orcPCIConfig(ORC_HCS * pCurHcb, int ch_idx); +extern int init_orchid(ORC_HCS * hcsp); + +extern int orc_num_scb; +extern ORC_HCS orc_hcs[]; + +/***************************************************************************** + Function name : inia100AppendSRBToQueue + Description : This function will push current request into save list + Input : pSRB - Pointer to SCSI request block. + pHCB - Pointer to host adapter structure + Output : None. + Return : None. +*****************************************************************************/ +static void inia100AppendSRBToQueue(ORC_HCS * pHCB, Scsi_Cmnd * pSRB) +{ + ULONG flags; + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_lock_irqsave(&(pHCB->pSRB_lock), flags); +#else + save_flags(flags); + cli(); +#endif + + pSRB->next = NULL; /* Pointer to next */ + if (pHCB->pSRB_head == NULL) + pHCB->pSRB_head = pSRB; + else + pHCB->pSRB_tail->next = pSRB; /* Pointer to next */ + pHCB->pSRB_tail = pSRB; +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags); +#else + restore_flags(flags); +#endif + return; +} + +/***************************************************************************** + Function name : inia100PopSRBFromQueue + Description : This function will pop current request from save list + Input : pHCB - Pointer to host adapter structure + Output : None. + Return : pSRB - Pointer to SCSI request block. +*****************************************************************************/ +static Scsi_Cmnd *inia100PopSRBFromQueue(ORC_HCS * pHCB) +{ + Scsi_Cmnd *pSRB; + ULONG flags; +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_lock_irqsave(&(pHCB->pSRB_lock), flags); +#else + save_flags(flags); + cli(); +#endif + + if ((pSRB = (Scsi_Cmnd *) pHCB->pSRB_head) != NULL) { + pHCB->pSRB_head = pHCB->pSRB_head->next; + pSRB->next = NULL; + } +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags); +#else + restore_flags(flags); +#endif + return (pSRB); +} + +/***************************************************************************** + Function name : inia100_setup + Description : + Input : pHCB - Pointer to host adapter structure + Output : None. + Return : pSRB - Pointer to SCSI request block. +*****************************************************************************/ +void inia100_setup(char *str, int *ints) +{ + if (setup_called) + inia100_panic("inia100: inia100_setup called twice.\n"); + + setup_called = ints[0]; + setup_str = str; +} + +/***************************************************************************** + Function name : orc_ReturnNumberOfAdapters + Description : This function will scan PCI bus to get all Orchid card + Input : None. + Output : None. + Return : SUCCESSFUL - Successful scan + ohterwise - No drives founded +*****************************************************************************/ +int orc_ReturnNumberOfAdapters(void) +{ + unsigned int i, iAdapters; + + iAdapters = 0; + /* + * PCI-bus probe. + */ + if (pcibios_present()) { + struct { + unsigned short vendor_id; + unsigned short device_id; + } const inia100_pci_devices[] = + { + {ORC_VENDOR_ID, I920_DEVICE_ID}, + {ORC_VENDOR_ID, ORC_DEVICE_ID} + }; + + unsigned int dRegValue; + unsigned short command; + WORD wBIOS, wBASE; + BYTE bPCIBusNum, bInterrupt, bPCIDeviceNum; + +#ifdef MMAPIO + unsigned long page_offset, base; +#endif + +#if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92) + struct pci_dev *pdev = NULL; +#else + int index; + unsigned char pci_bus, pci_devfn; +#endif + + bPCIBusNum = 0; + bPCIDeviceNum = 0; + init_inia100Adapter_table(); + for (i = 0; i < NUMBER(inia100_pci_devices); i++) { +#if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92) + pdev = NULL; + while ((pdev = pci_find_device(inia100_pci_devices[i].vendor_id, + inia100_pci_devices[i].device_id, + pdev))) +#else + index = 0; + while (!(pcibios_find_device(inia100_pci_devices[i].vendor_id, + inia100_pci_devices[i].device_id, + index++, &pci_bus, &pci_devfn))) +#endif + { + if (iAdapters >= MAX_SUPPORTED_ADAPTERS) + break; /* Never greater than maximum */ + + if (i == 0) { + /* + printk("inia100: The RAID controller is not supported by\n"); + printk("inia100: this driver, we are ignoring it.\n"); + */ + } else { + /* + * Read sundry information from PCI BIOS. + */ +#if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92) + bPCIBusNum = pdev->bus->number; + bPCIDeviceNum = pdev->devfn; + dRegValue = pdev->base_address[0]; + if (dRegValue == -1) { /* Check return code */ + printk("\n\rinia100: orchid read configuration error.\n"); + return (0); /* Read configuration space error */ + } + /* <02> read from base address + 0x50 offset to get the wBIOS balue. */ + wBASE = (WORD) dRegValue; + + /* Now read the interrupt line */ + dRegValue = pdev->irq; + bInterrupt = dRegValue & 0xFF; /* Assign interrupt line */ + pci_read_config_word(pdev, PCI_COMMAND, &command); + pci_write_config_word(pdev, PCI_COMMAND, + command | PCI_COMMAND_MASTER | PCI_COMMAND_IO); + +#else + bPCIBusNum = pci_bus; + bPCIDeviceNum = pci_devfn; + pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_0, + &dRegValue); + if (dRegValue == -1) { /* Check return code */ + printk("\n\rinia100: Orchid read configuration error.\n"); + return (0); /* Read configuration space error */ + } + /* <02> read from base address + 0x50 offset to get the wBIOS balue. */ + wBASE = (WORD) dRegValue; + + /* Now read the interrupt line */ + pcibios_read_config_dword(pci_bus, pci_devfn, PCI_INTERRUPT_LINE, + &dRegValue); + bInterrupt = dRegValue & 0xFF; /* Assign interrupt line */ + pcibios_read_config_word(pci_bus, pci_devfn, PCI_COMMAND, &command); + pcibios_write_config_word(pci_bus, pci_devfn, PCI_COMMAND, + command | PCI_COMMAND_MASTER | PCI_COMMAND_IO); +#endif + wBASE &= PCI_BASE_ADDRESS_IO_MASK; + wBIOS = ORC_RDWORD(wBASE, 0x50); + +#ifdef MMAPIO + base = wBASE & PAGE_MASK; + page_offset = wBASE - base; + + /* + * replace the next line with this one if you are using 2.1.x: + * temp_p->maddr = ioremap(base, page_offset + 256); + */ +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,0) + wBASE = ioremap(base, page_offset + 256); +#else + wBASE = (WORD) vremap(base, page_offset + 256); +#endif + if (wBASE) { + wBASE += page_offset; + } +#endif + + if (Addinia100_into_Adapter_table(wBIOS, wBASE, bInterrupt, bPCIBusNum, + bPCIDeviceNum) == SUCCESSFUL) + iAdapters++; + } + } /* while(pdev=....) */ + } /* for PCI_DEVICES */ + } /* PCI BIOS present */ + return (iAdapters); +} + +/***************************************************************************** + Function name : inia100_detect + Description : + Input : pHCB - Pointer to host adapter structure + Output : None. + Return : pSRB - Pointer to SCSI request block. +*****************************************************************************/ +int inia100_detect(Scsi_Host_Template * tpnt) +{ + ORC_HCS *pHCB; + struct Scsi_Host *hreg; + U32 sz; + U32 i; /* 01/14/98 */ + int ok = 0, iAdapters; + ULONG dBiosAdr; + BYTE *pbBiosAdr; + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) + tpnt->proc_dir = &proc_scsi_inia100; +#endif + if (setup_called) { + /* Setup by inia100_setup */ + printk("inia100: processing commandline: "); + } + /* Get total number of adapters in the motherboard */ + iAdapters = orc_ReturnNumberOfAdapters(); + + /* printk("inia100: Total Initio Adapters = %d\n", iAdapters); */ + if (iAdapters == 0) /* If no orc founded, return */ + return (0); + + orc_num_ch = (iAdapters > orc_num_ch) ? orc_num_ch : iAdapters; + orc_num_scb = ORC_MAXQUEUE; + + /* clear the memory needed for HCS */ + i = orc_num_ch * sizeof(ORC_HCS); + memset((unsigned char *) &orc_hcs[0], 0, i); /* Initialize orc_hcs 0 */ + +#if 0 + printk("orc_num_scb= %x orc_num_ch= %x hcsize= %x scbsize= %x escbsize= %x\n", + orc_num_scb, orc_num_ch, sizeof(ORC_HCS), sizeof(ORC_SCB), sizeof(ESCB)); +#endif + + for (i = 0, pHCB = &orc_hcs[0]; /* Get pointer for control block */ + i < orc_num_ch; + i++, pHCB++) { + + pHCB->pSRB_head = NULL; /* Initial SRB save queue */ + pHCB->pSRB_tail = NULL; /* Initial SRB save queue */ +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + pHCB->pSRB_lock = SPIN_LOCK_UNLOCKED; /* SRB save queue lock */ +#endif + /* Get total memory needed for SCB */ + sz = orc_num_scb * sizeof(ORC_SCB); + if ((pHCB->HCS_virScbArray = (PVOID) kmalloc(sz, GFP_ATOMIC | GFP_DMA)) == NULL) { + printk("inia100: SCB memory allocation error\n"); + return (0); + } + memset((unsigned char *) pHCB->HCS_virScbArray, 0, sz); + pHCB->HCS_physScbArray = (U32) VIRT_TO_BUS(pHCB->HCS_virScbArray); + + /* Get total memory needed for ESCB */ + sz = orc_num_scb * sizeof(ESCB); + if ((pHCB->HCS_virEscbArray = (PVOID) kmalloc(sz, GFP_ATOMIC | GFP_DMA)) == NULL) { + printk("inia100: ESCB memory allocation error\n"); + return (0); + } + memset((unsigned char *) pHCB->HCS_virEscbArray, 0, sz); + pHCB->HCS_physEscbArray = (U32) VIRT_TO_BUS(pHCB->HCS_virEscbArray); + + request_region(pHCB->HCS_Base, 0x100, "inia100"); /* Register */ + get_orcPCIConfig(pHCB, i); + + dBiosAdr = pHCB->HCS_BIOS; + dBiosAdr = (dBiosAdr << 4); + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) + pbBiosAdr = phys_to_virt(dBiosAdr); +#endif + + if (init_orchid(pHCB)) { /* Initial orchid chip */ + printk("inia100: initial orchid fail!!\n"); + return (0); + } + hreg = scsi_register(tpnt, sizeof(ORC_HCS)); + if (hreg == NULL) { + printk("Invalid scsi_register pointer.\n"); + } + hreg->io_port = pHCB->HCS_Base; + hreg->n_io_port = 0xff; + hreg->can_queue = orc_num_scb; /* 03/05/98 */ + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) + hreg->unique_id = pHCB->HCS_Base; + hreg->max_id = pHCB->HCS_MaxTar; +#endif + + hreg->max_lun = 32; /* 10/21/97 */ +/* + hreg->max_lun = 8; + hreg->max_channel = 1; + */ + hreg->irq = pHCB->HCS_Intr; + hreg->this_id = pHCB->HCS_SCSI_ID; /* Assign HCS index */ + hreg->base = (UCHAR *) pHCB; + +#if 1 + hreg->sg_tablesize = TOTAL_SG_ENTRY; /* Maximun support is 32 */ +#else + hreg->sg_tablesize = SG_NONE; /* No SG */ +#endif + + /* Initial orc chip */ + switch (i) { +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) + case 0: + ok = request_irq(pHCB->HCS_Intr, inia100_intr0, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + break; + case 1: + ok = request_irq(pHCB->HCS_Intr, inia100_intr1, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + break; + case 2: + ok = request_irq(pHCB->HCS_Intr, inia100_intr2, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + break; + case 3: + ok = request_irq(pHCB->HCS_Intr, inia100_intr3, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + break; + case 4: + ok = request_irq(pHCB->HCS_Intr, inia100_intr4, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + break; + case 5: + ok = request_irq(pHCB->HCS_Intr, inia100_intr5, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + break; + case 6: + ok = request_irq(pHCB->HCS_Intr, inia100_intr6, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + break; + case 7: + ok = request_irq(pHCB->HCS_Intr, inia100_intr7, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + break; + default: + inia100_panic("inia100: Too many host adapters\n"); + break; + } + + if (ok < 0) { + if (ok == -EINVAL) { + printk("inia100: bad IRQ %d.\n", pHCB->HCS_Intr); + printk(" Contact author.\n"); + } else { + if (ok == -EBUSY) + printk("inia100: IRQ %d already in use. Configure another.\n", pHCB->HCS_Intr); + else { + printk("\ninia100: Unexpected error code on requesting IRQ %d.\n", + pHCB->HCS_Intr); + printk(" Contact author.\n"); + } + } + inia100_panic("inia100: driver needs an IRQ.\n"); + } +#endif + } + + tpnt->this_id = -1; + tpnt->can_queue = 1; + return 1; +} + +/***************************************************************************** + Function name : inia100BuildSCB + Description : + Input : pHCB - Pointer to host adapter structure + Output : None. + Return : pSRB - Pointer to SCSI request block. +*****************************************************************************/ +static void inia100BuildSCB(ORC_HCS * pHCB, ORC_SCB * pSCB, Scsi_Cmnd * SCpnt) +{ /* Create corresponding SCB */ + struct scatterlist *pSrbSG; + ORC_SG *pSG; /* Pointer to SG list */ + int i; + U32 TotalLen; + ESCB *pEScb; + + pEScb = pSCB->SCB_EScb; + pEScb->SCB_Srb = SCpnt; + pSG = NULL; + + pSCB->SCB_Opcode = ORC_EXECSCSI; + pSCB->SCB_Flags = SCF_NO_DCHK; /* Clear done bit */ + pSCB->SCB_Target = SCpnt->target; + pSCB->SCB_Lun = SCpnt->lun; + pSCB->SCB_Reserved0 = 0; + pSCB->SCB_Reserved1 = 0; + pSCB->SCB_SGLen = 0; + + if ((pSCB->SCB_XferLen = (U32) SCpnt->request_bufflen)) { + pSG = (ORC_SG *) & pEScb->ESCB_SGList[0]; + if (SCpnt->use_sg) { + TotalLen = 0; + pSCB->SCB_SGLen = (U32) (SCpnt->use_sg * 8); + pSrbSG = (struct scatterlist *) SCpnt->request_buffer; + for (i = 0; i < SCpnt->use_sg; i++, pSG++, pSrbSG++) { +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) + pSG->SG_Ptr = (U32) (VIRT_TO_BUS(pSrbSG->address)); +#else + pSG->SG_Ptr = (U32) pSrbSG->address; +#endif + pSG->SG_Len = (U32) pSrbSG->length; + TotalLen += (U32) pSrbSG->length; + } + } else { /* Non SG */ + pSCB->SCB_SGLen = 0x8; +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) + pSG->SG_Ptr = (U32) (VIRT_TO_BUS(SCpnt->request_buffer)); +#else + pSG->SG_PTR = (U32) SCpnt->request_buffer; +#endif + pSG->SG_Len = (U32) SCpnt->request_bufflen; + } + } + pSCB->SCB_SGPAddr = (U32) pSCB->SCB_SensePAddr; + pSCB->SCB_HaStat = 0; + pSCB->SCB_TaStat = 0; + pSCB->SCB_Link = 0xFF; + pSCB->SCB_SenseLen = SENSE_SIZE; + pSCB->SCB_CDBLen = SCpnt->cmd_len; + if (pSCB->SCB_CDBLen >= IMAX_CDB) { + printk("max cdb length= %x\b", SCpnt->cmd_len); + pSCB->SCB_CDBLen = IMAX_CDB; + } + pSCB->SCB_Ident = SCpnt->lun | DISC_ALLOW; + if (SCpnt->device->tagged_supported) { /* Tag Support */ + pSCB->SCB_TagMsg = SIMPLE_QUEUE_TAG; /* Do simple tag only */ + } else { + pSCB->SCB_TagMsg = 0; /* No tag support */ + } + memcpy(&pSCB->SCB_CDB[0], &SCpnt->cmnd, pSCB->SCB_CDBLen); + return; +} + +/***************************************************************************** + Function name : inia100_queue + Description : Queue a command and setup interrupts for a free bus. + Input : pHCB - Pointer to host adapter structure + Output : None. + Return : pSRB - Pointer to SCSI request block. +*****************************************************************************/ +int inia100_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) +{ + register ORC_SCB *pSCB; + ORC_HCS *pHCB; /* Point to Host adapter control block */ + + if (SCpnt->lun > 16) { + SCpnt->result = (DID_TIME_OUT << 16); + done(SCpnt); /* Notify system DONE */ + return (0); + } + pHCB = (ORC_HCS *) SCpnt->host->base; + SCpnt->scsi_done = done; + /* Get free SCSI control block */ + if ((pSCB = orc_alloc_scb(pHCB)) == NULL) { + inia100AppendSRBToQueue(pHCB, SCpnt); /* Buffer this request */ + /* printk("inia100_entry: can't allocate SCB\n"); */ + return (0); + } + inia100BuildSCB(pHCB, pSCB, SCpnt); + orc_exec_scb(pHCB, pSCB); /* Start execute SCB */ + + return (0); +} + +/***************************************************************************** + Function name : inia100_command + Description : We only support command in interrupt-driven fashion + Input : pHCB - Pointer to host adapter structure + Output : None. + Return : pSRB - Pointer to SCSI request block. +*****************************************************************************/ +int inia100_command(Scsi_Cmnd * SCpnt) +{ + printk("inia100: interrupt driven driver; use inia100_queue()\n"); + return -1; +} + +/***************************************************************************** + Function name : inia100_abort + Description : Abort a queued command. + (commands that are on the bus can't be aborted easily) + Input : pHCB - Pointer to host adapter structure + Output : None. + Return : pSRB - Pointer to SCSI request block. +*****************************************************************************/ +int inia100_abort(Scsi_Cmnd * SCpnt) +{ + ORC_HCS *hcsp; + + hcsp = (ORC_HCS *) SCpnt->host->base; + return orc_abort_srb(hcsp, (ULONG) SCpnt); +} + +/***************************************************************************** + Function name : inia100_reset + Description : Reset registers, reset a hanging bus and + kill active and disconnected commands for target w/o soft reset + Input : pHCB - Pointer to host adapter structure + Output : None. + Return : pSRB - Pointer to SCSI request block. +*****************************************************************************/ +int inia100_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) +{ /* I need Host Control Block Information */ + ORC_HCS *pHCB; + pHCB = (ORC_HCS *) SCpnt->host->base; + + if (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET)) + return orc_reset_scsi_bus(pHCB); + else + return orc_device_reset(pHCB, (ULONG) SCpnt, SCpnt->target, reset_flags); + +} + +/***************************************************************************** + Function name : inia100SCBPost + Description : This is callback routine be called when orc finish one + SCSI command. + Input : pHCB - Pointer to host adapter control block. + pSCB - Pointer to SCSI control block. + Output : None. + Return : None. +*****************************************************************************/ +void inia100SCBPost(BYTE * pHcb, BYTE * pScb) +{ + Scsi_Cmnd *pSRB; /* Pointer to SCSI request block */ + ORC_HCS *pHCB; + ORC_SCB *pSCB; + ESCB *pEScb; + + pHCB = (ORC_HCS *) pHcb; + pSCB = (ORC_SCB *) pScb; + pEScb = pSCB->SCB_EScb; + if ((pSRB = (Scsi_Cmnd *) pEScb->SCB_Srb) == 0) { + printk("inia100SCBPost: SRB pointer is empty\n"); + orc_release_scb(pHCB, pSCB); /* Release SCB for current channel */ + return; + } + pEScb->SCB_Srb = NULL; + + switch (pSCB->SCB_HaStat) { + case 0x0: + case 0xa: /* Linked command complete without error and linked normally */ + case 0xb: /* Linked command complete without error interrupt generated */ + pSCB->SCB_HaStat = 0; + break; + + case 0x11: /* Selection time out-The initiator selection or target + reselection was not complete within the SCSI Time out period */ + pSCB->SCB_HaStat = DID_TIME_OUT; + break; + + case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus + phase sequence was requested by the target. The host adapter + will generate a SCSI Reset Condition, notifying the host with + a SCRD interrupt */ + pSCB->SCB_HaStat = DID_RESET; + break; + + case 0x1a: /* SCB Aborted. 07/21/98 */ + pSCB->SCB_HaStat = DID_ABORT; + break; + + case 0x12: /* Data overrun/underrun-The target attempted to transfer more data + than was allocated by the Data Length field or the sum of the + Scatter / Gather Data Length fields. */ + case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */ + case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid. */ + + default: + printk("inia100: %x %x\n", pSCB->SCB_HaStat, pSCB->SCB_TaStat); + pSCB->SCB_HaStat = DID_ERROR; /* Couldn't find any better */ + break; + } + + if (pSCB->SCB_TaStat == 2) { /* Check condition */ + memcpy((unsigned char *) &pSRB->sense_buffer[0], + (unsigned char *) &pEScb->ESCB_SGList[0], SENSE_SIZE); + } + pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16); + pSRB->scsi_done(pSRB); /* Notify system DONE */ + + /* Find the next pending SRB */ + if ((pSRB = inia100PopSRBFromQueue(pHCB)) != NULL) { /* Assume resend will success */ + /* Reuse old SCB */ + inia100BuildSCB(pHCB, pSCB, pSRB); /* Create corresponding SCB */ + orc_exec_scb(pHCB, pSCB); /* Start execute SCB */ + } else { /* No Pending SRB */ + orc_release_scb(pHCB, pSCB); /* Release SCB for current channel */ + } + return; +} + +/***************************************************************************** + Function name : inia100_biosparam + Description : Return the "logical geometry" + Input : pHCB - Pointer to host adapter structure + Output : None. + Return : pSRB - Pointer to SCSI request block. +*****************************************************************************/ +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) +int inia100_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array) +#else +int inia100_biosparam(Scsi_Disk * disk, int dev, int *info_array) +#endif +{ + ORC_HCS *pHcb; /* Point to Host adapter control block */ + ORC_TCS *pTcb; + + pHcb = (ORC_HCS *) disk->device->host->base; + pTcb = &pHcb->HCS_Tcs[disk->device->id]; + + if (pTcb->TCS_DrvHead) { + info_array[0] = pTcb->TCS_DrvHead; + info_array[1] = pTcb->TCS_DrvSector; + info_array[2] = disk->capacity / pTcb->TCS_DrvHead / pTcb->TCS_DrvSector; + } else { + if (pTcb->TCS_DrvFlags & TCF_DRV_255_63) { + info_array[0] = 255; + info_array[1] = 63; + info_array[2] = disk->capacity / 255 / 63; + } else { + info_array[0] = 64; + info_array[1] = 32; + info_array[2] = disk->capacity >> 11; + } + } + return 0; +} + + +static void subIntr(ORC_HCS * pHCB, int irqno) +{ +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + unsigned long flags; + + spin_lock_irqsave(&io_request_lock, flags); +#endif + + if (pHCB->HCS_Intr != irqno) { +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&io_request_lock, flags); +#endif + return; + } + orc_interrupt(pHCB); + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spin_unlock_irqrestore(&io_request_lock, flags); +#endif +} + +/* + * Interrupts handler (main routine of the driver) + */ +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) +static void inia100_intr0(int irqno, void *dev_id, struct pt_regs *regs) +#else +static void inia100_intr0(int irqno, struct pt_regs *regs) +#endif +{ + subIntr(&orc_hcs[0], irqno); +} + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) +static void inia100_intr1(int irqno, void *dev_id, struct pt_regs *regs) +#else +static void inia100_intr1(int irqno, struct pt_regs *regs) +#endif +{ + subIntr(&orc_hcs[1], irqno); +} + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) +static void inia100_intr2(int irqno, void *dev_id, struct pt_regs *regs) +#else +static void inia100_intr2(int irqno, struct pt_regs *regs) +#endif +{ + subIntr(&orc_hcs[2], irqno); +} + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) +static void inia100_intr3(int irqno, void *dev_id, struct pt_regs *regs) +#else +static void inia100_intr3(int irqno, struct pt_regs *regs) +#endif +{ + subIntr(&orc_hcs[3], irqno); +} + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) +static void inia100_intr4(int irqno, void *dev_id, struct pt_regs *regs) +#else +static void inia100_intr4(int irqno, struct pt_regs *regs) +#endif +{ + subIntr(&orc_hcs[4], irqno); +} + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) +static void inia100_intr5(int irqno, void *dev_id, struct pt_regs *regs) +#else +static void inia100_intr5(int irqno, struct pt_regs *regs) +#endif +{ + subIntr(&orc_hcs[5], irqno); +} + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) +static void inia100_intr6(int irqno, void *dev_id, struct pt_regs *regs) +#else +static void inia100_intr6(int irqno, struct pt_regs *regs) +#endif +{ + subIntr(&orc_hcs[6], irqno); +} + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) +static void inia100_intr7(int irqno, void *dev_id, struct pt_regs *regs) +#else +static void inia100_intr7(int irqno, struct pt_regs *regs) +#endif +{ + subIntr(&orc_hcs[7], irqno); +} + +/* + * Dump the current driver status and panic... + */ +static void inia100_panic(char *msg) +{ + printk("\ninia100_panic: %s\n", msg); + panic("inia100 panic"); +} + +/*#include "inia100scsi.c" */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/inia100.h linux.ac/drivers/scsi/inia100.h --- linux.vanilla/drivers/scsi/inia100.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/scsi/inia100.h Mon Feb 1 22:35:22 1999 @@ -0,0 +1,503 @@ +/************************************************************************** + * Initio A100 device driver for Linux. + * + * Copyright (c) 1994-1998 Initio Corporation + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * -------------------------------------------------------------------------- + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Where this Software is combined with software released under the terms of + * the GNU Public License ("GPL") and the terms of the GPL would require the + * combined work to also be released under the terms of the GPL, the terms + * and conditions of this License will apply in addition to those of the + * GPL with the exception of any terms or conditions of this License that + * conflict with, or are expressly prohibited by, the GPL. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ************************************************************************** + * + * Module: inia100.h + * Description: INI-A100U2W LINUX device driver header + * Revision History: + * 06/18/98 HL, Initial production Version 1.02 + * 12/19/98 bv, Use spinlocks for 2.1.95 and up + ****************************************************************************/ + +#ifndef CVT_LINUX_VERSION +#define CVT_LINUX_VERSION(V,P,S) (((V) * 65536) + ((P) * 256) + (S)) +#endif + +#ifndef LINUX_VERSION_CODE +#include +#endif + +#include "sd.h" + +extern int inia100_detect(Scsi_Host_Template *); +extern int inia100_command(Scsi_Cmnd *); +extern int inia100_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); +extern int inia100_abort(Scsi_Cmnd *); +extern int inia100_reset(Scsi_Cmnd *, unsigned int); + +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1, 3, 0) +extern int inia100_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */ +extern struct proc_dir_entry proc_scsi_inia100; +#else +extern int inia100_biosparam(Disk *, int, int *); /*for linux v1.13 */ +#endif + +#define inia100_REVID "Initio INI-A100U2W SCSI device driver; Revision: 1.02a" + +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(1, 3, 0) +#define INIA100 { \ + NULL, \ + NULL, \ + inia100_REVID, \ + inia100_detect, \ + NULL, \ + NULL, \ + inia100_command, \ + inia100_queue, \ + inia100_abort, \ + inia100_reset, \ + NULL, \ + inia100_biosparam, \ + 1, \ +7, \ +SG_ALL, \ +1, \ +0, \ +0, \ +ENABLE_CLUSTERING \ +} + +#else + +#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2, 1, 75) +#define INIA100 { \ + NULL, \ + NULL, \ + &proc_scsi_inia100, \ + NULL, \ + inia100_REVID, \ + inia100_detect, \ + NULL, \ + NULL, \ + inia100_command, \ + inia100_queue, \ + inia100_abort, \ + inia100_reset, \ + NULL, \ + inia100_biosparam, \ + 1, \ + 7, \ + 0, \ + 1, \ + 0, \ + 0, \ + ENABLE_CLUSTERING \ +} +#else /* Version >= 2.1.75 */ +#define INIA100 { \ + next: NULL, \ + module: NULL, \ + proc_dir: &proc_scsi_inia100, \ + proc_info: NULL, \ + name: inia100_REVID, \ + detect: inia100_detect, \ + release: NULL, \ + info: NULL, \ + command: inia100_command, \ + queuecommand: inia100_queue, \ + eh_strategy_handler: NULL, \ + eh_abort_handler: NULL, \ + eh_device_reset_handler: NULL, \ + eh_bus_reset_handler: NULL, \ + eh_host_reset_handler: NULL, \ + abort: inia100_abort, \ + reset: inia100_reset, \ + slave_attach: NULL, \ + bios_param: inia100_biosparam, \ + can_queue: 1, \ + this_id: 1, \ + sg_tablesize: SG_ALL, \ + cmd_per_lun: 1, \ + present: 0, \ + unchecked_isa_dma: 0, \ + use_clustering: ENABLE_CLUSTERING, \ + use_new_eh_code: 0 \ +} +#endif +#endif + +#define VIRT_TO_BUS(i) (unsigned int) virt_to_bus((void *)(i)) +#define ULONG unsigned long +#define PVOID void * +#define USHORT unsigned short +#define UCHAR unsigned char +#define BYTE unsigned char +#define WORD unsigned short +#define DWORD unsigned long +#define UBYTE unsigned char +#define UWORD unsigned short +#define UDWORD unsigned long +#ifdef ALPHA +#define U32 unsigned int +#else +#define U32 unsigned long +#endif + +#ifndef NULL +#define NULL 0 /* zero */ +#endif +#ifndef TRUE +#define TRUE (1) /* boolean true */ +#endif +#ifndef FALSE +#define FALSE (0) /* boolean false */ +#endif +#ifndef FAILURE +#define FAILURE (-1) +#endif +#if 1 +#define ORC_MAXQUEUE 245 +#else +#define ORC_MAXQUEUE 25 +#endif + +#define TOTAL_SG_ENTRY 32 +#define MAX_TARGETS 16 +#define IMAX_CDB 15 +#define SENSE_SIZE 14 +#define MAX_SUPPORTED_ADAPTERS 4 +#define SUCCESSFUL 0x00 + +#define I920_DEVICE_ID 0x0002 /* Initio's inic-950 product ID */ + +/************************************************************************/ +/* Scatter-Gather Element Structure */ +/************************************************************************/ +typedef struct ORC_SG_Struc { + U32 SG_Ptr; /* Data Pointer */ + U32 SG_Len; /* Data Length */ +} ORC_SG; + + +/* SCSI related definition */ +#define DISC_NOT_ALLOW 0x80 /* Disconnect is not allowed */ +#define DISC_ALLOW 0xC0 /* Disconnect is allowed */ + + +#define ORC_OFFSET_SCB 16 +#define ORC_MAX_SCBS 250 +#define MAX_CHANNELS 2 +#define MAX_ESCB_ELE 64 +#define TCF_DRV_255_63 0x0400 + +/********************************************************/ +/* Orchid Configuration Register Set */ +/********************************************************/ +#define ORC_PVID 0x00 /* Vendor ID */ +#define ORC_VENDOR_ID 0x1101 /* Orchid vendor ID */ +#define ORC_PDID 0x02 /* Device ID */ +#define ORC_DEVICE_ID 0x1060 /* Orchid device ID */ +#define ORC_COMMAND 0x04 /* Command */ +#define BUSMS 0x04 /* BUS MASTER Enable */ +#define IOSPA 0x01 /* IO Space Enable */ +#define ORC_STATUS 0x06 /* Status register */ +#define ORC_REVISION 0x08 /* Revision number */ +#define ORC_BASE 0x10 /* Base address */ +#define ORC_BIOS 0x50 /* Expansion ROM base address */ +#define ORC_INT_NUM 0x3C /* Interrupt line */ +#define ORC_INT_PIN 0x3D /* Interrupt pin */ + +/********************************************************/ +/* Orchid Host Command Set */ +/********************************************************/ +#define ORC_CMD_NOP 0x00 /* Host command - NOP */ +#define ORC_CMD_VERSION 0x01 /* Host command - Get F/W version */ +#define ORC_CMD_ECHO 0x02 /* Host command - ECHO */ +#define ORC_CMD_SET_NVM 0x03 /* Host command - Set NVRAM */ +#define ORC_CMD_GET_NVM 0x04 /* Host command - Get NVRAM */ +#define ORC_CMD_GET_BUS_STATUS 0x05 /* Host command - Get SCSI bus status */ +#define ORC_CMD_ABORT_SCB 0x06 /* Host command - Abort SCB */ +#define ORC_CMD_ISSUE_SCB 0x07 /* Host command - Issue SCB */ + +/********************************************************/ +/* Orchid Register Set */ +/********************************************************/ +#define ORC_GINTS 0xA0 /* Global Interrupt Status */ +#define QINT 0x04 /* Reply Queue Interrupt */ +#define ORC_GIMSK 0xA1 /* Global Interrupt MASK */ +#define MQINT 0x04 /* Mask Reply Queue Interrupt */ +#define ORC_GCFG 0xA2 /* Global Configure */ +#define EEPRG 0x01 /* Enable EEPROM programming */ +#define ORC_GSTAT 0xA3 /* Global status */ +#define WIDEBUS 0x10 /* Wide SCSI Devices connected */ +#define ORC_HDATA 0xA4 /* Host Data */ +#define ORC_HCTRL 0xA5 /* Host Control */ +#define SCSIRST 0x80 /* SCSI bus reset */ +#define HDO 0x40 /* Host data out */ +#define HOSTSTOP 0x02 /* Host stop RISC engine */ +#define DEVRST 0x01 /* Device reset */ +#define ORC_HSTUS 0xA6 /* Host Status */ +#define HDI 0x02 /* Host data in */ +#define RREADY 0x01 /* RISC engine is ready to receive */ +#define ORC_NVRAM 0xA7 /* Nvram port address */ +#define SE2CS 0x008 +#define SE2CLK 0x004 +#define SE2DO 0x002 +#define SE2DI 0x001 +#define ORC_PQUEUE 0xA8 /* Posting queue FIFO */ +#define ORC_PQCNT 0xA9 /* Posting queue FIFO Cnt */ +#define ORC_RQUEUE 0xAA /* Reply queue FIFO */ +#define ORC_RQUEUECNT 0xAB /* Reply queue FIFO Cnt */ +#define ORC_FWBASEADR 0xAC /* Firmware base address */ + +#define ORC_EBIOSADR0 0xB0 /* External Bios address */ +#define ORC_EBIOSADR1 0xB1 /* External Bios address */ +#define ORC_EBIOSADR2 0xB2 /* External Bios address */ +#define ORC_EBIOSDATA 0xB3 /* External Bios address */ + +#define ORC_SCBSIZE 0xB7 /* SCB size register */ +#define ORC_SCBBASE0 0xB8 /* SCB base address 0 */ +#define ORC_SCBBASE1 0xBC /* SCB base address 1 */ + +#define ORC_RISCCTL 0xE0 /* RISC Control */ +#define PRGMRST 0x002 +#define DOWNLOAD 0x001 +#define ORC_PRGMCTR0 0xE2 /* RISC program counter */ +#define ORC_PRGMCTR1 0xE3 /* RISC program counter */ +#define ORC_RISCRAM 0xEC /* RISC RAM data port 4 bytes */ + +typedef struct orc_extended_scb { /* Extended SCB */ + ORC_SG ESCB_SGList[TOTAL_SG_ENTRY]; /*0 Start of SG list */ + Scsi_Cmnd *SCB_Srb; /*50 SRB Pointer */ +} ESCB; + +/*********************************************************************** + SCSI Control Block +************************************************************************/ +typedef struct orc_scb { /* Scsi_Ctrl_Blk */ + UBYTE SCB_Opcode; /*00 SCB command code&residual */ + UBYTE SCB_Flags; /*01 SCB Flags */ + UBYTE SCB_Target; /*02 Target Id */ + UBYTE SCB_Lun; /*03 Lun */ + U32 SCB_Reserved0; /*04 Reserved for ORCHID must 0 */ + U32 SCB_XferLen; /*08 Data Transfer Length */ + U32 SCB_Reserved1; /*0C Reserved for ORCHID must 0 */ + U32 SCB_SGLen; /*10 SG list # * 8 */ + U32 SCB_SGPAddr; /*14 SG List Buf physical Addr */ + U32 SCB_SGPAddrHigh; /*18 SG Buffer high physical Addr */ + UBYTE SCB_HaStat; /*1C Host Status */ + UBYTE SCB_TaStat; /*1D Target Status */ + UBYTE SCB_Status; /*1E SCB status */ + UBYTE SCB_Link; /*1F Link pointer, default 0xFF */ + UBYTE SCB_SenseLen; /*20 Sense Allocation Length */ + UBYTE SCB_CDBLen; /*21 CDB Length */ + UBYTE SCB_Ident; /*22 Identify */ + UBYTE SCB_TagMsg; /*23 Tag Message */ + UBYTE SCB_CDB[IMAX_CDB]; /*24 SCSI CDBs */ + UBYTE SCB_ScbIdx; /*3C Index for this ORCSCB */ + U32 SCB_SensePAddr; /*34 Sense Buffer physical Addr */ + + ESCB *SCB_EScb; /*38 Extended SCB Pointer */ +#ifndef ALPHA + UBYTE SCB_Reserved2[4]; /*3E Reserved for Driver use */ +#endif +} ORC_SCB; + +/* Opcodes of ORCSCB_Opcode */ +#define ORC_EXECSCSI 0x00 /* SCSI initiator command with residual */ +#define ORC_BUSDEVRST 0x01 /* SCSI Bus Device Reset */ + +/* Status of ORCSCB_Status */ +#define SCB_COMPLETE 0x00 /* SCB request completed */ +#define SCB_POST 0x01 /* SCB is posted by the HOST */ + +/* Bit Definition for ORCSCB_Flags */ +#define SCF_DISINT 0x01 /* Disable HOST interrupt */ +#define SCF_DIR 0x18 /* Direction bits */ +#define SCF_NO_DCHK 0x00 /* Direction determined by SCSI */ +#define SCF_DIN 0x08 /* From Target to Initiator */ +#define SCF_DOUT 0x10 /* From Initiator to Target */ +#define SCF_NO_XF 0x18 /* No data transfer */ +#define SCF_POLL 0x40 + +/* Error Codes for ORCSCB_HaStat */ +#define HOST_SEL_TOUT 0x11 +#define HOST_DO_DU 0x12 +#define HOST_BUS_FREE 0x13 +#define HOST_BAD_PHAS 0x14 +#define HOST_INV_CMD 0x16 +#define HOST_SCSI_RST 0x1B +#define HOST_DEV_RST 0x1C + + +/* Error Codes for ORCSCB_TaStat */ +#define TARGET_CHK_COND 0x02 +#define TARGET_BUSY 0x08 +#define TARGET_TAG_FULL 0x28 + + +/* Queue tag msg: Simple_quque_tag, Head_of_queue_tag, Ordered_queue_tag */ +#define MSG_STAG 0x20 +#define MSG_HTAG 0x21 +#define MSG_OTAG 0x22 + +#define MSG_IGNOREWIDE 0x23 + +#define MSG_IDENT 0x80 +#define MSG_DISC 0x40 /* Disconnect allowed */ + + +/* SCSI MESSAGE */ +#define MSG_EXTEND 0x01 +#define MSG_SDP 0x02 +#define MSG_ABORT 0x06 +#define MSG_REJ 0x07 +#define MSG_NOP 0x08 +#define MSG_PARITY 0x09 +#define MSG_DEVRST 0x0C +#define MSG_STAG 0x20 + +/*********************************************************************** + Target Device Control Structure +**********************************************************************/ + +typedef struct ORC_Tar_Ctrl_Struc { + UBYTE TCS_DrvDASD; /* 6 */ + UBYTE TCS_DrvSCSI; /* 7 */ + UBYTE TCS_DrvHead; /* 8 */ + UWORD TCS_DrvFlags; /* 4 */ + UBYTE TCS_DrvSector; /* 7 */ +} ORC_TCS, *PORC_TCS; + +/* Bit Definition for TCF_DrvFlags */ +#define TCS_DF_NODASD_SUPT 0x20 /* Suppress OS/2 DASD Mgr support */ +#define TCS_DF_NOSCSI_SUPT 0x40 /* Suppress OS/2 SCSI Mgr support */ + + +/*********************************************************************** + Host Adapter Control Structure +************************************************************************/ +typedef struct ORC_Ha_Ctrl_Struc { + USHORT HCS_Base; /* 00 */ + UBYTE HCS_Index; /* 02 */ + UBYTE HCS_Intr; /* 04 */ + UBYTE HCS_SCSI_ID; /* 06 H/A SCSI ID */ + UBYTE HCS_BIOS; /* 07 BIOS configuration */ + + UBYTE HCS_Flags; /* 0B */ + UBYTE HCS_HAConfig1; /* 1B SCSI0MAXTags */ + UBYTE HCS_MaxTar; /* 1B SCSI0MAXTags */ + + USHORT HCS_Units; /* Number of units this adapter */ + USHORT HCS_AFlags; /* Adapter info. defined flags */ + ULONG HCS_Timeout; /* Adapter timeout value */ + PVOID HCS_virScbArray; /* 28 Virtual Pointer to SCB array */ + U32 HCS_physScbArray; /* Scb Physical address */ + PVOID HCS_virEscbArray; /* Virtual pointer to ESCB Scatter list */ + U32 HCS_physEscbArray; /* scatter list Physical address */ + UBYTE TargetFlag[16]; /* 30 target configuration, TCF_EN_TAG */ + UBYTE MaximumTags[16]; /* 40 ORC_MAX_SCBS */ + UBYTE ActiveTags[16][16]; /* 50 */ + ORC_TCS HCS_Tcs[16]; /* 28 */ + U32 BitAllocFlag[MAX_CHANNELS][8]; /* Max STB is 256, So 256/32 */ +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spinlock_t BitAllocFlagLock; +#endif + Scsi_Cmnd *pSRB_head; + Scsi_Cmnd *pSRB_tail; +#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) + spinlock_t pSRB_lock; +#endif +} ORC_HCS; + +/* Bit Definition for HCS_Flags */ + +#define HCF_SCSI_RESET 0x01 /* SCSI BUS RESET */ +#define HCF_PARITY 0x02 /* parity card */ +#define HCF_LVDS 0x10 /* parity card */ + +/* Bit Definition for TargetFlag */ + +#define TCF_EN_255 0x08 +#define TCF_EN_TAG 0x10 +#define TCF_BUSY 0x20 +#define TCF_DISCONNECT 0x40 +#define TCF_SPIN_UP 0x80 + +/* Bit Definition for HCS_AFlags */ +#define HCS_AF_IGNORE 0x01 /* Adapter ignore */ +#define HCS_AF_DISABLE_RESET 0x10 /* Adapter disable reset */ +#define HCS_AF_DISABLE_ADPT 0x80 /* Adapter disable */ + + +/*---------------------------------------*/ +/* TimeOut for RESET to complete (30s) */ +/* */ +/* After a RESET the drive is checked */ +/* every 200ms. */ +/*---------------------------------------*/ +#define DELAYED_RESET_MAX (30*1000L) +#define DELAYED_RESET_INTERVAL 200L + +/*----------------------------------------------*/ +/* TimeOut for IRQ from last interrupt (5s) */ +/*----------------------------------------------*/ +#define IRQ_TIMEOUT_INTERVAL (5*1000L) + +/*----------------------------------------------*/ +/* Retry Delay interval (200ms) */ +/*----------------------------------------------*/ +#define DELAYED_RETRY_INTERVAL 200L + +#define INQUIRY_SIZE 36 +#define CAPACITY_SIZE 8 +#define DEFAULT_SENSE_LEN 14 + +#define DEVICE_NOT_FOUND 0x86 + +/*----------------------------------------------*/ +/* Definition for PCI device */ +/*----------------------------------------------*/ +#define MAX_PCI_DEVICES 21 +#define MAX_PCI_BUSES 8 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/megaraid.c linux.ac/drivers/scsi/megaraid.c --- linux.vanilla/drivers/scsi/megaraid.c Thu Jan 14 01:25:25 1999 +++ linux.ac/drivers/scsi/megaraid.c Sat Jan 30 18:35:45 1999 @@ -1,24 +1,27 @@ /*=================================================================== * * Linux MegaRAID device driver - * + * * Copyright 1998 American Megatrends Inc. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. + * This program is free software; you can redistribute 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. * - * Version : 0.92 + * Version : 0.93 * * Description: Linux device driver for AMI MegaRAID controller * + * Supported controllers: MegaRAID 418, 428, 438, 466 + * + * Maintainer: Jeff L Jones + * * History: * * Version 0.90: - * Works and has been tested with the MegaRAID 428 controller, and - * the MegaRAID 438 controller. Probably works with the 466 also, - * but not tested. + * Original source contributed by Dell; integrated it into the kernel and + * cleaned up some things. Added support for 438/466 controllers. * * Version 0.91: * Aligned mailbox area on 16-byte boundry. @@ -35,31 +38,34 @@ * Removed setting of SA_INTERRUPT flag when requesting Irq. * * Version 0.92ac: - * Small changes to the comments/formatting. Plus a couple of - * added notes. Returned to the authors. No actual code changes - * save printk levels. - * 8 Oct 98 Alan Cox + * Small changes to the comments/formatting. Plus a couple of + * added notes. Returned to the authors. No actual code changes + * save printk levels. + * 8 Oct 98 Alan Cox * * Merged with 2.1.131 source tree. - * 12 Dec 98 K. Baranowski + * 12 Dec 98 K. Baranowski + * + * Version 0.93: + * Added support for vendor specific ioctl commands (0x80+xxh) + * Changed some fields in MEGARAID struct to better values. + * Added signature check for Rp controllers under 2.0 kernels + * Changed busy-wait loop to be time-based + * Fixed SMP race condition in isr + * Added kfree (sgList) on release + * Added #include linux/version.h to megaraid.h for hosts.h + * Changed max_id to represent max logical drives instead of targets. + * * * BUGS: - * Tested with 2.1.90, but unfortunately there is a bug in pci.c which - * fails to detect our controller. Does work with 2.1.118--don't know - * which kernel in between it was fixed in. - * With SMP enabled under 2.1.118 with more than one processor, gets an - * error message "scsi_end_request: buffer-list destroyed" under heavy - * IO, but doesn't seem to affect operation, or data integrity. The - * message doesn't occur without SMP enabled, or with one proccessor with - * SMP enabled, or under any combination under 2.0 kernels. + * Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that + * fails to detect the controller as a pci device on the system. * *===================================================================*/ -#define QISR 1 #define CRLFSTR "\n" -#define MULTIQ 1 - +#include #include #ifdef MODULE @@ -68,10 +74,8 @@ #if LINUX_VERSION_CODE >= 0x20100 char kernel_version[] = UTS_RELEASE; -/* originally ported by Dell Corporation; updated, released, and maintained by - American Megatrends */ -MODULE_AUTHOR("American Megatrends Inc."); -MODULE_DESCRIPTION("AMI MegaRAID driver"); +MODULE_AUTHOR ("American Megatrends Inc."); +MODULE_DESCRIPTION ("AMI MegaRAID driver"); #endif #endif @@ -93,6 +97,7 @@ #include #include #include /* for kmalloc() */ +#include /* for CONFIG_PCI */ #if LINUX_VERSION_CODE < 0x20100 #include #else @@ -108,18 +113,21 @@ #include "megaraid.h" -/*================================================================ - * - * #Defines - * - *================================================================*/ +//================================================================ +// +// #Defines +// +//================================================================ #if LINUX_VERSION_CODE < 0x020100 #define ioremap vremap #define iounmap vfree /* simulate spin locks */ -typedef struct {volatile char lock;} spinlock_t; +typedef struct { + volatile char lock; +} spinlock_t; + #define spin_lock_init(x) { (x)->lock = 0;} #define spin_lock_irqsave(x,flags) { while ((x)->lock) barrier();\ (x)->lock=1; save_flags(flags);\ @@ -154,125 +162,124 @@ spin_unlock_irqrestore(&mega_lock,cpuflag);\ }; -u_long RDINDOOR(mega_host_config *megaCfg) +u_long RDINDOOR (mega_host_config * megaCfg) { - return readl(megaCfg->base + 0x20); + return readl (megaCfg->base + 0x20); } -void WRINDOOR(mega_host_config *megaCfg, u_long value) +void WRINDOOR (mega_host_config * megaCfg, u_long value) { - writel(value,megaCfg->base+0x20); + writel (value, megaCfg->base + 0x20); } -u_long RDOUTDOOR(mega_host_config *megaCfg) +u_long RDOUTDOOR (mega_host_config * megaCfg) { - return readl(megaCfg->base+0x2C); + return readl (megaCfg->base + 0x2C); } -void WROUTDOOR(mega_host_config *megaCfg, u_long value) +void WROUTDOOR (mega_host_config * megaCfg, u_long value) { - writel(value,megaCfg->base+0x2C); + writel (value, megaCfg->base + 0x2C); } -/*================================================================ - * - * Function prototypes - * - *================================================================*/ -static int MegaIssueCmd(mega_host_config *megaCfg, - u_char *mboxData, - mega_scb *scb, +//================================================================ +// +// Function prototypes +// +//================================================================ +static int MegaIssueCmd (mega_host_config * megaCfg, + u_char * mboxData, + mega_scb * scb, int intr); -static int build_sglist(mega_host_config *megaCfg, mega_scb *scb, - u_long *buffer, u_long *length); +static int build_sglist (mega_host_config * megaCfg, mega_scb * scb, + u_long * buffer, u_long * length); -static void mega_runque(void *); -static void mega_rundoneq(void); -static void mega_cmd_done(mega_host_config *,mega_scb *, int); +static void mega_runque (void *); +static void mega_rundoneq (void); +static void mega_cmd_done (mega_host_config *, mega_scb *, int); +static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt); /* set SERDEBUG to 1 to enable serial debugging */ #define SERDEBUG 0 #if SERDEBUG -static void ser_init(void); -static void ser_puts(char *str); -static void ser_putc(char c); -static int ser_printk(const char *fmt, ...); +static void ser_init (void); +static void ser_puts (char *str); +static void ser_putc (char c); +static int ser_printk (const char *fmt,...); #endif -/*================================================================ - * - * Global variables - * - *================================================================*/ -static int numCtlrs = 0; -static mega_host_config *megaCtlrs[4] = { 0 }; +//================================================================ +// +// Global variables +// +//================================================================ +static int numCtlrs = 0; +static mega_host_config *megaCtlrs[12] = {0}; /* Change this to 0 if you want to see the raw drives */ -static int use_raid = 1; +static int use_raid = 1; /* Queue of pending/completed SCBs */ -static mega_scb *qPending = NULL; +static mega_scb *qPending = NULL; static Scsi_Cmnd *qCompleted = NULL; volatile static spinlock_t mega_lock; -static struct tq_struct runq = {0,0,mega_runque,NULL}; +static struct tq_struct runq = {0, 0, mega_runque, NULL}; -struct proc_dir_entry proc_scsi_megaraid = { +struct proc_dir_entry proc_scsi_megaraid = +{ PROC_SCSI_MEGARAID, 8, "megaraid", S_IFDIR | S_IRUGO | S_IXUGO, 2 }; #if SERDEBUG -static char strbuf[MAX_SERBUF+1]; +static char strbuf[MAX_SERBUF + 1]; -static void ser_init() +static void ser_init () { - unsigned port=COM_BASE; + unsigned port = COM_BASE; - outb(0x80,port+3); - outb(0,port+1); - /* 9600 Baud, if 19200: outb(6,port) */ - outb(12, port); - outb(3,port+3); - outb(0,port+1); + outb (0x80, port + 3); + outb (0, port + 1); + /* 9600 Baud, if 19200: outb(6,port) */ + outb (12, port); + outb (3, port + 3); + outb (0, port + 1); } -static void ser_puts(char *str) +static void ser_puts (char *str) { - char *ptr; + char *ptr; - ser_init(); - for (ptr=str;*ptr;++ptr) - ser_putc(*ptr); + ser_init (); + for (ptr = str; *ptr; ++ptr) + ser_putc (*ptr); } -static void ser_putc(char c) +static void ser_putc (char c) { - unsigned port=COM_BASE; + unsigned port = COM_BASE; - while ((inb(port+5) & 0x20)==0); - outb(c,port); - if (c==0x0a) - { - while ((inb(port+5) & 0x20)==0); - outb(0x0d,port); - } + while ((inb (port + 5) & 0x20) == 0); + outb (c, port); + if (c == 0x0a) { + while ((inb (port + 5) & 0x20) == 0); + outb (0x0d, port); + } } -static int ser_printk(const char *fmt, ...) +static int ser_printk (const char *fmt,...) { - va_list args; - int i; - long flags; + va_list args; + int i; + long flags; - spin_lock_irqsave(mega_lock,flags); - va_start(args,fmt); - i = vsprintf(strbuf,fmt,args); - ser_puts(strbuf); - va_end(args); - spin_unlock_irqrestore(&mega_lock,flags); + va_start (args, fmt); + i = vsprintf (strbuf, fmt, args); + ser_puts (strbuf); + va_end (args); - return i; + return i; } #define TRACE(a) { ser_printk a;} @@ -281,14 +288,14 @@ #define TRACE(A) #endif -void callDone(Scsi_Cmnd *SCpnt) +void callDone (Scsi_Cmnd * SCpnt) { if (SCpnt->result) { - TRACE(("*** %.08lx %.02x <%d.%d.%d> = %x\n", SCpnt->serial_number, - SCpnt->cmnd[0], SCpnt->channel, SCpnt->target, SCpnt->lun, - SCpnt->result)); + TRACE (("*** %.08lx %.02x <%d.%d.%d> = %x\n", SCpnt->serial_number, + SCpnt->cmnd[0], SCpnt->channel, SCpnt->target, SCpnt->lun, + SCpnt->result)); } - SCpnt->scsi_done(SCpnt); + SCpnt->scsi_done (SCpnt); } /*------------------------------------------------------------------------- @@ -297,82 +304,79 @@ * *-------------------------------------------------------------------------*/ -/*================================================ - * Initialize SCB structures - *================================================*/ -static void initSCB(mega_host_config *megaCfg) +//================================================ +// Initialize SCB structures +//================================================ +static void initSCB (mega_host_config * megaCfg) { int idx; - for(idx=0; idxmax_cmds; idx++) { - megaCfg->scbList[idx].idx = -1; - megaCfg->scbList[idx].flag = 0; + for (idx = 0; idx < megaCfg->max_cmds; idx++) { + megaCfg->scbList[idx].idx = -1; + megaCfg->scbList[idx].flag = 0; megaCfg->scbList[idx].sgList = NULL; - megaCfg->scbList[idx].SCpnt = NULL; + megaCfg->scbList[idx].SCpnt = NULL; } } -/*=========================== - * Allocate a SCB structure - *===========================*/ -static mega_scb *allocateSCB(mega_host_config *megaCfg,Scsi_Cmnd *SCpnt) +//=========================== +// Allocate a SCB structure +//=========================== +static mega_scb * allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt) { - int idx; - long flags; + int idx; + long flags; - spin_lock_irqsave(&mega_lock,flags); - for(idx=0; idxmax_cmds; idx++) { + spin_lock_irqsave (&mega_lock, flags); + for (idx = 0; idx < megaCfg->max_cmds; idx++) { if (megaCfg->scbList[idx].idx < 0) { - /* Set Index and SCB pointer */ - megaCfg->scbList[idx].flag = 0; - megaCfg->scbList[idx].idx = idx; + /* Set Index and SCB pointer */ + megaCfg->scbList[idx].flag = 0; + megaCfg->scbList[idx].idx = idx; megaCfg->scbList[idx].SCpnt = SCpnt; - megaCfg->scbList[idx].next = NULL; - spin_unlock_irqrestore(&mega_lock,flags); + megaCfg->scbList[idx].next = NULL; + spin_unlock_irqrestore (&mega_lock, flags); if (megaCfg->scbList[idx].sgList == NULL) { megaCfg->scbList[idx].sgList = - kmalloc(sizeof(mega_sglist)*MAX_SGLIST,GFP_ATOMIC|GFP_DMA); + kmalloc (sizeof (mega_sglist) * MAX_SGLIST, GFP_ATOMIC | GFP_DMA); } return &megaCfg->scbList[idx]; } } - spin_unlock_irqrestore(&mega_lock,flags); + spin_unlock_irqrestore (&mega_lock, flags); + + printk (KERN_WARNING "Megaraid: Could not allocate free SCB!!!\n"); - printk(KERN_WARNING "Megaraid: Could not allocate free SCB!!!\n"); - return NULL; } -/*======================= - * Free a SCB structure - *=======================*/ -static void freeSCB(mega_scb *scb) -{ - long flags; - - spin_lock_irqsave(&mega_lock,flags); - scb->flag = 0; - scb->idx = -1; - scb->next = NULL; +//======================= +// Free a SCB structure +//======================= +static void freeSCB (mega_scb * scb) +{ + scb->flag = 0; + scb->idx = -1; + scb->next = NULL; scb->SCpnt = NULL; - spin_unlock_irqrestore(&mega_lock,flags); } /* Run through the list of completed requests */ -static void mega_rundoneq() +static void mega_rundoneq () { mega_host_config *megaCfg; - Scsi_Cmnd *SCpnt; - long islogical; + Scsi_Cmnd *SCpnt; + long islogical; - while(1) { - DEQUEUE(SCpnt, Scsi_Cmnd, qCompleted, host_scribble); - if (SCpnt == NULL) return; + while (1) { + DEQUEUE (SCpnt, Scsi_Cmnd, qCompleted, host_scribble); + if (SCpnt == NULL) + return; - megaCfg = (mega_host_config *)SCpnt->host->hostdata; + megaCfg = (mega_host_config *) SCpnt->host->hostdata; /* Check if we're allowing access to RAID drives or physical * if use_raid == 1 and this wasn't a disk on the max channel or @@ -381,14 +385,15 @@ */ islogical = (SCpnt->channel == megaCfg->host->max_channel) ? 1 : 0; if (SCpnt->cmnd[0] == INQUIRY && - ((((u_char*)SCpnt->request_buffer)[0] & 0x1F) == TYPE_DISK) && + ((((u_char *) SCpnt->request_buffer)[0] & 0x1F) == TYPE_DISK) && (islogical != use_raid)) { - SCpnt->result = 0xF0; + SCpnt->result = 0xF0; } /* Convert result to error */ - switch(SCpnt->result) { - case 0x00: case 0x02: + switch (SCpnt->result) { + case 0x00: + case 0x02: SCpnt->result |= (DID_OK << 16); break; case 0x8: @@ -400,16 +405,20 @@ } /* Callback */ - callDone(SCpnt); + callDone (SCpnt); } } /* Add command to the list of completed requests */ -static void mega_cmd_done(mega_host_config *megaCfg,mega_scb *pScb, int status) +static void mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb, int status) { + long flags; + pScb->SCpnt->result = status; - ENQUEUE(pScb->SCpnt, Scsi_Cmnd, qCompleted, host_scribble); - freeSCB(pScb); + ENQUEUE (pScb->SCpnt, Scsi_Cmnd, qCompleted, host_scribble); + spin_lock_irqsave (&mega_lock, flags); + freeSCB (pScb); + spin_unlock_irqrestore (&mega_lock, flags); } /*---------------------------------------------------- @@ -417,42 +426,42 @@ * * Run as a scheduled task *----------------------------------------------------*/ -static void mega_runque(void *dummy) +static void mega_runque (void *dummy) { mega_host_config *megaCfg; - mega_scb *pScb; - long flags; + mega_scb *pScb; + long flags; /* Take care of any completed requests */ - mega_rundoneq(); + mega_rundoneq (); - DEQUEUE(pScb,mega_scb,qPending,next); + DEQUEUE (pScb, mega_scb, qPending, next); if (pScb) { - megaCfg = (mega_host_config *)pScb->SCpnt->host->hostdata; + megaCfg = (mega_host_config *) pScb->SCpnt->host->hostdata; - if (megaCfg->mbox->busy || megaCfg->flag & (IN_ISR|PENDING)) { - TRACE(("%.08lx %.02x <%d.%d.%d> intr%d busy%d isr%d pending%d\n", - pScb->SCpnt->serial_number, - pScb->SCpnt->cmnd[0], - pScb->SCpnt->channel, - pScb->SCpnt->target, - pScb->SCpnt->lun, - intr_count, - megaCfg->mbox->busy, - (megaCfg->flag & IN_ISR) ? 1 : 0, - (megaCfg->flag & PENDING) ? 1 : 0)); + if (megaCfg->mbox->busy || megaCfg->flag & (IN_ISR | PENDING)) { + TRACE (("%.08lx %.02x <%d.%d.%d> busy%d isr%d pending%d\n", + pScb->SCpnt->serial_number, + pScb->SCpnt->cmnd[0], + pScb->SCpnt->channel, + pScb->SCpnt->target, + pScb->SCpnt->lun, + megaCfg->mbox->busy, + (megaCfg->flag & IN_ISR) ? 1 : 0, + (megaCfg->flag & PENDING) ? 1 : 0)); } - if (MegaIssueCmd(megaCfg, pScb->mboxData, pScb, 1)) { + if (MegaIssueCmd (megaCfg, pScb->mboxData, pScb, 1)) { /* We're BUSY... come back later */ - spin_lock_irqsave(&mega_lock,flags); + spin_lock_irqsave (&mega_lock, flags); pScb->next = qPending; - qPending = pScb; - spin_unlock_irqrestore(&mega_lock,flags); + qPending = pScb; + spin_unlock_irqrestore (&mega_lock, flags); - if (!(megaCfg->flag & PENDING)) { /* If PENDING, irq will schedule task */ - queue_task(&runq, &tq_scheduler); + if (!(megaCfg->flag & PENDING)) { + /* If PENDING, irq will schedule task */ + queue_task (&runq, &tq_scheduler); } } } @@ -466,17 +475,20 @@ * If NULL is returned, the scsi_done function MUST have been called * *-------------------------------------------------------------------*/ -static mega_scb *mega_build_cmd(mega_host_config *megaCfg, Scsi_Cmnd *SCpnt) +static mega_scb * mega_build_cmd (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt) { - mega_scb *pScb; - mega_mailbox *mbox; + mega_scb *pScb; + mega_mailbox *mbox; mega_passthru *pthru; - long seg; + long seg; + + if (SCpnt->cmnd[0] & 0x80) /* ioctl from megamgr */ + return mega_ioctl (megaCfg, SCpnt); /* We don't support multi-luns */ if (SCpnt->lun != 0) { SCpnt->result = (DID_BAD_TARGET << 16); - callDone(SCpnt); + callDone (SCpnt); return NULL; } @@ -486,44 +498,44 @@ * *-----------------------------------------------------*/ if (SCpnt->channel == megaCfg->host->max_channel) { - switch(SCpnt->cmnd[0]) { + switch (SCpnt->cmnd[0]) { case TEST_UNIT_READY: - memset(SCpnt->request_buffer, 0, SCpnt->request_bufflen); + memset (SCpnt->request_buffer, 0, SCpnt->request_bufflen); SCpnt->result = (DID_OK << 16); - callDone(SCpnt); + callDone (SCpnt); return NULL; case MODE_SENSE: - memset(SCpnt->request_buffer, 0, SCpnt->cmnd[4]); + memset (SCpnt->request_buffer, 0, SCpnt->cmnd[4]); SCpnt->result = (DID_OK << 16); - callDone(SCpnt); + callDone (SCpnt); return NULL; case READ_CAPACITY: case INQUIRY: /* Allocate a SCB and initialize passthru */ - if ((pScb = allocateSCB(megaCfg,SCpnt)) == NULL) { + if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) { SCpnt->result = (DID_ERROR << 16); - callDone(SCpnt); + callDone (SCpnt); return NULL; } pthru = &pScb->pthru; - mbox = (mega_mailbox *)&pScb->mboxData; + mbox = (mega_mailbox *) & pScb->mboxData; - memset(mbox, 0, sizeof(pScb->mboxData)); - memset(pthru, 0, sizeof(mega_passthru)); - pthru->timeout = 0; - pthru->ars = 0; - pthru->islogical = 1; - pthru->logdrv = SCpnt->target; - pthru->cdblen = SCpnt->cmd_len; - pthru->dataxferaddr = virt_to_bus(SCpnt->request_buffer); - pthru->dataxferlen = SCpnt->request_bufflen; - memcpy(pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len); + memset (mbox, 0, sizeof (pScb->mboxData)); + memset (pthru, 0, sizeof (mega_passthru)); + pthru->timeout = 0; + pthru->ars = 0; + pthru->islogical = 1; + pthru->logdrv = SCpnt->target; + pthru->cdblen = SCpnt->cmd_len; + pthru->dataxferaddr = virt_to_bus (SCpnt->request_buffer); + pthru->dataxferlen = SCpnt->request_bufflen; + memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len); /* Initialize mailbox area */ - mbox->cmd = MEGA_MBOXCMD_PASSTHRU; - mbox->xferaddr = virt_to_bus(pthru); + mbox->cmd = MEGA_MBOXCMD_PASSTHRU; + mbox->xferaddr = virt_to_bus (pthru); return pScb; @@ -532,51 +544,51 @@ case READ_10: case WRITE_10: /* Allocate a SCB and initialize mailbox */ - if ((pScb = allocateSCB(megaCfg,SCpnt)) == NULL) { + if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) { SCpnt->result = (DID_ERROR << 16); - callDone(SCpnt); + callDone (SCpnt); return NULL; } - mbox = (mega_mailbox *)&pScb->mboxData; + mbox = (mega_mailbox *) & pScb->mboxData; - memset(mbox, 0, sizeof(pScb->mboxData)); + memset (mbox, 0, sizeof (pScb->mboxData)); mbox->logdrv = SCpnt->target; - mbox->cmd = (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == READ_10) ? + mbox->cmd = (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == READ_10) ? MEGA_MBOXCMD_LREAD : MEGA_MBOXCMD_LWRITE; - + /* 6-byte */ if (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == WRITE_6) { - mbox->numsectors = - (u_long)SCpnt->cmnd[4]; - mbox->lba = - ((u_long)SCpnt->cmnd[1] << 16) | - ((u_long)SCpnt->cmnd[2] << 8) | - (u_long)SCpnt->cmnd[3]; + mbox->numsectors = + (u_long) SCpnt->cmnd[4]; + mbox->lba = + ((u_long) SCpnt->cmnd[1] << 16) | + ((u_long) SCpnt->cmnd[2] << 8) | + (u_long) SCpnt->cmnd[3]; mbox->lba &= 0x1FFFFF; } - + /* 10-byte */ if (*SCpnt->cmnd == READ_10 || *SCpnt->cmnd == WRITE_10) { - mbox->numsectors = - (u_long)SCpnt->cmnd[8] | - ((u_long)SCpnt->cmnd[7] << 8); + mbox->numsectors = + (u_long) SCpnt->cmnd[8] | + ((u_long) SCpnt->cmnd[7] << 8); mbox->lba = - ((u_long)SCpnt->cmnd[2] << 24) | - ((u_long)SCpnt->cmnd[3] << 16) | - ((u_long)SCpnt->cmnd[4] << 8) | - (u_long)SCpnt->cmnd[5]; + ((u_long) SCpnt->cmnd[2] << 24) | + ((u_long) SCpnt->cmnd[3] << 16) | + ((u_long) SCpnt->cmnd[4] << 8) | + (u_long) SCpnt->cmnd[5]; } - + /* Calculate Scatter-Gather info */ - mbox->numsgelements = build_sglist(megaCfg, pScb, - (u_long*)&mbox->xferaddr, - (u_long*)&seg); + mbox->numsgelements = build_sglist (megaCfg, pScb, + (u_long *) & mbox->xferaddr, + (u_long *) & seg); return pScb; - + default: SCpnt->result = (DID_BAD_TARGET << 16); - callDone(SCpnt); + callDone (SCpnt); return NULL; } } @@ -587,31 +599,31 @@ *-----------------------------------------------------*/ else { /* Allocate a SCB and initialize passthru */ - if ((pScb = allocateSCB(megaCfg,SCpnt)) == NULL) { + if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) { SCpnt->result = (DID_ERROR << 16); - callDone(SCpnt); + callDone (SCpnt); return NULL; } pthru = &pScb->pthru; - mbox = (mega_mailbox *)pScb->mboxData; - - memset(mbox, 0, sizeof(pScb->mboxData)); - memset(pthru, 0, sizeof(mega_passthru)); - pthru->timeout = 0; - pthru->ars = 0; + mbox = (mega_mailbox *) pScb->mboxData; + + memset (mbox, 0, sizeof (pScb->mboxData)); + memset (pthru, 0, sizeof (mega_passthru)); + pthru->timeout = 0; + pthru->ars = 0; pthru->islogical = 0; - pthru->channel = SCpnt->channel; - pthru->target = SCpnt->target; - pthru->cdblen = SCpnt->cmd_len; - memcpy(pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len); - - pthru->numsgelements = build_sglist(megaCfg, pScb, - (u_long *)&pthru->dataxferaddr, - (u_long *)&pthru->dataxferlen); - + pthru->channel = SCpnt->channel; + pthru->target = SCpnt->target; + pthru->cdblen = SCpnt->cmd_len; + memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len); + + pthru->numsgelements = build_sglist (megaCfg, pScb, + (u_long *) & pthru->dataxferaddr, + (u_long *) & pthru->dataxferlen); + /* Initialize mailbox */ - mbox->cmd = MEGA_MBOXCMD_PASSTHRU; - mbox->xferaddr = virt_to_bus(pthru); + mbox->cmd = MEGA_MBOXCMD_PASSTHRU; + mbox->xferaddr = virt_to_bus (pthru); return pScb; } @@ -619,88 +631,163 @@ } /*-------------------------------------------------------------------- + * build RAID commands for controller, passed down through ioctl() + *--------------------------------------------------------------------*/ +static mega_scb * mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt) +{ + mega_scb *pScb; + mega_ioctl_mbox *mbox; + mega_mailbox *mailbox; + mega_passthru *pthru; + long seg; + + if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) { + SCpnt->result = (DID_ERROR << 16); + callDone (SCpnt); + return NULL; + } + + mbox = (mega_ioctl_mbox *) & pScb->mboxData; + mailbox = (mega_mailbox *) & pScb->mboxData; + memset (mailbox, 0, sizeof (pScb->mboxData)); + + if (SCpnt->cmnd[0] == 0x83) { /* passthrough command */ + char cdblen = SCpnt->cmnd[2]; + + pthru = &pScb->pthru; + memset (pthru, 0, sizeof (mega_passthru)); + pthru->islogical = SCpnt->cmnd[cdblen + 3] & 0x80; + pthru->timeout = SCpnt->cmnd[cdblen + 3] & 0x07; + pthru->reqsenselen = 10; /* ? MAX_SENSE; */ + pthru->ars = SCpnt->cmnd[cdblen + 3] & 0x08; + pthru->logdrv = SCpnt->cmnd[cdblen + 4]; + pthru->channel = SCpnt->cmnd[cdblen + 5]; + pthru->target = SCpnt->cmnd[cdblen + 6]; + pthru->cdblen = cdblen; + memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmnd[2]); + + mailbox->cmd = MEGA_MBOXCMD_PASSTHRU; + mailbox->xferaddr = virt_to_bus (pthru); + + pthru->numsgelements = build_sglist (megaCfg, pScb, + (u_long *) & pthru->dataxferaddr, + (u_long *) & pthru->dataxferlen); + + return pScb; + } + /* else normal (nonpassthru) command */ + + mbox->cmd = SCpnt->cmnd[0] & 0x7F; + mbox->channel = SCpnt->cmnd[1]; + mbox->param = SCpnt->cmnd[2]; + mbox->pad[0] = SCpnt->cmnd[3]; + mbox->logdrv = SCpnt->cmnd[4]; + + mbox->numsgelements = build_sglist (megaCfg, pScb, + (u_long *) & mbox->xferaddr, + (u_long *) & seg); + + return (pScb); +} + + +/*-------------------------------------------------------------------- * Interrupt service routine *--------------------------------------------------------------------*/ -static void megaraid_isr(int irq, void *devp, struct pt_regs *regs) +static void megaraid_isr (int irq, void *devp, struct pt_regs *regs) { - mega_host_config *megaCfg; - u_char byte, idx, sIdx; - u_long dword; - mega_mailbox *mbox; - mega_scb *pScb; - long flags; - int qCnt, qStatus; + mega_host_config *megaCfg; + u_char byte, idx, sIdx; + u_long dword; + mega_mailbox *mbox; + mega_scb *pScb; + long flags; + int qCnt, qStatus; - megaCfg = (mega_host_config *)devp; - mbox = (mega_mailbox *)megaCfg->mbox; + megaCfg = (mega_host_config *) devp; + mbox = (mega_mailbox *) megaCfg->mbox; if (megaCfg->host->irq == irq) { - spin_lock_irqsave(&mega_lock,flags); + +#if LINUX_VERSION_CODE >= 0x20100 + spin_lock_irqsave (&io_request_lock, flags); +#endif + + spin_lock_irqsave (&mega_lock, flags); if (megaCfg->flag & IN_ISR) { - TRACE(("ISR called reentrantly!!\n")); + TRACE (("ISR called reentrantly!!\n")); } megaCfg->flag |= IN_ISR; /* Check if a valid interrupt is pending */ if (megaCfg->flag & BOARD_QUARTZ) { - dword = RDOUTDOOR(megaCfg); - if (dword != 0x10001234) { - /* Spurious interrupt */ - megaCfg->flag &= ~IN_ISR; - spin_unlock_irqrestore(&mega_lock,flags); - return; - } - WROUTDOOR(megaCfg,dword); - } else { - byte = READ_PORT(megaCfg->host->io_port, INTR_PORT); - if ((byte & VALID_INTR_BYTE) == 0) { - /* Spurious interrupt */ - megaCfg->flag &= ~IN_ISR; - spin_unlock_irqrestore(&mega_lock,flags); - return; - } - WRITE_PORT(megaCfg->host->io_port, INTR_PORT, byte); + dword = RDOUTDOOR (megaCfg); + if (dword != 0x10001234) { + /* Spurious interrupt */ + megaCfg->flag &= ~IN_ISR; + spin_unlock_irqrestore (&mega_lock, flags); +#if LINUX_VERSION_CODE >= 0x20100 + spin_unlock_irqrestore (&io_request_lock, flags); +#endif + return; + } + WROUTDOOR (megaCfg, dword); + } + else { + byte = READ_PORT (megaCfg->host->io_port, INTR_PORT); + if ((byte & VALID_INTR_BYTE) == 0) { + /* Spurious interrupt */ + megaCfg->flag &= ~IN_ISR; + spin_unlock_irqrestore (&mega_lock, flags); +#if LINUX_VERSION_CODE >= 0x20100 + spin_unlock_irqrestore (&io_request_lock, flags); +#endif + return; + } + WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte); } - - qCnt = mbox->numstatus; + + qCnt = mbox->numstatus; qStatus = mbox->status; - if (qCnt > 1) {TRACE(("ISR: Received %d status\n", qCnt)) - printk(KERN_DEBUG "Got numstatus = %d\n",qCnt); + if (qCnt > 1) { + TRACE (("ISR: Received %d status\n", qCnt)) + printk (KERN_DEBUG "Got numstatus = %d\n", qCnt); } - - for(idx=0; idxcompleted[idx]; if (sIdx > 0) { - pScb = &megaCfg->scbList[sIdx-1]; - spin_unlock_irqrestore(&mega_lock,flags); /* locks within cmd_done */ - mega_cmd_done(megaCfg,&megaCfg->scbList[sIdx-1], qStatus); - spin_lock_irqsave(&mega_lock,flags); + pScb = &megaCfg->scbList[sIdx - 1]; + spin_unlock_irqrestore (&mega_lock, flags); /* megalock within cmd_done */ + mega_cmd_done (megaCfg, &megaCfg->scbList[sIdx - 1], qStatus); + spin_lock_irqsave (&mega_lock, flags); } } if (megaCfg->flag & BOARD_QUARTZ) { - WRINDOOR(megaCfg,virt_to_bus(megaCfg->mbox)|0x2); - while (RDINDOOR(megaCfg) & 0x02); - } else { - CLEAR_INTR(megaCfg->host->io_port); + WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2); + while (RDINDOOR (megaCfg) & 0x02); + } + else { + CLEAR_INTR (megaCfg->host->io_port); } megaCfg->flag &= ~IN_ISR; megaCfg->flag &= ~PENDING; - spin_unlock_irqrestore(&mega_lock,flags); + spin_unlock_irqrestore (&mega_lock, flags); + mega_runque (NULL); - spin_lock_irqsave(&io_request_lock, flags); - mega_runque(NULL); - spin_unlock_irqrestore(&io_request_lock,flags); +#if LINUX_VERSION_CODE >= 0x20100 + spin_unlock_irqrestore (&io_request_lock, flags); +#endif #if 0 /* Queue as a delayed ISR routine */ - queue_task_irq_off(&runq, &tq_immediate); - mark_bh(IMMEDIATE_BH); - spin_unlock_irqrestore(&mega_lock,flags); + queue_task_irq_off (&runq, &tq_immediate); + mark_bh (IMMEDIATE_BH); #endif } @@ -709,111 +796,128 @@ /*==================================================*/ /* Wait until the controller's mailbox is available */ /*==================================================*/ -static int busyWaitMbox(mega_host_config *megaCfg) +static int busyWaitMbox (mega_host_config * megaCfg) { - mega_mailbox *mbox = (mega_mailbox *)megaCfg->mbox; - long counter; + mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox; + long counter; - for(counter=0; counter<0xFFFFFF; counter++) { - if (!mbox->busy) return 0; + for (counter = 0; counter < 30000; counter++) { + udelay (100); + if (!mbox->busy) + return 0; } - return -1; -} - -/*===================================================== - * Post a command to the card - * - * Arguments: - * mega_host_config *megaCfg - Controller structure - * u_char *mboxData - Mailbox area, 16 bytes - * mega_scb *pScb - SCB posting (or NULL if N/A) - * int intr - if 1, interrupt, 0 is blocking - *=====================================================*/ -static int MegaIssueCmd(mega_host_config *megaCfg, - u_char *mboxData, - mega_scb *pScb, - int intr) -{ - mega_mailbox *mbox = (mega_mailbox *)megaCfg->mbox; - long flags; - u_char byte; - u_long cmdDone; + return -1; /* give up after 3 seconds */ +} - mboxData[0x1] = (pScb ? pScb->idx+1 : 0x00); /* Set cmdid */ - mboxData[0xF] = 1; /* Set busy */ +//===================================================== +// Post a command to the card +// +// Arguments: +// mega_host_config *megaCfg - Controller structure +// u_char *mboxData - Mailbox area, 16 bytes +// mega_scb *pScb - SCB posting (or NULL if N/A) +// int intr - if 1, interrupt, 0 is blocking +//===================================================== +static int MegaIssueCmd (mega_host_config * megaCfg, + u_char * mboxData, + mega_scb * pScb, + int intr) +{ + mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox; + long flags; + u_char byte; + u_long cmdDone; + + mboxData[0x1] = (pScb ? pScb->idx + 1 : 0x00); /* Set cmdid */ + mboxData[0xF] = 1; /* Set busy */ + + spin_lock_irqsave(&mega_lock,flags); /* one bad report of problem when issuing a command while pending. * Wasn't able to duplicate, but it doesn't really affect performance * anyway, so don't allow command while PENDING */ + if (megaCfg->flag & PENDING) { + spin_unlock_irqrestore(&mega_lock,flags); return -1; } /* Wait until mailbox is free */ - if (busyWaitMbox(megaCfg)) { + if (busyWaitMbox (megaCfg)) { if (pScb) { - TRACE(("Mailbox busy %.08lx <%d.%d.%d>\n", pScb->SCpnt->serial_number, - pScb->SCpnt->channel, pScb->SCpnt->target, pScb->SCpnt->lun)); + TRACE (("Mailbox busy %.08lx <%d.%d.%d>\n", pScb->SCpnt->serial_number, + pScb->SCpnt->channel, pScb->SCpnt->target, pScb->SCpnt->lun)); + } else { + TRACE(("pScb NULL in MegaIssueCmd!\n")); } + spin_unlock_irqrestore(&mega_lock,flags); return -1; } /* Copy mailbox data into host structure */ - spin_lock_irqsave(&mega_lock,flags); - memset(mbox, 0, sizeof(mega_mailbox)); - memcpy(mbox, mboxData, 16); - spin_unlock_irqrestore(&mega_lock,flags); + memset (mbox, 0, sizeof (mega_mailbox)); + memcpy (mbox, mboxData, 16); /* Kick IO */ megaCfg->flag |= PENDING; if (intr) { /* Issue interrupt (non-blocking) command */ if (megaCfg->flag & BOARD_QUARTZ) { - mbox->mraid_poll = 0; - mbox->mraid_ack = 0; - WRINDOOR(megaCfg, virt_to_bus(megaCfg->mbox) | 0x1); - } else { - ENABLE_INTR(megaCfg->host->io_port); - ISSUE_COMMAND(megaCfg->host->io_port); + mbox->mraid_poll = 0; + mbox->mraid_ack = 0; + WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x1); } + else { + ENABLE_INTR (megaCfg->host->io_port); + ISSUE_COMMAND (megaCfg->host->io_port); + } + spin_unlock_irqrestore(&mega_lock,flags); } - else { /* Issue non-ISR (blocking) command */ + else { /* Issue non-ISR (blocking) command */ if (megaCfg->flag & BOARD_QUARTZ) { - mbox->mraid_poll = 0; - mbox->mraid_ack = 0; - WRINDOOR(megaCfg, virt_to_bus(megaCfg->mbox) | 0x1); + mbox->mraid_poll = 0; + mbox->mraid_ack = 0; + WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x1); - while((cmdDone=RDOUTDOOR(megaCfg)) != 0x10001234); - WROUTDOOR(megaCfg, cmdDone); + while ((cmdDone = RDOUTDOOR (megaCfg)) != 0x10001234); + WROUTDOOR (megaCfg, cmdDone); + spin_unlock_irqrestore(&mega_lock,flags); if (pScb) { - mega_cmd_done(megaCfg,pScb, mbox->status); - mega_rundoneq(); + mega_cmd_done (megaCfg, pScb, mbox->status); + mega_rundoneq (); } - WRINDOOR(megaCfg,virt_to_bus(megaCfg->mbox) | 0x2); - while(RDINDOOR(megaCfg) & 0x2); + WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2); + while (RDINDOOR (megaCfg) & 0x2); megaCfg->flag &= ~PENDING; + } else { - DISABLE_INTR(megaCfg->host->io_port); - ISSUE_COMMAND(megaCfg->host->io_port); - - while(!((byte=READ_PORT(megaCfg->host->io_port,INTR_PORT))&INTR_VALID)); - WRITE_PORT(megaCfg->host->io_port, INTR_PORT, byte); - - ENABLE_INTR(megaCfg->host->io_port); - CLEAR_INTR(megaCfg->host->io_port); - + DISABLE_INTR (megaCfg->host->io_port); + ISSUE_COMMAND (megaCfg->host->io_port); + + while (!((byte = READ_PORT (megaCfg->host->io_port, INTR_PORT)) & INTR_VALID)); + WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte); + + + ENABLE_INTR (megaCfg->host->io_port); + CLEAR_INTR (megaCfg->host->io_port); + megaCfg->flag &= ~PENDING; + spin_unlock_irqrestore(&mega_lock,flags); + if (pScb) { - mega_cmd_done(megaCfg,pScb, mbox->status); - mega_rundoneq(); + mega_cmd_done (megaCfg, pScb, mbox->status); + mega_rundoneq (); } - megaCfg->flag &= ~PENDING; + else { + TRACE (("Error: NULL pScb!\n")); + } + } } @@ -823,42 +927,42 @@ /*------------------------------------------------------------------- * Copies data to SGLIST *-------------------------------------------------------------------*/ -static int build_sglist(mega_host_config *megaCfg, mega_scb *scb, - u_long *buffer, u_long *length) +static int build_sglist (mega_host_config * megaCfg, mega_scb * scb, + u_long * buffer, u_long * length) { struct scatterlist *sgList; int idx; /* Scatter-gather not used */ if (scb->SCpnt->use_sg == 0) { - *buffer = virt_to_bus(scb->SCpnt->request_buffer); - *length = (u_long)scb->SCpnt->request_bufflen; + *buffer = virt_to_bus (scb->SCpnt->request_buffer); + *length = (u_long) scb->SCpnt->request_bufflen; return 0; } - sgList = (struct scatterlist *)scb->SCpnt->buffer; + sgList = (struct scatterlist *) scb->SCpnt->buffer; if (scb->SCpnt->use_sg == 1) { - *buffer = virt_to_bus(sgList[0].address); - *length = (u_long)sgList[0].length; + *buffer = virt_to_bus (sgList[0].address); + *length = (u_long) sgList[0].length; return 0; } /* Copy Scatter-Gather list info into controller structure */ - for(idx=0; idxSCpnt->use_sg; idx++) { - scb->sgList[idx].address = virt_to_bus(sgList[idx].address); - scb->sgList[idx].length = (u_long)sgList[idx].length; + for (idx = 0; idx < scb->SCpnt->use_sg; idx++) { + scb->sgList[idx].address = virt_to_bus (sgList[idx].address); + scb->sgList[idx].length = (u_long) sgList[idx].length; } - + /* Reset pointer and length fields */ - *buffer = virt_to_bus(scb->sgList); + *buffer = virt_to_bus (scb->sgList); *length = 0; /* Return count of SG requests */ return scb->SCpnt->use_sg; } - + /*-------------------------------------------------------------------- - * Initializes the address of the controller's mailbox register + * Initializes the adress of the controller's mailbox register * The mailbox register is used to issue commands to the card. * Format of the mailbox area: * 00 01 command @@ -873,25 +977,25 @@ * 10 01 numstatus byte * 11 01 status byte *--------------------------------------------------------------------*/ -static int mega_register_mailbox(mega_host_config *megaCfg, u_long paddr) +static int mega_register_mailbox (mega_host_config * megaCfg, u_long paddr) { /* align on 16-byte boundry */ megaCfg->mbox = &megaCfg->mailbox; - megaCfg->mbox = (mega_mailbox *) ((((ulong)megaCfg->mbox) + 16)&0xfffffff0); - paddr = (paddr+16)&0xfffffff0; + megaCfg->mbox = (mega_mailbox *) ((((ulong) megaCfg->mbox) + 16) & 0xfffffff0); + paddr = (paddr + 16) & 0xfffffff0; /* Register mailbox area with the firmware */ if (megaCfg->flag & BOARD_QUARTZ) { } else { - WRITE_PORT(megaCfg->host->io_port, MBOX_PORT0, paddr & 0xFF); - WRITE_PORT(megaCfg->host->io_port, MBOX_PORT1, (paddr >> 8) & 0xFF); - WRITE_PORT(megaCfg->host->io_port, MBOX_PORT2, (paddr >> 16) & 0xFF); - WRITE_PORT(megaCfg->host->io_port, MBOX_PORT3, (paddr >> 24) & 0xFF); - WRITE_PORT(megaCfg->host->io_port, ENABLE_MBOX_REGION, ENABLE_MBOX_BYTE); - - CLEAR_INTR(megaCfg->host->io_port); - ENABLE_INTR(megaCfg->host->io_port); + WRITE_PORT (megaCfg->host->io_port, MBOX_PORT0, paddr & 0xFF); + WRITE_PORT (megaCfg->host->io_port, MBOX_PORT1, (paddr >> 8) & 0xFF); + WRITE_PORT (megaCfg->host->io_port, MBOX_PORT2, (paddr >> 16) & 0xFF); + WRITE_PORT (megaCfg->host->io_port, MBOX_PORT3, (paddr >> 24) & 0xFF); + WRITE_PORT (megaCfg->host->io_port, ENABLE_MBOX_REGION, ENABLE_MBOX_BYTE); + + CLEAR_INTR (megaCfg->host->io_port); + ENABLE_INTR (megaCfg->host->io_port); } return 0; } @@ -899,77 +1003,79 @@ /*------------------------------------------------------------------- * Issue an adapter info query to the controller *-------------------------------------------------------------------*/ -static int mega_i_query_adapter(mega_host_config *megaCfg) +static int mega_i_query_adapter (mega_host_config * megaCfg) { mega_RAIDINQ *adapterInfo; mega_mailbox *mbox; - u_char mboxData[16]; - u_long paddr; + u_char mboxData[16]; + u_long paddr; - spin_lock_init(&mega_lock); + spin_lock_init (&mega_lock); /* Initialize adapter inquiry */ - paddr = virt_to_bus(megaCfg->mega_buffer); - mbox = (mega_mailbox *)mboxData; + paddr = virt_to_bus (megaCfg->mega_buffer); + mbox = (mega_mailbox *) mboxData; - memset((void *)megaCfg->mega_buffer, 0, sizeof(megaCfg->mega_buffer)); - memset(mbox, 0, 16); + memset ((void *) megaCfg->mega_buffer, 0, sizeof (megaCfg->mega_buffer)); + memset (mbox, 0, 16); /* Initialize mailbox registers */ - mbox->cmd = MEGA_MBOXCMD_ADAPTERINQ; + mbox->cmd = MEGA_MBOXCMD_ADAPTERINQ; mbox->xferaddr = paddr; /* Issue a blocking command to the card */ - MegaIssueCmd(megaCfg, mboxData, NULL, 0); - + MegaIssueCmd (megaCfg, mboxData, NULL, 0); + /* Initialize host/local structures with Adapter info */ - adapterInfo = (mega_RAIDINQ *)megaCfg->mega_buffer; + adapterInfo = (mega_RAIDINQ *) megaCfg->mega_buffer; megaCfg->host->max_channel = adapterInfo->AdpInfo.ChanPresent; - megaCfg->host->max_id = adapterInfo->AdpInfo.MaxTargPerChan; - megaCfg->numldrv = adapterInfo->LogdrvInfo.NumLDrv; +/* megaCfg->host->max_id = adapterInfo->AdpInfo.MaxTargPerChan; */ + megaCfg->host->max_id = 9; /* max logical drives + 1 */ + megaCfg->numldrv = adapterInfo->LogdrvInfo.NumLDrv; #if 0 - printk(KERN_DEBUG "---- Logical drive info ----\n"); - for(i=0; inumldrv; i++) { - printk(KERN_DEBUG "%d: size: %ld prop: %x state: %x\n",i, - adapterInfo->LogdrvInfo.LDrvSize[i], - adapterInfo->LogdrvInfo.LDrvProp[i], - adapterInfo->LogdrvInfo.LDrvState[i]); - } - printk(KERN_DEBUG "---- Physical drive info ----\n"); - for(i=0; iPhysdrvInfo.PDrvState[i]); + printk ("KERN_DEBUG ---- Logical drive info ----\n"); + for (i = 0; i < megaCfg->numldrv; i++) { + printk ("%d: size: %ld prop: %x state: %x\n", i, + adapterInfo->LogdrvInfo.LDrvSize[i], + adapterInfo->LogdrvInfo.LDrvProp[i], + adapterInfo->LogdrvInfo.LDrvState[i]); + } + printk (KERN_DEBUG "---- Physical drive info ----\n"); + for (i = 0; i < MAX_PHYSICAL_DRIVES; i++) { + if (i && !(i % 8)) + printk ("\n"); + printk ("%d: %x ", i, adapterInfo->PhysdrvInfo.PDrvState[i]); } - printk("\n"); + printk ("\n"); #endif megaCfg->max_cmds = adapterInfo->AdpInfo.MaxConcCmds; -#ifdef HP /* use HP firmware and bios version encoding */ - sprintf(megaCfg->fwVer,"%c%d%d.%d%d", - adapterInfo->AdpInfo.FwVer[2], - adapterInfo->AdpInfo.FwVer[1] >> 8, - adapterInfo->AdpInfo.FwVer[1] & 0x0f, - adapterInfo->AdpInfo.FwVer[2] >> 8, - adapterInfo->AdpInfo.FwVer[2] & 0x0f); - sprintf(megaCfg->biosVer,"%c%d%d.%d%d", - adapterInfo->AdpInfo.BiosVer[2], - adapterInfo->AdpInfo.BiosVer[1] >> 8, - adapterInfo->AdpInfo.BiosVer[1] & 0x0f, - adapterInfo->AdpInfo.BiosVer[2] >> 8, - adapterInfo->AdpInfo.BiosVer[2] & 0x0f); +#ifdef HP /* use HP firmware and bios version encoding */ + sprintf (megaCfg->fwVer, "%c%d%d.%d%d", + adapterInfo->AdpInfo.FwVer[2], + adapterInfo->AdpInfo.FwVer[1] >> 8, + adapterInfo->AdpInfo.FwVer[1] & 0x0f, + adapterInfo->AdpInfo.FwVer[2] >> 8, + adapterInfo->AdpInfo.FwVer[2] & 0x0f); + sprintf (megaCfg->biosVer, "%c%d%d.%d%d", + adapterInfo->AdpInfo.BiosVer[2], + adapterInfo->AdpInfo.BiosVer[1] >> 8, + adapterInfo->AdpInfo.BiosVer[1] & 0x0f, + adapterInfo->AdpInfo.BiosVer[2] >> 8, + adapterInfo->AdpInfo.BiosVer[2] & 0x0f); #else - memcpy(megaCfg->fwVer, adapterInfo->AdpInfo.FwVer, 4); - megaCfg->fwVer[4] = 0; + memcpy (megaCfg->fwVer, adapterInfo->AdpInfo.FwVer, 4); + megaCfg->fwVer[4] = 0; - memcpy(megaCfg->biosVer, adapterInfo->AdpInfo.BiosVer, 4); - megaCfg->biosVer[4] = 0; + memcpy (megaCfg->biosVer, adapterInfo->AdpInfo.BiosVer, 4); + megaCfg->biosVer[4] = 0; #endif - printk(KERN_INFO "megaraid: [%s:%s] detected %d logical drives" CRLFSTR, - megaCfg->fwVer, - megaCfg->biosVer, - megaCfg->numldrv); + printk (KERN_INFO "megaraid: [%s:%s] detected %d logical drives" CRLFSTR, + megaCfg->fwVer, + megaCfg->biosVer, + megaCfg->numldrv); return 0; } @@ -982,47 +1088,56 @@ /*---------------------------------------------------------- * Returns data to be displayed in /proc/scsi/megaraid/X *----------------------------------------------------------*/ -int megaraid_proc_info(char *buffer, char **start, off_t offset, - int length, int inode, int inout) +int megaraid_proc_info (char *buffer, char **start, off_t offset, + int length, int inode, int inout) { *start = buffer; return 0; } -int findCard(Scsi_Host_Template *pHostTmpl, - u_short pciVendor, u_short pciDev, - long flag) +int findCard (Scsi_Host_Template * pHostTmpl, + u_short pciVendor, u_short pciDev, + long flag) { mega_host_config *megaCfg; struct Scsi_Host *host; - u_char pciBus, pciDevFun, megaIrq; - u_long megaBase; - u_short pciIdx = 0; + u_char pciBus, pciDevFun, megaIrq; + u_long megaBase; + u_short pciIdx = 0; #if LINUX_VERSION_CODE < 0x20100 - while(!pcibios_find_device(pciVendor, pciDev, pciIdx,&pciBus,&pciDevFun)) { + while (!pcibios_find_device (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) { + if (flag & BOARD_QUARTZ) { + u_int magic; + pcibios_read_config_dword (pciBus, pciDevFun, + PCI_CONF_AMISIG, + &magic); + if (magic != AMI_SIGNATURE) { + continue; /* not an AMI board */ + } + } #else - struct pci_dev *pdev=pci_devices; + struct pci_dev *pdev = pci_devices; - while((pdev = pci_find_device(pciVendor, pciDev, pdev))) { + while ((pdev = pci_find_device (pciVendor, pciDev, pdev))) { pciBus = pdev->bus->number; pciDevFun = pdev->devfn; #endif - printk(KERN_INFO "megaraid: found 0x%4.04x:0x%4.04x:idx %d:bus %d:slot %d:fun %d\n", - pciVendor, - pciDev, - pciIdx, pciBus, - PCI_SLOT(pciDevFun), - PCI_FUNC(pciDevFun)); - + printk (KERN_INFO "megaraid: found 0x%4.04x:0x%4.04x:idx %d:bus %d:slot %d:fun %d\n", + pciVendor, + pciDev, + pciIdx, pciBus, + PCI_SLOT (pciDevFun), + PCI_FUNC (pciDevFun)); + /* Read the base port and IRQ from PCI */ #if LINUX_VERSION_CODE < 0x20100 - pcibios_read_config_dword(pciBus, pciDevFun, - PCI_BASE_ADDRESS_0, - (u_int *)&megaBase); - pcibios_read_config_byte(pciBus, pciDevFun, - PCI_INTERRUPT_LINE, - &megaIrq); + pcibios_read_config_dword (pciBus, pciDevFun, + PCI_BASE_ADDRESS_0, + (u_int *) & megaBase); + pcibios_read_config_byte (pciBus, pciDevFun, + PCI_INTERRUPT_LINE, + &megaIrq); #else megaBase = pdev->base_address[0]; megaIrq = pdev->irq; @@ -1031,7 +1146,7 @@ if (flag & BOARD_QUARTZ) { megaBase &= PCI_BASE_ADDRESS_MEM_MASK; - megaBase = (long) ioremap(megaBase,128); + megaBase = (long) ioremap (megaBase, 128); } else { megaBase &= PCI_BASE_ADDRESS_IO_MASK; @@ -1039,47 +1154,47 @@ } /* Initialize SCSI Host structure */ - host = scsi_register(pHostTmpl, sizeof(mega_host_config)); - megaCfg = (mega_host_config *)host->hostdata; - memset(megaCfg, 0, sizeof(mega_host_config)); - - printk(KERN_INFO " scsi%d: Found a MegaRAID controller at 0x%x, IRQ: %d" CRLFSTR, - host->host_no, (u_int)megaBase, megaIrq); - + host = scsi_register (pHostTmpl, sizeof (mega_host_config)); + megaCfg = (mega_host_config *) host->hostdata; + memset (megaCfg, 0, sizeof (mega_host_config)); + + printk (KERN_INFO " scsi%d: Found a MegaRAID controller at 0x%x, IRQ: %d" CRLFSTR, + host->host_no, (u_int) megaBase, megaIrq); + /* Copy resource info into structure */ - megaCfg->flag = flag; - megaCfg->host = host; - megaCfg->base = megaBase; - megaCfg->host->irq = megaIrq; - megaCfg->host->io_port = megaBase; + megaCfg->flag = flag; + megaCfg->host = host; + megaCfg->base = megaBase; + megaCfg->host->irq = megaIrq; + megaCfg->host->io_port = megaBase; megaCfg->host->n_io_port = 16; megaCfg->host->unique_id = (pciBus << 8) | pciDevFun; - megaCtlrs[numCtlrs++] = megaCfg; + megaCtlrs[numCtlrs++] = megaCfg; if (flag != BOARD_QUARTZ) { /* Request our IO Range */ - if (check_region(megaBase, 16)) { - printk(KERN_WARNING "megaraid: Couldn't register I/O range!" CRLFSTR); - scsi_unregister(host); + if (check_region (megaBase, 16)) { + printk (KERN_WARNING "megaraid: Couldn't register I/O range!" CRLFSTR); + scsi_unregister (host); continue; } - request_region(megaBase, 16, "megaraid"); + request_region (megaBase, 16, "megaraid"); } /* Request our IRQ */ - if (request_irq(megaIrq, megaraid_isr, SA_SHIRQ, - "megaraid", megaCfg)) { - printk(KERN_WARNING "megaraid: Couldn't register IRQ %d!" CRLFSTR, - megaIrq); - scsi_unregister(host); + if (request_irq (megaIrq, megaraid_isr, SA_SHIRQ, + "megaraid", megaCfg)) { + printk (KERN_WARNING "megaraid: Couldn't register IRQ %d!" CRLFSTR, + megaIrq); + scsi_unregister (host); continue; } - mega_register_mailbox(megaCfg, virt_to_bus((void*)&megaCfg->mailbox)); - mega_i_query_adapter(megaCfg); + mega_register_mailbox (megaCfg, virt_to_bus ((void *) &megaCfg->mailbox)); + mega_i_query_adapter (megaCfg); /* Initialize SCBs */ - initSCB(megaCfg); + initSCB (megaCfg); } return pciIdx; @@ -1088,23 +1203,22 @@ /*--------------------------------------------------------- * Detects if a megaraid controller exists in this system *---------------------------------------------------------*/ -int megaraid_detect(Scsi_Host_Template *pHostTmpl) +int megaraid_detect (Scsi_Host_Template * pHostTmpl) { int count = 0; pHostTmpl->proc_dir = &proc_scsi_megaraid; #if LINUX_VERSION_CODE < 0x20100 - if (!pcibios_present()) - { - printk(KERN_WARNING "megaraid: PCI bios not present." CRLFSTR); - return 0; - } + if (!pcibios_present ()) { + printk (KERN_WARNING "megaraid: PCI bios not present." CRLFSTR); + return 0; + } #endif - count += findCard(pHostTmpl, 0x101E, 0x9010, 0); - count += findCard(pHostTmpl, 0x101E, 0x9060, 0); - count += findCard(pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ); + count += findCard (pHostTmpl, 0x101E, 0x9010, 0); + count += findCard (pHostTmpl, 0x101E, 0x9060, 0); + count += findCard (pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ); return count; } @@ -1112,33 +1226,40 @@ /*--------------------------------------------------------------------- * Release the controller's resources *---------------------------------------------------------------------*/ -int megaraid_release(struct Scsi_Host *pSHost) +int megaraid_release (struct Scsi_Host *pSHost) { mega_host_config *megaCfg; - mega_mailbox *mbox; - u_char mboxData[16]; + mega_mailbox *mbox; + u_char mboxData[16]; + int i; - megaCfg = (mega_host_config*)pSHost->hostdata; - mbox = (mega_mailbox *)mboxData; + megaCfg = (mega_host_config *) pSHost->hostdata; + mbox = (mega_mailbox *) mboxData; /* Flush cache to disk */ - memset(mbox, 0, 16); + memset (mbox, 0, 16); mboxData[0] = 0xA; /* Issue a blocking (interrupts disabled) command to the card */ - MegaIssueCmd(megaCfg, mboxData, NULL, 0); + MegaIssueCmd (megaCfg, mboxData, NULL, 0); - schedule(); + schedule (); /* Free our resources */ if (megaCfg->flag & BOARD_QUARTZ) { - iounmap((void *)megaCfg->base); - } else { - release_region(megaCfg->host->io_port, 16); - } - free_irq(megaCfg->host->irq, megaCfg); /* Must be freed first, otherwise - extra interrupt is generated */ - scsi_unregister(pSHost); + iounmap ((void *) megaCfg->base); + } + else { + release_region (megaCfg->host->io_port, 16); + } + free_irq (megaCfg->host->irq, megaCfg); /* Must be freed first, otherwise + + extra interrupt is generated */ + for (i = 0; i < megaCfg->max_cmds; i++) { + if (megaCfg->scbList[i].sgList) + kfree (megaCfg->scbList[i].sgList); /* free sgList */ + } + scsi_unregister (pSHost); return 0; } @@ -1146,20 +1267,20 @@ /*---------------------------------------------- * Get information about the card/driver *----------------------------------------------*/ -const char *megaraid_info(struct Scsi_Host *pSHost) +const char * megaraid_info (struct Scsi_Host *pSHost) { - static char buffer[512]; - mega_host_config *megaCfg; - mega_RAIDINQ *adapterInfo; + static char buffer[512]; + mega_host_config *megaCfg; + mega_RAIDINQ *adapterInfo; - megaCfg = (mega_host_config *)pSHost->hostdata; - adapterInfo = (mega_RAIDINQ *)megaCfg->mega_buffer; + megaCfg = (mega_host_config *) pSHost->hostdata; + adapterInfo = (mega_RAIDINQ *) megaCfg->mega_buffer; - sprintf(buffer, "AMI MegaRAID %s %d commands %d targs %d chans", - megaCfg->fwVer, - adapterInfo->AdpInfo.MaxConcCmds, - megaCfg->host->max_id, - megaCfg->host->max_channel); + sprintf (buffer, "AMI MegaRAID %s %d commands %d targs %d chans", + megaCfg->fwVer, + adapterInfo->AdpInfo.MaxConcCmds, + megaCfg->host->max_id, + megaCfg->host->max_channel); return buffer; } @@ -1178,29 +1299,29 @@ * 10 01 numstatus byte * 11 01 status byte *-----------------------------------------------------------------*/ -int megaraid_queue(Scsi_Cmnd *SCpnt, void (*pktComp)(Scsi_Cmnd *)) +int megaraid_queue (Scsi_Cmnd * SCpnt, void (*pktComp) (Scsi_Cmnd *)) { mega_host_config *megaCfg; - mega_scb *pScb; + mega_scb *pScb; - megaCfg = (mega_host_config *)SCpnt->host->hostdata; + megaCfg = (mega_host_config *) SCpnt->host->hostdata; if (!(megaCfg->flag & (1L << SCpnt->channel))) { - printk(KERN_INFO "scsi%d: scanning channel %c for devices.\n", - megaCfg->host->host_no, - SCpnt->channel + 'A'); + printk (KERN_INFO "scsi%d: scanning channel %c for devices.\n", + megaCfg->host->host_no, + SCpnt->channel + 'A'); megaCfg->flag |= (1L << SCpnt->channel); } SCpnt->scsi_done = pktComp; /* Allocate and build a SCB request */ - if ((pScb = mega_build_cmd(megaCfg, SCpnt)) != NULL) { + if ((pScb = mega_build_cmd (megaCfg, SCpnt)) != NULL) { /* Add SCB to the head of the pending queue */ - ENQUEUE(pScb, mega_scb, qPending, next); + ENQUEUE (pScb, mega_scb, qPending, next); /* Issue the command to the card */ - mega_runque(NULL); + mega_runque (NULL); } return 0; @@ -1208,37 +1329,44 @@ /*---------------------------------------------------------------------- * Issue a blocking command to the controller - * - * Note - this isnt 2.0.x SMP safe *----------------------------------------------------------------------*/ -volatile static int internal_done_flag = 0; +volatile static int internal_done_flag = 0; volatile static int internal_done_errcode = 0; -static void internal_done(Scsi_Cmnd *SCpnt) +static void internal_done (Scsi_Cmnd * SCpnt) { internal_done_errcode = SCpnt->result; internal_done_flag++; } /* - * This seems dangerous in an SMP environment because - * while spinning on internal_done_flag in 2.0.x SMP - * no IRQ's will be taken, including those that might - * be needed to clear this. - * - * I think this should be using a wait queue ? - * -- AC + * This seems dangerous in an SMP environment because + * while spinning on internal_done_flag in 2.0.x SMP + * no IRQ's will be taken, including those that might + * be needed to clear this. + * + * I think this should be using a wait queue ? + * -- AC + */ + +/* + * I'll probably fix this in the next version, but + * megaraid_command() will never get called since can_queue is set, + * except maybe in a *really* old kernel in which case it's very + * unlikely they'd be using SMP anyway. Really this function is + * just here for completeness. + * - JLJ */ - -int megaraid_command(Scsi_Cmnd *SCpnt) + +int megaraid_command (Scsi_Cmnd * SCpnt) { internal_done_flag = 0; /* Queue command, and wait until it has completed */ - megaraid_queue(SCpnt, internal_done); + megaraid_queue (SCpnt, internal_done); - while(!internal_done_flag) - barrier(); + while (!internal_done_flag) + barrier (); return internal_done_errcode; } @@ -1246,67 +1374,67 @@ /*--------------------------------------------------------------------- * Abort a previous SCSI request *---------------------------------------------------------------------*/ -int megaraid_abort(Scsi_Cmnd *SCpnt) +int megaraid_abort (Scsi_Cmnd * SCpnt) { mega_host_config *megaCfg; - int idx; - long flags; + int idx; + long flags; - spin_lock_irqsave(&mega_lock,flags); + spin_lock_irqsave (&mega_lock, flags); - megaCfg = (mega_host_config *)SCpnt->host->hostdata; + megaCfg = (mega_host_config *) SCpnt->host->hostdata; - TRACE(("ABORT!!! %.08lx %.02x <%d.%d.%d>\n", - SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target, - SCpnt->lun)); + TRACE (("ABORT!!! %.08lx %.02x <%d.%d.%d>\n", + SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target, + SCpnt->lun)); /* * Walk list of SCBs for any that are still outstanding */ - for(idx=0; idxmax_cmds; idx++) { + for (idx = 0; idx < megaCfg->max_cmds; idx++) { if (megaCfg->scbList[idx].idx >= 0) { if (megaCfg->scbList[idx].SCpnt == SCpnt) { - freeSCB(&megaCfg->scbList[idx]); + freeSCB (&megaCfg->scbList[idx]); - SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY<<24); - callDone(SCpnt); + SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24); + callDone (SCpnt); } } } - spin_unlock_irqrestore(&mega_lock,flags); + spin_unlock_irqrestore (&mega_lock, flags); return SCSI_ABORT_SNOOZE; } /*--------------------------------------------------------------------- * Reset a previous SCSI request *---------------------------------------------------------------------*/ -int megaraid_reset(Scsi_Cmnd *SCpnt, unsigned int rstflags) +int megaraid_reset (Scsi_Cmnd * SCpnt, unsigned int rstflags) { mega_host_config *megaCfg; - int idx; - long flags; + int idx; + long flags; - spin_lock_irqsave(&mega_lock,flags); + spin_lock_irqsave (&mega_lock, flags); - megaCfg = (mega_host_config *)SCpnt->host->hostdata; + megaCfg = (mega_host_config *) SCpnt->host->hostdata; - TRACE(("RESET: %.08lx %.02x <%d.%d.%d>\n", - SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target, - SCpnt->lun)); + TRACE (("RESET: %.08lx %.02x <%d.%d.%d>\n", + SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target, + SCpnt->lun)); /* * Walk list of SCBs for any that are still outstanding */ - for(idx=0; idxmax_cmds; idx++) { + for (idx = 0; idx < megaCfg->max_cmds; idx++) { if (megaCfg->scbList[idx].idx >= 0) { SCpnt = megaCfg->scbList[idx].SCpnt; - freeSCB(&megaCfg->scbList[idx]); - SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY<<24); - callDone(SCpnt); + freeSCB (&megaCfg->scbList[idx]); + SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24); + callDone (SCpnt); } } - spin_unlock_irqrestore(&mega_lock,flags); + spin_unlock_irqrestore (&mega_lock, flags); return SCSI_RESET_PUNT; -} +} /*------------------------------------------------------------- * Return the disk geometry for a particular disk @@ -1318,23 +1446,23 @@ * geom[1] = sectors * geom[2] = cylinders *-------------------------------------------------------------*/ -int megaraid_biosparam(Disk *disk, kdev_t dev, int *geom) +int megaraid_biosparam (Disk * disk, kdev_t dev, int *geom) { - int heads, sectors, cylinders; + int heads, sectors, cylinders; mega_host_config *megaCfg; /* Get pointer to host config structure */ - megaCfg = (mega_host_config *)disk->device->host->hostdata; + megaCfg = (mega_host_config *) disk->device->host->hostdata; /* Default heads (64) & sectors (32) */ - heads = 64; - sectors = 32; + heads = 64; + sectors = 32; cylinders = disk->capacity / (heads * sectors); /* Handle extended translation size for logical drives > 1Gb */ if (disk->capacity >= 0x200000) { - heads = 255; - sectors = 63; + heads = 255; + sectors = 63; cylinders = disk->capacity / (heads * sectors); } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/megaraid.h linux.ac/drivers/scsi/megaraid.h --- linux.vanilla/drivers/scsi/megaraid.h Tue Jan 26 09:44:21 1999 +++ linux.ac/drivers/scsi/megaraid.h Mon Feb 1 00:52:49 1999 @@ -1,7 +1,9 @@ #ifndef __MEGARAID_H__ #define __MEGARAID_H__ +#ifndef LINUX_VERSION_CODE #include +#endif #define IN_ISR 0x80000000L #define NO_INTR 0x40000000L @@ -20,7 +22,7 @@ #define MEGA_CMD_TIMEOUT 10 -#define MAX_SGLIST 20 +#define MAX_SGLIST 17 #define MAX_COMMANDS 254 #define MAX_LOGICAL_DRIVES 8 @@ -96,6 +98,8 @@ #define PCI_CONF_BASE_ADDR_OFFSET 0x10 #define PCI_CONF_IRQ_OFFSET 0x3c +#define PCI_CONF_AMISIG 0xa0 +#define AMI_SIGNATURE 0x11223344 #if LINUX_VERSION_CODE < 0x20100 #define MEGARAID \ @@ -113,14 +117,14 @@ megaraid_reset, /* Reset Command Function */\ NULL, /* Slave Attach Function */\ megaraid_biosparam, /* Disk BIOS Parameters */\ - 1, /* # of cmds that can be\ + 254, /* # of cmds that can be\ outstanding at any time */\ 7, /* HBA Target ID */\ MAX_SGLIST, /* Scatter/Gather Table Size */\ - 1, /* SCSI Commands per LUN */\ + 64, /* SCSI Commands per LUN */\ 0, /* Present */\ 0, /* Default Unchecked ISA DMA */\ - ENABLE_CLUSTERING } /* Enable Clustering */ + ENABLE_CLUSTERING } /* Enable Clustering */ #else #define MEGARAID \ {\ @@ -134,10 +138,10 @@ abort: megaraid_abort, /* Abort Command Function */\ reset: megaraid_reset, /* Reset Command Function */\ bios_param: megaraid_biosparam, /* Disk BIOS Parameters */\ - can_queue: 255, /* Can Queue */\ + can_queue: 254, /* Can Queue */\ this_id: 7, /* HBA Target ID */\ sg_tablesize: MAX_SGLIST, /* Scatter/Gather Table Size */\ - cmd_per_lun: 1, /* SCSI Commands per LUN */\ + cmd_per_lun: 64, /* SCSI Commands per LUN */\ present: 0, /* Present */\ unchecked_isa_dma:0, /* Default Unchecked ISA DMA */\ use_clustering: ENABLE_CLUSTERING /* Enable Clustering */\ @@ -145,140 +149,150 @@ #endif /* Structures */ -typedef struct _mega_ADP_INFO -{ - u_char MaxConcCmds; - u_char RbldRate; - u_char MaxTargPerChan; - u_char ChanPresent; - u_char FwVer[4]; - u_short AgeOfFlash; - u_char ChipSet; - u_char DRAMSize; - u_char CacheFlushInterval; - u_char BiosVer[4]; - u_char resvd[7]; +typedef struct _mega_ADP_INFO { + u_char MaxConcCmds; + u_char RbldRate; + u_char MaxTargPerChan; + u_char ChanPresent; + u_char FwVer[4]; + u_short AgeOfFlash; + u_char ChipSet; + u_char DRAMSize; + u_char CacheFlushInterval; + u_char BiosVer[4]; + u_char resvd[7]; } mega_ADP_INFO; -typedef struct _mega_LDRV_INFO -{ - u_char NumLDrv; - u_char resvd[3]; - u_long LDrvSize[MAX_LOGICAL_DRIVES]; - u_char LDrvProp[MAX_LOGICAL_DRIVES]; - u_char LDrvState[MAX_LOGICAL_DRIVES]; +typedef struct _mega_LDRV_INFO { + u_char NumLDrv; + u_char resvd[3]; + u_long LDrvSize[MAX_LOGICAL_DRIVES]; + u_char LDrvProp[MAX_LOGICAL_DRIVES]; + u_char LDrvState[MAX_LOGICAL_DRIVES]; } mega_LDRV_INFO; -typedef struct _mega_PDRV_INFO -{ - u_char PDrvState[MAX_PHYSICAL_DRIVES]; - u_char resvd; +typedef struct _mega_PDRV_INFO { + u_char PDrvState[MAX_PHYSICAL_DRIVES]; + u_char resvd; } mega_PDRV_INFO; // RAID inquiry: Mailbox command 0x5 -typedef struct _mega_RAIDINQ -{ - mega_ADP_INFO AdpInfo; - mega_LDRV_INFO LogdrvInfo; - mega_PDRV_INFO PhysdrvInfo; +typedef struct _mega_RAIDINQ { + mega_ADP_INFO AdpInfo; + mega_LDRV_INFO LogdrvInfo; + mega_PDRV_INFO PhysdrvInfo; } mega_RAIDINQ; // Passthrough command: Mailbox command 0x3 -typedef struct mega_passthru -{ - u_char timeout:3; /* 0=6sec/1=60sec/2=10min/3=3hrs */ - u_char ars:1; - u_char reserved:3; - u_char islogical:1; - u_char logdrv; /* if islogical == 1 */ - u_char channel; /* if islogical == 0 */ - u_char target; /* if islogical == 0 */ - u_char queuetag; /* unused */ - u_char queueaction; /* unused */ - u_char cdb[MAX_CDB_LEN]; - u_char cdblen; - u_char reqsenselen; - u_char reqsensearea[MAX_REQ_SENSE_LEN]; - u_char numsgelements; - u_char scsistatus; - u_long dataxferaddr; - u_long dataxferlen; +typedef struct mega_passthru { + u_char timeout:3; /* 0=6sec/1=60sec/2=10min/3=3hrs */ + u_char ars:1; + u_char reserved:3; + u_char islogical:1; + u_char logdrv; /* if islogical == 1 */ + u_char channel; /* if islogical == 0 */ + u_char target; /* if islogical == 0 */ + u_char queuetag; /* unused */ + u_char queueaction; /* unused */ + u_char cdb[MAX_CDB_LEN]; + u_char cdblen; + u_char reqsenselen; + u_char reqsensearea[MAX_REQ_SENSE_LEN]; + u_char numsgelements; + u_char scsistatus; + u_long dataxferaddr; + u_long dataxferlen; } mega_passthru; -typedef struct _mega_mailbox -{ - /* 0x0 */ u_char cmd; - /* 0x1 */ u_char cmdid; - /* 0x2 */ u_short numsectors; - /* 0x4 */ u_long lba; - /* 0x8 */ u_long xferaddr; - /* 0xC */ u_char logdrv; - /* 0xD */ u_char numsgelements; - /* 0xE */ u_char resvd; - /* 0xF */ u_char busy; - /* 0x10*/ u_char numstatus; - /* 0x11*/ u_char status; - /* 0x12*/ u_char completed[46]; - u_char mraid_poll; - u_char mraid_ack; - u_char pad[16]; +typedef struct _mega_mailbox { + /* 0x0 */ u_char cmd; + /* 0x1 */ u_char cmdid; + /* 0x2 */ u_short numsectors; + /* 0x4 */ u_long lba; + /* 0x8 */ u_long xferaddr; + /* 0xC */ u_char logdrv; + /* 0xD */ u_char numsgelements; + /* 0xE */ u_char resvd; + /* 0xF */ u_char busy; + /* 0x10 */ u_char numstatus; + /* 0x11 */ u_char status; + /* 0x12 */ u_char completed[46]; + u_char mraid_poll; + u_char mraid_ack; + u_char pad[16]; } mega_mailbox; -typedef struct _mega_sglist -{ - u_long address; - u_long length; +typedef struct _mega_ioctl_mbox { + /* 0x0 */ u_char cmd; + /* 0x1 */ u_char cmdid; + /* 0x2 */ u_char channel; + /* 0x3 */ u_char param; + /* 0x4 */ u_char pad[4]; + /* 0x8 */ u_long xferaddr; + /* 0xC */ u_char logdrv; + /* 0xD */ u_char numsgelements; + /* 0xE */ u_char resvd; + /* 0xF */ u_char busy; + /* 0x10 */ u_char numstatus; + /* 0x11 */ u_char status; + /* 0x12 */ u_char completed[46]; + u_char mraid_poll; + u_char mraid_ack; + u_char malign[16]; +} mega_ioctl_mbox; + +typedef struct _mega_sglist { + u_long address; + u_long length; } mega_sglist; /* Queued command data */ typedef struct _mega_scb mega_scb; -struct _mega_scb -{ - int idx; - u_long flag; - Scsi_Cmnd *SCpnt; - u_char mboxData[16]; - mega_passthru pthru; - mega_sglist *sgList; - mega_scb *next; +struct _mega_scb { + int idx; + u_long flag; + Scsi_Cmnd *SCpnt; + u_char mboxData[16]; + mega_passthru pthru; + mega_sglist *sgList; + mega_scb *next; }; /* Per-controller data */ -typedef struct _mega_host_config -{ - u_char numldrv; - u_long flag; - u_long base; - - struct tq_struct megaTq; - - /* Host adapter parameters */ - u_char fwVer[7]; - u_char biosVer[7]; - - struct Scsi_Host *host; - - /* The following must be DMA-able!! */ - volatile mega_mailbox *mbox; - volatile mega_mailbox mailbox; - volatile u_char mega_buffer[2*1024L]; +typedef struct _mega_host_config { + u_char numldrv; + u_long flag; + u_long base; + + struct tq_struct megaTq; + + /* Host adapter parameters */ + u_char fwVer[7]; + u_char biosVer[7]; + + struct Scsi_Host *host; + + /* The following must be DMA-able!! */ + volatile mega_mailbox *mbox; + volatile mega_mailbox mailbox; + volatile u_char mega_buffer[2 * 1024L]; - u_char max_cmds; - mega_scb scbList[MAX_COMMANDS]; + u_char max_cmds; + mega_scb scbList[MAX_COMMANDS]; } mega_host_config; extern struct proc_dir_entry proc_scsi_megaraid; -const char *megaraid_info( struct Scsi_Host * ); -int megaraid_detect( Scsi_Host_Template * ); -int megaraid_release(struct Scsi_Host *); -int megaraid_command( Scsi_Cmnd * ); -int megaraid_abort( Scsi_Cmnd * ); -int megaraid_reset( Scsi_Cmnd *, unsigned int); -int megaraid_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) ); -int megaraid_biosparam( Disk *, kdev_t, int * ); -int megaraid_proc_info( char *buffer, char **start, off_t offset, - int length, int hostno, int inout ); +const char *megaraid_info(struct Scsi_Host *); +int megaraid_detect(Scsi_Host_Template *); +int megaraid_release(struct Scsi_Host *); +int megaraid_command(Scsi_Cmnd *); +int megaraid_abort(Scsi_Cmnd *); +int megaraid_reset(Scsi_Cmnd *, unsigned int); +int megaraid_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); +int megaraid_biosparam(Disk *, kdev_t, int *); +int megaraid_proc_info(char *buffer, char **start, off_t offset, + int length, int hostno, int inout); #endif 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 Tue Jan 19 02:57:31 1999 +++ linux.ac/drivers/scsi/ncr53c8xx.c Tue Jan 19 03:09:19 1999 @@ -4996,7 +4996,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){ @@ -9796,7 +9796,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, diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/pci2000.c linux.ac/drivers/scsi/pci2000.c --- linux.vanilla/drivers/scsi/pci2000.c Sun Nov 8 15:07:54 1998 +++ linux.ac/drivers/scsi/pci2000.c Mon Jan 4 16:04:59 1999 @@ -108,7 +108,7 @@ do { if ( !inb_p (padapter->cmd) ) return FALSE; - } while ( timer > jiffies ); // test for timeout + } while ( time_after(timer, jiffies) ); // test for timeout return TRUE; } /**************************************************************** @@ -205,7 +205,7 @@ int bus; int z; - DEB(printk ("\npci2000 recieved interrupt ")); + DEB(printk ("\npci2000 received interrupt ")); for ( z = 0; z < NumAdapters; z++ ) // scan for interrupt to process { if ( PsiHost[z]->irq == (UCHAR)(irq & 0xFF) ) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/pci2220i.c linux.ac/drivers/scsi/pci2220i.c --- linux.vanilla/drivers/scsi/pci2220i.c Sun Nov 8 15:07:56 1998 +++ linux.ac/drivers/scsi/pci2220i.c Mon Jan 4 16:04:59 1999 @@ -152,7 +152,7 @@ outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear return 0; } - } while ( timer > jiffies ); // test for timeout + } while ( time_after(timer, jiffies) ); // test for timeout padapter->ide.ide.ides.cmd = 0; // null out the command byte return 1; @@ -192,7 +192,7 @@ return (WriteData (padapter)); return 0; } - } while ( timer > jiffies ); // test for timeout + } while ( time_after(timer, jiffies) ); // test for timeout padapter->ide.ide.ides.cmd = 0; // null out the command byte return status; @@ -288,7 +288,7 @@ UCHAR status; int z; -// DEB(printk ("\npci2220i recieved interrupt\n")); +// DEB(printk ("\npci2220i received interrupt\n")); for ( z = 0; z < NumAdapters; z++ ) // scan for interrupt to process { diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/psi240i.c linux.ac/drivers/scsi/psi240i.c --- linux.vanilla/drivers/scsi/psi240i.c Sun Nov 8 15:07:56 1998 +++ linux.ac/drivers/scsi/psi240i.c Mon Jan 4 16:04:59 1999 @@ -129,7 +129,7 @@ outsw (pports[PORT_DATA], padapter->buffer, (USHORT)padapter->ide.ide.ide[2] * 256); return 0; } - } while ( timer > jiffies ); // test for timeout + } while ( time_after(timer, jiffies) ); // test for timeout padapter->ide.ide.ides.cmd = 0; // null out the command byte return 1; @@ -169,7 +169,7 @@ return 0; } - } while ( timer > jiffies ); // test for timeout + } while ( time_after(timer, jiffies) ); // test for timeout padapter->ide.ide.ides.cmd = 0; // null out the command byte return status; @@ -264,7 +264,7 @@ UCHAR status; int z; - DEB(printk ("\npsi240i recieved interrupt\n")); + DEB(printk ("\npsi240i received interrupt\n")); shost = PsiHost[irq - 10]; if ( !shost ) 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 Sun Nov 8 15:07:54 1998 +++ linux.ac/drivers/scsi/qlogicfas.c Sun Nov 8 14:35:43 1998 @@ -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 Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/scsi/qlogicfc.c Wed Dec 23 19:37:14 1998 @@ -0,0 +1,1953 @@ +/* + * QLogic ISP2100 SCSI-FCP + * Written by Erik H. Moe, ehm@cris.com + * Copyright 1995, Erik H. Moe + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +/* 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 + */ + +/* + * $Date: 1995/09/22 02:23:15 $ + * $Revision: 0.5 $ + * + * $Log: isp1020.c,v $ + * Revision 0.5 1995/09/22 02:23:15 root + * do auto request sense + * + * Revision 0.4 1995/08/07 04:44:33 root + * supply firmware with driver. + * numerous bug fixes/general cleanup of code. + * + * Revision 0.3 1995/07/16 16:15:39 root + * added reset/abort code. + * + * Revision 0.2 1995/06/29 03:14:19 root + * fixed biosparam. + * added queue protocol. + * + * Revision 0.1 1995/06/25 01:55:45 root + * Initial release. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd.h" +#include "hosts.h" +#include "qlogicfc.h" + +/* Configuration section **************************************************** */ + +/* Set the following macro to 1 to reload the ISP2100's firmware. This is + version 1.13 of the firmware. */ + +#define RELOAD_FIRMWARE 1 + +#define USE_NVRAM_DEFAULTS 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 + +/* 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_ISP2100_FABRIC 1 +*/ +/* #define TRACE_ISP 1 */ + + +#define DEFAULT_LOOP_COUNT 1000000 + +/* End Configuration section ************************************************ */ + +#include + +#if TRACE_ISP + +#define TRACE_BUF_LEN (32*1024) + +struct { + u_long next; + struct { + u_long time; + u_int index; + u_int addr; + u_char *name; + } buf[TRACE_BUF_LEN]; +} trace; + +#define TRACE(w, i, a) \ +{ \ + unsigned long flags; \ + \ + save_flags(flags); \ + cli(); \ + trace.buf[trace.next].name = (w); \ + trace.buf[trace.next].time = jiffies; \ + trace.buf[trace.next].index = (i); \ + trace.buf[trace.next].addr = (long) (a); \ + trace.next = (trace.next + 1) & (TRACE_BUF_LEN - 1); \ + restore_flags(flags); \ +} + +#else +#define TRACE(w, i, a) +#endif + +#if DEBUG_ISP2100_FABRIC +#define DEBUG_FABRIC(x) x +#else +#define DEBUG_FABRIC(x) +#endif /* DEBUG_ISP2100_FABRIC */ + + +#if DEBUG_ISP2100 +#define ENTER(x) printk("isp2100 : entering %s()\n", x); +#define LEAVE(x) printk("isp2100 : leaving %s()\n", x); +#define DEBUG(x) x +#else +#define ENTER(x) +#define LEAVE(x) +#define DEBUG(x) +#endif /* DEBUG_ISP2100 */ + +#if DEBUG_ISP2100_INTR +#define ENTER_INTR(x) printk("isp2100 : entering %s()\n", x); +#define LEAVE_INTR(x) printk("isp2100 : 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 */ + + +#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__) +#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))) +#endif + +#define ISP2100_REV_ID 1 +#define ISP2100_REV_ID3 3 + +#define MAX_TARGETS 16 +#define MAX_LUNS 8 + +/* host configuration and control registers */ +#define HOST_HCCR 0xc0 /* host command and control */ + +/* pci bus interface registers */ +#define FLASH_BIOS_ADDR 0x00 +#define FLASH_BIOS_DATA 0x02 +#define ISP_CTRL_STATUS 0x06 /* configuration register #1 */ +#define PCI_INTER_CTL 0x08 /* pci interupt control */ +#define PCI_INTER_STS 0x0a /* pci interupt status */ +#define PCI_SEMAPHORE 0x0c /* pci semaphore */ +#define PCI_NVRAM 0x0e /* pci nvram interface */ + +/* mailbox registers */ +#define MBOX0 0x10 /* mailbox 0 */ +#define MBOX1 0x12 /* mailbox 1 */ +#define MBOX2 0x14 /* mailbox 2 */ +#define MBOX3 0x16 /* mailbox 3 */ +#define MBOX4 0x18 /* mailbox 4 */ +#define MBOX5 0x1a /* mailbox 5 */ +#define MBOX6 0x1c /* mailbox 6 */ +#define MBOX7 0x1e /* mailbox 7 */ + +/* mailbox command complete status codes */ +#define MBOX_COMMAND_COMPLETE 0x4000 +#define INVALID_COMMAND 0x4001 +#define HOST_INTERFACE_ERROR 0x4002 +#define TEST_FAILED 0x4003 +#define COMMAND_ERROR 0x4005 +#define COMMAND_PARAM_ERROR 0x4006 +#define PORT_ID_USED 0x4007 +#define LOOP_ID_USED 0x4008 +#define ALL_IDS_USED 0x4009 + +/* async event status codes */ +#define RESET_DETECTED 0x8001 +#define SYSTEM_ERROR 0x8002 +#define REQUEST_TRANSFER_ERROR 0x8003 +#define RESPONSE_TRANSFER_ERROR 0x8004 +#define REQUEST_QUEUE_WAKEUP 0x8005 +#define LIP_OCCURED 0x8010 +#define LOOP_UP 0x8011 +#define LOOP_DOWN 0x8012 +#define LIP_RECEIVED 0x8013 +#define PORT_DB_CHANGED 0x8014 +#define CHANGE_NOTIFICATION 0x8015 +#define SCSI_COMMAND_COMPLETE 0x8020 + +struct Entry_header { + u_char entry_type; + u_char entry_cnt; + u_char sys_def_1; + u_char flags; +}; + +/* entry header type commands */ +#define ENTRY_COMMAND 0x19 +#define ENTRY_CONTINUATION 0x0a +#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 + +struct dataseg { + u_int d_base_lo; + u_int d_base_high; + u_int d_count; +}; + +struct Command_Entry { + struct Entry_header hdr; + u_int handle; + u_char target_lun; + u_char target_id; + u_short rsvd1; + 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]; +}; + +/* command entry control flag definitions */ +#define CFLAG_NODISC 0x01 +#define CFLAG_HEAD_TAG 0x02 +#define CFLAG_ORDERED_TAG 0x04 +#define CFLAG_SIMPLE_TAG 0x08 +#define CFLAG_TAR_RTN 0x10 +#define CFLAG_READ 0x20 +#define CFLAG_WRITE 0x40 + +struct Ext_Command_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 Continuation_Entry { + struct Entry_header hdr; + struct dataseg dataseg[5]; +}; + +struct Marker_Entry { + struct Entry_header hdr; + u_int reserved; + u_char target_lun; + u_char target_id; + u_char modifier; + u_char rsvd; + u_char rsvds[52]; +}; + +/* marker entry modifier definitions */ +#define SYNC_DEVICE 0 +#define SYNC_TARGET 1 +#define SYNC_ALL 2 + +struct Status_Entry { + struct Entry_header hdr; + u_int handle; + u_short scsi_status; + u_short completion_status; + u_short state_flags; + u_short status_flags; + u_short res_info_len; + u_short req_sense_len; + u_int residual; + u_char res_info[8]; + u_char req_sense_data[32]; +}; + +/* status entry completion status definitions */ +#define CS_COMPLETE 0x0000 +#define CS_INCOMPLETE 0x0001 +#define CS_DMA_ERROR 0x0002 +#define CS_TRANSPORT_ERROR 0x0003 +#define CS_RESET_OCCURRED 0x0004 +#define CS_ABORTED 0x0005 +#define CS_TIMEOUT 0x0006 +#define CS_DATA_OVERRUN 0x0007 +#define CS_ABORT_MSG_FAILED 0x000e +#define CS_REJECT_MSG_FAILED 0x000f +#define CS_DATA_UNDERRUN 0x0015 +#define CS_PORT_UNAVAILABLE 0x0028 +#define CS_PORT_LOGGED_OUT 0x0029 +#define CS_PORT_CONFIG_CHANGED 0x002a + +/* status entry state flag definitions */ +#define SF_SENT_CDB 0x0400 +#define SF_TRANSFERRED_DATA 0x0800 +#define SF_GOT_STATUS 0x1000 + +/* status entry status flag definitions */ +#define STF_BUS_RESET 0x0008 +#define STF_DEVICE_RESET 0x0010 +#define STF_ABORTED 0x0020 +#define STF_TIMEOUT 0x0040 + +/* interupt control commands */ +#define ISP_EN_INT 0x8000 +#define ISP_EN_RISC 0x0008 + +/* host control commands */ +#define HCCR_NOP 0x0000 +#define HCCR_RESET 0x1000 +#define HCCR_PAUSE 0x2000 +#define HCCR_RELEASE 0x3000 +#define HCCR_SINGLE_STEP 0x4000 +#define HCCR_SET_HOST_INTR 0x5000 +#define HCCR_CLEAR_HOST_INTR 0x6000 +#define HCCR_CLEAR_RISC_INTR 0x7000 +#define HCCR_BP_ENABLE 0x8000 +#define HCCR_BIOS_DISABLE 0x9000 +#define HCCR_TEST_MODE 0xf000 + +#define RISC_BUSY 0x0004 + +/* mailbox commands */ +#define MBOX_NO_OP 0x0000 +#define MBOX_LOAD_RAM 0x0001 +#define MBOX_EXEC_FIRMWARE 0x0002 +#define MBOX_DUMP_RAM 0x0003 +#define MBOX_WRITE_RAM_WORD 0x0004 +#define MBOX_READ_RAM_WORD 0x0005 +#define MBOX_MAILBOX_REG_TEST 0x0006 +#define MBOX_VERIFY_CHECKSUM 0x0007 +#define MBOX_ABOUT_FIRMWARE 0x0008 +#define MBOX_LOAD_RISC_RAM 0x0009 +#define MBOX_DUMP_RISC_RAM 0x000a +#define MBOX_CHECK_FIRMWARE 0x000e +#define MBOX_INIT_REQ_QUEUE 0x0010 +#define MBOX_INIT_RES_QUEUE 0x0011 +#define MBOX_EXECUTE_IOCB 0x0012 +#define MBOX_WAKE_UP 0x0013 +#define MBOX_STOP_FIRMWARE 0x0014 +#define MBOX_ABORT_IOCB 0x0015 +#define MBOX_ABORT_DEVICE 0x0016 +#define MBOX_ABORT_TARGET 0x0017 +#define MBOX_BUS_RESET 0x0018 +#define MBOX_STOP_QUEUE 0x0019 +#define MBOX_START_QUEUE 0x001a +#define MBOX_SINGLE_STEP_QUEUE 0x001b +#define MBOX_ABORT_QUEUE 0x001c +#define MBOX_GET_DEV_QUEUE_STATUS 0x001d +#define MBOX_GET_FIRMWARE_STATUS 0x001f +#define MBOX_GET_INIT_SCSI_ID 0x0020 +#define MBOX_GET_RETRY_COUNT 0x0022 +#define MBOX_GET_TARGET_PARAMS 0x0028 +#define MBOX_GET_DEV_QUEUE_PARAMS 0x0029 +#define MBOX_SET_RETRY_COUNT 0x0032 +#define MBOX_SET_TARGET_PARAMS 0x0038 +#define MBOX_SET_DEV_QUEUE_PARAMS 0x0039 +#define MBOX_EXECUTE_IOCB64 0x0054 +#define MBOX_INIT_FIRMWARE 0x0060 +#define MBOX_GET_INIT_CB 0x0061 +#define MBOX_INIT_LIP 0x0062 +#define MBOX_GET_POS_MAP 0x0063 +#define MBOX_GET_PORT_DB 0x0064 +#define MBOX_CLEAR_ACA 0x0065 +#define MBOX_TARGET_RESET 0x0066 +#define MBOX_CLEAR_TASK_SET 0x0067 +#define MBOX_ABORT_TASK_SET 0x0068 +#define MBOX_GET_FIRMWARE_STATE 0x0069 +#define MBOX_GET_PORT_NAME 0x006a +#define MBOX_SEND_SNS 0x006e +#define MBOX_PORT_LOGIN 0x006f +#define MBOX_SEND_CHANGE_REQUEST 0x0070 +#define MBOX_PORT_LOGOUT 0x0071 + +#include "qlogicfc_asm.c" + +/* Each element in mbox_param is an 8 bit bitmap where each bit indicates + if that mbox should be copied as input. For example 0x2 would mean + only copy mbox1. */ + +const u_char mbox_param[] = +{ + 0x01, /* MBOX_NO_OP */ + 0x1f, /* MBOX_LOAD_RAM */ + 0x03, /* MBOX_EXEC_FIRMWARE */ + 0x1f, /* MBOX_DUMP_RAM */ + 0x07, /* MBOX_WRITE_RAM_WORD */ + 0x03, /* MBOX_READ_RAM_WORD */ + 0xff, /* MBOX_MAILBOX_REG_TEST */ + 0x03, /* MBOX_VERIFY_CHECKSUM */ + 0x01, /* MBOX_ABOUT_FIRMWARE */ + 0xff, /* MBOX_LOAD_RISC_RAM */ + 0xff, /* MBOX_DUMP_RISC_RAM */ + 0x00, /* 0x000b */ + 0x00, /* 0x000c */ + 0x00, /* 0x000d */ + 0x01, /* MBOX_CHECK_FIRMWARE */ + 0x00, /* 0x000f */ + 0x1f, /* MBOX_INIT_REQ_QUEUE */ + 0x2f, /* MBOX_INIT_RES_QUEUE */ + 0x0f, /* MBOX_EXECUTE_IOCB */ + 0x03, /* MBOX_WAKE_UP */ + 0x01, /* MBOX_STOP_FIRMWARE */ + 0x0f, /* MBOX_ABORT_IOCB */ + 0x03, /* MBOX_ABORT_DEVICE */ + 0x07, /* MBOX_ABORT_TARGET */ + 0x03, /* MBOX_BUS_RESET */ + 0x03, /* MBOX_STOP_QUEUE */ + 0x03, /* MBOX_START_QUEUE */ + 0x03, /* MBOX_SINGLE_STEP_QUEUE */ + 0x03, /* MBOX_ABORT_QUEUE */ + 0x03, /* MBOX_GET_DEV_QUEUE_STATUS */ + 0x00, /* 0x001e */ + 0x01, /* MBOX_GET_FIRMWARE_STATUS */ + 0x01, /* MBOX_GET_INIT_SCSI_ID */ + 0x00, /* 0x0021 */ + 0x01, /* MBOX_GET_RETRY_COUNT */ + 0x00, /* 0x0023 */ + 0x00, /* 0x0024 */ + 0x00, /* 0x0025 */ + 0x00, /* 0x0026 */ + 0x00, /* 0x0027 */ + 0x03, /* MBOX_GET_TARGET_PARAMS */ + 0x03, /* MBOX_GET_DEV_QUEUE_PARAMS */ + 0x00, /* 0x002a */ + 0x00, /* 0x002b */ + 0x00, /* 0x002c */ + 0x00, /* 0x002d */ + 0x00, /* 0x002e */ + 0x00, /* 0x002f */ + 0x00, /* 0x0030 */ + 0x00, /* 0x0031 */ + 0x07, /* MBOX_SET_RETRY_COUNT */ + 0x00, /* 0x0033 */ + 0x00, /* 0x0034 */ + 0x00, /* 0x0035 */ + 0x00, /* 0x0036 */ + 0x00, /* 0x0037 */ + 0x0f, /* MBOX_SET_TARGET_PARAMS */ + 0x0f, /* MBOX_SET_DEV_QUEUE_PARAMS */ + 0x00, /* 0x003a */ + 0x00, /* 0x003b */ + 0x00, /* 0x003c */ + 0x00, /* 0x003d */ + 0x00, /* 0x003e */ + 0x00, /* 0x003f */ + 0x00, /* 0x0040 */ + 0x00, /* 0x0041 */ + 0x00, /* 0x0042 */ + 0x00, /* 0x0043 */ + 0x00, /* 0x0044 */ + 0x00, /* 0x0045 */ + 0x00, /* 0x0046 */ + 0x00, /* 0x0047 */ + 0x00, /* 0x0048 */ + 0x00, /* 0x0049 */ + 0x00, /* 0x004a */ + 0x00, /* 0x004b */ + 0x00, /* 0x004c */ + 0x00, /* 0x004d */ + 0x00, /* 0x004e */ + 0x00, /* 0x004f */ + 0x00, /* 0x0050 */ + 0x00, /* 0x0051 */ + 0x00, /* 0x0052 */ + 0x00, /* 0x0053 */ + 0xcf, /* MBOX_EXECUTE_IOCB64 */ + 0x00, /* 0x0055 */ + 0x00, /* 0x0056 */ + 0x00, /* 0x0057 */ + 0x00, /* 0x0058 */ + 0x00, /* 0x0059 */ + 0x00, /* 0x005a */ + 0x00, /* 0x005b */ + 0x00, /* 0x005c */ + 0x00, /* 0x005d */ + 0x00, /* 0x005e */ + 0x00, /* 0x005f */ + 0xff, /* MBOX_INIT_FIRMWARE */ + 0xcd, /* MBOX_GET_INIT_CB */ + 0x01, /* MBOX_INIT_LIP */ + 0xcd, /* MBOX_GET_POS_MAP */ + 0xcf, /* MBOX_GET_PORT_DB */ + 0x03, /* MBOX_CLEAR_ACA */ + 0x03, /* MBOX_TARGET_RESET */ + 0x03, /* MBOX_CLEAR_TASK_SET */ + 0x03, /* MBOX_ABORT_TASK_SET */ + 0x01, /* MBOX_GET_FIRMWARE_STATE */ + 0x03, /* MBOX_GET_PORT_NAME */ + 0x00, /* 0x006b */ + 0x00, /* 0x006c */ + 0x00, /* 0x006d */ + 0xcf, /* MBOX_SEND_SNS */ + 0x0f, /* MBOX_PORT_LOGIN */ + 0x03, /* MBOX_SEND_CHANGE_REQUEST */ + 0x03, /* MBOX_PORT_LOGOUT */ +}; + +#define MAX_MBOX_COMMAND (sizeof(mbox_param)/sizeof(u_short)) + + +struct id_name_map { + u64 wwn; + u_char loop_id; +}; + +struct sns_cb { + u_short len; + u_short res1; + u_int response_low; + u_int response_high; + u_short sub_len; + u_short res2; + u_short data[22]; +}; + +/* address of instance of this struct is passed to adapter to initialize things + */ +struct init_cb { + u_char version; + u_char reseverd1[1]; + u_short firm_opts; + u_short max_frame_len; + u_short max_iocb; + u_short exec_throttle; + u_char retry_cnt; + u_char retry_delay; + u_short node_name[4]; + u_short hard_addr; + u_char reserved2[10]; + u_short req_queue_out; + u_short res_queue_in; + u_short req_queue_len; + u_short res_queue_len; + u_int req_queue_addr_lo; + u_int req_queue_addr_high; + u_int res_queue_addr_lo; + u_int res_queue_addr_high; +}; + +/* + * The result queue can be quite a bit smaller since continuation entries + * do not show up there: + */ +#define RES_QUEUE_LEN ((QLOGICFC_REQ_QUEUE_LEN + 1) / 8 - 1) +#define QUEUE_ENTRY_LEN 64 + +#if ISP2100_FABRIC +#define QLOGICFC_MAX_ID 0xff +#else +#define QLOGICFC_MAX_ID 0x80 +#endif + +struct isp2100_hostdata { + u_char revision; + struct pci_dev *pci_dev; + /* result and request queues (shared with isp2100): */ + u_int req_in_ptr; /* index of next request slot */ + u_int res_out_ptr; /* index of next result slot */ + + /* this is here so the queues are nicely aligned */ + long send_marker; /* do we need to send a marker? */ + + 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; + unsigned long int tag_ages[126]; + Scsi_Cmnd *handle_ptrs[QLOGICFC_REQ_QUEUE_LEN + 1]; + unsigned long handle_serials[QLOGICFC_REQ_QUEUE_LEN + 1]; + struct id_name_map port_db[QLOGICFC_MAX_ID + 1]; + u_char mbox_done; + u64 wwn; + u_int port_id; + u_char queued; +}; + + +/* queue length's _must_ be power of two: */ +#define QUEUE_DEPTH(in, out, ql) ((in - out) & (ql)) +#define REQ_QUEUE_DEPTH(in, out) QUEUE_DEPTH(in, out, \ + 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 *); + +#if ISP2100_FABRIC +static int isp2100_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); +#endif + +#if DEBUG_ISP2100 +static void isp2100_print_scsi_cmd(Scsi_Cmnd *); +#endif + +#if DEBUG_ISP2100_INTR +static void isp2100_print_status_entry(struct Status_Entry *); +#endif + +static struct proc_dir_entry proc_scsi_isp2100 = +{ + PROC_SCSI_QLOGICFC, 7, "isp2100", + S_IFDIR | S_IRUGO | S_IXUGO, 2 +}; + + +static inline void isp2100_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) +{ + outw(0x0, host->io_port + PCI_INTER_CTL); +} + + +int isp2100_detect(Scsi_Host_Template * tmpt) +{ + int hosts = 0; + int wait_time; + struct Scsi_Host *host = NULL; + struct isp2100_hostdata *hostdata; + struct pci_dev *pdev = NULL; + + ENTER("isp2100_detect"); + + tmpt->proc_dir = &proc_scsi_isp2100; + + 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 = tmpt->this_id; + + 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"); + + 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 + 20 * HZ; wait_time > jiffies && hostdata->loop_up == 0;) + barrier(); + + 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; + } + hosts++; + } + + + /* this busy loop should not be needed but the isp2100 seems to need + some time before recognizing it is attached to a fabric */ + +#if ISP2100_FABRIC + for (wait_time = jiffies + 5 * HZ; wait_time > jiffies;) + barrier(); +#endif + + LEAVE("isp2100_detect"); + + return hosts; +} + + +static int isp2100_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; + + isp2100_disable_irqs(host); + + memset(temp, 0, sizeof(temp)); + hostdata = (struct isp2100_hostdata *) host->hostdata; + +#if ISP2100_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); + + if (param[0] != MBOX_COMMAND_COMPLETE) { + printk("logout failed %x %x\n", i, param[0]); + } + } +#endif + + + param[0] = MBOX_GET_INIT_SCSI_ID; + + isp2100_mbox_command(host, param); + + if (param[0] == MBOX_COMMAND_COMPLETE) { + host->this_id = param[1]; + hostdata->port_id = ((u_int) param[3]) << 16; + hostdata->port_id |= param[2]; + } + + for (i = 0, j = 0; i <= QLOGICFC_MAX_ID; i++) { + param[0] = MBOX_GET_PORT_NAME; + param[1] = (i << 8) & 0xff00; + + isp2100_mbox_command(host, param); + + if (param[0] == MBOX_COMMAND_COMPLETE) { + temp[j].loop_id = i; + temp[j].wwn = ((u64) (param[2] & 0xff)) << 56; + temp[j].wwn |= ((u64) ((param[2] >> 8) & 0xff)) << 48; + temp[j].wwn |= ((u64) (param[3] & 0xff)) << 40; + temp[j].wwn |= ((u64) ((param[3] >> 8) & 0xff)) << 32; + temp[j].wwn |= ((u64) (param[6] & 0xff)) << 24; + temp[j].wwn |= ((u64) ((param[6] >> 8) & 0xff)) << 16; + temp[j].wwn |= ((u64) (param[7] & 0xff)) << 8; + temp[j].wwn |= ((u64) ((param[7] >> 8) & 0xff)); + + j++; + + } + } + + +#if ISP2100_FABRIC + isp2100_init_fabric(host, temp, j); +#endif + + for (i = 0; i <= QLOGICFC_MAX_ID; i++) { + if (temp[i].wwn != hostdata->port_db[i].wwn) { + for (j = 0; j <= QLOGICFC_MAX_ID; j++) { + if (temp[j].wwn == hostdata->port_db[i].wwn) { + hostdata->port_db[i].loop_id = temp[j].loop_id; + break; + } + } + if (j == QLOGICFC_MAX_ID + 1) + hostdata->port_db[i].loop_id = host->this_id; + + for (j = 0; j <= QLOGICFC_MAX_ID; j++) { + if (hostdata->port_db[j].wwn == temp[i].wwn || !hostdata->port_db[j].wwn) { + break; + } + } + if (j == QLOGICFC_MAX_ID + 1) + printk("qlogicfc.c: Too many scsi devices, no more room in port map.\n"); + if (!hostdata->port_db[j].wwn) { + hostdata->port_db[j].loop_id = temp[i].loop_id; + hostdata->port_db[j].wwn = temp[i].wwn; + } + } else + hostdata->port_db[i].loop_id = temp[i].loop_id; + + } + + isp2100_enable_irqs(host); + + return 0; +} + + +#if ISP2100_FABRIC + +int isp2100_init_fabric(struct Scsi_Host *host, struct id_name_map *port_db, int j) +{ + + u_short param[8]; + u64 wwn; + int done = 0; + u_short loop_id = 0x81; + u_short scsi_id = j; + u_int port_id; + struct sns_cb req; + u_char sns_response[608]; + struct isp2100_hostdata *hostdata; + + hostdata = (struct isp2100_hostdata *) host->hostdata; + + DEBUG_FABRIC(printk("qlogicfc.c: Checking for a fabric.\n")); + param[0] = MBOX_GET_PORT_NAME; + param[1] = 0x7E00; + + isp2100_mbox_command(host, param); + + if (param[0] != MBOX_COMMAND_COMPLETE) { + DEBUG_FABRIC(printk("fabric check result %x\n", param[0])); + return 0; + } + printk("qlogicfc.c: Fabric found.\n"); + + + port_id = hostdata->port_id; + while (!done) { + memset(&req, 0, sizeof(req)); + + req.len = 304; + 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); + + param[0] = MBOX_SEND_SNS; + param[1] = 14; + 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); + + isp2100_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(" 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; + port_id |= ((u_int) sns_response[19]); + wwn = ((u64) sns_response[20]) << 56; + wwn |= ((u64) sns_response[21]) << 48; + wwn |= ((u64) sns_response[22]) << 40; + wwn |= ((u64) sns_response[23]) << 32; + wwn |= ((u64) sns_response[24]) << 24; + wwn |= ((u64) sns_response[25]) << 16; + 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)); + 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); + + if (param[0] == MBOX_COMMAND_COMPLETE) { + port_db[scsi_id].wwn = wwn; + port_db[scsi_id].loop_id = loop_id; + 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)); + } + + } + if (hostdata->port_id == port_id) + done = 1; + } else { + printk("qlogicfc.c: Get All Next failed %x.\n", param[0]); + return 0; + } + } + + return 1; +} + +#endif /* ISP2100_FABRIC */ + + +int isp2100_release(struct Scsi_Host *host) +{ + struct isp2100_hostdata *hostdata; + + ENTER("isp2100_release"); + + hostdata = (struct isp2100_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"); + + return 0; +} + + +const char *isp2100_info(struct Scsi_Host *host) +{ + static char buf[80]; + struct isp2100_hostdata *hostdata; + ENTER("isp2100_info"); + + hostdata = (struct isp2100_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, + host->io_port); + + + LEAVE("isp2100_info"); + + return buf; +} + + +/* + * The middle SCSI layer ensures that queuecommand never gets invoked + * concurrently with itself or the interrupt handler (though the + * interrupt handler may call this routine as part of + * request-completion handling). + */ +int isp2100_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *)) +{ + int i, sg_count, n, num_free; + u_int in_ptr, out_ptr; + struct dataseg *ds; + struct scatterlist *sg; + struct Command_Entry *cmd; + struct Continuation_Entry *cont; + struct Scsi_Host *host; + struct isp2100_hostdata *hostdata; + + ENTER("isp2100_queuecommand"); + + + + host = Cmnd->host; + hostdata = (struct isp2100_hostdata *) host->hostdata; + Cmnd->scsi_done = done; + + DEBUG(isp2100_print_scsi_cmd(Cmnd)); + + if (hostdata->loop_up == 2) { + hostdata->loop_up = 1; + isp2100_make_portdb(host); + 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)); + } + } + if (hostdata->loop_up == -1) { + printk("qlogicfc.c: The firmware is dead, just return.\n"); + host->max_id = 0; + return 0; + } + out_ptr = inw(host->io_port + MBOX4); + in_ptr = hostdata->req_in_ptr; + + DEBUG(printk("qlogicfc : request queue depth %d\n", + 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) { + printk("qlogicfc : request queue overflow\n"); + return 1; + } + if (hostdata->send_marker) { + struct Marker_Entry *marker; + + TRACE("queue marker", in_ptr, 0); + + DEBUG(printk("qlogicfc : adding marker entry\n")); + marker = (struct Marker_Entry *) cmd; + memset(marker, 0, sizeof(struct Marker_Entry)); + + marker->hdr.entry_type = ENTRY_MARKER; + marker->hdr.entry_cnt = 1; + marker->modifier = SYNC_ALL; + + hostdata->send_marker = 0; + + if (((in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN) == out_ptr) { + outw(in_ptr, host->io_port + MBOX4); + hostdata->req_in_ptr = in_ptr; + printk("qlogicfc : request queue overflow\n"); + return 1; + } + cmd = (struct Command_Entry *) &hostdata->req[in_ptr][0]; + in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN; + } + TRACE("queue command", in_ptr, Cmnd); + + memset(cmd, 0, sizeof(struct Command_Entry)); + + /* find a free handle mapping slot */ + for (i = in_ptr; i != (in_ptr - 1) && hostdata->handle_ptrs[i]; i = ((i + 1) % (QLOGICFC_REQ_QUEUE_LEN + 1))); + + if (!hostdata->handle_ptrs[i]) { + 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"); + + cmd->hdr.entry_type = ENTRY_COMMAND; + cmd->hdr.entry_cnt = 1; + cmd->target_lun = Cmnd->lun; + cmd->target_id = hostdata->port_db[Cmnd->target].loop_id; + cmd->total_byte_cnt = (u_int) Cmnd->request_bufflen; + cmd->time_out = SCSI_TIMEOUT / HZ; + + memcpy(cmd->cdb, Cmnd->cmnd, Cmnd->cmd_len); + + if (Cmnd->use_sg) { + cmd->segment_cnt = sg_count = Cmnd->use_sg; + sg = (struct scatterlist *) Cmnd->request_buffer; + ds = cmd->dataseg; + /* fill in first two sg entries: */ + n = sg_count; + if (n > 2) + n = 2; + 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_count = sg->length; + ++sg; + } + sg_count -= 2; + + while (sg_count > 0) { + ++cmd->hdr.entry_cnt; + cont = (struct Continuation_Entry *) + &hostdata->req[in_ptr][0]; + memset(cont, 0, sizeof(struct Continuation_Entry)); + in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN; + if (in_ptr == out_ptr) { + printk("isp2100: unexpected request queue " + "overflow\n"); + 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; + 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_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->segment_cnt = 1; + } + + switch (Cmnd->cmnd[0]) { + case WRITE_10: + case WRITE_6: + case WRITE_BUFFER: + 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->segment_cnt = 1; + cmd->control_flags = CFLAG_READ; + break; + default: + cmd->control_flags = CFLAG_READ; + break; + } + + + if (Cmnd->device->tagged_supported) { + switch (Cmnd->tag) { + case SIMPLE_QUEUE_TAG: + cmd->control_flags |= CFLAG_SIMPLE_TAG; + break; + case HEAD_OF_QUEUE_TAG: + cmd->control_flags |= CFLAG_HEAD_TAG; + break; + case ORDERED_QUEUE_TAG: + cmd->control_flags |= CFLAG_ORDERED_TAG; + break; + default: + if ((jiffies - hostdata->tag_ages[Cmnd->target]) > (5 * HZ)) { + cmd->control_flags |= CFLAG_ORDERED_TAG; + hostdata->tag_ages[Cmnd->target] = jiffies; + } else + cmd->control_flags |= CFLAG_SIMPLE_TAG; + } + } + outw(in_ptr, host->io_port + MBOX4); + 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; + host->can_queue = hostdata->queued + num_free; + if (host->can_queue > QLOGICFC_REQ_QUEUE_LEN) + host->can_queue = QLOGICFC_REQ_QUEUE_LEN; + host->sg_tablesize = QLOGICFC_MAX_SG(num_free); + + /* this is really gross */ + if (host->can_queue < host->host_busy){ + if (host->can_queue+2 < host->host_busy) + printk("qlogicfc.c crosses its fingers.\n"); + host->can_queue = host->host_busy; + } + + LEAVE("isp2100_queuecommand"); + + return 0; +} + + +#define ASYNC_EVENT_INTERRUPT 0x01 + + +void do_isp2100_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); + spin_unlock_irqrestore(&io_request_lock, flags); +} + +void isp2100_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; + u_int in_ptr, out_ptr, handle, num_free; + u_short status; + + ENTER_INTR("isp2100_intr_handler"); + + hostdata = (struct isp2100_hostdata *) host->hostdata; + + DEBUG_INTR(printk("qlogicfc : interrupt on line %d\n", irq)); + + if (!(inw(host->io_port + PCI_INTER_STS) & 0x08)) { + /* spurious interrupts can happen legally */ + DEBUG_INTR(printk("qlogicfc: got spurious interrupt\n")); + return; + } + in_ptr = inw(host->io_port + MBOX5); + out_ptr = hostdata->res_out_ptr; + + 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)); + + switch (status) { + case LOOP_UP: + hostdata->loop_up = 2; + break; + case LOOP_DOWN: + hostdata->loop_up = 0; + break; + case LIP_OCCURED: + case CHANGE_NOTIFICATION: + if (hostdata->loop_up == 1) + hostdata->loop_up = 2; + break; + case SYSTEM_ERROR: + printk("The firmware just choked.\n"); + hostdata->loop_up = -1; + break; + case SCSI_COMMAND_COMPLETE: + handle = inw(host->io_port + MBOX1) | (inw(host->io_port + MBOX2) << 16); + Cmnd = hostdata->handle_ptrs[handle]; + hostdata->handle_ptrs[handle] = NULL; + hostdata->handle_serials[handle] = 0; + hostdata->queued--; + if (Cmnd != NULL) { + Cmnd->result = 0x0; + (*Cmnd->scsi_done) (Cmnd); + } else + printk("qlogicfc.c: got a null value out of handle_ptrs, this sucks\n"); + break; + case MBOX_COMMAND_COMPLETE: + case INVALID_COMMAND: + case HOST_INTERFACE_ERROR: + case TEST_FAILED: + case COMMAND_ERROR: + case COMMAND_PARAM_ERROR: + case PORT_ID_USED: + case LOOP_ID_USED: + case ALL_IDS_USED: + hostdata->mbox_done = 1; + outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR); + return; + default: + printk("qlogicfc: got an unknown status? %x\n", 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))); + + while (out_ptr != in_ptr) { + sts = (struct Status_Entry *) &hostdata->res[out_ptr][0]; + out_ptr = (out_ptr + 1) & RES_QUEUE_LEN; + Cmnd = hostdata->handle_ptrs[sts->handle]; + + hostdata->handle_ptrs[sts->handle] = NULL; + + if (hostdata->handle_serials[sts->handle] != Cmnd->serial_number) { + hostdata->queued--; + hostdata->handle_serials[sts->handle] = 0; + outw(out_ptr, host->io_port + MBOX5); + continue; + } + hostdata->handle_serials[sts->handle] = 0; + + TRACE("done", out_ptr, Cmnd); + DEBUG_INTR(isp2100_print_status_entry(sts)); + if (sts->hdr.entry_type == ENTRY_STATUS) { + Cmnd->result = isp2100_return_status(sts); + } 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; + + if (sts->scsi_status & 0x0200) + memcpy(Cmnd->sense_buffer, sts->req_sense_data, + sizeof(Cmnd->sense_buffer)); + + outw(out_ptr, host->io_port + MBOX5); + + hostdata->queued--; + if (Cmnd->scsi_done != NULL) { + (*Cmnd->scsi_done) (Cmnd); + } else + printk("Ouch, scsi done is NULL\n"); + } + hostdata->res_out_ptr = out_ptr; + } + + + out_ptr = inw(host->io_port + MBOX4); + in_ptr = hostdata->req_in_ptr; + + num_free = QLOGICFC_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr); + num_free = num_free-2; + host->can_queue = hostdata->queued + num_free; + if (host->can_queue > QLOGICFC_REQ_QUEUE_LEN) + host->can_queue = QLOGICFC_REQ_QUEUE_LEN; + host->sg_tablesize = QLOGICFC_MAX_SG(num_free); + + /* this is really gross */ + if (host->can_queue < host->host_busy){ + if (host->can_queue+2 < host->host_busy) + printk("1 qlogicfc crosses its fingers.\n"); + host->can_queue = host->host_busy; + } + + outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR); + LEAVE_INTR("isp2100_intr_handler"); +} + + +static int isp2100_return_status(struct Status_Entry *sts) +{ + int host_status = DID_ERROR; +#if DEBUG_ISP2100_INTR + static char *reason[] = + { + "DID_OK", + "DID_NO_CONNECT", + "DID_BUS_BUSY", + "DID_TIME_OUT", + "DID_BAD_TARGET", + "DID_ABORT", + "DID_PARITY", + "DID_ERROR", + "DID_RESET", + "DID_BAD_INTR" + }; +#endif /* DEBUG_ISP2100_INTR */ + + ENTER("isp2100_return_status"); + + DEBUG(printk("qlogicfc : completion status = 0x%04x\n", + sts->completion_status)); + + switch (sts->completion_status) { + case CS_COMPLETE: + host_status = DID_OK; + break; + case CS_INCOMPLETE: + if (!(sts->state_flags & SF_SENT_CDB)) + host_status = DID_ERROR; + else if (!(sts->state_flags & SF_TRANSFERRED_DATA)) + host_status = DID_ERROR; + else if (!(sts->state_flags & SF_GOT_STATUS)) + host_status = DID_ERROR; + break; + case CS_DMA_ERROR: + case CS_TRANSPORT_ERROR: + host_status = DID_ERROR; + break; + case CS_RESET_OCCURRED: + host_status = DID_RESET; + break; + case CS_ABORTED: + host_status = DID_ABORT; + break; + case CS_TIMEOUT: + host_status = DID_TIME_OUT; + break; + case CS_DATA_OVERRUN: + case CS_ABORT_MSG_FAILED: + host_status = DID_ERROR; + break; + case CS_DATA_UNDERRUN: + host_status = DID_OK; + break; + case CS_PORT_UNAVAILABLE: + case CS_PORT_LOGGED_OUT: + case CS_PORT_CONFIG_CHANGED: + host_status = DID_BAD_TARGET; + break; + default: + printk("qlogicfc : unknown completion status 0x%04x\n", + sts->completion_status); + host_status = DID_ERROR; + break; + } + + DEBUG_INTR(printk("qlogicfc : host status (%s) scsi status %x\n", + reason[host_status], sts->scsi_status)); + + LEAVE("isp2100_return_status"); + + return (sts->scsi_status & STATUS_MASK) | (host_status << 16); +} + + +int isp2100_abort(Scsi_Cmnd * Cmnd) +{ + u_short param[8]; + int i; + struct Scsi_Host *host; + struct isp2100_hostdata *hostdata; + int return_status = SCSI_ABORT_SUCCESS; + + ENTER("isp2100_abort"); + + host = Cmnd->host; + hostdata = (struct isp2100_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; + + isp2100_disable_irqs(host); + + param[0] = MBOX_ABORT_IOCB; + param[1] = (((u_short) Cmnd->target) << 8) | Cmnd->lun; + param[2] = i >> 16; + param[3] = i & 0xffff; + + isp2100_mbox_command(host, param); + + if (param[0] != MBOX_COMMAND_COMPLETE) { + printk("qlogicfc : scsi abort failure: %x\n", 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; + } + isp2100_enable_irqs(host); + + LEAVE("isp2100_abort"); + + return return_status; +} + + +int isp2100_reset(Scsi_Cmnd * Cmnd, unsigned int reset_flags) +{ + u_short param[8]; + struct Scsi_Host *host; + struct isp2100_hostdata *hostdata; + int return_status = SCSI_RESET_SUCCESS; + + ENTER("isp2100_reset"); + + host = Cmnd->host; + hostdata = (struct isp2100_hostdata *) host->hostdata; + param[0] = MBOX_BUS_RESET; + param[1] = 3; + + isp2100_disable_irqs(host); + + isp2100_mbox_command(host, param); + + if (param[0] != MBOX_COMMAND_COMPLETE) { + printk("qlogicfc : scsi bus reset failure: %x\n", param[0]); + return_status = SCSI_RESET_ERROR; + } + isp2100_enable_irqs(host); + + LEAVE("isp2100_reset"); + + return return_status;; +} + + +int isp2100_biosparam(Disk * disk, kdev_t n, int ip[]) +{ + int size = disk->capacity; + + ENTER("isp2100_biosparam"); + + ip[0] = 64; + ip[1] = 32; + ip[2] = size >> 11; + if (ip[2] > 1024) { + ip[0] = 255; + ip[1] = 63; + ip[2] = size / (ip[0] * ip[1]); + if (ip[2] > 1023) + ip[2] = 1023; + } + LEAVE("isp2100_biosparam"); + + return 0; +} + + +static int isp2100_reset_hardware(struct Scsi_Host *host) +{ + u_short param[8]; + struct isp2100_hostdata *hostdata; + int loop_count; + + ENTER("isp2100_reset_hardware"); + + outw(0x01, host->io_port + ISP_CTRL_STATUS); + outw(HCCR_RESET, host->io_port + HOST_HCCR); + outw(HCCR_RELEASE, host->io_port + HOST_HCCR); + outw(HCCR_BIOS_DISABLE, host->io_port + HOST_HCCR); + + loop_count = DEFAULT_LOOP_COUNT; + while (--loop_count && inw(host->io_port + HOST_HCCR) == RISC_BUSY) + barrier(); + if (!loop_count) + printk("qlogicfc: reset_hardware loop timeout\n"); + + + +#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 */ + + DEBUG(printk("qlogicfc : verifying checksum\n")); + +#if RELOAD_FIRMWARE + { + int i; + for (i = 0; i < risc_code_length01; i++) { + param[0] = MBOX_WRITE_RAM_WORD; + param[1] = risc_code_addr01 + i; + param[2] = risc_code01[i]; + + isp2100_mbox_command(host, param); + + if (param[0] != MBOX_COMMAND_COMPLETE) { + printk("qlogicfc : firmware load failure\n"); + return 1; + } + } + } +#endif /* RELOAD_FIRMWARE */ + + param[0] = MBOX_VERIFY_CHECKSUM; + param[1] = risc_code_addr01; + + isp2100_mbox_command(host, param); + + if (param[0] != MBOX_COMMAND_COMPLETE) { + printk("qlogicfc : ram checksum failure\n"); + return 1; + } + DEBUG(printk("qlogicfc : executing firmware\n")); + + param[0] = MBOX_EXEC_FIRMWARE; + param[1] = risc_code_addr01; + + isp2100_mbox_command(host, param); + + param[0] = MBOX_ABOUT_FIRMWARE; + + isp2100_mbox_command(host, param); + + if (param[0] != MBOX_COMMAND_COMPLETE) { + printk("qlogicfc : about firmware failure\n"); + 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; + +#ifdef USE_NVRAM_DEFAULTS + + if (isp2100_get_nvram_defaults(host, &hostdata->control_block) != 0) { + printk("qlogicfc: Could not read from NVRAM\n"); + } +#endif + + hostdata->wwn = (u64) (hostdata->control_block.node_name[0]) << 56; + hostdata->wwn |= (u64) (hostdata->control_block.node_name[0] & 0xff00) << 48; + hostdata->wwn |= (u64) (hostdata->control_block.node_name[1] & 0xff00) << 24; + hostdata->wwn |= (u64) (hostdata->control_block.node_name[1] & 0x00ff) << 48; + hostdata->wwn |= (u64) (hostdata->control_block.node_name[2] & 0x00ff) << 24; + hostdata->wwn |= (u64) (hostdata->control_block.node_name[2] & 0xff00) << 8; + hostdata->wwn |= (u64) (hostdata->control_block.node_name[3] & 0x00ff) << 8; + hostdata->wwn |= (u64) (hostdata->control_block.node_name[3] & 0xff00) >> 8; + + param[0] = MBOX_INIT_FIRMWARE; + param[2] = (u_short) (virt_to_bus_low32(&hostdata->control_block) >> 16); + param[3] = (u_short) (virt_to_bus_low32(&hostdata->control_block) & 0xffff); + param[4] = 0; + 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); + if (param[0] != MBOX_COMMAND_COMPLETE) { + printk("qlogicfc.c: Ouch 0x%04x\n", param[0]); + return 1; + } + param[0] = MBOX_GET_FIRMWARE_STATE; + isp2100_mbox_command(host, param); + if (param[0] != MBOX_COMMAND_COMPLETE) { + printk("qlogicfc.c: 0x%04x\n", param[0]); + return 1; + } + /* this command returns the status loop down and generates + an interupt when the loop comes up */ + param[0] = MBOX_INIT_LIP; + isp2100_mbox_command(host, param); + + param[0] = MBOX_GET_FIRMWARE_STATE; + isp2100_mbox_command(host, param); + if (param[0] != MBOX_COMMAND_COMPLETE) { + printk("qlogicfc.c: 0x%04x\n", param[0]); + return 1; + } + LEAVE("isp2100_reset_hardware"); + + return 0; +} + +#ifdef USE_NVRAM_DEFAULTS + +static int isp2100_get_nvram_defaults(struct Scsi_Host *host, struct init_cb *control_block) +{ + + u_short value; + if (isp2100_read_nvram_word(host, 0) != 0x5349) + return 1; + + control_block->version = isp2100_read_nvram_word(host, 3) & 0xff; + control_block->firm_opts = isp2100_read_nvram_word(host, 4); + control_block->max_frame_len = isp2100_read_nvram_word(host, 5); + control_block->max_iocb = isp2100_read_nvram_word(host, 6); + control_block->exec_throttle = isp2100_read_nvram_word(host, 7); + value = isp2100_read_nvram_word(host, 8); + control_block->retry_cnt = value & 0xff; + control_block->retry_delay = (value >> 8) & 0xff; + 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); + + return 0; + +} + +#endif + +static int isp2100_init(struct Scsi_Host *sh) +{ + u_int io_base; + struct isp2100_hostdata *hostdata; + u_char revision; + u_int irq; + u_short command; + struct pci_dev *pdev; + + + ENTER("isp2100_init"); + + hostdata = (struct isp2100_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"); + 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", + pdev->vendor); + return 1; + } + if (pdev->device != PCI_DEVICE_ID_QLOGIC_ISP2100) { + printk("qlogicfc : 0x%04x does not match ISP2100 device id\n", + 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"); + return 1; + } + + if (!(command & PCI_COMMAND_MASTER)) { + printk("qlogicfc : bus mastering is disabled\n"); + return 1; + } + if (revision != ISP2100_REV_ID && revision != ISP2100_REV_ID3) + printk("qlogicfc : new isp2100 revision ID (%d)\n", revision); + + + hostdata->revision = revision; + + sh->irq = irq; + sh->io_port = io_base; + + LEAVE("isp2100_init"); + + return 0; +} + +#if USE_NVRAM_DEFAULTS + +#define NVRAM_DELAY() udelay(10) /* 10 microsecond delay */ + + +u_short isp2100_read_nvram_word(struct Scsi_Host * host, u_short byte) +{ + int i; + u_short value, output, input; + + outw(0x2, host->io_port + PCI_NVRAM); + NVRAM_DELAY(); + outw(0x3, host->io_port + PCI_NVRAM); + NVRAM_DELAY(); + + byte &= 0xff; + byte |= 0x0600; + for (i = 10; i >= 0; i--) { + output = ((byte >> i) & 0x1) ? 0x4 : 0x0; + outw(output | 0x2, host->io_port + PCI_NVRAM); + NVRAM_DELAY(); + outw(output | 0x3, host->io_port + PCI_NVRAM); + NVRAM_DELAY(); + outw(output | 0x2, host->io_port + PCI_NVRAM); + NVRAM_DELAY(); + } + + for (i = 0xf, value = 0; i >= 0; i--) { + value <<= 1; + outw(0x3, host->io_port + PCI_NVRAM); + NVRAM_DELAY(); + input = inw(host->io_port + PCI_NVRAM); + NVRAM_DELAY(); + outw(0x2, host->io_port + PCI_NVRAM); + NVRAM_DELAY(); + if (input & 0x8) + value |= 1; + } + + outw(0x0, host->io_port + PCI_NVRAM); + NVRAM_DELAY(); + + return value; +} + + +#endif /* USE_NVRAM_DEFAULTS */ + + + +/* + * 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[]) +{ + int loop_count; + struct isp2100_hostdata *hostdata = (struct isp2100_hostdata *) host->hostdata; + + if (mbox_param[param[0]] == 0) + 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"); + param[0] = 0x4006; + return 1; + } + hostdata->mbox_done = 0; + + if (mbox_param[param[0]] == 0) + printk("qlogicfc: invalid mbox command\n"); + + if (mbox_param[param[0]] & 0x80) + outw(param[7], host->io_port + MBOX7); + if (mbox_param[param[0]] & 0x40) + outw(param[6], host->io_port + MBOX6); + if (mbox_param[param[0]] & 0x20) + outw(param[5], host->io_port + MBOX5); + if (mbox_param[param[0]] & 0x10) + outw(param[4], host->io_port + MBOX4); + if (mbox_param[param[0]] & 0x08) + outw(param[3], host->io_port + MBOX3); + if (mbox_param[param[0]] & 0x04) + outw(param[2], host->io_port + MBOX2); + if (mbox_param[param[0]] & 0x02) + outw(param[1], host->io_port + MBOX1); + if (mbox_param[param[0]] & 0x01) + outw(param[0], host->io_port + MBOX0); + + + outw(HCCR_SET_HOST_INTR, host->io_port + HOST_HCCR); + + while (1) { + loop_count = DEFAULT_LOOP_COUNT; + while (--loop_count && !(inw(host->io_port + PCI_INTER_STS) & 0x08)) { + barrier(); + } + + if (!loop_count) { + printk("qlogicfc: mbox_command loop timeout #2\n"); + break; + } + isp2100_intr_handler(host->irq, host, NULL); + + if (hostdata->mbox_done == 1) + break; + + } + + loop_count = DEFAULT_LOOP_COUNT; + while (--loop_count && inw(host->io_port + MBOX0) == 0x04) { + barrier(); + } + if (!loop_count) + printk("qlogicfc: mbox_command loop timeout #3\n"); + + param[7] = inw(host->io_port + MBOX7); + param[6] = inw(host->io_port + MBOX6); + param[5] = inw(host->io_port + MBOX5); + param[4] = inw(host->io_port + MBOX4); + param[3] = inw(host->io_port + MBOX3); + param[2] = inw(host->io_port + MBOX2); + param[1] = inw(host->io_port + MBOX1); + param[0] = inw(host->io_port + MBOX0); + + + outw(0x0, host->io_port + PCI_SEMAPHORE); + + if (inw(host->io_port + HOST_HCCR) & 0x0080) { + printk("mbox op is still pending\n"); + } + return 0; +} + + +#if DEBUG_ISP2100_INTR + +void isp2100_print_status_entry(struct Status_Entry *status) +{ + int i; + + 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", + 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); + printk("qlogicfc : residual transfer length = 0x%08x, response = 0x%02x\n", status->residual, status->res_info[3]); + +} + +#endif /* DEBUG_ISP2100_INTR */ + + +#if DEBUG_ISP2100 + +void isp2100_print_scsi_cmd(Scsi_Cmnd * cmd) +{ + int i; + + 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++) + printk("0x%02x ", cmd->cmnd[i]); + printk("\n"); +} + +#endif /* DEBUG_ISP2100 */ + + +#ifdef MODULE + +Scsi_Host_Template driver_template = QLOGICFC; + +#include "scsi_module.c" + +#endif 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 Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/scsi/qlogicfc.h Wed Dec 23 19:37:14 1998 @@ -0,0 +1,102 @@ +/* + * QLogic ISP2100 SCSI-FCP + * + * Written by Erik H. Moe, ehm@cris.com + * Copyright 1995, Erik H. Moe + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +/* 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 + */ + + +/* + * $Date: 1995/09/22 02:32:56 $ + * $Revision: 0.5 $ + * + * $Log: isp1020.h,v $ + * Revision 0.5 1995/09/22 02:32:56 root + * do auto request sense + * + * Revision 0.4 1995/08/07 04:48:28 root + * supply firmware with driver. + * numerous bug fixes/general cleanup of code. + * + * Revision 0.3 1995/07/16 16:17:16 root + * added reset/abort code. + * + * Revision 0.2 1995/06/29 03:19:43 root + * fixed biosparam. + * added queue protocol. + * + * Revision 0.1 1995/06/25 01:56:13 root + * Initial release. + * + */ + +#ifndef _QLOGICFC_H +#define _QLOGICFC_H + +/* + * With the qlogic interface, every queue slot can hold a SCSI + * command with up to 2 scatter/gather entries. If we need more + * than 2 entries, continuation entries can be used that hold + * another 5 entries each. Unlike for other drivers, this means + * that the maximum number of scatter/gather entries we can + * support at any given time is a function of the number of queue + * slots available. That is, host->can_queue and host->sg_tablesize + * are dynamic and _not_ independent. This all works fine because + * 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)) +#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[]); + +#ifndef NULL +#define NULL (0) +#endif + +extern struct proc_dir_entry proc_scsi_isp2100; + +#define QLOGICFC { \ + detect: isp2100_detect, \ + release: isp2100_release, \ + info: isp2100_info, \ + queuecommand: isp2100_queuecommand, \ + abort: isp2100_abort, \ + reset: isp2100_reset, \ + bios_param: isp2100_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, \ + present: 0, \ + unchecked_isa_dma: 0, \ + use_clustering: DISABLE_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 Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/scsi/qlogicfc_asm.c Tue Dec 22 17:09:51 1998 @@ -0,0 +1,2985 @@ +/************************************************************************ + * * + * --- ISP2100 Fabric Initiator/Target Firmware --- * + * * + * * + * * + ************************************************************************ + */ +/* + * Firmware Version 1.13.00 (18:06 May 04, 1998) + */ + +unsigned short risc_code_version = 1*1024+13; + +unsigned char firmware_version[] = {1,13,0}; + +unsigned short risc_code_addr01 = 0x1000 ; + +unsigned short risc_code01[] = { + 0x0078, 0x1029, 0x0000, 0x5c95, 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, 0x3133, 0x2020, 0x2020, + 0x2400, 0x20c1, 0x0021, 0x20a1, 0x6c95, 0x2009, 0x0000, 0x20a9, + 0x076b, 0x41a4, 0x3400, 0x20c9, 0x71ff, 0x2091, 0x2000, 0x2059, + 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x1e36, 0x2051, 0x6d00, + 0x2a70, 0x705b, 0x8c00, 0x705f, 0xffff, 0x7057, 0x8bf9, 0x7063, + 0x0300, 0x1078, 0x1264, 0x20a1, 0x7400, 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, 0x122b, 0x1078, 0x134e, 0x1078, 0x14d3, 0x1078, 0x17d7, + 0x1078, 0x324a, 0x1078, 0x54fc, 0x1078, 0x12d9, 0x1078, 0x2191, + 0x1078, 0x3875, 0x1078, 0x3655, 0x1078, 0x4064, 0x1078, 0x1c35, + 0x1078, 0x4213, 0x1078, 0x3d73, 0x1078, 0x1b5d, 0x1078, 0x1c14, + 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, 0x2a96, 0x1078, 0x21b9, 0x1078, 0x38c5, + 0x1078, 0x373c, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048, + 0x10c1, 0x1078, 0x4078, 0x0078, 0x10a4, 0x1079, 0x10c5, 0x0078, + 0x10aa, 0x1078, 0x52d8, 0x0078, 0x10b9, 0x10cf, 0x10d0, 0x1151, + 0x10cd, 0x11aa, 0x1228, 0x1229, 0x122a, 0x1078, 0x12b7, 0x007c, + 0x127e, 0x0f7e, 0x2091, 0x8000, 0x1078, 0x2aec, 0x2079, 0x0100, + 0x7844, 0xa005, 0x00c0, 0x1142, 0x2011, 0x318e, 0x1078, 0x40d1, + 0x780f, 0x00ff, 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011, 0x8010, + 0x73b8, 0x1078, 0x2a53, 0x1078, 0x5129, 0x2011, 0x0004, 0x1078, + 0x6135, 0x1078, 0x35ef, 0x70c7, 0x0000, 0x70bf, 0x0000, 0x70c3, + 0x0000, 0x1078, 0x1145, 0x2011, 0x0000, 0x2079, 0x6d51, 0x7804, + 0xd0ac, 0x0040, 0x1104, 0xc295, 0x70a4, 0xa005, 0x0040, 0x1109, + 0xc29d, 0x72be, 0xa296, 0x0004, 0x0040, 0x112a, 0x2011, 0x0001, + 0x1078, 0x6135, 0x708b, 0x0000, 0x708f, 0xffff, 0x7003, 0x0002, + 0x0f7f, 0x1078, 0x1ee6, 0x2011, 0x0005, 0x1078, 0x5232, 0x1078, + 0x476a, 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f, 0x127f, + 0x0078, 0x1144, 0x7003, 0x0003, 0x2001, 0x0000, 0x1078, 0x1dc9, + 0x2011, 0x0000, 0x1078, 0x5232, 0x2011, 0x0000, 0x1078, 0x523c, + 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f, 0x1078, 0x476a, + 0x1078, 0x4821, 0x0f7f, 0x127f, 0x007c, 0x0c7e, 0x20a9, 0x0082, + 0x2009, 0x007e, 0x1078, 0x342f, 0x8108, 0x00f0, 0x114a, 0x0c7f, + 0x007c, 0x127e, 0x2091, 0x8000, 0x708c, 0xa086, 0xffff, 0x0040, + 0x115f, 0x1078, 0x1ee6, 0x1078, 0x476a, 0x0078, 0x11a8, 0x70bc, + 0xd09c, 0x0040, 0x1187, 0xd084, 0x0040, 0x1187, 0x0f7e, 0x2079, + 0x0100, 0x790c, 0xc1b5, 0x790e, 0x0f7f, 0xd08c, 0x0040, 0x1187, + 0x70c0, 0xa086, 0xffff, 0x0040, 0x1183, 0x1078, 0x1fdb, 0x1078, + 0x476a, 0x2011, 0x0001, 0x2019, 0x0000, 0x1078, 0x2013, 0x1078, + 0x476a, 0x0078, 0x11a8, 0x70c4, 0xa005, 0x00c0, 0x11a8, 0x7088, + 0xa005, 0x00c0, 0x11a8, 0x7003, 0x0003, 0x708f, 0xffff, 0x2001, + 0x0000, 0x1078, 0x1dc9, 0x1078, 0x2ad1, 0x2001, 0x6f11, 0x2004, + 0xa086, 0x0005, 0x00c0, 0x11a0, 0x2011, 0x0000, 0x1078, 0x5232, + 0x2011, 0x0000, 0x1078, 0x523c, 0x1078, 0x476a, 0x1078, 0x4821, + 0x127f, 0x007c, 0x017e, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079, + 0x0100, 0x7843, 0x0000, 0x7924, 0xd1b4, 0x0040, 0x11b9, 0x7827, + 0x0040, 0xd19c, 0x0040, 0x11be, 0x7827, 0x0008, 0x007e, 0x037e, + 0x157e, 0x7900, 0xa18a, 0x0003, 0x0050, 0x11e4, 0x7954, 0xd1ac, + 0x00c0, 0x11e4, 0x2009, 0x00f8, 0x1078, 0x3233, 0x7843, 0x0090, + 0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x00c0, 0x11dc, + 0x7824, 0xd0ac, 0x00c0, 0x1218, 0x00f0, 0x11d4, 0x2001, 0x0001, + 0x1078, 0x1dc9, 0x0078, 0x1221, 0x7853, 0x0000, 0x782f, 0x0020, + 0x20a9, 0x0008, 0x00e0, 0x11ea, 0x2091, 0x6000, 0x00f0, 0x11ea, + 0x7853, 0x0400, 0x782f, 0x0000, 0x2009, 0x00f8, 0x1078, 0x3233, + 0x20a9, 0x000e, 0x0005, 0x00f0, 0x11fa, 0x7853, 0x1400, 0x7843, + 0x0090, 0x7843, 0x0010, 0x2019, 0x61a8, 0x7854, 0x0005, 0x0005, + 0xd08c, 0x0040, 0x120f, 0x7824, 0xd0ac, 0x00c0, 0x1218, 0x8319, + 0x00c0, 0x1205, 0x2001, 0x0001, 0x1078, 0x1dc9, 0x0078, 0x121f, + 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, 0x1237, 0x704f, 0xffff, 0x0078, 0x1239, 0x704f, + 0x0000, 0x7053, 0xffff, 0x7067, 0x0000, 0x706b, 0x0000, 0x2061, + 0x6f00, 0x6003, 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, + 0x0200, 0x6013, 0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, + 0x07d0, 0x2061, 0x6f08, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, + 0x0000, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, + 0x0001, 0x601f, 0x0000, 0x007c, 0x1078, 0x128a, 0x2011, 0x0000, + 0x81ff, 0x0040, 0x1289, 0xa186, 0x0001, 0x00c0, 0x1279, 0x705f, + 0x8fff, 0x7057, 0x7c01, 0x7063, 0x0100, 0x705b, 0x7c00, 0x0078, + 0x1287, 0xa186, 0x0002, 0x00c0, 0x1281, 0x2011, 0x0000, 0x0078, + 0x1287, 0xa186, 0x0005, 0x00c0, 0x1287, 0x2011, 0x0001, 0x1078, + 0x12b1, 0x007c, 0x2009, 0x0000, 0x2011, 0x0000, 0x1078, 0x12b1, + 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2362, 0x2c24, 0x2061, 0x7fff, + 0x2c04, 0xa406, 0x0040, 0x129f, 0xc18d, 0x0078, 0x12ac, 0xc185, + 0x2011, 0x0001, 0x1078, 0x12b1, 0x2061, 0xffff, 0x2362, 0x2c04, + 0xa306, 0x00c0, 0x12ac, 0xc195, 0x2011, 0x0001, 0x1078, 0x12b1, + 0x007c, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x007c, 0x2091, + 0x8000, 0x0068, 0x12b9, 0x007e, 0x017e, 0x2079, 0x0000, 0x7818, + 0xa084, 0x0000, 0x00c0, 0x12bf, 0x017f, 0x792e, 0x007f, 0x782a, + 0x007f, 0x7826, 0x7823, 0x8002, 0x781b, 0x0001, 0x2091, 0x5000, + 0x2091, 0x4080, 0x2079, 0x6d00, 0x7803, 0x0005, 0x0078, 0x12d6, + 0x007c, 0x2071, 0x6d00, 0x7158, 0x712e, 0x2021, 0x0001, 0xa190, + 0x002d, 0xa298, 0x002d, 0x0048, 0x12ef, 0x705c, 0xa302, 0x00c8, + 0x12ef, 0x220a, 0x2208, 0x2310, 0x8420, 0x0078, 0x12e1, 0x200b, + 0x0000, 0x749e, 0x74a2, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000, + 0x2071, 0x6d00, 0x70a0, 0xa0ea, 0x0010, 0x00c8, 0x1302, 0xa06e, + 0x0078, 0x130c, 0x8001, 0x70a2, 0x702c, 0x2068, 0x2d04, 0x702e, + 0x206b, 0x0000, 0x6807, 0x0000, 0x127f, 0x0e7f, 0x007c, 0x0e7e, + 0x2071, 0x6d00, 0x127e, 0x2091, 0x8000, 0x70a0, 0x8001, 0x00c8, + 0x131c, 0xa06e, 0x0078, 0x1325, 0x70a2, 0x702c, 0x2068, 0x2d04, + 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x127f, 0x0e7f, 0x007c, + 0x0e7e, 0x127e, 0x2091, 0x8000, 0x2071, 0x6d00, 0x702c, 0x206a, + 0x2d00, 0x702e, 0x70a0, 0x8000, 0x70a2, 0x127f, 0x0e7f, 0x007c, + 0x8dff, 0x0040, 0x1344, 0x6804, 0x6807, 0x0000, 0x007e, 0x1078, + 0x1328, 0x0d7f, 0x0078, 0x1338, 0x007c, 0x0e7e, 0x2071, 0x6d00, + 0x70a0, 0xa08a, 0x0010, 0xa00d, 0x0e7f, 0x007c, 0x0e7e, 0x2071, + 0x6f31, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x2071, + 0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x0e7f, 0x007c, 0x0e7e, + 0x2270, 0x700b, 0x0000, 0x2071, 0x6f31, 0x7018, 0xa088, 0x6f3a, + 0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, 0x00c0, + 0x1377, 0x0f7e, 0x2079, 0x0010, 0x1078, 0x1388, 0x0f7f, 0x0e7f, + 0x007c, 0x0e7e, 0x2071, 0x6f31, 0x7004, 0xa005, 0x00c0, 0x1386, + 0x0f7e, 0x2079, 0x0010, 0x1078, 0x1388, 0x0f7f, 0x0e7f, 0x007c, + 0x7000, 0x0079, 0x138b, 0x138f, 0x13f9, 0x1416, 0x1416, 0x7018, + 0x711c, 0xa106, 0x00c0, 0x1397, 0x7007, 0x0000, 0x007c, 0x0d7e, + 0xa180, 0x6f3a, 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, 0x13b9, 0x7007, 0x0001, 0x1078, 0x13be, + 0x007c, 0x7007, 0x0002, 0x1078, 0x13d4, 0x007c, 0x017e, 0x027e, + 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x13c9, 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, 0x13e8, 0x2110, 0xa006, + 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803, 0x0020, 0x7803, + 0x0001, 0x3300, 0x7016, 0x157f, 0x147f, 0x137f, 0x027f, 0x017f, + 0x007c, 0x137e, 0x147e, 0x157e, 0x2099, 0x6dc5, 0x20a1, 0x0018, + 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, 0x2091, 0x8000, + 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x700b, + 0x6dc0, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x137e, 0x147e, + 0x157e, 0x2001, 0x6df4, 0x209c, 0x20a1, 0x0014, 0x7803, 0x0026, + 0x2001, 0x6df5, 0x20ac, 0x53a6, 0x2099, 0x6df6, 0x20a1, 0x0018, + 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, 0x2091, 0x8000, + 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c, 0x7002, 0x700b, + 0x6df1, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x017e, 0x0e7e, + 0x2071, 0x6f31, 0x0f7e, 0x2079, 0x0010, 0x7904, 0x7803, 0x0002, + 0xd1fc, 0x0040, 0x1459, 0xa18c, 0x0700, 0x0040, 0x1456, 0x7008, + 0xa080, 0x0002, 0x2003, 0x0200, 0x0078, 0x1459, 0x7004, 0x1079, + 0x145d, 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x1388, 0x1465, 0x1487, + 0x14a1, 0x14ca, 0x1463, 0x0078, 0x1463, 0x137e, 0x147e, 0x157e, + 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x7010, 0x20a8, + 0x53a5, 0x3400, 0x7016, 0x157f, 0x147f, 0x137f, 0x700c, 0xa005, + 0x0040, 0x148e, 0x1078, 0x13be, 0x007c, 0x7008, 0xa080, 0x0002, + 0x2003, 0x0100, 0x7007, 0x0000, 0x1078, 0x1388, 0x007c, 0x700c, + 0xa005, 0x0040, 0x148e, 0x1078, 0x13d4, 0x007c, 0x0d7e, 0x7008, + 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, 0x682e, 0x783c, + 0x6832, 0x680b, 0x0100, 0x0d7f, 0x7007, 0x0000, 0x1078, 0x1388, + 0x007c, 0x137e, 0x147e, 0x157e, 0x2001, 0x6dc3, 0x2004, 0xa080, + 0x000d, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, + 0x53a5, 0x2001, 0x6dc5, 0x2004, 0xd0bc, 0x0040, 0x14c0, 0x2001, + 0x6dce, 0x2004, 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020, 0x53a5, + 0x157f, 0x147f, 0x137f, 0x7007, 0x0000, 0x1078, 0x396e, 0x1078, + 0x1388, 0x007c, 0x2001, 0x6df3, 0x2003, 0x0100, 0x7007, 0x0000, + 0x1078, 0x1388, 0x007c, 0x127e, 0x2091, 0x2100, 0x2079, 0x0030, + 0x2071, 0x6f42, 0x7003, 0x0000, 0x700f, 0x6f48, 0x7013, 0x6f48, + 0x780f, 0x0070, 0x127f, 0x007c, 0x6934, 0xa184, 0x0007, 0x0079, + 0x14e9, 0x14f1, 0x151b, 0x14f1, 0x14f1, 0x14f1, 0x1500, 0x14f1, + 0x14f5, 0xa085, 0x0001, 0x0078, 0x1531, 0x684c, 0xd0bc, 0x0040, + 0x14f1, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x0078, 0x1523, + 0xa18c, 0x00ff, 0xa186, 0x0015, 0x00c0, 0x14f1, 0x684c, 0xd0ac, + 0x0040, 0x14f1, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, + 0x000f, 0xa080, 0x1a82, 0x2004, 0x6832, 0xa006, 0x682e, 0x682a, + 0x6858, 0x0078, 0x152b, 0x684c, 0xd0ac, 0x0040, 0x14f1, 0xa006, + 0x682e, 0x682a, 0x6858, 0xa18c, 0x000f, 0xa188, 0x1a82, 0x210c, + 0x6932, 0x2d08, 0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, + 0x680a, 0x007c, 0x82ff, 0x0040, 0x1545, 0xa280, 0x0004, 0x0d7e, + 0x206c, 0x684c, 0xd0dc, 0x00c0, 0x1541, 0x1078, 0x14e4, 0x10c0, + 0x12b7, 0x6808, 0x8000, 0x680a, 0x0d7f, 0x127e, 0x047e, 0x037e, + 0x027e, 0x2091, 0x2100, 0x027f, 0x037f, 0x047f, 0x7000, 0xa005, + 0x00c0, 0x1559, 0x7206, 0x2001, 0x156d, 0x007e, 0x2260, 0x0078, + 0x164f, 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, 0x8108, + 0xa182, 0x6f63, 0x0048, 0x1566, 0x2009, 0x6f48, 0x710e, 0x7000, + 0xa005, 0x00c0, 0x156d, 0x1078, 0x1638, 0x127f, 0x007c, 0x127e, + 0x027e, 0x037e, 0x0c7e, 0x007e, 0x2091, 0x2100, 0x007f, 0x047f, + 0x037f, 0x027f, 0x0c7e, 0x0d7e, 0x2460, 0x6110, 0x2168, 0x6a62, + 0x6b5e, 0xa005, 0x0040, 0x15bc, 0x6808, 0xa005, 0x0040, 0x15ea, + 0x7000, 0xa005, 0x00c0, 0x158e, 0x0078, 0x15b4, 0x700c, 0x7110, + 0xa106, 0x00c0, 0x15ba, 0x7004, 0xa406, 0x00c0, 0x15b4, 0x2001, + 0x0005, 0x2004, 0xd08c, 0x00c0, 0x15ee, 0x2001, 0x0207, 0x2004, + 0xd09c, 0x00c0, 0x1597, 0x7804, 0xa084, 0x6000, 0x0040, 0x15ae, + 0xa086, 0x6000, 0x0040, 0x15ae, 0x0078, 0x1597, 0x7803, 0x0004, + 0x7003, 0x0000, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x5591, + 0x0078, 0x15ee, 0x0078, 0x15ee, 0x6808, 0xa005, 0x0040, 0x15ea, + 0x7000, 0xa005, 0x00c0, 0x15c6, 0x0078, 0x15ea, 0x700c, 0x7110, + 0xa106, 0x00c0, 0x15ba, 0x7004, 0xa406, 0x00c0, 0x15ea, 0x2001, + 0x0005, 0x2004, 0xd08c, 0x00c0, 0x15ee, 0x2001, 0x0207, 0x2004, + 0xd09c, 0x00c0, 0x15cf, 0x7804, 0xa084, 0x6000, 0x0040, 0x15e6, + 0xa086, 0x6000, 0x0040, 0x15e6, 0x0078, 0x15cf, 0x7803, 0x0004, + 0x7003, 0x0000, 0x2009, 0x0048, 0x1078, 0x5591, 0x0d7f, 0x0c7f, + 0x127f, 0x007c, 0x0f7e, 0x0e7e, 0x2071, 0x6f42, 0x7000, 0xa086, + 0x0000, 0x0040, 0x1635, 0x7004, 0xac06, 0x00c0, 0x1626, 0x2079, + 0x0030, 0x7804, 0xd0fc, 0x00c0, 0x1622, 0x2001, 0x0207, 0x2004, + 0xd09c, 0x00c0, 0x1601, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0, + 0x160d, 0x7908, 0xd1ec, 0x00c0, 0x1619, 0x2009, 0x0009, 0x0078, + 0x161b, 0x2009, 0x0019, 0x7803, 0x0002, 0x7902, 0x7003, 0x0003, + 0x0078, 0x1635, 0x1078, 0x16e5, 0x0078, 0x15f6, 0x157e, 0x20a9, + 0x0009, 0x2009, 0x6f48, 0x2104, 0xac06, 0x00c0, 0x1630, 0x200a, + 0xa188, 0x0003, 0x00f0, 0x162b, 0x157f, 0x0e7f, 0x0f7f, 0x007c, + 0x700c, 0x7110, 0xa106, 0x00c0, 0x1640, 0x7003, 0x0000, 0x007c, + 0x2104, 0x7006, 0x2060, 0x8108, 0x211c, 0x8108, 0x2124, 0x8108, + 0xa182, 0x6f63, 0x0048, 0x164e, 0x2009, 0x6f48, 0x7112, 0x8cff, + 0x00c0, 0x1658, 0x7803, 0x0019, 0x7003, 0x0003, 0x0078, 0x167b, + 0x6010, 0x2068, 0x2d58, 0x6828, 0xa406, 0x00c0, 0x1663, 0x682c, + 0xa306, 0x0040, 0x1667, 0x1078, 0x1aa2, 0x00c0, 0x1652, 0x6824, + 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, + 0x2009, 0x0011, 0x1078, 0x167c, 0x0040, 0x167a, 0x2009, 0x0001, + 0x1078, 0x167c, 0x2d58, 0x007c, 0x8aff, 0x0040, 0x16e0, 0xa03e, + 0x2730, 0x6850, 0xd0fc, 0x00c0, 0x169b, 0x0d7e, 0x2804, 0xac68, + 0x2900, 0x0079, 0x168b, 0x16ca, 0x16ab, 0x16ab, 0x16ca, 0x16ca, + 0x16c2, 0x16ca, 0x16ab, 0x16ca, 0x16b1, 0x16b1, 0x16ca, 0x16ca, + 0x16ca, 0x16ca, 0x16b1, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, + 0x6c20, 0x0d7e, 0xd99c, 0x0040, 0x16cd, 0x2804, 0xac68, 0x6f08, + 0x6e0c, 0x0078, 0x16cd, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0078, + 0x16cd, 0x7b0c, 0xd3bc, 0x0040, 0x16ba, 0x7b08, 0xa39c, 0x0fff, + 0x0078, 0x16bb, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, + 0x0078, 0x16cd, 0x0d7f, 0x1078, 0x1a3f, 0x00c0, 0x167c, 0xa00e, + 0x0078, 0x16e0, 0x0d7f, 0x1078, 0x12b7, 0x7b22, 0x7a26, 0x7d32, + 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x0d7f, + 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x1078, 0x1a3f, + 0x007c, 0x1078, 0x12b7, 0x1078, 0x12b7, 0x127e, 0x2091, 0x2100, + 0x007e, 0x017e, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, + 0xa184, 0x0700, 0x00c0, 0x16e3, 0xa184, 0x0003, 0xa086, 0x0003, + 0x0040, 0x16e3, 0x7000, 0x0079, 0x16fd, 0x1701, 0x1703, 0x1779, + 0x17c0, 0x1078, 0x12b7, 0x8001, 0x7002, 0xa184, 0x0880, 0x00c0, + 0x1718, 0x8aff, 0x0040, 0x175b, 0x2009, 0x0001, 0x1078, 0x167c, + 0x0040, 0x17d3, 0x2009, 0x0001, 0x1078, 0x167c, 0x0078, 0x17d3, + 0x7803, 0x0004, 0x7003, 0x0000, 0xd1dc, 0x0040, 0x1751, 0x027e, + 0x037e, 0x6b28, 0x6a2c, 0x7820, 0x686e, 0xa31a, 0x7824, 0x6872, + 0xa213, 0x6b2a, 0x6a2e, 0x037f, 0x027f, 0x7830, 0x681e, 0x7834, + 0x6822, 0x1078, 0x1a58, 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, + 0x6832, 0x7003, 0x0000, 0x6850, 0xc0fd, 0x6852, 0x6808, 0x8001, + 0x680a, 0x00c0, 0x174d, 0x684c, 0xd0e4, 0x0040, 0x174d, 0x7004, + 0x2060, 0x2009, 0x0048, 0x1078, 0x5591, 0x1078, 0x1638, 0x0078, + 0x17d3, 0x057e, 0x7d0c, 0xd5bc, 0x00c0, 0x1758, 0x1078, 0x6c41, + 0x057f, 0x0078, 0x1773, 0x684c, 0xc0f5, 0x684e, 0x7814, 0xa005, + 0x00c0, 0x1773, 0x7003, 0x0000, 0x6808, 0x8001, 0x680a, 0x00c0, + 0x176f, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x5591, 0x1078, + 0x1638, 0x0078, 0x17d3, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, + 0x17d3, 0x8001, 0x7002, 0xd194, 0x0040, 0x178b, 0x7804, 0xd0fc, + 0x00c0, 0x16ed, 0x8aff, 0x0040, 0x17d3, 0x2009, 0x0001, 0x1078, + 0x167c, 0x0078, 0x17d3, 0xa184, 0x0880, 0x00c0, 0x1798, 0x8aff, + 0x0040, 0x17d3, 0x2009, 0x0001, 0x1078, 0x167c, 0x0078, 0x17d3, + 0x7803, 0x0004, 0x7003, 0x0000, 0xd1dc, 0x0040, 0x17b9, 0x027e, + 0x037e, 0x6b28, 0x6a2c, 0x1078, 0x1a58, 0x0d7e, 0x2804, 0xac68, + 0x6034, 0xd09c, 0x00c0, 0x17b2, 0x6808, 0xa31a, 0x680c, 0xa213, + 0x0078, 0x17b6, 0x6810, 0xa31a, 0x6814, 0xa213, 0x0d7f, 0x0078, + 0x1723, 0x057e, 0x7d0c, 0x1078, 0x6c41, 0x057f, 0x0078, 0x1773, + 0x7003, 0x0000, 0x7004, 0xa00d, 0x0040, 0x17d1, 0x6808, 0x8001, + 0x680a, 0x00c0, 0x17d1, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, + 0x5591, 0x1078, 0x1638, 0x017f, 0x007f, 0x127f, 0x007c, 0x0e7e, + 0x2071, 0x6f63, 0x7003, 0x0000, 0x0e7f, 0x007c, 0x0d7e, 0xa280, + 0x0004, 0x206c, 0x694c, 0xd1dc, 0x00c0, 0x1836, 0x6934, 0xa184, + 0x0007, 0x0079, 0x17eb, 0x17f3, 0x1821, 0x17f3, 0x17f3, 0x17f3, + 0x1806, 0x17f3, 0x17f5, 0x1078, 0x12b7, 0x684c, 0xd0b4, 0x0040, + 0x192f, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, + 0x680a, 0x6880, 0x680e, 0x6958, 0x0078, 0x1829, 0xa18c, 0x00ff, + 0xa186, 0x0015, 0x00c0, 0x1836, 0x684c, 0xd0b4, 0x0040, 0x192f, + 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, + 0x1a82, 0x2004, 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, 0x0078, + 0x1832, 0x684c, 0xd0b4, 0x0040, 0x16e1, 0x6958, 0xa006, 0x682e, + 0x682a, 0x2d00, 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, 0x1a82, + 0x2004, 0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, 0x0d7f, 0x007c, + 0x0f7e, 0x2079, 0x0020, 0x7804, 0xd0fc, 0x10c0, 0x1933, 0x0e7e, + 0x0d7e, 0x2071, 0x6f63, 0x7000, 0xa005, 0x00c0, 0x18b2, 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, 0x1874, 0x017e, + 0x2009, 0x0008, 0xa102, 0x017f, 0xa108, 0x791a, 0x7116, 0x701e, + 0x680c, 0xa081, 0x0000, 0x781e, 0x701a, 0xa006, 0x700e, 0x7012, + 0x7004, 0x692c, 0x6814, 0xa106, 0x00c0, 0x188b, 0x6928, 0x6810, + 0xa106, 0x0040, 0x1898, 0x037e, 0x047e, 0x6b14, 0x6c10, 0x1078, + 0x1aa2, 0x047f, 0x037f, 0x0040, 0x1898, 0x0c7f, 0x0078, 0x18b2, + 0x8aff, 0x00c0, 0x18a0, 0x0c7f, 0xa085, 0x0001, 0x0078, 0x18b2, + 0x127e, 0x2091, 0x8000, 0x2079, 0x0020, 0x2009, 0x0001, 0x1078, + 0x18b6, 0x0040, 0x18af, 0x2009, 0x0001, 0x1078, 0x18b6, 0x127f, + 0x0c7f, 0xa006, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x077e, 0x067e, + 0x057e, 0x047e, 0x037e, 0x027e, 0x8aff, 0x0040, 0x1928, 0x700c, + 0x7214, 0xa202, 0x7010, 0x7218, 0xa203, 0x0048, 0x1927, 0xa03e, + 0x2730, 0x6850, 0xd0fc, 0x00c0, 0x18e3, 0x0d7e, 0x2804, 0xac68, + 0x2900, 0x0079, 0x18d3, 0x1909, 0x18f3, 0x18f3, 0x1909, 0x1909, + 0x1901, 0x1909, 0x18f3, 0x1909, 0x18f9, 0x18f9, 0x1909, 0x1909, + 0x1909, 0x1909, 0x18f9, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, + 0x6c20, 0xd99c, 0x0040, 0x190d, 0x0d7e, 0x2804, 0xac68, 0x6f08, + 0x6e0c, 0x0078, 0x190c, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0078, + 0x190c, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0078, + 0x190c, 0x0d7f, 0x1078, 0x1a3f, 0x00c0, 0x18bc, 0xa00e, 0x0078, + 0x1928, 0x0d7f, 0x1078, 0x12b7, 0x0d7f, 0x7b22, 0x7a26, 0x7d32, + 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x6828, + 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x700c, 0xa300, 0x700e, + 0x7010, 0xa201, 0x7012, 0x1078, 0x1a3f, 0x0078, 0x1928, 0xa006, + 0x027f, 0x037f, 0x047f, 0x057f, 0x067f, 0x077f, 0x007c, 0x1078, + 0x12b7, 0x1078, 0x12b7, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, + 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x2079, 0x0020, 0x2071, 0x6f63, + 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, + 0x00c0, 0x1931, 0x7000, 0x0079, 0x194d, 0x1a09, 0x1951, 0x19d6, + 0x1a07, 0x8001, 0x7002, 0xd19c, 0x00c0, 0x1965, 0x8aff, 0x0040, + 0x199a, 0x2009, 0x0001, 0x1078, 0x18b6, 0x0040, 0x1a09, 0x2009, + 0x0001, 0x1078, 0x18b6, 0x0078, 0x1a09, 0x7803, 0x0004, 0xd194, + 0x0040, 0x1975, 0x6850, 0xc0fc, 0x6852, 0x8aff, 0x00c0, 0x1990, + 0x684c, 0xc0f5, 0x684e, 0x0078, 0x1990, 0x027e, 0x037e, 0x6b28, + 0x6a2c, 0x701c, 0xa005, 0x10c0, 0x1a11, 0x7820, 0x686e, 0xa31a, + 0x7824, 0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x037f, 0x027f, 0x7830, + 0x681e, 0x7834, 0x6822, 0x1078, 0x1a58, 0x6850, 0xc0fd, 0x6852, + 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, + 0x0078, 0x1a09, 0x711c, 0x81ff, 0x0040, 0x19af, 0x7922, 0x7827, + 0x0000, 0x7803, 0x0001, 0x7000, 0x8000, 0x7002, 0x700c, 0xa100, + 0x700e, 0x7010, 0xa081, 0x0000, 0x7012, 0x0078, 0x1a09, 0x0f7e, + 0x027e, 0x781c, 0x007e, 0x7818, 0x007e, 0x2079, 0x0100, 0x7a14, + 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x7820, 0xd0bc, 0x00c0, + 0x19bd, 0x79c8, 0x007f, 0xa102, 0x78ca, 0x79c4, 0x007f, 0xa102, + 0x78c6, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x027f, 0x0f7f, + 0x7803, 0x0008, 0x7003, 0x0000, 0x0078, 0x1a09, 0x8001, 0x7002, + 0xd194, 0x0040, 0x19eb, 0x7804, 0xd0fc, 0x00c0, 0x1943, 0xd19c, + 0x00c0, 0x1a05, 0x8aff, 0x0040, 0x1a09, 0x2009, 0x0001, 0x1078, + 0x18b6, 0x0078, 0x1a09, 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x1078, + 0x1a58, 0x0d7e, 0x2804, 0xac68, 0x6034, 0xd09c, 0x00c0, 0x19fe, + 0x6808, 0xa31a, 0x680c, 0xa213, 0x0078, 0x1a02, 0x6810, 0xa31a, + 0x6814, 0xa213, 0x0d7f, 0x0078, 0x1979, 0x0078, 0x1975, 0x1078, + 0x12b7, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x017f, 0x007f, 0x127f, + 0x007c, 0x7920, 0xa108, 0x7922, 0x7924, 0xa189, 0x0000, 0x7926, + 0x7930, 0xa10a, 0x7932, 0x7934, 0xa18b, 0x0000, 0x7936, 0x007c, + 0x0f7e, 0x0e7e, 0x2071, 0x6f63, 0x7000, 0xa086, 0x0000, 0x0040, + 0x1a3c, 0x2079, 0x0020, 0x7804, 0xa084, 0x0003, 0x0040, 0x1a36, + 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0, 0x1a32, 0x20e1, 0x9040, + 0x7803, 0x0002, 0x7003, 0x0000, 0x0e7f, 0x0f7f, 0x007c, 0x8840, + 0x2804, 0xa005, 0x00c0, 0x1a53, 0x6004, 0xa005, 0x0040, 0x1a55, + 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x1a82, 0x2044, + 0x88ff, 0x1040, 0x12b7, 0x8a51, 0x007c, 0x2051, 0x0000, 0x007c, + 0x8a50, 0x8841, 0x2804, 0xa005, 0x00c0, 0x1a72, 0x2c00, 0xad06, + 0x0040, 0x1a67, 0x6000, 0xa005, 0x00c0, 0x1a67, 0x2d00, 0x2060, + 0x681a, 0x6034, 0xa084, 0x000f, 0xa080, 0x1a92, 0x2044, 0x88ff, + 0x1040, 0x12b7, 0x007c, 0x0000, 0x0011, 0x0015, 0x0019, 0x001d, + 0x0021, 0x0025, 0x0029, 0x0000, 0x000f, 0x0015, 0x001b, 0x0021, + 0x0027, 0x0000, 0x0000, 0x1a78, 0x1a74, 0x0000, 0x0000, 0x8000, + 0x0000, 0x1a78, 0x0000, 0x1a7f, 0x1a7c, 0x0000, 0x0000, 0x0000, + 0x0000, 0x1a7f, 0x0000, 0x1a7a, 0x1a7a, 0x0000, 0x0000, 0x8000, + 0x0000, 0x1a7a, 0x0000, 0x1a80, 0x1a80, 0x0000, 0x0000, 0x0000, + 0x0000, 0x1a80, 0x0a7e, 0x097e, 0x087e, 0x6858, 0xa055, 0x0040, + 0x1b28, 0x2d60, 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x1a82, 0xa986, + 0x0007, 0x0040, 0x1ab7, 0xa986, 0x000f, 0x00c0, 0x1abb, 0x605c, + 0xa422, 0x6060, 0xa31a, 0x2804, 0xa045, 0x00c0, 0x1ac9, 0x0050, + 0x1ac3, 0x0078, 0x1b28, 0x6004, 0xa065, 0x0040, 0x1b28, 0x0078, + 0x1aaa, 0x2804, 0xa005, 0x0040, 0x1ae7, 0xac68, 0xd99c, 0x00c0, + 0x1ad7, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0078, 0x1adb, 0x6810, + 0xa422, 0x6814, 0xa31b, 0x0048, 0x1af5, 0x2300, 0xa405, 0x0040, + 0x1aed, 0x8a51, 0x0040, 0x1b28, 0x8840, 0x0078, 0x1ac9, 0x6004, + 0xa065, 0x0040, 0x1b28, 0x0078, 0x1aaa, 0x8a51, 0x8840, 0x2b68, + 0x6850, 0xc0fc, 0x6852, 0x0078, 0x1b22, 0x8422, 0x8420, 0x831a, + 0xa399, 0x0000, 0x0d7e, 0x2b68, 0x6c6e, 0x6b72, 0x0d7f, 0xd99c, + 0x00c0, 0x1b10, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, + 0x1048, 0x12b7, 0x6800, 0xa420, 0x6804, 0xa319, 0x0078, 0x1b1c, + 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x1048, 0x12b7, + 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22, 0x6850, + 0xc0fd, 0x6852, 0x007f, 0x007f, 0x007f, 0xa006, 0x0078, 0x1b2d, + 0x087f, 0x097f, 0x0a7f, 0xa085, 0x0001, 0x007c, 0x2001, 0x0005, + 0x2004, 0xa084, 0x0007, 0x0079, 0x1b35, 0x1b3d, 0x1b3e, 0x1b41, + 0x1b44, 0x1b49, 0x1b4c, 0x1b51, 0x1b56, 0x007c, 0x1078, 0x1933, + 0x007c, 0x1078, 0x16e5, 0x007c, 0x1078, 0x16e5, 0x1078, 0x1933, + 0x007c, 0x1078, 0x143e, 0x007c, 0x1078, 0x1933, 0x1078, 0x143e, + 0x007c, 0x1078, 0x16e5, 0x1078, 0x143e, 0x007c, 0x1078, 0x16e5, + 0x1078, 0x1933, 0x1078, 0x143e, 0x007c, 0x127e, 0x2091, 0x2300, + 0x2079, 0x0200, 0x2071, 0x7280, 0x2069, 0x6d00, 0x2009, 0x0004, + 0x7912, 0x7916, 0x1078, 0x1df6, 0x781b, 0x0002, 0x20e1, 0x8700, + 0x127f, 0x007c, 0x127e, 0x2091, 0x2300, 0x781c, 0xa084, 0x0007, + 0x0079, 0x1b7a, 0x1b9e, 0x1b82, 0x1b86, 0x1b8a, 0x1b90, 0x1b94, + 0x1b98, 0x1b9c, 0x1078, 0x3d7c, 0x0078, 0x1b9e, 0x1078, 0x3db0, + 0x0078, 0x1b9e, 0x1078, 0x3d7c, 0x1078, 0x3db0, 0x0078, 0x1b9e, + 0x1078, 0x1ba0, 0x0078, 0x1b9e, 0x1078, 0x1ba0, 0x0078, 0x1b9e, + 0x1078, 0x1ba0, 0x0078, 0x1b9e, 0x1078, 0x1ba0, 0x127f, 0x007c, + 0x007e, 0x017e, 0x027e, 0x7930, 0xa184, 0x0003, 0x0040, 0x1baa, + 0x1078, 0x12b7, 0xa184, 0x0030, 0x0040, 0x1bbb, 0x6a00, 0xa286, + 0x0003, 0x00c0, 0x1bb5, 0x1078, 0x12b7, 0x1078, 0x31cb, 0x20e1, + 0x9010, 0x0078, 0x1bc7, 0xa184, 0x00c0, 0x0040, 0x1bc1, 0x1078, + 0x12b7, 0xa184, 0x0300, 0x0040, 0x1bc7, 0x20e1, 0x9020, 0x7932, + 0x027f, 0x017f, 0x007f, 0x007c, 0x017e, 0x0e7e, 0x0f7e, 0x2071, + 0x6d00, 0x7128, 0x2001, 0x6f03, 0x2102, 0x2001, 0x6f0b, 0x2102, + 0xa182, 0x0211, 0x00c8, 0x1be0, 0x2009, 0x0008, 0x0078, 0x1c0a, + 0xa182, 0x0259, 0x00c8, 0x1be8, 0x2009, 0x0007, 0x0078, 0x1c0a, + 0xa182, 0x02c1, 0x00c8, 0x1bf0, 0x2009, 0x0006, 0x0078, 0x1c0a, + 0xa182, 0x0349, 0x00c8, 0x1bf8, 0x2009, 0x0005, 0x0078, 0x1c0a, + 0xa182, 0x0421, 0x00c8, 0x1c00, 0x2009, 0x0004, 0x0078, 0x1c0a, + 0xa182, 0x0581, 0x00c8, 0x1c08, 0x2009, 0x0003, 0x0078, 0x1c0a, + 0x2009, 0x0002, 0x2079, 0x0200, 0x7912, 0x7916, 0x1078, 0x1df6, + 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x127e, 0x2091, 0x2200, 0x2061, + 0x0100, 0x2071, 0x6d00, 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, 0x6d2d, 0x2003, + 0x0000, 0x2001, 0x6d2c, 0x2003, 0x0001, 0x007c, 0x127e, 0x2091, + 0x2200, 0x007e, 0x017e, 0x027e, 0x6124, 0xa184, 0x002c, 0x00c0, + 0x1c4d, 0xa184, 0x0007, 0x0079, 0x1c53, 0xa195, 0x0004, 0xa284, + 0x0007, 0x0079, 0x1c53, 0x1c7f, 0x1c5b, 0x1c5f, 0x1c63, 0x1c69, + 0x1c6d, 0x1c73, 0x1c79, 0x1078, 0x4226, 0x0078, 0x1c7f, 0x1078, + 0x42e4, 0x0078, 0x1c7f, 0x1078, 0x42e4, 0x1078, 0x4226, 0x0078, + 0x1c7f, 0x1078, 0x1c84, 0x0078, 0x1c7f, 0x1078, 0x4226, 0x1078, + 0x1c84, 0x0078, 0x1c7f, 0x1078, 0x42e4, 0x1078, 0x1c84, 0x0078, + 0x1c7f, 0x1078, 0x42e4, 0x1078, 0x4226, 0x1078, 0x1c84, 0x027f, + 0x017f, 0x007f, 0x127f, 0x007c, 0xd1ac, 0x0040, 0x1d24, 0x017e, + 0x047e, 0x0c7e, 0x644c, 0x74ba, 0xa48c, 0xff00, 0xa196, 0xff00, + 0x0040, 0x1cb3, 0x6030, 0xa084, 0x00ff, 0x810f, 0xa116, 0x0040, + 0x1cb3, 0x7130, 0xd18c, 0x00c0, 0x1cb3, 0x2011, 0x6d52, 0x2214, + 0xd2ec, 0x0040, 0x1ca7, 0xc18d, 0x7132, 0x0078, 0x1cb3, 0x6240, + 0xa294, 0x0010, 0x0040, 0x1cf2, 0x6248, 0xa294, 0xff00, 0xa296, + 0xff00, 0x00c0, 0x1cf2, 0x2011, 0x8013, 0x1078, 0x2a53, 0x7130, + 0xc185, 0x7132, 0x2011, 0x6d52, 0x220c, 0xd1a4, 0x0040, 0x1cda, + 0x017e, 0x2009, 0x0001, 0x2011, 0x0100, 0x1078, 0x41f4, 0x2019, + 0x000e, 0x1078, 0x6b8f, 0xa484, 0x00ff, 0xa080, 0x2091, 0x200c, + 0xa18c, 0xff00, 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x1078, + 0x6bf7, 0x017f, 0xd1ac, 0x00c0, 0x1ce3, 0x2019, 0x0004, 0x1078, + 0x202f, 0x0078, 0x1cf2, 0x157e, 0x20a9, 0x007f, 0x2009, 0x0000, + 0x1078, 0x3447, 0x00c0, 0x1cee, 0x1078, 0x3256, 0x8108, 0x00f0, + 0x1ce8, 0x157f, 0x0c7f, 0x047f, 0x6043, 0x0000, 0x2009, 0x00f7, + 0x1078, 0x3233, 0x2011, 0x0003, 0x1078, 0x5232, 0x2011, 0x0002, + 0x1078, 0x523c, 0x1078, 0x5148, 0x1078, 0x414c, 0x037e, 0x2019, + 0x0000, 0x1078, 0x51da, 0x037f, 0x60e3, 0x0000, 0x017f, 0x2001, + 0x6d00, 0x2014, 0xa296, 0x0004, 0x00c0, 0x1d1c, 0xd19c, 0x00c0, + 0x1d1c, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0x6d20, + 0x2003, 0x0000, 0x6027, 0x0020, 0xd194, 0x0040, 0x1d9d, 0x017e, + 0x6220, 0xd2b4, 0x0040, 0x1d5b, 0x1078, 0x414c, 0x1078, 0x4fe5, + 0x6027, 0x0004, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, + 0x0040, 0x1d3e, 0x6803, 0x1000, 0x6803, 0x0000, 0x0d7f, 0x0c7e, + 0x2061, 0x6f10, 0x6028, 0xa09a, 0x0002, 0x00c8, 0x1d4e, 0x8000, + 0x602a, 0x0c7f, 0x1078, 0x4fd7, 0x0078, 0x1d9c, 0x2019, 0x6f19, + 0x2304, 0xa065, 0x0040, 0x1d58, 0x2009, 0x0014, 0x1078, 0x5591, + 0x0c7f, 0x0078, 0x1d9c, 0xd2bc, 0x0040, 0x1d9c, 0x1078, 0x415a, + 0x6017, 0x0010, 0x6027, 0x0004, 0x0d7e, 0x2069, 0x0140, 0x6804, + 0xa084, 0x4000, 0x0040, 0x1d70, 0x6803, 0x1000, 0x6803, 0x0000, + 0x0d7f, 0x0c7e, 0x2061, 0x6f10, 0x6044, 0xa09a, 0x0002, 0x00c8, + 0x1d91, 0x8000, 0x6046, 0x603c, 0x0c7f, 0xa005, 0x0040, 0x1d9c, + 0x1078, 0x4151, 0xa080, 0x0007, 0x2004, 0xa086, 0x0006, 0x00c0, + 0x1d8d, 0x6017, 0x0012, 0x0078, 0x1d9c, 0x6017, 0x0016, 0x0078, + 0x1d9c, 0x2019, 0x6f1f, 0x2304, 0xa065, 0x0040, 0x1d9b, 0x2009, + 0x004a, 0x1078, 0x5591, 0x0c7f, 0x017f, 0xd19c, 0x0040, 0x1dc5, + 0x017e, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x1078, 0x5232, + 0x2011, 0x0002, 0x1078, 0x523c, 0x1078, 0x5148, 0x1078, 0x414c, + 0x037e, 0x2019, 0x0000, 0x1078, 0x51da, 0x037f, 0x60e3, 0x0000, + 0x1078, 0x6c5f, 0x1078, 0x6c7d, 0x2001, 0x6d00, 0x2003, 0x0004, + 0x6027, 0x0008, 0x1078, 0x11aa, 0x017f, 0xa18c, 0xffd0, 0x6126, + 0x007c, 0x007e, 0x017e, 0x027e, 0x0e7e, 0x0f7e, 0x127e, 0x2091, + 0x8000, 0x2071, 0x6d00, 0x71b0, 0x70b2, 0xa116, 0x0040, 0x1def, + 0x81ff, 0x0040, 0x1de1, 0x2011, 0x8011, 0x1078, 0x2a53, 0x0078, + 0x1def, 0x2011, 0x8012, 0x1078, 0x2a53, 0x037e, 0x0c7e, 0x2061, + 0x0100, 0x2019, 0x0028, 0x1078, 0x202f, 0x0c7f, 0x037f, 0x127f, + 0x0f7f, 0x0e7f, 0x027f, 0x017f, 0x007f, 0x007c, 0x0c7e, 0x0f7e, + 0x007e, 0x027e, 0x2061, 0x0100, 0xa190, 0x1e09, 0x2204, 0x60f2, + 0xa190, 0x1e12, 0x2204, 0x60ee, 0x027f, 0x007f, 0x0f7f, 0x0c7f, + 0x007c, 0x083e, 0x083e, 0x083e, 0x0580, 0x0420, 0x0348, 0x02c0, + 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, 0x0140, 0x00f8, + 0x00d0, 0x00b0, 0x00a0, 0x2028, 0x2130, 0xa094, 0xff00, 0x00c0, + 0x1e24, 0x81ff, 0x0040, 0x1e28, 0x1078, 0x3f00, 0x0078, 0x1e2f, + 0xa080, 0x2091, 0x200c, 0xa18c, 0xff00, 0x810f, 0xa006, 0x007c, + 0xa080, 0x2091, 0x200c, 0xa18c, 0x00ff, 0x007c, 0x1e56, 0x1e5a, + 0x1e5e, 0x1e64, 0x1e6a, 0x1e70, 0x1e76, 0x1e7e, 0x1e86, 0x1e8c, + 0x1e92, 0x1e9a, 0x1ea2, 0x1eaa, 0x1eb2, 0x1ebc, 0x1ec6, 0x1ec6, + 0x1ec6, 0x1ec6, 0x1ec6, 0x1ec6, 0x1ec6, 0x1ec6, 0x1ec6, 0x1ec6, + 0x1ec6, 0x1ec6, 0x1ec6, 0x1ec6, 0x1ec6, 0x1ec6, 0x107e, 0x007e, + 0x0078, 0x1edf, 0x107e, 0x007e, 0x0078, 0x1edf, 0x107e, 0x007e, + 0x1078, 0x1c3e, 0x0078, 0x1edf, 0x107e, 0x007e, 0x1078, 0x1c3e, + 0x0078, 0x1edf, 0x107e, 0x007e, 0x1078, 0x1b2e, 0x0078, 0x1edf, + 0x107e, 0x007e, 0x1078, 0x1b2e, 0x0078, 0x1edf, 0x107e, 0x007e, + 0x1078, 0x1c3e, 0x1078, 0x1b2e, 0x0078, 0x1edf, 0x107e, 0x007e, + 0x1078, 0x1c3e, 0x1078, 0x1b2e, 0x0078, 0x1edf, 0x107e, 0x007e, + 0x1078, 0x1b72, 0x0078, 0x1edf, 0x107e, 0x007e, 0x1078, 0x1b72, + 0x0078, 0x1edf, 0x107e, 0x007e, 0x1078, 0x1c3e, 0x1078, 0x1b72, + 0x0078, 0x1edf, 0x107e, 0x007e, 0x1078, 0x1c3e, 0x1078, 0x1b72, + 0x0078, 0x1edf, 0x107e, 0x007e, 0x1078, 0x1b2e, 0x1078, 0x1b72, + 0x0078, 0x1edf, 0x107e, 0x007e, 0x1078, 0x1b2e, 0x1078, 0x1b72, + 0x0078, 0x1edf, 0x107e, 0x007e, 0x1078, 0x1c3e, 0x1078, 0x1b2e, + 0x1078, 0x1b72, 0x0078, 0x1edf, 0x107e, 0x007e, 0x1078, 0x1c3e, + 0x1078, 0x1b2e, 0x1078, 0x1b72, 0x0078, 0x1edf, 0x0005, 0x0078, + 0x1ec6, 0xb084, 0x003c, 0x8004, 0x8004, 0x0079, 0x1ecf, 0x1edf, + 0x1e5c, 0x1e60, 0x1e66, 0x1e6c, 0x1e72, 0x1e78, 0x1e80, 0x1e88, + 0x1e8e, 0x1e94, 0x1e9c, 0x1ea4, 0x1eac, 0x1eb4, 0x1ebe, 0x0008, + 0x1ec9, 0x007f, 0x107f, 0x2091, 0x8001, 0x007c, 0x0c7e, 0x027e, + 0x2041, 0x007e, 0x70bc, 0xd09c, 0x0040, 0x1ef0, 0x2041, 0x007f, + 0x2001, 0x010c, 0x203c, 0x727c, 0x82ff, 0x0040, 0x1f3b, 0x037e, + 0x738c, 0xa38e, 0xffff, 0x00c0, 0x1eff, 0x2019, 0x0001, 0x8314, + 0xa2e0, 0x73c0, 0x2c04, 0xa38c, 0x0001, 0x0040, 0x1f0c, 0xa084, + 0xff00, 0x8007, 0x0078, 0x1f0e, 0xa084, 0x00ff, 0xa70e, 0x0040, + 0x1f30, 0xa08e, 0x00ff, 0x0040, 0x1f36, 0x2009, 0x0000, 0x1078, + 0x1e1b, 0x1078, 0x3410, 0x00c0, 0x1f33, 0x6004, 0xa084, 0x00ff, + 0xa086, 0x0006, 0x00c0, 0x1f2a, 0x1078, 0x1f8d, 0x0040, 0x1f33, + 0x0078, 0x1f30, 0x1078, 0x208d, 0x1078, 0x1fb4, 0x0040, 0x1f33, + 0x8318, 0x0078, 0x1eff, 0x738e, 0x0078, 0x1f38, 0x708f, 0xffff, + 0x037f, 0x0078, 0x1f8a, 0xa780, 0x2091, 0x203c, 0xa7bc, 0xff00, + 0x873f, 0x708c, 0xa096, 0xffff, 0x0040, 0x1f4d, 0xa812, 0x00c8, + 0x1f5d, 0x708f, 0xffff, 0x0078, 0x1f87, 0x2009, 0x0000, 0x70bc, + 0xd09c, 0x0040, 0x1f58, 0xd094, 0x0040, 0x1f58, 0x2009, 0x007e, + 0x2100, 0xa802, 0x20a8, 0x0078, 0x1f61, 0x2008, 0x2810, 0xa202, + 0x20a8, 0x2700, 0x157e, 0x017e, 0xa106, 0x0040, 0x1f7e, 0x1078, + 0x3410, 0x00c0, 0x1f87, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x00c0, 0x1f78, 0x1078, 0x1f8d, 0x0040, 0x1f87, 0x0078, 0x1f7e, + 0x1078, 0x208d, 0x1078, 0x1fb4, 0x0040, 0x1f87, 0x017f, 0x8108, + 0x157f, 0x00f0, 0x1f61, 0x708f, 0xffff, 0x0078, 0x1f8a, 0x017f, + 0x157f, 0x718e, 0x027f, 0x0c7f, 0x007c, 0x017e, 0x077e, 0x0d7e, + 0x0c7e, 0x2c68, 0x1078, 0x5504, 0x0040, 0x1faf, 0x2d00, 0x601a, + 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x33df, 0x2001, 0x0000, + 0x1078, 0x33f3, 0x127e, 0x2091, 0x8000, 0x7088, 0x8000, 0x708a, + 0x127f, 0x2009, 0x0004, 0x1078, 0x5591, 0xa085, 0x0001, 0x0c7f, + 0x0d7f, 0x077f, 0x017f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, + 0x2c68, 0x1078, 0x5504, 0x0040, 0x1fd6, 0x2d00, 0x601a, 0x601f, + 0x0001, 0x2001, 0x0000, 0x1078, 0x33df, 0x2001, 0x0002, 0x1078, + 0x33f3, 0x127e, 0x2091, 0x8000, 0x7088, 0x8000, 0x708a, 0x127f, + 0x2009, 0x0002, 0x1078, 0x5591, 0xa085, 0x0001, 0x0c7f, 0x0d7f, + 0x077f, 0x017f, 0x007c, 0x0c7e, 0x027e, 0x2009, 0x0080, 0x1078, + 0x3410, 0x00c0, 0x1fe9, 0x1078, 0x1fec, 0x0040, 0x1fe9, 0x70c3, + 0xffff, 0x027f, 0x0c7f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, + 0x2c68, 0x1078, 0x5504, 0x0040, 0x200e, 0x2d00, 0x601a, 0x601f, + 0x0001, 0x2001, 0x0000, 0x1078, 0x33df, 0x2001, 0x0002, 0x1078, + 0x33f3, 0x127e, 0x2091, 0x8000, 0x70c4, 0x8000, 0x70c6, 0x127f, + 0x2009, 0x0002, 0x1078, 0x5591, 0xa085, 0x0001, 0x0c7f, 0x0d7f, + 0x077f, 0x017f, 0x007c, 0x0c7e, 0x0d7e, 0x2009, 0x007f, 0x1078, + 0x3410, 0x00c0, 0x202c, 0x2c68, 0x1078, 0x5504, 0x0040, 0x202c, + 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, 0x620a, 0x2009, 0x0022, + 0x1078, 0x5591, 0xa085, 0x0001, 0x0d7f, 0x0c7f, 0x007c, 0x0e7e, + 0x0c7e, 0x067e, 0x037e, 0x027e, 0x1078, 0x4463, 0x1078, 0x4417, + 0x1078, 0x59ce, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, + 0x3447, 0x00c0, 0x2047, 0x1078, 0x35cf, 0x1078, 0x3256, 0x017f, + 0x8108, 0x00f0, 0x203e, 0x027f, 0x037f, 0x067f, 0x0c7f, 0x0e7f, + 0x007c, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x6218, 0x2270, + 0x72a0, 0x027e, 0x2019, 0x0029, 0x1078, 0x445c, 0x1078, 0x43a9, + 0x2c08, 0x1078, 0x6a57, 0x017f, 0x2e60, 0x1078, 0x35cf, 0x1078, + 0x3256, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, + 0x007e, 0x6018, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x00c0, 0x2083, + 0x2071, 0x6d00, 0x7088, 0xa005, 0x0040, 0x2080, 0x8001, 0x708a, + 0x007f, 0x0e7f, 0x007c, 0x2071, 0x6d00, 0x70c4, 0xa005, 0x0040, + 0x2080, 0x8001, 0x70c6, 0x0078, 0x2080, 0x6000, 0xc08c, 0x6002, + 0x007c, 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, + 0x80da, 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, + 0x79ce, 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, + 0x77c5, 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, + 0x72b3, 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, + 0x6ea9, 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, + 0x809b, 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, + 0x8081, 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, + 0x8073, 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, + 0x5b69, 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, + 0x8056, 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, + 0x804c, 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, + 0x803c, 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, + 0x4831, 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, + 0x8026, 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, + 0x8017, 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, + 0x8000, 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, + 0x8000, 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x3300, 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x3100, 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, + 0x2c00, 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, + 0x2800, 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, + 0x8000, 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, + 0x8000, 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, + 0x1500, 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, + 0x8000, 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, + 0x8000, 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, + 0x8000, 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, + 0x8000, 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x0000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x2071, 0x6d6d, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, + 0x703a, 0x703e, 0x7033, 0x6d7d, 0x7037, 0x6d7d, 0x7007, 0x0001, + 0x2061, 0x6d9d, 0x6003, 0x0002, 0x007c, 0x0090, 0x21b8, 0x0068, + 0x21b8, 0x2071, 0x6d6d, 0x2b78, 0x7818, 0xd084, 0x00c0, 0x21b8, + 0x2a60, 0x7820, 0xa08e, 0x0069, 0x00c0, 0x229c, 0x0079, 0x223c, + 0x007c, 0x2071, 0x6d6d, 0x7004, 0x0079, 0x21be, 0x21c2, 0x21c3, + 0x21cd, 0x21df, 0x007c, 0x0090, 0x21cc, 0x0068, 0x21cc, 0x2b78, + 0x7818, 0xd084, 0x0040, 0x21eb, 0x007c, 0x2b78, 0x2061, 0x6d9d, + 0x6008, 0xa08e, 0x0100, 0x0040, 0x21da, 0xa086, 0x0200, 0x0040, + 0x2294, 0x007c, 0x7014, 0x2068, 0x2a60, 0x7018, 0x007a, 0x7010, + 0x2068, 0x6834, 0xa086, 0x0103, 0x0040, 0x21e7, 0x007c, 0x2a60, + 0x2b78, 0x7018, 0x007a, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x00c8, + 0x21f4, 0x61b0, 0x0079, 0x21fc, 0x2100, 0xa08a, 0x0033, 0x00c8, + 0x2290, 0x61b0, 0x0079, 0x223c, 0x2272, 0x22a4, 0x22ac, 0x22b0, + 0x22b8, 0x22be, 0x22c2, 0x22cb, 0x22cf, 0x22d7, 0x22db, 0x2290, + 0x2290, 0x2290, 0x22df, 0x2290, 0x22ef, 0x2306, 0x231d, 0x2399, + 0x239e, 0x23cb, 0x2416, 0x2425, 0x2446, 0x247c, 0x2486, 0x2493, + 0x24a6, 0x24be, 0x24c7, 0x2504, 0x250a, 0x2290, 0x251a, 0x2290, + 0x2290, 0x2290, 0x2290, 0x2290, 0x251e, 0x2524, 0x2290, 0x2290, + 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x252c, 0x2290, + 0x2290, 0x2290, 0x2290, 0x2290, 0x2539, 0x253f, 0x2290, 0x2290, + 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, + 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, + 0x2290, 0x2290, 0x2290, 0x2290, 0x22d7, 0x22db, 0x2290, 0x2290, + 0x2551, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, 0x2290, + 0x2290, 0x2290, 0x2290, 0x2290, 0x259e, 0x265d, 0x2671, 0x2678, + 0x26db, 0x2736, 0x2741, 0x2783, 0x2790, 0x279d, 0x27a0, 0x2555, + 0x27c9, 0x2811, 0x281e, 0x28fd, 0x29cb, 0x29f2, 0x2ade, 0x713c, + 0x0078, 0x2272, 0x2021, 0x4000, 0x1078, 0x2a2d, 0x127e, 0x2091, + 0x8000, 0x0068, 0x227f, 0x7818, 0xd084, 0x0040, 0x2282, 0x127f, + 0x0078, 0x2276, 0x781b, 0x0001, 0x7c22, 0x7926, 0x7a2a, 0x7b2e, + 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, 0x5000, 0x127f, 0x007c, + 0x2021, 0x4001, 0x0078, 0x2274, 0x2021, 0x4002, 0x0078, 0x2274, + 0x2021, 0x4003, 0x0078, 0x2274, 0x2021, 0x4005, 0x0078, 0x2274, + 0x2021, 0x4006, 0x0078, 0x2274, 0xa02e, 0x2520, 0x7b28, 0x7a2c, + 0x7824, 0x7930, 0x0078, 0x2a3c, 0x7823, 0x0004, 0x7824, 0x007a, + 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0078, 0x2a40, + 0x7924, 0x7828, 0x2114, 0x200a, 0x0078, 0x2272, 0x7924, 0x2114, + 0x0078, 0x2272, 0x2099, 0x0009, 0x20a1, 0x0009, 0x20a9, 0x0007, + 0x53a3, 0x0078, 0x2272, 0x7824, 0x2060, 0x0078, 0x22e1, 0x2009, + 0x0001, 0x2011, 0x000d, 0x2019, 0x0000, 0x0078, 0x2272, 0x7d38, + 0x7c3c, 0x0078, 0x22a6, 0x7d38, 0x7c3c, 0x0078, 0x22b2, 0x2061, + 0x1000, 0x610c, 0xa006, 0x2c14, 0xa200, 0x8c60, 0x8109, 0x00c0, + 0x22e3, 0x2010, 0xa005, 0x0040, 0x2272, 0x0078, 0x2298, 0x2061, + 0x6d51, 0x7824, 0x7930, 0xa11a, 0x00c8, 0x22a0, 0x8019, 0x0040, + 0x22a0, 0x604a, 0x6142, 0x782c, 0x6052, 0x7828, 0x6056, 0xa006, + 0x605a, 0x605e, 0x1078, 0x3890, 0x0078, 0x2272, 0x2061, 0x6d51, + 0x7824, 0x7930, 0xa11a, 0x00c8, 0x22a0, 0x8019, 0x0040, 0x22a0, + 0x604e, 0x6146, 0x782c, 0x6062, 0x7828, 0x6066, 0xa006, 0x606a, + 0x606e, 0x1078, 0x366e, 0x0078, 0x2272, 0xa02e, 0x2520, 0x81ff, + 0x00c0, 0x229c, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1, + 0x6d74, 0x41a1, 0x1078, 0x2a04, 0x0040, 0x229c, 0x2009, 0x0020, + 0x1078, 0x2a3c, 0x701b, 0x2335, 0x007c, 0x6834, 0x2008, 0xa084, + 0x00ff, 0xa096, 0x0011, 0x0040, 0x2341, 0xa096, 0x0019, 0x00c0, + 0x229c, 0x810f, 0xa18c, 0x00ff, 0x0040, 0x229c, 0x710e, 0x700c, + 0x8001, 0x0040, 0x2372, 0x700e, 0x1078, 0x2a04, 0x0040, 0x229c, + 0x2009, 0x0020, 0x2061, 0x6d9d, 0x6224, 0x6328, 0x642c, 0x6530, + 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, + 0x1078, 0x2a3c, 0x701b, 0x2365, 0x007c, 0x6834, 0xa084, 0x00ff, + 0xa096, 0x0002, 0x0040, 0x2370, 0xa096, 0x000a, 0x00c0, 0x229c, + 0x0078, 0x2347, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, 0x1078, + 0x3344, 0x00c0, 0x2380, 0x7007, 0x0003, 0x701b, 0x2382, 0x007c, + 0x1078, 0x372d, 0x127e, 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, + 0x6d74, 0x530a, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, + 0xa5a9, 0x0000, 0xad80, 0x000d, 0x2009, 0x0020, 0x127f, 0x0078, + 0x2a40, 0x6198, 0x7824, 0x609a, 0x0078, 0x2272, 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, 0x229c, 0x1078, 0x2a1c, + 0x0040, 0x22a0, 0x7c28, 0x7d2c, 0x1078, 0x3592, 0xd28c, 0x00c0, + 0x23dd, 0x1078, 0x3522, 0x0078, 0x23df, 0x1078, 0x355e, 0x00c0, + 0x2409, 0x2061, 0x7400, 0x127e, 0x2091, 0x8000, 0x6000, 0xa086, + 0x0000, 0x0040, 0x23f7, 0x6010, 0xa06d, 0x0040, 0x23f7, 0x683c, + 0xa406, 0x00c0, 0x23f7, 0x6840, 0xa506, 0x0040, 0x2402, 0x127f, + 0xace0, 0x0008, 0x2001, 0x6d15, 0x2004, 0xac02, 0x00c8, 0x229c, + 0x0078, 0x23e3, 0x1078, 0x5f5d, 0x127f, 0x0040, 0x229c, 0x0078, + 0x2272, 0xa00e, 0x2001, 0x0005, 0x1078, 0x372d, 0x127e, 0x2091, + 0x8000, 0x1078, 0x36a1, 0x127f, 0x0078, 0x2272, 0x81ff, 0x00c0, + 0x229c, 0x1078, 0x2a1c, 0x0040, 0x22a0, 0x1078, 0x34d7, 0x1078, + 0x35a3, 0x0040, 0x229c, 0x0078, 0x2272, 0x81ff, 0x00c0, 0x229c, + 0x1078, 0x2a1c, 0x0040, 0x22a0, 0x2031, 0x000f, 0x1078, 0x34d7, + 0x8631, 0x00c8, 0x242e, 0x2019, 0x0005, 0x1078, 0x35c4, 0x0040, + 0x229c, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x22a0, 0x8003, 0x800b, + 0x810b, 0xa108, 0x1078, 0x40de, 0x0078, 0x2272, 0x127e, 0x2091, + 0x8000, 0x81ff, 0x00c0, 0x2476, 0x2029, 0x00ff, 0x644c, 0x2400, + 0xa506, 0x0040, 0x2470, 0x2508, 0x1078, 0x3447, 0x00c0, 0x2470, + 0x2031, 0x000f, 0x1078, 0x34d7, 0x8631, 0x00c8, 0x245a, 0x2019, + 0x0004, 0x1078, 0x35c4, 0x0040, 0x2476, 0x7824, 0xa08a, 0x1000, + 0x00c8, 0x2479, 0x8003, 0x800b, 0x810b, 0xa108, 0x1078, 0x40de, + 0x8529, 0x00c8, 0x244f, 0x127f, 0x0078, 0x2272, 0x127f, 0x0078, + 0x229c, 0x127f, 0x0078, 0x22a0, 0x1078, 0x2a1c, 0x0040, 0x22a0, + 0x1078, 0x3507, 0x1078, 0x3592, 0x0078, 0x2272, 0x81ff, 0x00c0, + 0x229c, 0x1078, 0x2a1c, 0x0040, 0x22a0, 0x1078, 0x34f0, 0x1078, + 0x3592, 0x0078, 0x2272, 0x81ff, 0x00c0, 0x229c, 0x1078, 0x2a1c, + 0x0040, 0x22a0, 0x1078, 0x3561, 0x0040, 0x229c, 0x1078, 0x338c, + 0x1078, 0x351b, 0x1078, 0x3592, 0x0078, 0x2272, 0x1078, 0x2a1c, + 0x0040, 0x22a0, 0x1078, 0x34d7, 0x62a0, 0x2019, 0x0005, 0x0c7e, + 0x1078, 0x35cf, 0x0c7f, 0x1078, 0x445c, 0x1078, 0x43a9, 0x2c08, + 0x1078, 0x6a57, 0x1078, 0x3592, 0x0078, 0x2272, 0x1078, 0x2a1c, + 0x0040, 0x22a0, 0x1078, 0x3592, 0x2208, 0x0078, 0x2272, 0x157e, + 0x0d7e, 0x0e7e, 0x2069, 0x6ddf, 0x6810, 0x6914, 0xa10a, 0x00c8, + 0x24d3, 0x2009, 0x0000, 0x6816, 0x2011, 0x0000, 0x2019, 0x0000, + 0x20a9, 0x007e, 0x2069, 0x6e00, 0x2d04, 0xa075, 0x0040, 0x24e8, + 0x704c, 0x1078, 0x24f2, 0xa210, 0x7080, 0x1078, 0x24f2, 0xa318, + 0x8d68, 0x00f0, 0x24dc, 0x2300, 0xa218, 0x0e7f, 0x0d7f, 0x157f, + 0x0078, 0x2272, 0x0f7e, 0x017e, 0xa07d, 0x0040, 0x2501, 0x2001, + 0x0000, 0x8000, 0x2f0c, 0x81ff, 0x0040, 0x2501, 0x2178, 0x0078, + 0x24f9, 0x017f, 0x0f7f, 0x007c, 0x2069, 0x6ddf, 0x6910, 0x629c, + 0x0078, 0x2272, 0x81ff, 0x00c0, 0x229c, 0x614c, 0xa190, 0x2091, + 0x2214, 0xa294, 0x00ff, 0x6068, 0xa084, 0xff00, 0xa215, 0x6364, + 0x0078, 0x2272, 0x613c, 0x6240, 0x0078, 0x2272, 0x1078, 0x2a1c, + 0x0040, 0x22a0, 0x0078, 0x2272, 0x1078, 0x2a1c, 0x0040, 0x22a0, + 0x6244, 0x6338, 0x0078, 0x2272, 0x613c, 0x6240, 0x7824, 0x603e, + 0x7b28, 0x6342, 0x2069, 0x6d51, 0x831f, 0xa305, 0x6816, 0x0078, + 0x2272, 0x1078, 0x2a1c, 0x0040, 0x22a0, 0x0078, 0x2272, 0x1078, + 0x2a1c, 0x0040, 0x22a0, 0x7828, 0xa00d, 0x0040, 0x22a0, 0x782c, + 0xa005, 0x0040, 0x22a0, 0x6244, 0x6146, 0x6338, 0x603a, 0x0078, + 0x2272, 0x7d38, 0x7c3c, 0x0078, 0x231f, 0x7824, 0xa09c, 0x00ff, + 0xa39a, 0x0003, 0x00c8, 0x229c, 0x624c, 0xa084, 0xff00, 0x8007, + 0xa206, 0x00c0, 0x256d, 0x2001, 0x6d40, 0x2009, 0x000c, 0x7a2c, + 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x2a40, 0x81ff, 0x00c0, 0x229c, + 0x1078, 0x2a1c, 0x0040, 0x22a0, 0x6004, 0xa084, 0x00ff, 0xa086, + 0x0006, 0x00c0, 0x229c, 0x0c7e, 0x1078, 0x2a04, 0x0c7f, 0x0040, + 0x229c, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x6223, + 0x0040, 0x229c, 0x7007, 0x0003, 0x701b, 0x258f, 0x007c, 0x6830, + 0xa086, 0x0100, 0x0040, 0x229c, 0xad80, 0x000e, 0x2009, 0x000c, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x2a40, 0x1078, 0x2a04, + 0x0040, 0x229c, 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, + 0x1078, 0x2a3c, 0x701b, 0x25ad, 0x007c, 0xade8, 0x000d, 0x6800, + 0xa005, 0x0040, 0x22a0, 0x6804, 0xd0ac, 0x0040, 0x25ba, 0xd0a4, + 0x0040, 0x22a0, 0xd094, 0x0040, 0x25c5, 0x0c7e, 0x2061, 0x0100, + 0x6104, 0xa18c, 0xffdf, 0x6106, 0x0c7f, 0xd08c, 0x0040, 0x25d0, + 0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18d, 0x0010, 0x6106, 0x0c7f, + 0x2009, 0x0100, 0x210c, 0xa18a, 0x0002, 0x0048, 0x25e5, 0xd084, + 0x0040, 0x25e5, 0x6828, 0xa08a, 0x007f, 0x00c8, 0x22a0, 0xa088, + 0x2091, 0x210c, 0xa18c, 0x00ff, 0x6152, 0xd0dc, 0x0040, 0x25ee, + 0x6828, 0xa08a, 0x007f, 0x00c8, 0x22a0, 0x604e, 0x6808, 0xa08a, + 0x0100, 0x0048, 0x22a0, 0xa08a, 0x0841, 0x00c8, 0x22a0, 0xa084, + 0x0007, 0x00c0, 0x22a0, 0x680c, 0xa005, 0x0040, 0x22a0, 0x6810, + 0xa005, 0x0040, 0x22a0, 0x6848, 0x6940, 0xa10a, 0x00c8, 0x22a0, + 0x8001, 0x0040, 0x22a0, 0x684c, 0x6944, 0xa10a, 0x00c8, 0x22a0, + 0x8001, 0x0040, 0x22a0, 0x20a9, 0x001c, 0x2d98, 0x2069, 0x6d51, + 0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff, 0x613e, 0x8007, 0xa084, + 0x00ff, 0x6042, 0x1078, 0x3890, 0x1078, 0x366e, 0x6000, 0xa086, + 0x0000, 0x00c0, 0x265b, 0x6808, 0x602a, 0x1078, 0x1bcc, 0x6818, + 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, + 0x611a, 0x621e, 0x6322, 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, + 0x6312, 0x1078, 0x4168, 0x0c7e, 0x2061, 0x0100, 0x602f, 0x0040, + 0x602f, 0x0000, 0x0c7f, 0x60b4, 0xa005, 0x0040, 0x2657, 0x6003, + 0x0001, 0x2091, 0x301d, 0x1078, 0x31cb, 0x0078, 0x265b, 0x6003, + 0x0004, 0x2091, 0x301d, 0x0078, 0x2272, 0x6000, 0xa086, 0x0000, + 0x0040, 0x229c, 0x2069, 0x6d51, 0x7830, 0x6842, 0x7834, 0x6846, + 0x2d00, 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, + 0x2a40, 0x81ff, 0x00c0, 0x229c, 0x1078, 0x31cb, 0x0078, 0x2272, + 0x81ff, 0x00c0, 0x229c, 0x617c, 0x81ff, 0x0040, 0x2692, 0x703f, + 0x0000, 0x2001, 0x73c0, 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, + 0x7d38, 0x127e, 0x2091, 0x8000, 0x1078, 0x2a40, 0x701b, 0x226f, + 0x127f, 0x007c, 0x703f, 0x0001, 0x0d7e, 0x2069, 0x73c0, 0x20a9, + 0x0040, 0x20a1, 0x73c0, 0x2019, 0xffff, 0x43a4, 0x654c, 0xa588, + 0x2091, 0x210c, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, + 0x2100, 0xa506, 0x0040, 0x26c4, 0x1078, 0x3447, 0x00c0, 0x26c4, + 0x6014, 0x821c, 0x0048, 0x26bc, 0xa398, 0x73c0, 0xa085, 0xff00, + 0x8007, 0x201a, 0x0078, 0x26c3, 0xa398, 0x73c0, 0x2324, 0xa4a4, + 0xff00, 0xa405, 0x201a, 0x8210, 0x8108, 0xa182, 0x0080, 0x00c8, + 0x26cb, 0x0078, 0x26a8, 0x8201, 0x8007, 0x2d0c, 0xa105, 0x206a, + 0x0d7f, 0x20a9, 0x0040, 0x20a1, 0x73c0, 0x2099, 0x73c0, 0x1078, + 0x3213, 0x0078, 0x2681, 0x1078, 0x2a1c, 0x0040, 0x22a0, 0x0c7e, + 0x1078, 0x2a04, 0x0c7f, 0x0040, 0x229c, 0x2001, 0x6d52, 0x2004, + 0xd0b4, 0x0040, 0x2708, 0x6000, 0xd08c, 0x00c0, 0x2708, 0x6004, + 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2708, 0x6837, 0x0000, + 0x6838, 0xc0fd, 0x683a, 0x1078, 0x625b, 0x0040, 0x229c, 0x7007, + 0x0003, 0x701b, 0x2704, 0x007c, 0x1078, 0x2a1c, 0x0040, 0x22a0, + 0x20a9, 0x0029, 0x2c98, 0xade8, 0x0002, 0x2da0, 0x53a3, 0x20a9, + 0x0002, 0xac80, 0x0004, 0x2098, 0xad80, 0x0004, 0x20a0, 0x1078, + 0x3213, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, 0xad80, 0x0006, + 0x20a0, 0x1078, 0x3213, 0x20a9, 0x0004, 0xac80, 0x000a, 0x2098, + 0xad80, 0x000a, 0x20a0, 0x1078, 0x3213, 0x2d00, 0x2009, 0x0029, + 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x2a40, 0x81ff, 0x00c0, + 0x229c, 0x1078, 0x2a1c, 0x0040, 0x22a0, 0x1078, 0x35ae, 0x0078, + 0x2272, 0x81ff, 0x00c0, 0x229c, 0x7828, 0xa08a, 0x1000, 0x00c8, + 0x22a0, 0x1078, 0x2a1c, 0x0040, 0x22a0, 0x2031, 0x000f, 0x1078, + 0x34d7, 0x8631, 0x00c8, 0x274f, 0x2019, 0x0004, 0x1078, 0x35c4, + 0x7924, 0x810f, 0x7a28, 0x1078, 0x275f, 0x0078, 0x2272, 0xa186, + 0x00ff, 0x0040, 0x2767, 0x1078, 0x2777, 0x0078, 0x2776, 0x2029, + 0x007e, 0x2061, 0x6d00, 0x644c, 0x2400, 0xa506, 0x0040, 0x2773, + 0x2508, 0x1078, 0x2777, 0x8529, 0x00c8, 0x276c, 0x007c, 0x1078, + 0x3447, 0x00c0, 0x2782, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108, + 0x1078, 0x40de, 0x007c, 0x81ff, 0x00c0, 0x229c, 0x1078, 0x2a1c, + 0x0040, 0x22a0, 0x1078, 0x34d7, 0x1078, 0x35b9, 0x0078, 0x2272, + 0x81ff, 0x00c0, 0x229c, 0x1078, 0x2a1c, 0x0040, 0x22a0, 0x1078, + 0x34d7, 0x1078, 0x35a3, 0x0078, 0x2272, 0x6100, 0x0078, 0x2272, + 0x1078, 0x2a1c, 0x0040, 0x22a0, 0x6004, 0xa086, 0x0707, 0x0040, + 0x22a0, 0x2001, 0x6d00, 0x2004, 0xa086, 0x0003, 0x00c0, 0x229c, + 0x0d7e, 0xace8, 0x000a, 0x7924, 0xd184, 0x0040, 0x27b9, 0xace8, + 0x0006, 0x680c, 0x8007, 0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, + 0x831f, 0x6a00, 0x8217, 0x0d7f, 0x6100, 0xa18c, 0x0200, 0x0078, + 0x2272, 0x81ff, 0x00c0, 0x229c, 0x7828, 0xa08a, 0x1000, 0x00c8, + 0x22a0, 0x7924, 0xa184, 0x00ff, 0xa082, 0x0010, 0x00c8, 0x22a0, + 0xa18c, 0xff00, 0x810f, 0xa186, 0x00ff, 0x0040, 0x27e6, 0xa182, + 0x007f, 0x00c8, 0x22a0, 0x2100, 0x1078, 0x1e30, 0x027e, 0x0c7e, + 0x127e, 0x2091, 0x8000, 0x2061, 0x6f23, 0x601b, 0x0000, 0x601f, + 0x0000, 0x2061, 0x6d00, 0x6003, 0x0001, 0x2061, 0x0100, 0x6030, + 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, 0x6043, 0x0090, 0x6043, + 0x0010, 0x2009, 0x001e, 0x2011, 0x31f0, 0x1078, 0x415f, 0x7924, + 0x810f, 0x7a28, 0x1078, 0x275f, 0x127f, 0x0c7f, 0x027f, 0x0078, + 0x2272, 0x7924, 0xa18c, 0xff00, 0x810f, 0x0c7e, 0x1078, 0x3410, + 0x2c08, 0x0c7f, 0x00c0, 0x22a0, 0x0078, 0x2272, 0x81ff, 0x00c0, + 0x229c, 0x60bc, 0xd09c, 0x0040, 0x229c, 0x1078, 0x2a04, 0x0040, + 0x229c, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x2a3c, + 0x701b, 0x2833, 0x007c, 0x2009, 0x0080, 0x1078, 0x3447, 0x00c0, + 0x229c, 0x0d7e, 0xade8, 0x000d, 0x6900, 0x6a08, 0x6b0c, 0x6c10, + 0x6d14, 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0040, 0x28a7, 0xa0be, + 0x0112, 0x0040, 0x28a7, 0xa0be, 0x0113, 0x0040, 0x28a7, 0xa0be, + 0x0114, 0x0040, 0x28a7, 0xa0be, 0x0117, 0x0040, 0x28a7, 0xa0be, + 0x011a, 0x0040, 0x28a7, 0xa0be, 0x0121, 0x0040, 0x289d, 0xa0be, + 0x0131, 0x0040, 0x289d, 0xa0be, 0x0171, 0x0040, 0x28a7, 0xa0be, + 0x01a1, 0x00c0, 0x2870, 0x6830, 0x8007, 0x6832, 0x0078, 0x28ad, + 0xa0be, 0x0212, 0x0040, 0x28a3, 0xa0be, 0x0213, 0x0040, 0x28a3, + 0xa0be, 0x0214, 0x0040, 0x2895, 0xa0be, 0x0217, 0x0040, 0x288f, + 0xa0be, 0x021a, 0x00c0, 0x2889, 0x6838, 0x8007, 0x683a, 0x0078, + 0x28a7, 0xa0be, 0x0300, 0x0040, 0x28a7, 0x0078, 0x229c, 0xad80, + 0x0010, 0x20a9, 0x0007, 0x1078, 0x28d9, 0xad80, 0x000e, 0x20a9, + 0x0001, 0x1078, 0x28d9, 0x0078, 0x28a7, 0xad80, 0x000c, 0x1078, + 0x28e7, 0x0078, 0x28ad, 0xad80, 0x000e, 0x1078, 0x28e7, 0xad80, + 0x000c, 0x20a9, 0x0001, 0x1078, 0x28d9, 0x0c7e, 0x1078, 0x2a04, + 0x0040, 0x28ce, 0x6837, 0x0119, 0x684f, 0x0020, 0x685b, 0x0001, + 0x810b, 0x697e, 0x6883, 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, + 0x6996, 0x689b, 0x0000, 0x0c7f, 0x0d7f, 0x1078, 0x623f, 0x0040, + 0x229c, 0x7007, 0x0003, 0x701b, 0x28d2, 0x007c, 0x0c7f, 0x0d7f, + 0x0078, 0x229c, 0x6820, 0xa086, 0x8001, 0x0040, 0x229c, 0x0078, + 0x2272, 0x017e, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, + 0x8108, 0x280a, 0x8108, 0x00f0, 0x28db, 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, 0x229c, + 0x7924, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0081, 0x0048, 0x22a0, + 0xa182, 0x00ff, 0x00c8, 0x22a0, 0x7a2c, 0x7b28, 0x6064, 0xa306, + 0x00c0, 0x2918, 0x6068, 0xa206, 0x00c0, 0x2918, 0x0078, 0x22a0, + 0x0c7e, 0x1078, 0x297b, 0x2c68, 0x0c7f, 0x0040, 0x2939, 0xa0c6, + 0x4007, 0x00c0, 0x2926, 0x7c26, 0x0078, 0x2936, 0xa0c6, 0x4008, + 0x00c0, 0x292e, 0x7f26, 0x7e2a, 0x0078, 0x2936, 0xa0c6, 0x4009, + 0x00c0, 0x2934, 0x0078, 0x2936, 0x2001, 0x4006, 0x2020, 0x0078, + 0x2274, 0x017e, 0x0b7e, 0x0c7e, 0x0e7e, 0x2c70, 0x1078, 0x5504, + 0x0040, 0x2969, 0x2d00, 0x601a, 0x2e58, 0x0e7f, 0x0e7e, 0x0c7e, + 0x1078, 0x2a04, 0x0c7f, 0x2b70, 0x0040, 0x229c, 0x6837, 0x0000, + 0x2d00, 0x6012, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x33df, + 0x2001, 0x0002, 0x1078, 0x33f3, 0x127e, 0x2091, 0x8000, 0x7088, + 0x8000, 0x708a, 0x127f, 0x2009, 0x0002, 0x1078, 0x5591, 0xa085, + 0x0001, 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, 0x0040, 0x229c, 0x7007, + 0x0003, 0x701b, 0x2974, 0x007c, 0x6830, 0xa086, 0x0100, 0x00c0, + 0x2272, 0x0078, 0x229c, 0x0e7e, 0x0d7e, 0x2029, 0x0000, 0x2021, + 0x0081, 0x20a9, 0x007e, 0x2071, 0x6e81, 0x2e04, 0xa005, 0x00c0, + 0x298f, 0x2100, 0xa406, 0x0040, 0x29c0, 0x0078, 0x29b4, 0x2068, + 0x6f10, 0x2700, 0xa306, 0x00c0, 0x29a5, 0x6e14, 0x2600, 0xa206, + 0x00c0, 0x29a5, 0x2400, 0xa106, 0x00c0, 0x29a1, 0x2d60, 0x0078, + 0x29c6, 0x2001, 0x4007, 0x0078, 0x29c7, 0x2400, 0xa106, 0x00c0, + 0x29b4, 0x6e14, 0x87ff, 0x00c0, 0x29b0, 0x86ff, 0x0040, 0x29c0, + 0x2001, 0x4008, 0x0078, 0x29c7, 0x8420, 0x8e70, 0x00f0, 0x2985, + 0x2001, 0x4009, 0x0078, 0x29c7, 0x2001, 0x0001, 0x0078, 0x29c7, + 0x1078, 0x3410, 0x00c0, 0x29bc, 0x6312, 0x6216, 0xa006, 0xa005, + 0x0d7f, 0x0e7f, 0x007c, 0x81ff, 0x00c0, 0x229c, 0x1078, 0x2a04, + 0x0040, 0x229c, 0x6837, 0x0000, 0x7824, 0xa005, 0x0040, 0x22a0, + 0xa096, 0x00ff, 0x0040, 0x29e0, 0xa092, 0x0004, 0x00c8, 0x22a0, + 0x2010, 0x2d18, 0x1078, 0x2013, 0x0040, 0x229c, 0x7007, 0x0003, + 0x701b, 0x29eb, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x229c, + 0x0078, 0x2272, 0x7924, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0081, + 0x0048, 0x22a0, 0xa182, 0x00ff, 0x00c8, 0x22a0, 0x1078, 0x615b, + 0x1078, 0x342f, 0x0078, 0x2272, 0x1078, 0x12f4, 0x0040, 0x2a1b, + 0xa006, 0x6802, 0x7010, 0xa005, 0x00c0, 0x2a13, 0x2d00, 0x7012, + 0x7016, 0x0078, 0x2a19, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, + 0x7016, 0xad80, 0x000d, 0x007c, 0x7e24, 0x860f, 0xa18c, 0x00ff, + 0x1078, 0x3447, 0x00c0, 0x2a2a, 0xa6b4, 0x00ff, 0xa682, 0x0010, + 0x0048, 0x2a2b, 0xa066, 0x8cff, 0x007c, 0x017e, 0x7110, 0x81ff, + 0x0040, 0x2a38, 0x2168, 0x6904, 0x1078, 0x1328, 0x0078, 0x2a2f, + 0x7112, 0x7116, 0x017f, 0x007c, 0x2031, 0x0001, 0x0078, 0x2a42, + 0x2031, 0x0000, 0x2061, 0x6d9d, 0x6606, 0x6112, 0x600e, 0x6226, + 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x135f, 0x7007, 0x0002, + 0x701b, 0x2272, 0x007c, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079, + 0x0000, 0x2001, 0x6d7b, 0x2004, 0xa005, 0x00c0, 0x2a6e, 0x0068, + 0x2a6e, 0x7818, 0xd084, 0x00c0, 0x2a6e, 0x781b, 0x0001, 0x7a22, + 0x7b26, 0x7c2a, 0x2091, 0x4080, 0x0078, 0x2a93, 0x017e, 0x0c7e, + 0x0e7e, 0x2071, 0x6d6d, 0x7138, 0xa182, 0x0004, 0x0048, 0x2a7c, + 0x7030, 0x2060, 0x0078, 0x2a8d, 0x7030, 0xa0e0, 0x0008, 0xac82, + 0x6d9d, 0x0048, 0x2a85, 0x2061, 0x6d7d, 0x2c00, 0x7032, 0x81ff, + 0x00c0, 0x2a8b, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, + 0x0e7f, 0x0c7f, 0x017f, 0x127f, 0x0f7f, 0x007c, 0x0e7e, 0x2071, + 0x6d6d, 0x7038, 0xa005, 0x0040, 0x2acf, 0x127e, 0x2091, 0x8000, + 0x0068, 0x2ace, 0x0f7e, 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, + 0x2acd, 0x0c7e, 0x781b, 0x0001, 0x7034, 0x2060, 0x2c04, 0x7822, + 0x6004, 0x7826, 0x6008, 0x782a, 0x2091, 0x4080, 0x7038, 0x8001, + 0x703a, 0xa005, 0x00c0, 0x2ac3, 0x7033, 0x6d7d, 0x7037, 0x6d7d, + 0x0c7f, 0x0078, 0x2acd, 0xac80, 0x0008, 0xa0fa, 0x6d9d, 0x0048, + 0x2acb, 0x2001, 0x6d7d, 0x7036, 0x0c7f, 0x0f7f, 0x127f, 0x0e7f, + 0x007c, 0x027e, 0x2001, 0x6d52, 0x2004, 0xd0c4, 0x0040, 0x2adc, + 0x2011, 0x8014, 0x1078, 0x2a53, 0x027f, 0x007c, 0x81ff, 0x00c0, + 0x229c, 0x127e, 0x2091, 0x8000, 0x6030, 0xc08d, 0x6032, 0x1078, + 0x31cb, 0x127f, 0x0078, 0x2272, 0x127e, 0x0c7e, 0x0e7e, 0x2061, + 0x0100, 0x2071, 0x6d00, 0x6044, 0xd0a4, 0x00c0, 0x2b11, 0xd084, + 0x0040, 0x2afe, 0x1078, 0x2c34, 0x0078, 0x2b11, 0xd08c, 0x0040, + 0x2b05, 0x1078, 0x2b4b, 0x0078, 0x2b11, 0xd094, 0x0040, 0x2b0c, + 0x1078, 0x2b2c, 0x0078, 0x2b11, 0xd09c, 0x0040, 0x2b11, 0x1078, + 0x2b15, 0x0e7f, 0x0c7f, 0x127f, 0x007c, 0x6043, 0x0040, 0x6043, + 0x0000, 0x706f, 0x0000, 0x7087, 0x0001, 0x70a7, 0x0000, 0x2009, + 0x73c0, 0x200b, 0x0000, 0x7073, 0x000f, 0x2009, 0x000f, 0x2011, + 0x3187, 0x1078, 0x415f, 0x007c, 0x7070, 0xa005, 0x00c0, 0x2b4a, + 0x2011, 0x3187, 0x1078, 0x40d1, 0x6043, 0x0020, 0x6043, 0x0000, + 0x6044, 0xd08c, 0x00c0, 0x2b46, 0x7003, 0x0001, 0x7083, 0x0000, + 0x6043, 0x0090, 0x6043, 0x0010, 0x0078, 0x2b4a, 0x7077, 0x0000, + 0x0078, 0x2b4a, 0x007c, 0x7074, 0xa08a, 0x0003, 0x00c8, 0x2b54, + 0x1079, 0x2b57, 0x0078, 0x2b56, 0x1078, 0x12b7, 0x007c, 0x2b5a, + 0x2ba9, 0x2c33, 0x0f7e, 0x7077, 0x0001, 0x20e1, 0xa000, 0x20e1, + 0x8700, 0x1078, 0x1bcc, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2079, + 0x7200, 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, 0x720c, 0x207b, 0x1101, 0x7807, 0x0000, 0x2099, + 0x6d05, 0x20a1, 0x720e, 0x20a9, 0x0004, 0x53a3, 0x2079, 0x7212, + 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0x7200, 0x20a1, 0x020b, + 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, 0x1078, + 0x31b2, 0x0f7f, 0x707b, 0x0000, 0x6043, 0x0008, 0x6043, 0x0000, + 0x007c, 0x0d7e, 0x7078, 0x707b, 0x0000, 0xa025, 0x0040, 0x2c1d, + 0x6020, 0xd0b4, 0x00c0, 0x2c1b, 0x7184, 0x81ff, 0x0040, 0x2c04, + 0xa486, 0x000c, 0x00c0, 0x2c0f, 0xa480, 0x0018, 0x8004, 0x20a8, + 0x2011, 0x7280, 0x2019, 0x7200, 0x220c, 0x2304, 0xa106, 0x00c0, + 0x2bdb, 0x8210, 0x8318, 0x00f0, 0x2bc4, 0x6043, 0x0004, 0x608b, + 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x7077, 0x0002, 0x7083, + 0x0002, 0x0078, 0x2c1b, 0x2069, 0x7280, 0x6930, 0xa18e, 0x1101, + 0x00c0, 0x2c0f, 0x6834, 0xa005, 0x00c0, 0x2c0f, 0x6900, 0xa18c, + 0x00ff, 0x00c0, 0x2bef, 0x6804, 0xa005, 0x0040, 0x2c04, 0x2011, + 0x728e, 0x2019, 0x6d05, 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102, + 0x0048, 0x2c02, 0x00c0, 0x2c0f, 0x8210, 0x8318, 0x00f0, 0x2bf5, + 0x0078, 0x2c0f, 0x7087, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x2099, 0x7280, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043, + 0x0008, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x2c1b, 0x60c3, + 0x000c, 0x1078, 0x31b2, 0x0d7f, 0x007c, 0x6020, 0xd0b4, 0x00c0, + 0x2c1b, 0x60c3, 0x000c, 0x2011, 0x6f1a, 0x2013, 0x0000, 0x707b, + 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x1078, + 0x4fdc, 0x0078, 0x2c1b, 0x007c, 0x7080, 0xa08a, 0x001d, 0x00c8, + 0x2c3d, 0x1079, 0x2c40, 0x0078, 0x2c3f, 0x1078, 0x12b7, 0x007c, + 0x2c64, 0x2c73, 0x2ca6, 0x2cbb, 0x2ced, 0x2d17, 0x2d49, 0x2d73, + 0x2da5, 0x2dcb, 0x2e1a, 0x2e3c, 0x2e60, 0x2e76, 0x2e9c, 0x2eaf, + 0x2eb8, 0x2ed1, 0x2f01, 0x2f2b, 0x2f5b, 0x2f85, 0x2fce, 0x3003, + 0x3025, 0x3063, 0x3087, 0x30a0, 0x30ad, 0x7003, 0x0007, 0x6004, + 0xa084, 0xfff9, 0x6006, 0x007c, 0x608b, 0xbc94, 0x608f, 0xf0f0, + 0x6043, 0x0002, 0x7083, 0x0001, 0x2009, 0x07d0, 0x2011, 0x318e, + 0x1078, 0x40c4, 0x007c, 0x0f7e, 0x7078, 0xa086, 0x0014, 0x00c0, + 0x2ca4, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x2ca4, 0x2079, + 0x7280, 0x7a30, 0xa296, 0x1102, 0x00c0, 0x2ca2, 0x7834, 0xa005, + 0x00c0, 0x2ca2, 0x7a38, 0xd2fc, 0x0040, 0x2c98, 0x70a4, 0xa005, + 0x00c0, 0x2c98, 0x2019, 0x002a, 0x1078, 0x202f, 0x70a7, 0x0001, + 0x2011, 0x318e, 0x1078, 0x40d1, 0x7083, 0x0010, 0x1078, 0x2eb8, + 0x0078, 0x2ca4, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0003, + 0x6043, 0x0004, 0x1078, 0x321b, 0x20a3, 0x1102, 0x20a3, 0x0000, + 0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x2cb2, 0x60c3, 0x0014, + 0x1078, 0x31b2, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x2ceb, + 0x2011, 0x318e, 0x1078, 0x40d1, 0xa086, 0x0014, 0x00c0, 0x2ce7, + 0x2079, 0x7280, 0x7a30, 0xa296, 0x1102, 0x00c0, 0x2ce7, 0x7834, + 0xa005, 0x00c0, 0x2ce7, 0x7a38, 0xd2fc, 0x0040, 0x2ce1, 0x70a4, + 0xa005, 0x00c0, 0x2ce1, 0x2019, 0x002a, 0x1078, 0x202f, 0x70a7, + 0x0001, 0x7083, 0x0004, 0x1078, 0x2ced, 0x0078, 0x2ceb, 0x7083, + 0x0002, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0005, 0x1078, + 0x321b, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0x728e, + 0x706c, 0xa005, 0x00c0, 0x2d09, 0x714c, 0xa186, 0xffff, 0x0040, + 0x2d09, 0x1078, 0x3152, 0x0040, 0x2d09, 0x2019, 0x002a, 0x1078, + 0x202f, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x31b2, 0x007c, 0x0f7e, + 0x7078, 0xa005, 0x0040, 0x2d47, 0x2011, 0x318e, 0x1078, 0x40d1, + 0xa086, 0x0014, 0x00c0, 0x2d43, 0x2079, 0x7280, 0x7a30, 0xa296, + 0x1103, 0x00c0, 0x2d43, 0x7834, 0xa005, 0x00c0, 0x2d43, 0x7a38, + 0xd2fc, 0x0040, 0x2d3d, 0x70a4, 0xa005, 0x00c0, 0x2d3d, 0x2019, + 0x002a, 0x1078, 0x202f, 0x70a7, 0x0001, 0x7083, 0x0006, 0x1078, + 0x2d49, 0x0078, 0x2d47, 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f, + 0x007c, 0x7083, 0x0007, 0x1078, 0x321b, 0x20a3, 0x1104, 0x20a3, + 0x0000, 0x3430, 0x2011, 0x728e, 0x706c, 0xa005, 0x00c0, 0x2d65, + 0x7150, 0xa186, 0xffff, 0x0040, 0x2d65, 0xa180, 0x2091, 0x200c, + 0xa18c, 0xff00, 0x810f, 0x1078, 0x3152, 0x20a9, 0x0008, 0x2298, + 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, + 0x1078, 0x31b2, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x2da3, + 0x2011, 0x318e, 0x1078, 0x40d1, 0xa086, 0x0014, 0x00c0, 0x2d9f, + 0x2079, 0x7280, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x2d9f, 0x7834, + 0xa005, 0x00c0, 0x2d9f, 0x7a38, 0xd2fc, 0x0040, 0x2d99, 0x70a4, + 0xa005, 0x00c0, 0x2d99, 0x2019, 0x002a, 0x1078, 0x202f, 0x70a7, + 0x0001, 0x7083, 0x0008, 0x1078, 0x2da5, 0x0078, 0x2da3, 0x7083, + 0x0002, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0009, 0x1078, + 0x321b, 0x20a3, 0x1105, 0x20a3, 0x0100, 0x3430, 0x706c, 0xa005, + 0x00c0, 0x2db8, 0x1078, 0x30bc, 0x0040, 0x2dc8, 0x0078, 0x2dc2, + 0x20a9, 0x0008, 0x2099, 0x728e, 0x26a0, 0x53a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x31b2, 0x0078, 0x2dca, + 0x1078, 0x2c5d, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x2e18, + 0x2011, 0x318e, 0x1078, 0x40d1, 0xa086, 0x0014, 0x00c0, 0x2e14, + 0x2079, 0x7280, 0x7a30, 0xa296, 0x1105, 0x00c0, 0x2e14, 0x7834, + 0x2011, 0x0100, 0xa21e, 0x00c0, 0x2dfb, 0x7a38, 0xd2fc, 0x0040, + 0x2df3, 0x70a4, 0xa005, 0x00c0, 0x2df3, 0x2019, 0x002a, 0x1078, + 0x202f, 0x70a7, 0x0001, 0x707f, 0x0001, 0x7083, 0x000a, 0x1078, + 0x2e1a, 0x0078, 0x2e18, 0xa005, 0x00c0, 0x2e14, 0x7a38, 0xd2fc, + 0x0040, 0x2e0c, 0x70a4, 0xa005, 0x00c0, 0x2e0c, 0x2019, 0x002a, + 0x1078, 0x202f, 0x70a7, 0x0001, 0x707f, 0x0000, 0x7083, 0x000e, + 0x1078, 0x2e9c, 0x0078, 0x2e18, 0x7083, 0x0002, 0x707b, 0x0000, + 0x0f7f, 0x007c, 0x7083, 0x000b, 0x2011, 0x720e, 0x22a0, 0x20a9, + 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000, + 0x41a4, 0x1078, 0x321b, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x6030, + 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, 0x60c3, + 0x0084, 0x1078, 0x31b2, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, + 0x2e5e, 0x2011, 0x318e, 0x1078, 0x40d1, 0xa086, 0x0084, 0x00c0, + 0x2e5a, 0x2079, 0x7280, 0x7a30, 0xa296, 0x1106, 0x00c0, 0x2e5a, + 0x7834, 0xa005, 0x00c0, 0x2e5a, 0x7083, 0x000c, 0x1078, 0x2e60, + 0x0078, 0x2e5e, 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f, 0x007c, + 0x7083, 0x000d, 0x1078, 0x321b, 0x20a3, 0x1107, 0x20a3, 0x0000, + 0x2099, 0x728e, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x0084, 0x1078, 0x31b2, 0x007c, 0x0f7e, 0x7078, + 0xa005, 0x0040, 0x2e9a, 0x2011, 0x318e, 0x1078, 0x40d1, 0xa086, + 0x0084, 0x00c0, 0x2e96, 0x2079, 0x7280, 0x7a30, 0xa296, 0x1107, + 0x00c0, 0x2e96, 0x7834, 0xa005, 0x00c0, 0x2e96, 0x1078, 0x320d, + 0x7083, 0x000e, 0x1078, 0x2e9c, 0x0078, 0x2e9a, 0x7083, 0x0002, + 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x000f, 0x707b, 0x0000, + 0x608b, 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, + 0x2009, 0x07d0, 0x2011, 0x318e, 0x1078, 0x40c4, 0x007c, 0x7078, + 0xa005, 0x0040, 0x2eb7, 0x2011, 0x318e, 0x1078, 0x40d1, 0x007c, + 0x7083, 0x0011, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x7280, + 0x20a1, 0x020b, 0x7478, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, + 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014, 0x1078, 0x31b2, + 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x2eff, 0x2011, 0x318e, + 0x1078, 0x40d1, 0xa086, 0x0014, 0x00c0, 0x2efd, 0x2079, 0x7280, + 0x7a30, 0xa296, 0x1103, 0x00c0, 0x2efd, 0x7834, 0xa005, 0x00c0, + 0x2efd, 0x7a38, 0xd2fc, 0x0040, 0x2ef7, 0x70a4, 0xa005, 0x00c0, + 0x2ef7, 0x2019, 0x002a, 0x1078, 0x202f, 0x70a7, 0x0001, 0x7083, + 0x0012, 0x1078, 0x2f01, 0x0078, 0x2eff, 0x707b, 0x0000, 0x0f7f, + 0x007c, 0x7083, 0x0013, 0x1078, 0x3227, 0x20a3, 0x1103, 0x20a3, + 0x0000, 0x3430, 0x2011, 0x728e, 0x706c, 0xa005, 0x00c0, 0x2f1d, + 0x714c, 0xa186, 0xffff, 0x0040, 0x2f1d, 0x1078, 0x3152, 0x0040, + 0x2f1d, 0x2019, 0x002a, 0x1078, 0x202f, 0x20a9, 0x0008, 0x2298, + 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, + 0x1078, 0x31b2, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x2f59, + 0x2011, 0x318e, 0x1078, 0x40d1, 0xa086, 0x0014, 0x00c0, 0x2f57, + 0x2079, 0x7280, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x2f57, 0x7834, + 0xa005, 0x00c0, 0x2f57, 0x7a38, 0xd2fc, 0x0040, 0x2f51, 0x70a4, + 0xa005, 0x00c0, 0x2f51, 0x2019, 0x002a, 0x1078, 0x202f, 0x70a7, + 0x0001, 0x7083, 0x0014, 0x1078, 0x2f5b, 0x0078, 0x2f59, 0x707b, + 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0015, 0x1078, 0x3227, 0x20a3, + 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0x728e, 0x706c, 0xa006, + 0x00c0, 0x2f77, 0x7150, 0xa186, 0xffff, 0x0040, 0x2f77, 0xa180, + 0x2091, 0x200c, 0xa18c, 0xff00, 0x810f, 0x1078, 0x3152, 0x20a9, + 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0014, 0x1078, 0x31b2, 0x007c, 0x0f7e, 0x7078, 0xa005, + 0x0040, 0x2fcc, 0x2011, 0x318e, 0x1078, 0x40d1, 0xa086, 0x0014, + 0x00c0, 0x2fca, 0x2079, 0x7280, 0x7a30, 0xa296, 0x1105, 0x00c0, + 0x2fca, 0x7834, 0x2011, 0x0100, 0xa21e, 0x00c0, 0x2fb1, 0x7a38, + 0xd2fc, 0x0040, 0x2fad, 0x70a4, 0xa005, 0x00c0, 0x2fad, 0x2019, + 0x002a, 0x1078, 0x202f, 0x70a7, 0x0001, 0x707f, 0x0001, 0x0078, + 0x2fc4, 0xa005, 0x00c0, 0x2fca, 0x7a38, 0xd2fc, 0x0040, 0x2fc2, + 0x70a4, 0xa005, 0x00c0, 0x2fc2, 0x2019, 0x002a, 0x1078, 0x202f, + 0x70a7, 0x0001, 0x707f, 0x0000, 0x7083, 0x0016, 0x1078, 0x2fce, + 0x0078, 0x2fcc, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x2099, 0x7280, 0x20a1, 0x020b, 0x20a9, 0x000e, + 0x53a6, 0x3430, 0x2011, 0x728e, 0x707c, 0xa005, 0x0040, 0x2fe4, + 0x7083, 0x0017, 0x0078, 0x2fe6, 0x7083, 0x001b, 0x706c, 0xa005, + 0x00c0, 0x2ff0, 0x1078, 0x30bc, 0x0040, 0x3000, 0x0078, 0x2ffa, + 0x20a9, 0x0008, 0x2099, 0x728e, 0x26a0, 0x53a6, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x31b2, 0x0078, 0x3002, + 0x1078, 0x2c5d, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x3023, + 0x2011, 0x318e, 0x1078, 0x40d1, 0xa086, 0x0084, 0x00c0, 0x3021, + 0x2079, 0x7280, 0x7a30, 0xa296, 0x1106, 0x00c0, 0x3021, 0x7834, + 0xa005, 0x00c0, 0x3021, 0x7083, 0x0018, 0x1078, 0x3025, 0x0078, + 0x3023, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0019, 0x1078, + 0x3227, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430, 0x2099, 0x728e, + 0x2039, 0x720e, 0x27a0, 0x20a9, 0x0040, 0x53a3, 0x2728, 0x2514, + 0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, + 0xa205, 0x202a, 0x6030, 0x2310, 0x8214, 0xa2a0, 0x720e, 0x2414, + 0xa38c, 0x0001, 0x0040, 0x3050, 0xa294, 0xff00, 0x0078, 0x3053, + 0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, + 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, + 0x1078, 0x31b2, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x3085, + 0x2011, 0x318e, 0x1078, 0x40d1, 0xa086, 0x0084, 0x00c0, 0x3083, + 0x2079, 0x7280, 0x7a30, 0xa296, 0x1107, 0x00c0, 0x3083, 0x7834, + 0xa005, 0x00c0, 0x3083, 0x1078, 0x320d, 0x7083, 0x001a, 0x1078, + 0x3087, 0x0078, 0x3085, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, + 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x7280, 0x20a1, + 0x020b, 0x7478, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, + 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x1078, 0x31b2, 0x007c, + 0x7078, 0xa005, 0x0040, 0x30ac, 0x2011, 0x318e, 0x1078, 0x40d1, + 0x7083, 0x001c, 0x1078, 0x30ad, 0x007c, 0x707b, 0x0000, 0x608b, + 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0001, 0x2009, 0x07d0, 0x2011, + 0x318e, 0x1078, 0x40c4, 0x007c, 0x087e, 0x097e, 0x2029, 0x6d52, + 0x252c, 0x20a9, 0x0008, 0x2041, 0x720e, 0x28a0, 0x2099, 0x728e, + 0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0040, 0x30d2, + 0x2011, 0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, 0xffff, 0x00c0, + 0x30e4, 0xd5d4, 0x0040, 0x30df, 0x8210, 0x0078, 0x30e0, 0x8211, + 0x00f0, 0x30d2, 0x0078, 0x3149, 0x82ff, 0x00c0, 0x30f6, 0xd5d4, + 0x0040, 0x30f0, 0xa1a6, 0x3fff, 0x0040, 0x30dc, 0x0078, 0x30f4, + 0xa1a6, 0x3fff, 0x0040, 0x3149, 0xa18d, 0xc000, 0x20a9, 0x0010, + 0x2019, 0x0001, 0xd5d4, 0x0040, 0x30ff, 0x2019, 0x0010, 0x2120, + 0xd5d4, 0x0040, 0x3106, 0x8423, 0x0078, 0x3107, 0x8424, 0x00c8, + 0x3114, 0xd5d4, 0x0040, 0x310f, 0x8319, 0x0078, 0x3110, 0x8318, + 0x00f0, 0x3100, 0x0078, 0x3149, 0x23a8, 0x2021, 0x0001, 0x8426, + 0x8425, 0x00f0, 0x3118, 0x2328, 0x8529, 0xa2be, 0x0007, 0x0040, + 0x312c, 0x007e, 0x2039, 0x0007, 0x2200, 0xa73a, 0x007f, 0x27a8, + 0xa5a8, 0x0010, 0x00f0, 0x3128, 0x754e, 0xa5c8, 0x2091, 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, + 0x314f, 0xa006, 0x0078, 0x314f, 0xa006, 0x1078, 0x12b7, 0x097f, + 0x087f, 0x007c, 0x2118, 0x2021, 0x0000, 0x2001, 0x0007, 0xa39a, + 0x0010, 0x0048, 0x315f, 0x8420, 0x8001, 0x0078, 0x3157, 0x2118, + 0x84ff, 0x0040, 0x3168, 0xa39a, 0x0010, 0x8421, 0x00c0, 0x3163, + 0x2021, 0x0001, 0x83ff, 0x0040, 0x3171, 0x8423, 0x8319, 0x00c0, + 0x316d, 0xa238, 0x2704, 0xa42c, 0x00c0, 0x3186, 0xa405, 0x203a, + 0x714e, 0xa1a0, 0x2091, 0x242c, 0xa5ac, 0x00ff, 0x6532, 0x60e7, + 0x0000, 0x65ea, 0x706f, 0x0001, 0xa084, 0x0000, 0x007c, 0x0e7e, + 0x2071, 0x6d00, 0x7073, 0x0000, 0x0e7f, 0x007c, 0x0e7e, 0x0f7e, + 0x2079, 0x0100, 0x2071, 0x0140, 0x1078, 0x4fe5, 0x7004, 0xa084, + 0x4000, 0x0040, 0x319f, 0x7003, 0x1000, 0x7003, 0x0000, 0x127e, + 0x2091, 0x8000, 0x2071, 0x6d00, 0x7003, 0x0001, 0x2071, 0x6d20, + 0x2073, 0x0000, 0x7843, 0x0090, 0x7843, 0x0010, 0x127f, 0x0f7f, + 0x0e7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x2011, 0x6f1a, 0x2013, + 0x0000, 0x707b, 0x0000, 0x127f, 0x20e1, 0x9080, 0x60a3, 0x0056, + 0x60a7, 0x9575, 0x1078, 0x4fdc, 0x2009, 0x07d0, 0x2011, 0x318e, + 0x1078, 0x415f, 0x007c, 0x017e, 0x027e, 0x0c7e, 0x127e, 0x2091, + 0x8000, 0x2009, 0x00f7, 0x1078, 0x3233, 0x2061, 0x6f23, 0x601b, + 0x0000, 0x601f, 0x0000, 0x2061, 0x6d00, 0x6003, 0x0001, 0x2061, + 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x001e, 0x2011, + 0x31f0, 0x1078, 0x40c4, 0x127f, 0x0c7f, 0x027f, 0x017f, 0x007c, + 0x0e7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0x0100, 0x1078, + 0x4fe5, 0x2071, 0x0140, 0xa084, 0x4000, 0x0040, 0x3203, 0x7003, + 0x1000, 0x7003, 0x0000, 0x2001, 0x0001, 0x1078, 0x1dc9, 0x1078, + 0x31cb, 0x127f, 0x007f, 0x0e7f, 0x007c, 0x20a9, 0x0040, 0x20a1, + 0x73c0, 0x2099, 0x728e, 0x3304, 0x8007, 0x20a2, 0x9398, 0x94a0, + 0x00f0, 0x3213, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, + 0x7200, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x007c, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x2099, 0x7280, 0x20a1, 0x020b, 0x20a9, + 0x000c, 0x53a6, 0x007c, 0x0c7e, 0x007e, 0x2061, 0x0100, 0x810f, + 0x2001, 0x6d2c, 0x2004, 0xa005, 0x00c0, 0x3244, 0x6030, 0xa084, + 0x00ff, 0xa105, 0x0078, 0x3246, 0xa185, 0x00f7, 0x604a, 0x007f, + 0x0c7f, 0x007c, 0x157e, 0x20a9, 0x00ff, 0x2009, 0x6e00, 0xa006, + 0x200a, 0x8108, 0x00f0, 0x3250, 0x157f, 0x007c, 0x0d7e, 0x037e, + 0x157e, 0x137e, 0x147e, 0x2069, 0x6d51, 0xa006, 0x6002, 0x6007, + 0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x2091, 0x231c, 0xa39c, + 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, 0x23a0, 0x40a4, + 0x20a9, 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, 0x603e, 0x6042, + 0x604e, 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, 0x6066, 0x606a, + 0x606e, 0x6072, 0x6076, 0x607a, 0x607e, 0x6082, 0x6086, 0x608a, + 0x608e, 0x6092, 0x6096, 0x609a, 0x609e, 0x61a2, 0x604a, 0x6810, + 0x603a, 0x680c, 0x6046, 0x147f, 0x137f, 0x157f, 0x037f, 0x0d7f, + 0x007c, 0x127e, 0x2091, 0x8000, 0x6944, 0xa1b4, 0x00ff, 0xa682, + 0x0010, 0x00c8, 0x3337, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, + 0x00c8, 0x333d, 0xa188, 0x6e00, 0x2104, 0xa065, 0x0040, 0x3316, + 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x331c, 0x6078, + 0xa00d, 0x0040, 0x32c1, 0xa680, 0x6c84, 0x2004, 0xa10c, 0x00c0, + 0x3310, 0x607c, 0xa00d, 0x0040, 0x32dd, 0xa680, 0x6c84, 0x2004, + 0xa10c, 0x0040, 0x32dd, 0x694c, 0xd1fc, 0x00c0, 0x32d3, 0x1078, + 0x33d0, 0x0078, 0x330b, 0x1078, 0x33a1, 0x694c, 0xd1ec, 0x00c0, + 0x330b, 0x1078, 0x34f0, 0x0078, 0x330b, 0x694c, 0xa184, 0xa000, + 0x0040, 0x32fb, 0xd1ec, 0x0040, 0x32f4, 0xd1fc, 0x0040, 0x32ec, + 0x1078, 0x3507, 0x0078, 0x32f7, 0xa680, 0x6c84, 0x200c, 0x607c, + 0xa105, 0x607e, 0x0078, 0x32fb, 0xd1fc, 0x0040, 0x32fb, 0x1078, + 0x33a1, 0x0078, 0x330b, 0x6050, 0xa00d, 0x0040, 0x3306, 0x2d00, + 0x200a, 0x6803, 0x0000, 0x6052, 0x0078, 0x330b, 0x2d00, 0x6052, + 0x604e, 0x6803, 0x0000, 0x1078, 0x4346, 0xa006, 0x127f, 0x007c, + 0x2001, 0x0005, 0x2009, 0x0000, 0x0078, 0x3341, 0x2001, 0x0028, + 0x2009, 0x0000, 0x0078, 0x3341, 0xa082, 0x0006, 0x0048, 0x32b7, + 0x2009, 0x6d0c, 0x210c, 0xd18c, 0x0040, 0x332a, 0x2001, 0x0004, + 0x0078, 0x3333, 0xd184, 0x0040, 0x3331, 0x2001, 0x0004, 0x0078, + 0x3333, 0x2001, 0x0029, 0x2009, 0x0000, 0x0078, 0x3341, 0x2001, + 0x0029, 0x2009, 0x0000, 0x0078, 0x3341, 0x2001, 0x0029, 0x2009, + 0x0000, 0xa005, 0x127f, 0x007c, 0x6944, 0xa1b4, 0x00ff, 0xa682, + 0x0010, 0x00c8, 0x3386, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, + 0x00c8, 0x3376, 0xa188, 0x6e00, 0x2104, 0xa065, 0x0040, 0x3376, + 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x337c, 0x684c, + 0xd0ec, 0x0040, 0x3369, 0x1078, 0x3507, 0x1078, 0x33a1, 0x0078, + 0x3371, 0x1078, 0x33a1, 0x684c, 0xd0fc, 0x0040, 0x3371, 0x1078, + 0x34f0, 0x1078, 0x351b, 0xa006, 0x0078, 0x338a, 0x2001, 0x0028, + 0x2009, 0x0000, 0x0078, 0x338a, 0xa082, 0x0006, 0x0048, 0x335f, + 0x2001, 0x0029, 0x2009, 0x0000, 0x0078, 0x338a, 0x2001, 0x0029, + 0x2009, 0x0000, 0xa005, 0x007c, 0x127e, 0x2091, 0x8000, 0x6050, + 0xa00d, 0x0040, 0x339a, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, + 0x127f, 0x007c, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0078, + 0x3398, 0x127e, 0x2091, 0x8000, 0x604c, 0xa005, 0x0040, 0x33ad, + 0x6802, 0x2d00, 0x604e, 0x127f, 0x007c, 0x2d00, 0x6052, 0x604e, + 0x6803, 0x0000, 0x0078, 0x33ab, 0x127e, 0x2091, 0x8000, 0x604c, + 0xa06d, 0x0040, 0x33c2, 0x6800, 0xa005, 0x00c0, 0x33c0, 0x6052, + 0x604e, 0xad05, 0x127f, 0x007c, 0x604c, 0xa06d, 0x0040, 0x33cf, + 0x6800, 0xa005, 0x00c0, 0x33cd, 0x6052, 0x604e, 0xad05, 0x007c, + 0x6803, 0x0000, 0x6084, 0xa00d, 0x0040, 0x33da, 0x2d00, 0x200a, + 0x6086, 0x007c, 0x2d00, 0x6086, 0x6082, 0x0078, 0x33d9, 0x127e, + 0x0c7e, 0x027e, 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, + 0x0040, 0x33ed, 0xc285, 0x0078, 0x33ee, 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, 0x3419, 0xa085, 0x0001, 0x0078, + 0x342d, 0xa190, 0x6e00, 0x2204, 0xa065, 0x00c0, 0x342c, 0x017e, + 0x0d7e, 0x1078, 0x12f4, 0x2d60, 0x0d7f, 0x017f, 0x0040, 0x3415, + 0x2c00, 0x2012, 0x1078, 0x3256, 0xa006, 0x027f, 0x007c, 0x027e, + 0xa182, 0x00ff, 0x0048, 0x3438, 0xa085, 0x0001, 0x0078, 0x3445, + 0x0d7e, 0xa190, 0x6e00, 0x2204, 0xa06d, 0x0040, 0x3443, 0x2013, + 0x0000, 0x1078, 0x1328, 0x0d7f, 0xa006, 0x027f, 0x007c, 0x017e, + 0xa182, 0x00ff, 0x0048, 0x3450, 0xa085, 0x0001, 0x0078, 0x3457, + 0xa188, 0x6e00, 0x2104, 0xa065, 0x0040, 0x344c, 0xa006, 0x017f, + 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x600b, 0x0000, 0x600f, + 0x0000, 0x6000, 0xc08c, 0x6002, 0x2069, 0x728e, 0x6808, 0x605e, + 0x6810, 0x6062, 0x6138, 0xa10a, 0x0048, 0x346f, 0x603a, 0x6814, + 0x6066, 0x2099, 0x7296, 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, + 0x53a3, 0x2099, 0x729a, 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, + 0x53a3, 0x2069, 0x72ae, 0x6904, 0xa18c, 0x00ff, 0x810f, 0x6808, + 0xa084, 0x00ff, 0xa105, 0x606a, 0x690c, 0x616e, 0x6810, 0x6072, + 0x6818, 0x6076, 0xa182, 0x0211, 0x00c8, 0x349a, 0x2009, 0x0008, + 0x0078, 0x34c4, 0xa182, 0x0259, 0x00c8, 0x34a2, 0x2009, 0x0007, + 0x0078, 0x34c4, 0xa182, 0x02c1, 0x00c8, 0x34aa, 0x2009, 0x0006, + 0x0078, 0x34c4, 0xa182, 0x0349, 0x00c8, 0x34b2, 0x2009, 0x0005, + 0x0078, 0x34c4, 0xa182, 0x0421, 0x00c8, 0x34ba, 0x2009, 0x0004, + 0x0078, 0x34c4, 0xa182, 0x0581, 0x00c8, 0x34c2, 0x2009, 0x0003, + 0x0078, 0x34c4, 0x2009, 0x0002, 0x6192, 0x147f, 0x137f, 0x157f, + 0x0d7f, 0x007c, 0x0e7e, 0x2071, 0x728d, 0x2e04, 0x6896, 0x2071, + 0x728e, 0x7004, 0x689a, 0x701c, 0x689e, 0x0e7f, 0x007c, 0x2001, + 0x6c84, 0xa600, 0x2004, 0x127e, 0x2091, 0x8000, 0x6178, 0xa10d, + 0x617a, 0x127f, 0x007c, 0x2001, 0x6c84, 0xa600, 0x2004, 0x8002, + 0x127e, 0x2091, 0x8000, 0x6178, 0xa10c, 0x617a, 0x127f, 0x007c, + 0x2001, 0x6c84, 0xa600, 0x2004, 0x8002, 0x127e, 0x2091, 0x8000, + 0x617c, 0xa10c, 0x617e, 0x127f, 0x0078, 0x3500, 0x1078, 0x338c, + 0x1078, 0x3561, 0x00c0, 0x34fe, 0x1078, 0x351b, 0x007c, 0x2001, + 0x6c84, 0xa600, 0x2004, 0x127e, 0x2091, 0x8000, 0x617c, 0xa10d, + 0x617e, 0x127f, 0x0078, 0x3516, 0x1078, 0x33d0, 0x1078, 0x3525, + 0x00c0, 0x3514, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x4346, + 0x127f, 0x007c, 0xa01e, 0x0078, 0x3527, 0x2019, 0x0001, 0xa00e, + 0x127e, 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x00c0, + 0x3547, 0x8dff, 0x0040, 0x355c, 0x83ff, 0x0040, 0x353f, 0x6844, + 0xa084, 0x00ff, 0xa606, 0x0040, 0x354c, 0x0078, 0x3547, 0x683c, + 0xa406, 0x00c0, 0x3547, 0x6840, 0xa506, 0x0040, 0x354c, 0x2d08, + 0x6800, 0x2068, 0x0078, 0x3531, 0x6a00, 0x604c, 0xad06, 0x00c0, + 0x3554, 0x624e, 0x0078, 0x3557, 0xa180, 0x0000, 0x2202, 0x82ff, + 0x00c0, 0x355c, 0x6152, 0x8dff, 0x127f, 0x007c, 0xa01e, 0x0078, + 0x3563, 0x2019, 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x0040, + 0x3591, 0x83ff, 0x0040, 0x3574, 0x6844, 0xa084, 0x00ff, 0xa606, + 0x0040, 0x3581, 0x0078, 0x357c, 0x683c, 0xa406, 0x00c0, 0x357c, + 0x6840, 0xa506, 0x0040, 0x3581, 0x2d08, 0x6800, 0x2068, 0x0078, + 0x3566, 0x6a00, 0x6080, 0xad06, 0x00c0, 0x3589, 0x6282, 0x0078, + 0x358c, 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, 0x3591, 0x6186, + 0x8dff, 0x007c, 0x2001, 0x6c84, 0xa600, 0x2004, 0x6178, 0xa10c, + 0x0040, 0x359c, 0x2011, 0x0001, 0x617c, 0xa10c, 0x0040, 0x35a2, + 0xa295, 0x0002, 0x007c, 0x1078, 0x35ec, 0x0040, 0x35ab, 0x1078, + 0x61f8, 0x0078, 0x35ad, 0xa085, 0x0001, 0x007c, 0x1078, 0x35ec, + 0x0040, 0x35b6, 0x1078, 0x6187, 0x0078, 0x35b8, 0xa085, 0x0001, + 0x007c, 0x1078, 0x35ec, 0x0040, 0x35c1, 0x1078, 0x61cd, 0x0078, + 0x35c3, 0xa085, 0x0001, 0x007c, 0x1078, 0x35ec, 0x0040, 0x35cc, + 0x1078, 0x61a3, 0x0078, 0x35ce, 0xa085, 0x0001, 0x007c, 0x127e, + 0x007e, 0x0d7e, 0x2091, 0x8000, 0x6080, 0xa06d, 0x0040, 0x35e4, + 0x6800, 0x007e, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, + 0x36a1, 0x007f, 0x0078, 0x35d5, 0x6083, 0x0000, 0x6087, 0x0000, + 0x0d7f, 0x007f, 0x127f, 0x007c, 0x609c, 0xd0a4, 0x007c, 0x0f7e, + 0x2079, 0x6d51, 0x7804, 0xd0a4, 0x0040, 0x3618, 0x157e, 0x0c7e, + 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x3447, 0x00c0, + 0x360c, 0x6004, 0xa084, 0xff00, 0x8007, 0xa086, 0x0006, 0x00c0, + 0x360c, 0x6000, 0xc0ed, 0x6002, 0x017f, 0x8108, 0x00f0, 0x35fc, + 0x0c7f, 0x157f, 0x2009, 0x07d0, 0x2011, 0x361a, 0x1078, 0x415f, + 0x0f7f, 0x007c, 0x2011, 0x361a, 0x1078, 0x40d1, 0x157e, 0x0c7e, + 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x3447, 0x00c0, + 0x3646, 0x6000, 0xd0ec, 0x0040, 0x3646, 0x047e, 0x62a0, 0xa294, + 0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, 0x1078, 0x6bf7, 0x6000, + 0xc0e5, 0xc0ec, 0x6002, 0x2019, 0x0029, 0x1078, 0x445c, 0x1078, + 0x43a9, 0x2009, 0x0000, 0x1078, 0x6a57, 0x047f, 0x017f, 0x8108, + 0x00f0, 0x3624, 0x0c7f, 0x157f, 0x007c, 0x0c7e, 0x6018, 0x2060, + 0x6000, 0xc0ec, 0x6002, 0x0c7f, 0x007c, 0x2071, 0x6ddf, 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, + 0x6ddf, 0x684c, 0xa005, 0x00c0, 0x367c, 0x7028, 0xc085, 0x702a, + 0xa085, 0x0001, 0x0078, 0x369f, 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, 0x36f2, 0x6804, 0xa00d, + 0x0040, 0x36c0, 0x0d7e, 0x0e7e, 0x2071, 0x6d00, 0x027e, 0xa016, + 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x00c0, + 0x36b1, 0x702e, 0x70a0, 0xa200, 0x70a2, 0x027f, 0x0e7f, 0x0d7f, + 0x2071, 0x6ddf, 0x701c, 0xa005, 0x00c0, 0x3703, 0x0068, 0x3701, + 0x2071, 0x6d51, 0x7004, 0xd09c, 0x0040, 0x3701, 0x6934, 0xa186, + 0x0103, 0x00c0, 0x3714, 0x6948, 0x6844, 0xa105, 0x00c0, 0x36f4, + 0x2009, 0x8020, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x3701, + 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, + 0x4080, 0x2071, 0x6d00, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70a0, + 0x8000, 0x70a2, 0x0e7f, 0x007c, 0x6844, 0xa086, 0x0100, 0x00c0, + 0x3701, 0x6868, 0xa005, 0x00c0, 0x3701, 0x2009, 0x8020, 0x0078, + 0x36da, 0x2071, 0x6ddf, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, + 0x7012, 0x7018, 0xa06d, 0x711a, 0x0040, 0x3711, 0x6902, 0x0078, + 0x3712, 0x711e, 0x0078, 0x36f2, 0xa18c, 0x00ff, 0xa18e, 0x0017, + 0x0040, 0x371e, 0xa18e, 0x001f, 0x00c0, 0x3701, 0x684c, 0xd0cc, + 0x0040, 0x3701, 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0, + 0x3701, 0x2009, 0x8021, 0x0078, 0x36da, 0x007e, 0x6837, 0x0103, + 0x20a9, 0x001c, 0xad80, 0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, + 0x007f, 0x684a, 0x6952, 0x007c, 0x2071, 0x6ddf, 0x7004, 0x0079, + 0x3741, 0x3749, 0x3758, 0x37e4, 0x37e5, 0x37f5, 0x37fb, 0x374a, + 0x37d2, 0x007c, 0x127e, 0x2091, 0x8000, 0x0068, 0x3757, 0x2009, + 0x000d, 0x7030, 0x200a, 0x2091, 0x4080, 0x7007, 0x0001, 0x127f, + 0x701c, 0xa06d, 0x0040, 0x37d1, 0x0e7e, 0x2071, 0x6d51, 0x7004, + 0xd09c, 0x0040, 0x37b3, 0x6934, 0xa186, 0x0103, 0x00c0, 0x378d, + 0x6948, 0x6844, 0xa105, 0x00c0, 0x37a6, 0x2009, 0x8020, 0x127e, + 0x2091, 0x8000, 0x0068, 0x3789, 0x2071, 0x0000, 0x7018, 0xd084, + 0x00c0, 0x3789, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, + 0x0001, 0x2091, 0x4080, 0x127f, 0x0e7f, 0x1078, 0x382e, 0x0078, + 0x37d1, 0x127f, 0x0e7f, 0x0078, 0x37d1, 0xa18c, 0x00ff, 0xa18e, + 0x0017, 0x0040, 0x3797, 0xa18e, 0x001f, 0x00c0, 0x37b3, 0x684c, + 0xd0cc, 0x0040, 0x37b3, 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, + 0x00c0, 0x37b3, 0x2009, 0x8021, 0x0078, 0x376f, 0x6844, 0xa086, + 0x0100, 0x00c0, 0x37b3, 0x6868, 0xa005, 0x00c0, 0x37b3, 0x2009, + 0x8020, 0x0078, 0x376f, 0x0e7f, 0x1078, 0x3842, 0x0040, 0x37d1, + 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, 0x00c0, + 0x37c8, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0040, 0x37c8, 0x710e, + 0x7007, 0x0003, 0x1078, 0x3862, 0x7050, 0xa086, 0x0100, 0x0040, + 0x37e5, 0x007c, 0x701c, 0xa06d, 0x0040, 0x37e3, 0x1078, 0x3842, + 0x0040, 0x37e3, 0x7007, 0x0003, 0x1078, 0x3862, 0x7050, 0xa086, + 0x0100, 0x0040, 0x37e5, 0x007c, 0x007c, 0x7050, 0xa09e, 0x0100, + 0x00c0, 0x37ee, 0x7007, 0x0004, 0x0078, 0x37f5, 0xa086, 0x0200, + 0x00c0, 0x37f4, 0x7007, 0x0005, 0x007c, 0x1078, 0x37fc, 0x7006, + 0x1078, 0x382e, 0x007c, 0x007c, 0x702c, 0x7130, 0x8108, 0xa102, + 0x0048, 0x3809, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0078, + 0x3813, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x3813, 0x7070, + 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, 0x8001, 0x700e, 0x00c0, + 0x3827, 0x127e, 0x2091, 0x8000, 0x0068, 0x382a, 0x2001, 0x000d, + 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x127f, 0x007c, 0x2001, + 0x0007, 0x007c, 0x2001, 0x0006, 0x127f, 0x007c, 0x701c, 0xa06d, + 0x0040, 0x3841, 0x127e, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, + 0x2d04, 0x701e, 0xa005, 0x00c0, 0x383e, 0x701a, 0x127f, 0x1078, + 0x1328, 0x007c, 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e, 0x0040, + 0x3851, 0x2304, 0x230c, 0xa10e, 0x0040, 0x3851, 0xa006, 0x0078, + 0x3861, 0x732c, 0x8319, 0x7130, 0xa102, 0x00c0, 0x385b, 0x2300, + 0xa005, 0x0078, 0x3861, 0x0048, 0x3860, 0xa302, 0x0078, 0x3861, + 0x8002, 0x007c, 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, + 0x0000, 0x127e, 0x2091, 0x8000, 0x2009, 0x6f31, 0x2104, 0xc08d, + 0x200a, 0x127f, 0x1078, 0x1379, 0x007c, 0x2071, 0x6dad, 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, 0x6dad, 0x6848, 0xa005, 0x00c0, 0x389e, 0x7028, + 0xc085, 0x702a, 0xa085, 0x0001, 0x0078, 0x38c3, 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, 0x6dad, + 0x7004, 0x1079, 0x3923, 0x700c, 0x0079, 0x38ce, 0x38d3, 0x38c8, + 0x38c8, 0x38c8, 0x38c8, 0x007c, 0x700c, 0x0079, 0x38d7, 0x38dc, + 0x3921, 0x3921, 0x3922, 0x3922, 0x7830, 0x7930, 0xa106, 0x0040, + 0x38e6, 0x7830, 0x7930, 0xa106, 0x00c0, 0x390c, 0x7030, 0xa10a, + 0x0040, 0x390c, 0x00c8, 0x38ee, 0x712c, 0xa10a, 0xa18a, 0x0002, + 0x00c8, 0x390d, 0x1078, 0x12f4, 0x0040, 0x390c, 0x2d00, 0x705a, + 0x7063, 0x0040, 0x2001, 0x0003, 0x7057, 0x0000, 0x127e, 0x007e, + 0x2091, 0x8000, 0x2009, 0x6f31, 0x2104, 0xc085, 0x200a, 0x007f, + 0x700e, 0x127f, 0x1078, 0x1379, 0x007c, 0x1078, 0x12f4, 0x0040, + 0x390c, 0x2d00, 0x705a, 0x1078, 0x12f4, 0x00c0, 0x3919, 0x0078, + 0x38f8, 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, 0x0078, + 0x38fc, 0x007c, 0x007c, 0x3934, 0x3935, 0x396c, 0x396d, 0x3921, + 0x39a3, 0x39a8, 0x39df, 0x39e0, 0x39fb, 0x39fc, 0x39fd, 0x39fe, + 0x39ff, 0x3a00, 0x3a69, 0x3a93, 0x007c, 0x700c, 0x0079, 0x3938, + 0x393d, 0x3940, 0x3950, 0x396b, 0x396b, 0x1078, 0x38d4, 0x007c, + 0x127e, 0x8001, 0x700e, 0x7058, 0x007e, 0x1078, 0x3d52, 0x0040, + 0x394d, 0x2091, 0x8000, 0x1078, 0x38d4, 0x0d7f, 0x0078, 0x3959, + 0x127e, 0x8001, 0x700e, 0x1078, 0x3d52, 0x7058, 0x2068, 0x7084, + 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, + 0xa08a, 0x0020, 0x00c8, 0x3968, 0x1079, 0x3983, 0x127f, 0x007c, + 0x127f, 0x1078, 0x3a01, 0x007c, 0x007c, 0x007c, 0x0e7e, 0x2071, + 0x6dad, 0x700c, 0x0079, 0x3974, 0x3979, 0x3979, 0x3979, 0x397b, + 0x397f, 0x0e7f, 0x007c, 0x700f, 0x0001, 0x0078, 0x3981, 0x700f, + 0x0002, 0x0e7f, 0x007c, 0x3a01, 0x3a01, 0x3a1d, 0x3a01, 0x3aff, + 0x3a01, 0x3a01, 0x3a01, 0x3a01, 0x3a01, 0x3a1d, 0x3b44, 0x3b8d, + 0x3be5, 0x3bf8, 0x3a01, 0x3a01, 0x3a39, 0x3a1d, 0x3a01, 0x3a01, + 0x3a4f, 0x3c74, 0x3c91, 0x3a01, 0x3a39, 0x3a01, 0x3a01, 0x3a01, + 0x3a01, 0x3a01, 0x3c91, 0x7020, 0x2068, 0x1078, 0x1328, 0x007c, + 0x700c, 0x0079, 0x39ab, 0x39b0, 0x39b3, 0x39c3, 0x39de, 0x39de, + 0x1078, 0x38d4, 0x007c, 0x127e, 0x8001, 0x700e, 0x7058, 0x007e, + 0x1078, 0x3d52, 0x0040, 0x39c0, 0x2091, 0x8000, 0x1078, 0x38d4, + 0x0d7f, 0x0078, 0x39cc, 0x127e, 0x8001, 0x700e, 0x1078, 0x3d52, + 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, + 0x6834, 0xa084, 0x00ff, 0xa08a, 0x001a, 0x00c8, 0x39db, 0x1079, + 0x39e1, 0x127f, 0x007c, 0x127f, 0x1078, 0x3a01, 0x007c, 0x007c, + 0x007c, 0x3a01, 0x3a1d, 0x3ae9, 0x3a01, 0x3a1d, 0x3a01, 0x3a1d, + 0x3a1d, 0x3a01, 0x3a1d, 0x3ae9, 0x3a1d, 0x3a1d, 0x3a1d, 0x3a1d, + 0x3a1d, 0x3a01, 0x3a1d, 0x3ae9, 0x3a01, 0x3a01, 0x3a1d, 0x3a01, + 0x3a01, 0x3a01, 0x3a1d, 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, + 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a, + 0x127e, 0x2091, 0x8000, 0x1078, 0x36a1, 0x127f, 0x007c, 0x7007, + 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0e5, 0x683a, 0x127e, 0x2091, + 0x8000, 0x1078, 0x36a1, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, + 0xa084, 0x00ff, 0xc0ed, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, + 0x36a1, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, + 0xc0dd, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x36a1, 0x127f, + 0x007c, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0040, 0x3a0f, 0x8001, + 0x00c0, 0x3a46, 0x7007, 0x0001, 0x0078, 0x3ac8, 0x7007, 0x0006, + 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x3ac8, 0x007c, 0x2d00, + 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, 0x20a1, + 0x6dd8, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x00c8, 0x3a2b, + 0x6884, 0xa08a, 0x0003, 0x00c8, 0x3a2b, 0xa080, 0x3ab9, 0x2004, + 0x70c6, 0x7010, 0xa015, 0x0040, 0x3ab3, 0x1078, 0x12f4, 0x00c0, + 0x3a74, 0x7007, 0x000f, 0x007c, 0x2d00, 0x7022, 0x70c4, 0x2060, + 0x6000, 0x6836, 0x6004, 0xad00, 0x7096, 0x6008, 0xa20a, 0x00c8, + 0x3a83, 0xa00e, 0x2200, 0x7112, 0x620c, 0x8003, 0x800b, 0xa296, + 0x0004, 0x0040, 0x3a8c, 0xa108, 0x719a, 0x810b, 0x719e, 0xae90, + 0x0022, 0x1078, 0x135f, 0x7090, 0xa08e, 0x0100, 0x0040, 0x3aa7, + 0xa086, 0x0200, 0x0040, 0x3a9f, 0x7007, 0x0010, 0x007c, 0x7020, + 0x2068, 0x1078, 0x1328, 0x7014, 0x2068, 0x0078, 0x3a2b, 0x7020, + 0x2068, 0x7018, 0x6802, 0x6807, 0x0000, 0x2d08, 0x2068, 0x6906, + 0x711a, 0x0078, 0x3a69, 0x7014, 0x2068, 0x7007, 0x0001, 0x0078, + 0x3ac8, 0x3abc, 0x3ac0, 0x3ac4, 0x0002, 0x0011, 0x0007, 0x0004, + 0x000a, 0x000f, 0x0005, 0x0006, 0x0012, 0x000f, 0x0005, 0x0006, + 0x2009, 0x6d2c, 0x210c, 0x81ff, 0x00c0, 0x3ae3, 0x6838, 0xa084, + 0x00ff, 0x683a, 0x6853, 0x0000, 0x1078, 0x3299, 0x00c0, 0x3ad9, + 0x007c, 0x1078, 0x372d, 0x127e, 0x2091, 0x8000, 0x1078, 0x36a1, + 0x127f, 0x0078, 0x3ad8, 0x2001, 0x0028, 0x2009, 0x0000, 0x0078, + 0x3ad9, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, 0x711a, 0x7010, + 0x8001, 0x7012, 0x0040, 0x3af8, 0x7007, 0x0006, 0x0078, 0x3afe, + 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x107a, 0x007c, 0x7007, + 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, 0xa084, 0x00ff, + 0x20a9, 0x0001, 0xa096, 0x0001, 0x0040, 0x3b2a, 0x2009, 0x0000, + 0x20a9, 0x007e, 0xa096, 0x0002, 0x0040, 0x3b2a, 0xa005, 0x00c0, + 0x3b41, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x3447, 0x00c0, + 0x3b41, 0x067e, 0x6e44, 0xa6b4, 0x000f, 0x1078, 0x34e3, 0x067f, + 0x0078, 0x3b41, 0x047e, 0x2011, 0x6d0c, 0x2224, 0xc484, 0xc48c, + 0x2412, 0x047f, 0x0c7e, 0x1078, 0x3447, 0x00c0, 0x3b3d, 0x2091, + 0x8000, 0x607b, 0x0000, 0x2091, 0x8001, 0x8108, 0x00f0, 0x3b33, + 0x0c7f, 0x1078, 0x1328, 0x007c, 0x127e, 0x2091, 0x8000, 0x7007, + 0x0001, 0x2001, 0x6d52, 0x2004, 0xd0a4, 0x0040, 0x3b84, 0x6944, + 0x1078, 0x3d6e, 0x6100, 0xd184, 0x0040, 0x3b69, 0x6858, 0xa084, + 0x00ff, 0x00c0, 0x3b87, 0x6000, 0xd084, 0x0040, 0x3b84, 0x6004, + 0xa005, 0x00c0, 0x3b8a, 0x6003, 0x0000, 0x600b, 0x0000, 0x0078, + 0x3b81, 0x2011, 0x0001, 0x6860, 0xa005, 0x00c0, 0x3b71, 0x2001, + 0x001e, 0x8000, 0x6016, 0x6858, 0xa084, 0x00ff, 0x0040, 0x3b84, + 0x6006, 0x6858, 0x8007, 0xa084, 0x00ff, 0x0040, 0x3b84, 0x600a, + 0x6202, 0x127f, 0x0078, 0x3d41, 0x127f, 0x0078, 0x3d39, 0x127f, + 0x0078, 0x3d31, 0x127f, 0x0078, 0x3d35, 0x127e, 0x2091, 0x8000, + 0x7007, 0x0001, 0x2001, 0x6d52, 0x2004, 0xd0a4, 0x0040, 0x3be2, + 0x6944, 0x1078, 0x3d6e, 0x6000, 0xa084, 0x0001, 0x0040, 0x3be2, + 0x6204, 0x6308, 0x6c48, 0xa484, 0x0003, 0x0040, 0x3bba, 0x6958, + 0xa18c, 0x00ff, 0x8001, 0x00c0, 0x3bb3, 0x2100, 0xa210, 0x0048, + 0x3bdf, 0x0078, 0x3bba, 0x8001, 0x00c0, 0x3bdf, 0x2100, 0xa212, + 0x0048, 0x3bdf, 0xa484, 0x000c, 0x0040, 0x3bd4, 0x6958, 0x810f, + 0xa18c, 0x00ff, 0xa082, 0x0004, 0x00c0, 0x3bcc, 0x2100, 0xa318, + 0x0048, 0x3bdf, 0x0078, 0x3bd4, 0xa082, 0x0004, 0x00c0, 0x3bdf, + 0x2100, 0xa31a, 0x0048, 0x3bdf, 0x6860, 0xa005, 0x0040, 0x3bda, + 0x8000, 0x6016, 0x6206, 0x630a, 0x127f, 0x0078, 0x3d41, 0x127f, + 0x0078, 0x3d3d, 0x127f, 0x0078, 0x3d39, 0x127e, 0x2091, 0x8000, + 0x7007, 0x0001, 0x6944, 0x1078, 0x3d6e, 0x6308, 0x8318, 0x0048, + 0x3bf5, 0x630a, 0x127f, 0x0078, 0x3d4f, 0x127f, 0x0078, 0x3d3d, + 0x127e, 0x0c7e, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac, + 0x0040, 0x3c0c, 0x027e, 0x2009, 0x0000, 0x2011, 0xfcff, 0x1078, + 0x41f4, 0x027f, 0x0078, 0x3c42, 0x6858, 0xa005, 0x0040, 0x3c56, + 0x685c, 0xa065, 0x0040, 0x3c52, 0x2001, 0x6d2c, 0x2004, 0xa005, + 0x0040, 0x3c1e, 0x1078, 0x6283, 0x0078, 0x3c24, 0x6013, 0x0400, + 0x2009, 0x0041, 0x1078, 0x5591, 0x6958, 0xa18c, 0xe600, 0xa186, + 0x2000, 0x0040, 0x3c3a, 0xa186, 0x0400, 0x0040, 0x3c3a, 0x6944, + 0x0c7e, 0x1078, 0x416d, 0x6000, 0xa084, 0xfdff, 0x6002, 0x0c7f, + 0x0078, 0x3c42, 0x027e, 0x2009, 0x0000, 0x2011, 0xfdff, 0x1078, + 0x41f4, 0x027f, 0x684c, 0xd0c4, 0x0040, 0x3c4e, 0x6944, 0x1078, + 0x416d, 0x6008, 0x8000, 0x0048, 0x3c4e, 0x600a, 0x0c7f, 0x127f, + 0x0078, 0x3d41, 0x0c7f, 0x127f, 0x0078, 0x3d39, 0x6954, 0xa186, + 0x0020, 0x0040, 0x3c6c, 0xa186, 0x0029, 0x00c0, 0x3c52, 0x6944, + 0xa18c, 0xff00, 0x810f, 0x1078, 0x3447, 0x00c0, 0x3c42, 0x6000, + 0xc0e4, 0x6002, 0x0078, 0x3c42, 0x685c, 0xa065, 0x0040, 0x3c52, + 0x6017, 0x0014, 0x0078, 0x3c42, 0x6944, 0x1078, 0x3d6e, 0x6000, + 0xa084, 0x0001, 0x0040, 0x3c8d, 0x2091, 0x8000, 0x6204, 0x8210, + 0x0048, 0x3c87, 0x6206, 0x2091, 0x8001, 0x0078, 0x3d4f, 0x2091, + 0x8001, 0x6853, 0x0016, 0x0078, 0x3d48, 0x6853, 0x0007, 0x0078, + 0x3d48, 0x6834, 0x8007, 0xa084, 0x00ff, 0x00c0, 0x3c9b, 0x1078, + 0x3a0f, 0x0078, 0x3cad, 0x2030, 0x8001, 0x00c0, 0x3ca5, 0x7007, + 0x0001, 0x1078, 0x3cae, 0x0078, 0x3cad, 0x7007, 0x0006, 0x7012, + 0x2d00, 0x7016, 0x701a, 0x704b, 0x3cae, 0x007c, 0x0e7e, 0x2009, + 0x6d2c, 0x210c, 0x81ff, 0x00c0, 0x3d28, 0x6848, 0x2070, 0xae82, + 0x7400, 0x0048, 0x3d18, 0x2001, 0x6d15, 0x2004, 0xae02, 0x00c8, + 0x3d18, 0x6944, 0x1078, 0x3d6e, 0x6100, 0xa184, 0x0001, 0x0040, + 0x3cfe, 0xa184, 0x0100, 0x00c0, 0x3d1c, 0xa184, 0x0200, 0x00c0, + 0x3d20, 0x601c, 0xa005, 0x00c0, 0x3d24, 0x711c, 0xa186, 0x0006, + 0x00c0, 0x3d03, 0x6853, 0x0000, 0x6803, 0x0000, 0x2d08, 0x127e, + 0x2091, 0x8000, 0x7010, 0xa005, 0x00c0, 0x3cf5, 0x7112, 0x7018, + 0xa065, 0x0040, 0x3d28, 0x6000, 0xd0e4, 0x00c0, 0x3d2c, 0x2e60, + 0x1078, 0x4176, 0x127f, 0x0e7f, 0x007c, 0x2068, 0x6800, 0xa005, + 0x00c0, 0x3cf5, 0x6902, 0x127f, 0x0e7f, 0x007c, 0x0e7f, 0x6853, + 0x0006, 0x0078, 0x3d48, 0x6944, 0xa18c, 0xff00, 0x810f, 0x1078, + 0x3447, 0x00c0, 0x3d2c, 0x6000, 0xd0e4, 0x00c0, 0x3d2c, 0x711c, + 0xa186, 0x0007, 0x00c0, 0x3d18, 0x6853, 0x0002, 0x0078, 0x3d2e, + 0x6853, 0x0008, 0x0078, 0x3d2e, 0x6853, 0x000e, 0x0078, 0x3d2e, + 0x6853, 0x0017, 0x0078, 0x3d2e, 0x6853, 0x0035, 0x0078, 0x3d2e, + 0x6853, 0x0028, 0x0078, 0x3d2e, 0x6853, 0x0029, 0x0e7f, 0x0078, + 0x3d48, 0x2009, 0x003e, 0x0078, 0x3d43, 0x2009, 0x0004, 0x0078, + 0x3d43, 0x2009, 0x0006, 0x0078, 0x3d43, 0x2009, 0x0016, 0x0078, + 0x3d43, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00, 0xa105, 0x6856, + 0x2091, 0x8000, 0x1078, 0x36a1, 0x2091, 0x8001, 0x007c, 0x1078, + 0x1328, 0x007c, 0x702c, 0x7130, 0x8108, 0xa102, 0x0048, 0x3d5f, + 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0078, 0x3d6b, 0x7070, + 0xa080, 0x0040, 0x7072, 0x00c8, 0x3d6b, 0x7074, 0xa081, 0x0000, + 0x7076, 0xa085, 0x0001, 0x7932, 0x7132, 0x007c, 0x0d7e, 0x1078, + 0x416d, 0x0d7f, 0x007c, 0x0d7e, 0x2011, 0x0004, 0x2204, 0xa085, + 0x8002, 0x2012, 0x0d7f, 0x007c, 0x20e1, 0x0002, 0x3d08, 0x20e1, + 0x2000, 0x3d00, 0xa084, 0x7000, 0x0040, 0x3d8a, 0xa086, 0x1000, + 0x00c0, 0x3dab, 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x00c0, 0x3d91, + 0x3e60, 0xac84, 0x0007, 0x00c0, 0x3dab, 0xac82, 0x7400, 0x0048, + 0x3dab, 0x6854, 0xac02, 0x00c8, 0x3dab, 0x2009, 0x0047, 0x1078, + 0x5591, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x7a28, 0x7a1c, 0xd284, + 0x00c0, 0x3d7c, 0x007c, 0xa016, 0x1078, 0x1532, 0x0078, 0x3da1, + 0x157e, 0x137e, 0x147e, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584, + 0x0070, 0x00c0, 0x3dd9, 0xa484, 0x7000, 0xa086, 0x1000, 0x00c0, + 0x3dd9, 0x1078, 0x3de6, 0x0040, 0x3dd9, 0x20e1, 0x3000, 0x7828, + 0x7828, 0x1078, 0x3e04, 0x147f, 0x137f, 0x157f, 0x2009, 0x6f18, + 0x2104, 0xa005, 0x00c0, 0x3dd5, 0x007c, 0x1078, 0x476a, 0x0078, + 0x3dd4, 0x1078, 0x6c23, 0x1078, 0x3de6, 0x20e1, 0x3000, 0x7828, + 0x7828, 0x147f, 0x137f, 0x157f, 0x0078, 0x3dd4, 0xa484, 0x01ff, + 0x687a, 0xa005, 0x0040, 0x3df8, 0xa080, 0x001f, 0xa084, 0x03f8, + 0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x007c, + 0x20a9, 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, + 0xa085, 0x0001, 0x0078, 0x3df7, 0x7000, 0xa084, 0xff00, 0xa08c, + 0xf000, 0x8007, 0xa196, 0x0000, 0x00c0, 0x3e11, 0x0078, 0x3f51, + 0x007c, 0xa196, 0x2000, 0x00c0, 0x3e22, 0x6900, 0xa18e, 0x0001, + 0x00c0, 0x3e1e, 0x1078, 0x2aec, 0x0078, 0x3e10, 0x1078, 0x3e2a, + 0x0078, 0x3e10, 0xa196, 0x8000, 0x00c0, 0x3e10, 0x1078, 0x3fd7, + 0x0078, 0x3e10, 0x0c7e, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa196, + 0x0001, 0x0040, 0x3e37, 0xa196, 0x0023, 0x00c0, 0x3ef8, 0xa08e, + 0x0023, 0x00c0, 0x3e68, 0x1078, 0x404e, 0x0040, 0x3ef8, 0x7124, + 0x610a, 0x7030, 0xa08e, 0x0200, 0x00c0, 0x3e50, 0x7034, 0xa005, + 0x00c0, 0x3ef8, 0x2009, 0x0015, 0x1078, 0x5591, 0x0078, 0x3ef8, + 0xa08e, 0x0210, 0x00c0, 0x3e5a, 0x2009, 0x0015, 0x1078, 0x5591, + 0x0078, 0x3ef8, 0xa08e, 0x0100, 0x00c0, 0x3ef8, 0x7034, 0xa005, + 0x00c0, 0x3ef8, 0x2009, 0x0016, 0x1078, 0x5591, 0x0078, 0x3ef8, + 0xa08e, 0x0022, 0x00c0, 0x3ef8, 0x7030, 0xa08e, 0x0300, 0x00c0, + 0x3e79, 0x7034, 0xa005, 0x00c0, 0x3ef8, 0x2009, 0x0017, 0x0078, + 0x3eda, 0xa08e, 0x0500, 0x00c0, 0x3e85, 0x7034, 0xa005, 0x00c0, + 0x3ef8, 0x2009, 0x0018, 0x0078, 0x3eda, 0xa08e, 0x2010, 0x00c0, + 0x3e8d, 0x2009, 0x0019, 0x0078, 0x3eda, 0xa08e, 0x2110, 0x00c0, + 0x3e95, 0x2009, 0x001a, 0x0078, 0x3eda, 0xa08e, 0x5200, 0x00c0, + 0x3ea1, 0x7034, 0xa005, 0x00c0, 0x3ef8, 0x2009, 0x001b, 0x0078, + 0x3eda, 0xa08e, 0x5000, 0x00c0, 0x3ead, 0x7034, 0xa005, 0x00c0, + 0x3ef8, 0x2009, 0x001c, 0x0078, 0x3eda, 0xa08e, 0x2400, 0x00c0, + 0x3eb3, 0x0078, 0x3ed8, 0xa08e, 0x5300, 0x00c0, 0x3eb9, 0x0078, + 0x3ed8, 0xa08e, 0x0f00, 0x00c0, 0x3ec1, 0x2009, 0x0020, 0x0078, + 0x3eda, 0xa08e, 0x5300, 0x00c0, 0x3ec7, 0x0078, 0x3ed8, 0xa08e, + 0x6104, 0x00c0, 0x3ed8, 0x2009, 0x728e, 0x2011, 0x8015, 0x211c, + 0x8108, 0x2124, 0x1078, 0x2a53, 0x2009, 0x0023, 0x0078, 0x3eda, + 0x2009, 0x001d, 0x017e, 0x2011, 0x7283, 0x2204, 0x8211, 0x220c, + 0x1078, 0x1e1b, 0x00c0, 0x3efa, 0x1078, 0x3410, 0x00c0, 0x3efa, + 0x6612, 0x6516, 0x0c7e, 0x1078, 0x5504, 0x0040, 0x3efd, 0x017f, + 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, 0x1078, 0x5591, + 0x0c7f, 0x007c, 0x017f, 0x0078, 0x3ef8, 0x0c7f, 0x0078, 0x3efa, + 0x0e7e, 0x0d7e, 0x2028, 0x2130, 0xa696, 0x00ff, 0x00c0, 0x3f20, + 0xa596, 0xfffd, 0x00c0, 0x3f10, 0x2009, 0x007f, 0x0078, 0x3f4d, + 0xa596, 0xfffe, 0x00c0, 0x3f18, 0x2009, 0x007e, 0x0078, 0x3f4d, + 0xa596, 0xfffc, 0x00c0, 0x3f20, 0x2009, 0x0080, 0x0078, 0x3f4d, + 0x2011, 0x0000, 0x2021, 0x007e, 0x20a9, 0x0082, 0x2071, 0x6e7e, + 0x2e1c, 0x83ff, 0x00c0, 0x3f32, 0x82ff, 0x00c0, 0x3f41, 0x2410, + 0x0078, 0x3f41, 0x2368, 0x6b10, 0x007e, 0x2100, 0xa31e, 0x007f, + 0x00c0, 0x3f41, 0x6b14, 0xa31e, 0x00c0, 0x3f41, 0x2408, 0x0078, + 0x3f4d, 0x8420, 0x8e70, 0x00f0, 0x3f28, 0x82ff, 0x00c0, 0x3f4c, + 0xa085, 0x0001, 0x0078, 0x3f4e, 0x2208, 0xa006, 0x0d7f, 0x0e7f, + 0x007c, 0xa084, 0x0007, 0x0079, 0x3f56, 0x007c, 0x3f5e, 0x3f5e, + 0x3f5e, 0x3f5e, 0x3f5e, 0x3f5f, 0x3f78, 0x3fc0, 0x007c, 0x7110, + 0xd1bc, 0x0040, 0x3f77, 0x7120, 0x2160, 0xac8c, 0x0007, 0x00c0, + 0x3f77, 0xac8a, 0x7400, 0x0048, 0x3f77, 0x6854, 0xac02, 0x00c8, + 0x3f77, 0x7124, 0x610a, 0x2009, 0x0046, 0x1078, 0x5591, 0x007c, + 0x0c7e, 0x7110, 0xd1bc, 0x00c0, 0x3fbe, 0x2011, 0x7283, 0x2204, + 0x8211, 0x220c, 0x1078, 0x1e1b, 0x00c0, 0x3fbe, 0x1078, 0x3447, + 0x00c0, 0x3fbe, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, + 0x00c0, 0x3fa3, 0x0c7e, 0x1078, 0x5504, 0x017f, 0x0040, 0x3fbe, + 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x2009, 0x0044, 0x1078, + 0x5591, 0x0078, 0x3fbe, 0x0c7e, 0x1078, 0x5504, 0x017f, 0x0040, + 0x3fbe, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004, + 0x00c0, 0x3fb6, 0x6007, 0x0005, 0x0078, 0x3fb8, 0x6007, 0x0001, + 0x6003, 0x0001, 0x1078, 0x4376, 0x1078, 0x476a, 0x0c7f, 0x007c, + 0x7110, 0xd1bc, 0x0040, 0x3fd6, 0x7020, 0x2060, 0xac84, 0x0007, + 0x00c0, 0x3fd6, 0xac82, 0x7400, 0x0048, 0x3fd6, 0x6854, 0xac02, + 0x00c8, 0x3fd6, 0x2009, 0x0045, 0x1078, 0x5591, 0x007c, 0x7110, + 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, 0x00c0, 0x3fe7, 0xa084, + 0x000f, 0xa08a, 0x0006, 0x10c8, 0x12b7, 0x1079, 0x3fe8, 0x007c, + 0x3fee, 0x3fef, 0x3fee, 0x3fee, 0x4030, 0x403f, 0x007c, 0x7110, + 0xd1bc, 0x00c0, 0x402f, 0x700c, 0x7108, 0x1078, 0x1e1b, 0x00c0, + 0x402f, 0x1078, 0x3410, 0x00c0, 0x402f, 0x6612, 0x6516, 0x6204, + 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x00c0, 0x4018, 0x0c7e, + 0x1078, 0x5504, 0x017f, 0x0040, 0x402f, 0x611a, 0x601f, 0x0005, + 0x7120, 0x610a, 0x2009, 0x0028, 0x1078, 0x5591, 0x0078, 0x402f, + 0x0c7e, 0x1078, 0x5504, 0x017f, 0x0040, 0x402f, 0x611a, 0x601f, + 0x0004, 0x7120, 0x610a, 0xa286, 0x0004, 0x00c0, 0x402b, 0x2009, + 0x0005, 0x0078, 0x402d, 0x2009, 0x0001, 0x1078, 0x5591, 0x007c, + 0x7110, 0xd1bc, 0x0040, 0x403e, 0x1078, 0x404e, 0x0040, 0x403e, + 0x7124, 0x610a, 0x2009, 0x0029, 0x1078, 0x5591, 0x007c, 0x7110, + 0xd1bc, 0x0040, 0x404d, 0x1078, 0x404e, 0x0040, 0x404d, 0x7124, + 0x610a, 0x2009, 0x002a, 0x1078, 0x5591, 0x007c, 0x7020, 0x2060, + 0xac84, 0x0007, 0x00c0, 0x4061, 0xac82, 0x7400, 0x0048, 0x4061, + 0x2001, 0x6d15, 0x2004, 0xac02, 0x00c8, 0x4061, 0xa085, 0x0001, + 0x007c, 0xa006, 0x0078, 0x4060, 0x2071, 0x6f23, 0x7003, 0x0003, + 0x700f, 0x0361, 0xa006, 0x701a, 0x7012, 0x7017, 0x7400, 0x7007, + 0x0000, 0x7026, 0x702b, 0x4ff2, 0x7032, 0x7037, 0x503e, 0x007c, + 0x2071, 0x6f23, 0x00e0, 0x40be, 0x2091, 0x6000, 0x700c, 0x8001, + 0x700e, 0x00c0, 0x4087, 0x700f, 0x0361, 0x7007, 0x0001, 0x127e, + 0x2091, 0x8000, 0x7024, 0xa00d, 0x0040, 0x409b, 0x7020, 0x8001, + 0x7022, 0x00c0, 0x409b, 0x7023, 0x0009, 0x8109, 0x7126, 0x00c0, + 0x409b, 0x7028, 0x107a, 0x7030, 0xa00d, 0x0040, 0x40ac, 0x702c, + 0x8001, 0x702e, 0x00c0, 0x40ac, 0x702f, 0x0009, 0x8109, 0x7132, + 0x00c0, 0x40ac, 0x7034, 0x107a, 0x7018, 0xa00d, 0x0040, 0x40bd, + 0x7008, 0x8001, 0x700a, 0x00c0, 0x40bd, 0x700b, 0x0009, 0x8109, + 0x711a, 0x00c0, 0x40bd, 0x701c, 0x107a, 0x127f, 0x7004, 0x0079, + 0x40c1, 0x40e8, 0x40e9, 0x4105, 0x0e7e, 0x2071, 0x6f23, 0x7018, + 0xa005, 0x00c0, 0x40cf, 0x711a, 0x721e, 0x700b, 0x0009, 0x0e7f, + 0x007c, 0x0e7e, 0x007e, 0x2071, 0x6f23, 0x701c, 0xa206, 0x00c0, + 0x40db, 0x701a, 0x701e, 0x007f, 0x0e7f, 0x007c, 0x0e7e, 0x2071, + 0x6f23, 0x6088, 0xa102, 0x0048, 0x40e6, 0x618a, 0x0e7f, 0x007c, + 0x007c, 0x7110, 0x1078, 0x3447, 0x00c0, 0x40fb, 0x6088, 0x8001, + 0x0048, 0x40fb, 0x608a, 0x00c0, 0x40fb, 0x127e, 0x2091, 0x8000, + 0x1078, 0x476a, 0x127f, 0x8108, 0xa182, 0x00ff, 0x0048, 0x4103, + 0xa00e, 0x7007, 0x0002, 0x7112, 0x007c, 0x7014, 0x2060, 0x127e, + 0x2091, 0x8000, 0x6014, 0xa005, 0x0040, 0x4134, 0x8001, 0x6016, + 0x00c0, 0x4134, 0x611c, 0xa186, 0x0003, 0x0040, 0x411b, 0xa186, + 0x0006, 0x00c0, 0x4132, 0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, + 0x0048, 0x4132, 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a, 0x0048, + 0x412b, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, + 0x0078, 0x4134, 0x1078, 0x5fea, 0x127f, 0xac88, 0x0008, 0x7116, + 0x2001, 0x6d16, 0x2004, 0xa102, 0x0048, 0x4142, 0x7017, 0x7400, + 0x7007, 0x0000, 0x007c, 0x0e7e, 0x2071, 0x6f23, 0x7027, 0x07d0, + 0x7023, 0x0009, 0x0e7f, 0x007c, 0x2001, 0x6f2c, 0x2003, 0x0000, + 0x007c, 0x0e7e, 0x2071, 0x6f23, 0x7033, 0x07d0, 0x702f, 0x0009, + 0x0e7f, 0x007c, 0x2011, 0x6f2f, 0x2013, 0x0000, 0x007c, 0x0e7e, + 0x2071, 0x6f23, 0x711a, 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, + 0x0c7e, 0x2061, 0x6fb2, 0x0c7f, 0x007c, 0xa184, 0x000f, 0x8003, + 0x8003, 0x8003, 0xa080, 0x6fb2, 0x2060, 0x007c, 0x684c, 0xa08c, + 0x00c0, 0xa18e, 0x00c0, 0x0040, 0x41ac, 0xd0b4, 0x00c0, 0x4188, + 0xd0bc, 0x00c0, 0x419a, 0x2009, 0x0006, 0x1078, 0x41cf, 0x007c, + 0xd0fc, 0x0040, 0x4195, 0xa084, 0x0003, 0xa08e, 0x0003, 0x0040, + 0x41c8, 0xa08e, 0x0000, 0x00c0, 0x41c8, 0x2009, 0x0043, 0x1078, + 0x5591, 0x007c, 0xd0fc, 0x0040, 0x41a7, 0xa084, 0x0003, 0xa08e, + 0x0003, 0x0040, 0x41c8, 0xa08e, 0x0000, 0x00c0, 0x41c8, 0x2009, + 0x0042, 0x1078, 0x5591, 0x007c, 0xd0fc, 0x0040, 0x41be, 0xa084, + 0x0003, 0xa08e, 0x0003, 0x0040, 0x41c8, 0xa08e, 0x0002, 0x0040, + 0x41c2, 0x2009, 0x0041, 0x1078, 0x5591, 0x007c, 0x1078, 0x41cd, + 0x0078, 0x41bd, 0x2009, 0x0043, 0x1078, 0x5591, 0x0078, 0x41bd, + 0x2009, 0x0004, 0x1078, 0x41cf, 0x007c, 0x2009, 0x0001, 0x6010, + 0xa0ec, 0xf000, 0x0040, 0x41f3, 0x2068, 0x6952, 0x6800, 0x6012, + 0xa186, 0x0001, 0x00c0, 0x41ed, 0x694c, 0xa18c, 0x8100, 0xa18e, + 0x8100, 0x00c0, 0x41ed, 0x0c7e, 0x6944, 0x1078, 0x416d, 0x6204, + 0x8210, 0x0048, 0x41ec, 0x6206, 0x0c7f, 0x1078, 0x36a1, 0x6010, + 0xa06d, 0x10c0, 0x4176, 0x007c, 0x157e, 0x0c7e, 0x20a9, 0x0010, + 0x2061, 0x6fb2, 0x6000, 0x81ff, 0x0040, 0x4201, 0xa205, 0x0078, + 0x4202, 0xa204, 0x6002, 0xace0, 0x0008, 0x00f0, 0x41fa, 0x0c7f, + 0x157f, 0x007c, 0x6808, 0xa005, 0x0040, 0x4212, 0x8001, 0x680a, + 0xa085, 0x0001, 0x007c, 0x127e, 0x2091, 0x2200, 0x2079, 0x6f10, + 0x127f, 0x0d7e, 0x2069, 0x6f10, 0x6803, 0x0005, 0x2069, 0x0004, + 0x2d04, 0xa085, 0x8001, 0x206a, 0x0d7f, 0x007c, 0x0c7e, 0x6027, + 0x0001, 0x7804, 0xa084, 0x0007, 0x0079, 0x422e, 0x4238, 0x425d, + 0x428e, 0x423e, 0x425d, 0x4236, 0x4236, 0x4236, 0x1078, 0x12b7, + 0x1078, 0x414c, 0x1078, 0x476a, 0x0c7f, 0x007c, 0x62c0, 0x82ff, + 0x00c0, 0x4244, 0x0c7f, 0x007c, 0x2011, 0x318e, 0x1078, 0x40d1, + 0x7828, 0xa092, 0x0002, 0x00c8, 0x4253, 0x8000, 0x782a, 0x1078, + 0x31c2, 0x0078, 0x4242, 0x1078, 0x318e, 0x7807, 0x0003, 0x7827, + 0x0000, 0x782b, 0x0000, 0x0078, 0x4242, 0x1078, 0x414c, 0x62c0, + 0x82ff, 0x00c0, 0x426f, 0x782b, 0x0000, 0x7824, 0xa065, 0x1040, + 0x12b7, 0x2009, 0x0013, 0x1078, 0x5591, 0x0c7f, 0x007c, 0x0c7e, + 0x7824, 0xa065, 0x1040, 0x12b7, 0x7804, 0xa086, 0x0004, 0x0040, + 0x42cc, 0x7828, 0xa092, 0x2710, 0x00c8, 0x4285, 0x8000, 0x782a, + 0x0c7f, 0x1078, 0x4fd7, 0x0078, 0x426d, 0x1078, 0x6c76, 0x2009, + 0x0014, 0x1078, 0x5591, 0x0c7f, 0x0078, 0x426d, 0x2001, 0x6f2c, + 0x2003, 0x0000, 0x62c0, 0x82ff, 0x00c0, 0x42a2, 0x782b, 0x0000, + 0x7824, 0xa065, 0x1040, 0x12b7, 0x2009, 0x0013, 0x1078, 0x55df, + 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x7824, 0xa005, 0x1040, 0x12b7, + 0x781c, 0xa06d, 0x1040, 0x12b7, 0x6800, 0xc0dc, 0x6802, 0x7924, + 0x2160, 0x1078, 0x556a, 0x693c, 0x81ff, 0x1040, 0x12b7, 0x8109, + 0x693e, 0x6854, 0xa015, 0x0040, 0x42c0, 0x7a1e, 0x0078, 0x42c2, + 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x0d7f, 0x0c7f, + 0x1078, 0x476a, 0x0078, 0x42a0, 0x6104, 0xa186, 0x0002, 0x0040, + 0x42d7, 0xa186, 0x0004, 0x0040, 0x42d7, 0x0078, 0x4279, 0x7808, + 0xac06, 0x0040, 0x4279, 0x1078, 0x4671, 0x1078, 0x4376, 0x0c7f, + 0x1078, 0x476a, 0x0078, 0x426d, 0x0c7e, 0x6027, 0x0002, 0x2011, + 0x6f2f, 0x2013, 0x0000, 0x62c8, 0x82ff, 0x00c0, 0x42fe, 0x62c4, + 0x82ff, 0x00c0, 0x42fe, 0x793c, 0xa1e5, 0x0000, 0x0040, 0x42fc, + 0x2009, 0x0049, 0x1078, 0x5591, 0x0c7f, 0x007c, 0x6017, 0x0010, + 0x793c, 0x81ff, 0x0040, 0x42fc, 0x7944, 0xa192, 0x2710, 0x00c8, + 0x431d, 0x8108, 0x7946, 0x1078, 0x4151, 0x793c, 0xa188, 0x0007, + 0x210c, 0xa18e, 0x0006, 0x00c0, 0x4319, 0x6017, 0x0012, 0x0078, + 0x42fc, 0x6017, 0x0016, 0x0078, 0x42fc, 0x1078, 0x6c76, 0x793c, + 0x2160, 0x2009, 0x004a, 0x1078, 0x5591, 0x0078, 0x42fc, 0x007e, + 0x017e, 0x0c7e, 0x127e, 0x600f, 0x0000, 0x2c08, 0x2061, 0x6f10, + 0x2091, 0x8000, 0x6020, 0x8000, 0x6022, 0x6010, 0xa005, 0x0040, + 0x4342, 0xa080, 0x0003, 0x2102, 0x6112, 0x127f, 0x0c7f, 0x017f, + 0x007f, 0x007c, 0x6116, 0x6112, 0x0078, 0x433d, 0x0d7e, 0x2069, + 0x6f10, 0x6000, 0xd0d4, 0x0040, 0x435d, 0x6820, 0x8000, 0x6822, + 0xa086, 0x0001, 0x00c0, 0x4356, 0x2c00, 0x681e, 0x6804, 0xa084, + 0x0007, 0x0079, 0x4772, 0x0d7f, 0x007c, 0xc0d5, 0x6002, 0x6818, + 0xa005, 0x0040, 0x436f, 0x6056, 0x605b, 0x0000, 0x007e, 0x2c00, + 0x681a, 0x0d7f, 0x685a, 0x2069, 0x6f10, 0x0078, 0x434d, 0x6056, + 0x605a, 0x2c00, 0x681a, 0x681e, 0x0078, 0x434d, 0x007e, 0x017e, + 0x0c7e, 0x127e, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, + 0x6f10, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0040, 0x4391, + 0xa080, 0x0003, 0x2102, 0x610a, 0x127f, 0x0c7f, 0x017f, 0x007f, + 0x007c, 0x610e, 0x610a, 0x0078, 0x438c, 0x0c7e, 0x600f, 0x0000, + 0x2c08, 0x2061, 0x6f10, 0x6034, 0xa005, 0x0040, 0x43a5, 0xa080, + 0x0003, 0x2102, 0x6136, 0x0c7f, 0x007c, 0x613a, 0x6136, 0x0078, + 0x43a3, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x027e, 0x007e, + 0x127e, 0x2071, 0x6f10, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, + 0x8cff, 0x0040, 0x4405, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, + 0x00c0, 0x4400, 0x703c, 0xac06, 0x00c0, 0x43cb, 0x6003, 0x000a, + 0x630a, 0x0078, 0x4400, 0x7038, 0xac36, 0x00c0, 0x43d1, 0x660c, + 0x763a, 0x7034, 0xac36, 0x00c0, 0x43df, 0x2c00, 0xaf36, 0x0040, + 0x43dd, 0x2f00, 0x7036, 0x0078, 0x43df, 0x7037, 0x0000, 0x660c, + 0x067e, 0x2c00, 0xaf06, 0x0040, 0x43e8, 0x7e0e, 0x0078, 0x43e9, + 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, + 0x00c0, 0x440e, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, + 0x36a1, 0x1078, 0x6276, 0x1078, 0x6283, 0x0c7f, 0x0078, 0x43b8, + 0x2c78, 0x600c, 0x2060, 0x0078, 0x43b8, 0x127f, 0x007f, 0x027f, + 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, + 0x0006, 0x00c0, 0x43f2, 0x1078, 0x6bb3, 0x0078, 0x43fb, 0x007e, + 0x067e, 0x0c7e, 0x0d7e, 0x0f7e, 0x2031, 0x0000, 0x127e, 0x2091, + 0x8000, 0x2079, 0x6f10, 0x7838, 0xa065, 0x0040, 0x444a, 0x600c, + 0x007e, 0x600f, 0x0000, 0x783c, 0xac06, 0x00c0, 0x4435, 0x6003, + 0x000a, 0x630a, 0x2c30, 0x0078, 0x4447, 0x6010, 0x2068, 0x601c, + 0xa086, 0x0003, 0x00c0, 0x4453, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x1078, 0x36a1, 0x1078, 0x6276, 0x1078, 0x6283, 0x007f, + 0x0078, 0x4424, 0x7e3a, 0x7e36, 0x127f, 0x0f7f, 0x0d7f, 0x0c7f, + 0x067f, 0x007f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x443c, + 0x1078, 0x6bb3, 0x0078, 0x4445, 0x027e, 0x1078, 0x4470, 0x1078, + 0x4507, 0x027f, 0x007c, 0x0f7e, 0x127e, 0x2079, 0x6f10, 0x2091, + 0x8000, 0x1078, 0x4599, 0x1078, 0x4601, 0x127f, 0x0f7f, 0x007c, + 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2091, + 0x8000, 0x2071, 0x6f10, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0040, + 0x44f6, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x44f1, + 0x7024, 0xac06, 0x00c0, 0x44b6, 0x2069, 0x0100, 0x68c0, 0xa005, + 0x0040, 0x44b1, 0x1078, 0x4fe5, 0x68c3, 0x0000, 0x1078, 0x54a4, + 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, + 0x0040, 0x44a6, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, + 0x6824, 0xd084, 0x0040, 0x44ae, 0x6827, 0x0001, 0x037f, 0x0078, + 0x44b6, 0x6003, 0x0009, 0x630a, 0x0078, 0x44f1, 0x7014, 0xac36, + 0x00c0, 0x44bc, 0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x44ca, + 0x2c00, 0xaf36, 0x0040, 0x44c8, 0x2f00, 0x7012, 0x0078, 0x44ca, + 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x44d3, + 0x7e0e, 0x0078, 0x44d4, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, + 0x1078, 0x6120, 0x0040, 0x44ea, 0x601c, 0xa086, 0x0003, 0x00c0, + 0x44fe, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x36a1, + 0x1078, 0x6276, 0x1078, 0x6283, 0x1078, 0x5374, 0x0c7f, 0x0078, + 0x447e, 0x2c78, 0x600c, 0x2060, 0x0078, 0x447e, 0x127f, 0x007f, + 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, + 0x0006, 0x00c0, 0x44e1, 0x1078, 0x6bb3, 0x0078, 0x44ea, 0x0c7e, + 0x007e, 0x127e, 0x2091, 0x8000, 0xa280, 0x6e00, 0x2004, 0xa065, + 0x0040, 0x4595, 0x0f7e, 0x0e7e, 0x0d7e, 0x067e, 0x2071, 0x6f10, + 0x6654, 0x7018, 0xac06, 0x00c0, 0x451e, 0x761a, 0x701c, 0xac06, + 0x00c0, 0x452a, 0x86ff, 0x00c0, 0x4529, 0x7018, 0x701e, 0x0078, + 0x452a, 0x761e, 0x6058, 0xa07d, 0x0040, 0x452f, 0x7e56, 0xa6ed, + 0x0000, 0x0040, 0x4535, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b, + 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x33c4, 0x0040, + 0x4591, 0x7624, 0x86ff, 0x0040, 0x4586, 0xa680, 0x0004, 0x2004, + 0xad06, 0x00c0, 0x4586, 0x0d7e, 0x2069, 0x0100, 0x68c0, 0xa005, + 0x0040, 0x457d, 0x1078, 0x4fe5, 0x68c3, 0x0000, 0x1078, 0x54a4, + 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, + 0x0040, 0x4566, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, + 0x6824, 0xd084, 0x0040, 0x456e, 0x6827, 0x0001, 0x037f, 0x0d7f, + 0x0c7e, 0x603c, 0xa005, 0x0040, 0x4577, 0x8001, 0x603e, 0x2660, + 0x1078, 0x6283, 0x0c7f, 0x0078, 0x4586, 0x0d7f, 0x0c7e, 0x2660, + 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, 0x453d, 0x6837, 0x0103, + 0x6b4a, 0x6847, 0x0000, 0x1078, 0x36a1, 0x1078, 0x5374, 0x0078, + 0x453d, 0x067f, 0x0d7f, 0x0e7f, 0x0f7f, 0x127f, 0x007f, 0x0c7f, + 0x007c, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x2031, 0x0000, 0x7814, + 0xa065, 0x0040, 0x45f1, 0x600c, 0x007e, 0x600f, 0x0000, 0x7824, + 0xac06, 0x00c0, 0x45d6, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, + 0x45d0, 0x1078, 0x4fe5, 0x68c3, 0x0000, 0x1078, 0x54a4, 0x7827, + 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, + 0x45c5, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, + 0xd084, 0x0040, 0x45cd, 0x6827, 0x0001, 0x037f, 0x0078, 0x45d6, + 0x6003, 0x0009, 0x630a, 0x2c30, 0x0078, 0x45ee, 0x6010, 0x2068, + 0x1078, 0x6120, 0x0040, 0x45ea, 0x601c, 0xa086, 0x0003, 0x00c0, + 0x45f8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x36a1, + 0x1078, 0x6276, 0x1078, 0x6283, 0x1078, 0x5374, 0x007f, 0x0078, + 0x45a0, 0x7e16, 0x7e12, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, + 0x601c, 0xa086, 0x0006, 0x00c0, 0x45e1, 0x1078, 0x6bb3, 0x0078, + 0x45ea, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x7818, 0xa065, 0x0040, + 0x466a, 0x6054, 0x007e, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, + 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x33c4, 0x0040, 0x4667, 0x7e24, + 0x86ff, 0x0040, 0x465c, 0xa680, 0x0004, 0x2004, 0xad06, 0x00c0, + 0x465c, 0x0d7e, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x4653, + 0x1078, 0x4fe5, 0x68c3, 0x0000, 0x1078, 0x54a4, 0x7827, 0x0000, + 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x463c, + 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, + 0x0040, 0x4644, 0x6827, 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, + 0xa005, 0x0040, 0x464d, 0x8001, 0x603e, 0x2660, 0x1078, 0x6283, + 0x0c7f, 0x0078, 0x465c, 0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009, + 0x630a, 0x0c7f, 0x0078, 0x4613, 0x6837, 0x0103, 0x6b4a, 0x6847, + 0x0000, 0x1078, 0x36a1, 0x1078, 0x5374, 0x0078, 0x4613, 0x007f, + 0x0078, 0x4606, 0x781e, 0x781a, 0x0d7f, 0x0c7f, 0x067f, 0x007f, + 0x007c, 0x0e7e, 0x0c7e, 0x2071, 0x6f10, 0x7004, 0xa084, 0x0007, + 0x0079, 0x467a, 0x4684, 0x4687, 0x46a0, 0x46bc, 0x4701, 0x4684, + 0x4682, 0x4682, 0x1078, 0x12b7, 0x0c7f, 0x0e7f, 0x007c, 0x7024, + 0xa065, 0x0040, 0x4695, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015, + 0x0040, 0x469c, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, + 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7216, 0x7212, 0x0078, 0x4695, + 0x6018, 0x2060, 0x1078, 0x33c4, 0x6000, 0xc0dc, 0x6002, 0x7020, + 0x8001, 0x7022, 0x0040, 0x46b1, 0x6054, 0xa015, 0x0040, 0x46b8, + 0x721e, 0x7007, 0x0000, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, + 0x7218, 0x721e, 0x0078, 0x46b1, 0x7024, 0xa065, 0x0040, 0x46fe, + 0x700c, 0xac06, 0x00c0, 0x46d3, 0x1078, 0x5374, 0x600c, 0xa015, + 0x0040, 0x46cf, 0x720e, 0x600f, 0x0000, 0x0078, 0x46fc, 0x720e, + 0x720a, 0x0078, 0x46fc, 0x7014, 0xac06, 0x00c0, 0x46e6, 0x1078, + 0x5374, 0x600c, 0xa015, 0x0040, 0x46e2, 0x7216, 0x600f, 0x0000, + 0x0078, 0x46fc, 0x7216, 0x7212, 0x0078, 0x46fc, 0x6018, 0x2060, + 0x1078, 0x33c4, 0x6000, 0xc0dc, 0x6002, 0x1078, 0x5374, 0x701c, + 0xa065, 0x0040, 0x46fc, 0x6054, 0xa015, 0x0040, 0x46fa, 0x721e, + 0x0078, 0x46fc, 0x7218, 0x721e, 0x7027, 0x0000, 0x0c7f, 0x0e7f, + 0x007c, 0x7024, 0xa065, 0x0040, 0x470e, 0x1078, 0x5374, 0x600c, + 0xa015, 0x0040, 0x4715, 0x720e, 0x600f, 0x0000, 0x1078, 0x54a4, + 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x720e, 0x720a, 0x0078, + 0x470e, 0x0d7e, 0x2069, 0x6f10, 0x6830, 0xa084, 0x0003, 0x0079, + 0x4721, 0x4727, 0x4729, 0x474f, 0x4725, 0x1078, 0x12b7, 0x0d7f, + 0x007c, 0x0c7e, 0x6840, 0xa086, 0x0001, 0x0040, 0x4745, 0x683c, + 0xa065, 0x0040, 0x473a, 0x600c, 0xa015, 0x0040, 0x4741, 0x6a3a, + 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c7f, 0x0d7f, + 0x007c, 0x683a, 0x6836, 0x0078, 0x473a, 0x6843, 0x0000, 0x6838, + 0xa065, 0x0040, 0x473a, 0x6003, 0x0003, 0x0078, 0x473a, 0x0c7e, + 0x6843, 0x0000, 0x6847, 0x0000, 0x683c, 0xa065, 0x0040, 0x4767, + 0x600c, 0xa015, 0x0040, 0x4763, 0x6a3a, 0x600f, 0x0000, 0x683f, + 0x0000, 0x0078, 0x4767, 0x683f, 0x0000, 0x683a, 0x6836, 0x0c7f, + 0x0d7f, 0x007c, 0x0d7e, 0x2069, 0x6f10, 0x6804, 0xa084, 0x0007, + 0x0079, 0x4772, 0x477c, 0x4810, 0x4810, 0x4810, 0x4810, 0x4812, + 0x477a, 0x477a, 0x1078, 0x12b7, 0x6820, 0xa005, 0x00c0, 0x4782, + 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x4791, 0x6807, + 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x4858, 0x0c7f, 0x0d7f, + 0x007c, 0x6814, 0xa065, 0x0040, 0x479f, 0x6807, 0x0001, 0x6826, + 0x682b, 0x0000, 0x1078, 0x4858, 0x0c7f, 0x0d7f, 0x007c, 0x0e7e, + 0x037e, 0x6a1c, 0xa2f5, 0x0000, 0x0040, 0x480b, 0x704c, 0xa00d, + 0x0040, 0x47ae, 0x7088, 0xa005, 0x0040, 0x47c6, 0x7054, 0xa075, + 0x0040, 0x47b7, 0xa20e, 0x0040, 0x480b, 0x0078, 0x47bc, 0x6818, + 0xa20e, 0x0040, 0x480b, 0x2070, 0x704c, 0xa00d, 0x0040, 0x47ae, + 0x7088, 0xa005, 0x00c0, 0x47ae, 0x2e00, 0x681e, 0x733c, 0x7038, + 0xa302, 0x00c8, 0x47ae, 0x1078, 0x5539, 0x0040, 0x480b, 0x8318, + 0x733e, 0x6112, 0x2e10, 0x621a, 0xa180, 0x0015, 0x2004, 0xa08a, + 0x199a, 0x0048, 0x47dd, 0x2001, 0x1999, 0x8003, 0x801b, 0x831b, + 0xa318, 0x6316, 0x037f, 0x0f7e, 0x2c78, 0x71a0, 0xd1bc, 0x0040, + 0x47ed, 0x2009, 0x0000, 0x0078, 0x47f2, 0xa1e0, 0x2091, 0x2c0c, + 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x1078, 0x4c44, 0x7300, + 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, + 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, 0x0f7f, 0x0e7f, + 0x0c7f, 0x0d7f, 0x007c, 0x037f, 0x0e7f, 0x0c7f, 0x0078, 0x4809, + 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x481e, 0x6807, + 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x4858, 0x0c7f, 0x0d7f, + 0x007c, 0x0f7e, 0x0d7e, 0x2069, 0x6f10, 0x6830, 0xa086, 0x0000, + 0x00c0, 0x483f, 0x6838, 0xa07d, 0x0040, 0x483f, 0x6833, 0x0001, + 0x683e, 0x6847, 0x0000, 0x127e, 0x0f7e, 0x2091, 0x2200, 0x027f, + 0x1078, 0x1838, 0x00c0, 0x4842, 0x127f, 0x1078, 0x4ed5, 0x0d7f, + 0x0f7f, 0x007c, 0x127f, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, + 0xa015, 0x0040, 0x4854, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, + 0x683f, 0x0000, 0x0078, 0x483f, 0x683a, 0x6836, 0x0078, 0x484e, + 0x601c, 0xa084, 0x000f, 0x1079, 0x485e, 0x007c, 0x4867, 0x4869, + 0x4b33, 0x4c15, 0x4869, 0x4b33, 0x4c15, 0x4867, 0x4869, 0x1078, + 0x12b7, 0x157e, 0x137e, 0x147e, 0x0c7e, 0x0f7e, 0x6004, 0xa08a, + 0x0024, 0x10c8, 0x12b7, 0x6118, 0x2178, 0x79a0, 0xa1f8, 0x2091, + 0x2f0c, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0x1079, + 0x4887, 0x0f7f, 0x0c7f, 0x147f, 0x137f, 0x157f, 0x007c, 0x48ad, + 0x48ec, 0x4904, 0x494c, 0x4979, 0x4981, 0x49a2, 0x49b3, 0x49c4, + 0x49cc, 0x49dd, 0x49cc, 0x4a25, 0x49b3, 0x4a55, 0x4a5d, 0x49c4, + 0x4a5d, 0x4a6e, 0x48ab, 0x48ab, 0x48ab, 0x48ab, 0x48ab, 0x48ab, + 0x48ab, 0x48ab, 0x48ab, 0x48ab, 0x48ab, 0x48ab, 0x50b8, 0x50cd, + 0x50f0, 0x5114, 0x49a2, 0x1078, 0x12b7, 0x20a1, 0x020b, 0x1078, + 0x4a83, 0x20a3, 0x5200, 0x20a3, 0x0000, 0x0d7e, 0x2069, 0x6d51, + 0x6804, 0xd084, 0x0040, 0x48ce, 0x6828, 0x017e, 0x2069, 0x6d00, + 0x694c, 0xa106, 0x017f, 0x00c0, 0x48ce, 0x20a3, 0x0000, 0x6030, + 0xa084, 0x00ff, 0x20a2, 0x0d7f, 0x0078, 0x48d3, 0x0d7f, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0x6d05, 0x53a6, + 0x20a9, 0x0004, 0x2099, 0x6d01, 0x53a6, 0x20a3, 0x0000, 0x6030, + 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, + 0x001c, 0x1078, 0x4fd1, 0x007c, 0x20a1, 0x020b, 0x1078, 0x4a83, + 0x20a3, 0x0500, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x6030, 0xa084, + 0x00ff, 0x20a2, 0x20a9, 0x0004, 0x2099, 0x6d05, 0x53a6, 0x60c3, + 0x0010, 0x1078, 0x4fd1, 0x007c, 0x20a1, 0x020b, 0x1078, 0x4a83, + 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, 0x4917, + 0x20a3, 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0078, 0x4919, 0x20a3, + 0x0300, 0x20a3, 0x0000, 0x2099, 0x6f00, 0x20a9, 0x0008, 0x53a6, + 0x20a9, 0x0004, 0x2099, 0x6d05, 0x53a6, 0x20a9, 0x0004, 0x2099, + 0x6d01, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x492c, + 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x4932, 0x2099, 0x6f08, + 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, + 0x493d, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x4943, 0x60c3, + 0x0074, 0x1078, 0x4fd1, 0x007c, 0x20a1, 0x020b, 0x1078, 0x4a83, + 0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079, + 0x6d51, 0x7904, 0x0f7f, 0xd1ac, 0x00c0, 0x4968, 0xa085, 0x0020, + 0xd1a4, 0x0040, 0x496d, 0xa085, 0x0010, 0xa085, 0x0002, 0x20a2, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x4fd1, + 0x007c, 0x20a1, 0x020b, 0x1078, 0x4a83, 0x20a3, 0x5000, 0x0078, + 0x4919, 0x20a1, 0x020b, 0x1078, 0x4a83, 0x20a3, 0x2110, 0x20a3, + 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, + 0x0022, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, + 0x4fd1, 0x007c, 0x20a1, 0x020b, 0x1078, 0x4afa, 0x20a3, 0x0200, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, + 0x1078, 0x4fd1, 0x007c, 0x20a1, 0x020b, 0x1078, 0x4afa, 0x20a3, + 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, + 0x0008, 0x1078, 0x4fd1, 0x007c, 0x20a1, 0x020b, 0x1078, 0x4afa, + 0x20a3, 0x0200, 0x0078, 0x4919, 0x20a1, 0x020b, 0x1078, 0x4afa, + 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x7810, 0x20a2, + 0x60c3, 0x0008, 0x1078, 0x4fd1, 0x007c, 0x0d7e, 0x20a1, 0x020b, + 0x1078, 0x4afa, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800, + 0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x00c0, 0x4a03, 0x6998, + 0xa184, 0xc000, 0x00c0, 0x49ff, 0xd1ec, 0x0040, 0x49fb, 0x20a3, + 0x2100, 0x0078, 0x4a05, 0x20a3, 0x0100, 0x0078, 0x4a05, 0x20a3, + 0x0400, 0x0078, 0x4a05, 0x20a3, 0x0700, 0xa006, 0x20a2, 0x20a2, + 0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079, 0x6d51, 0x7904, 0x0f7f, + 0xd1ac, 0x00c0, 0x4a15, 0xa085, 0x0020, 0xd1a4, 0x0040, 0x4a1a, + 0xa085, 0x0010, 0xa085, 0x0002, 0x20a2, 0x20a2, 0x20a2, 0x60c3, + 0x0014, 0x1078, 0x4fd1, 0x0d7f, 0x007c, 0x20a1, 0x020b, 0x1078, + 0x4afa, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x6018, + 0x0d7e, 0x2068, 0x6804, 0x0d7f, 0xa084, 0x00ff, 0xa086, 0x0006, + 0x0040, 0x4a3e, 0x20a3, 0x0400, 0x0078, 0x4a40, 0x20a3, 0x0100, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x60c3, 0x0014, 0x1078, 0x4fd1, 0x007c, 0x20a1, 0x020b, 0x1078, + 0x4afa, 0x20a3, 0x0200, 0x0078, 0x48b3, 0x20a1, 0x020b, 0x1078, + 0x4afa, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, + 0x2a00, 0x60c3, 0x0008, 0x1078, 0x4fd1, 0x007c, 0x20e1, 0x9080, + 0x20e1, 0x4000, 0x20a1, 0x020b, 0x1078, 0x4afa, 0x20a3, 0x0100, + 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3, 0x0000, 0x60c3, 0x0008, + 0x1078, 0x4fd1, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x00c0, 0x4a96, + 0x20a3, 0x22ff, 0x20a3, 0xfffe, 0x0078, 0x4ac4, 0xa286, 0x007f, + 0x00c0, 0x4aa1, 0x0d7e, 0x20a3, 0x22ff, 0x20a3, 0xfffd, 0x0078, + 0x4ab8, 0xd2bc, 0x0040, 0x4ac0, 0xa286, 0x0080, 0x0d7e, 0x00c0, + 0x4aaf, 0x20a3, 0x22ff, 0x20a3, 0xfffc, 0x0078, 0x4ab8, 0xa2e8, + 0x6e00, 0x2d6c, 0x6810, 0xa085, 0x2200, 0x20a2, 0x6814, 0x20a2, + 0x2069, 0x6d19, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x4ac8, + 0x20a3, 0x2200, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, + 0x20a3, 0x0129, 0x20a3, 0x0000, 0x1078, 0x4fc0, 0x22a2, 0x20a3, + 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x027f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, + 0x02ff, 0x2011, 0xfffc, 0x22a2, 0x0d7e, 0x2069, 0x6d19, 0x2da6, + 0x8d68, 0x2da6, 0x0d7f, 0x20a3, 0x2029, 0x20a3, 0x0000, 0x0078, + 0x4acc, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, + 0x0000, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, + 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x4b19, 0x0d7e, + 0xa0e8, 0x6e00, 0x2d6c, 0x6810, 0xa085, 0x2300, 0x20a2, 0x6814, + 0x20a2, 0x2069, 0x6d19, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, + 0x4b21, 0x20a3, 0x2300, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, + 0x22a2, 0x20a3, 0x0198, 0x20a3, 0x0000, 0x1078, 0x4fc0, 0x22a2, + 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x027f, 0x007c, 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0025, + 0x1048, 0x12b7, 0xa08a, 0x002c, 0x10c8, 0x12b7, 0x6118, 0x2178, + 0x79a0, 0xa1f8, 0x2091, 0x2f0c, 0xa18c, 0x00ff, 0x2c78, 0x2061, + 0x0100, 0x619a, 0xa082, 0x0025, 0x1079, 0x4b51, 0x0f7f, 0x0c7f, + 0x007c, 0x4b5a, 0x4b65, 0x4b7f, 0x4b58, 0x4b58, 0x4b58, 0x4b5a, + 0x1078, 0x12b7, 0x147e, 0x20a1, 0x020b, 0x1078, 0x4b8e, 0x60c3, + 0x0000, 0x1078, 0x4fd1, 0x147f, 0x007c, 0x147e, 0x20a1, 0x020b, + 0x1078, 0x4bbb, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, + 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x000c, 0x1078, 0x4fd1, 0x147f, 0x007c, 0x147e, + 0x20a1, 0x020b, 0x1078, 0x4be8, 0x20a3, 0x0003, 0x20a3, 0x0300, + 0x60c3, 0x0004, 0x1078, 0x4fd1, 0x147f, 0x007c, 0x027e, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, + 0x007e, 0x0048, 0x4bad, 0x0d7e, 0xa0e8, 0x6e00, 0x2d6c, 0x6810, + 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x6d19, 0x2da6, + 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x4bb5, 0x20a3, 0x8100, 0x6298, + 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0009, 0x20a3, + 0x0000, 0x0078, 0x4acc, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, + 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x4bda, + 0x0d7e, 0xa0e8, 0x6e00, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0x6d19, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, + 0x0078, 0x4be2, 0x20a3, 0x8400, 0x6298, 0x22a2, 0x20a3, 0x0000, + 0x6230, 0x22a2, 0x20a3, 0x00d1, 0x20a3, 0x0000, 0x0078, 0x4b25, + 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0xa092, 0x007e, 0x0048, 0x4c07, 0x0d7e, 0xa0e8, 0x6e00, + 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, + 0x6d19, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x4c0f, 0x20a3, + 0x8500, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, + 0x00d1, 0x20a3, 0x0000, 0x0078, 0x4b25, 0x0c7e, 0x0f7e, 0x2c78, + 0x7804, 0xa08a, 0x0040, 0x1048, 0x12b7, 0xa08a, 0x004f, 0x10c8, + 0x12b7, 0x7918, 0x2160, 0x61a0, 0xa1e0, 0x2091, 0x2c0c, 0xa18c, + 0x00ff, 0x2061, 0x0100, 0x619a, 0xa082, 0x0040, 0x1079, 0x4c33, + 0x0f7f, 0x0c7f, 0x007c, 0x4c44, 0x4d28, 0x4cd0, 0x4e50, 0x4c42, + 0x4c42, 0x4c42, 0x4c42, 0x4c42, 0x4c42, 0x4c42, 0x528d, 0x529e, + 0x52af, 0x52c0, 0x1078, 0x12b7, 0x0d7e, 0x157e, 0x147e, 0x20a1, + 0x020b, 0x1078, 0x4c93, 0x7910, 0x2168, 0x6944, 0xa18c, 0x00ff, + 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, 0x0006, + 0x8004, 0x20a2, 0xd1ac, 0x0040, 0x4c61, 0x20a3, 0x0002, 0x0078, + 0x4c6d, 0xd1b4, 0x0040, 0x4c68, 0x20a3, 0x0001, 0x0078, 0x4c6d, + 0x20a3, 0x0000, 0x2230, 0x0078, 0x4c6f, 0x6a80, 0x6e7c, 0x20a9, + 0x0008, 0xad80, 0x0017, 0x200c, 0x810f, 0x21a2, 0x8000, 0x00f0, + 0x4c73, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, 0x6014, + 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0x6f2c, 0x2003, + 0x07d0, 0x2001, 0x6f2b, 0x2003, 0x0009, 0x1078, 0x14e4, 0x147f, + 0x157f, 0x0d7f, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7a18, + 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, + 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x4cb9, 0x0d7e, + 0xa0e8, 0x6e00, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, + 0x20a2, 0x2069, 0x6d19, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, + 0x4cc1, 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, 0x4cf0, + 0x7810, 0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2, 0x6880, 0x20a2, + 0x687c, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x60c3, + 0x000c, 0x1078, 0x4fd1, 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, + 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0xd0bc, 0x0040, 0x4d0e, 0x0d7e, 0xa0e8, 0x6e00, 0x2d6c, + 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x6d19, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x4d16, 0x20a3, 0x0500, + 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0889, + 0x20a3, 0x0000, 0x1078, 0x4fc0, 0x22a2, 0x20a3, 0x0000, 0x7a08, + 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, + 0x0d7e, 0x157e, 0x137e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x4e18, + 0x7810, 0x2068, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, + 0x7810, 0xa084, 0xf000, 0x00c0, 0x4d45, 0x7810, 0xa084, 0x0700, + 0x8007, 0x1079, 0x4d4d, 0x0078, 0x4d48, 0xa006, 0x1079, 0x4d4d, + 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x4d57, 0x4db9, 0x4dbd, + 0x4de0, 0x4ded, 0x4dff, 0x4e03, 0x4d55, 0x1078, 0x12b7, 0x017e, + 0x037e, 0x694c, 0xa18c, 0x0003, 0xa186, 0x0000, 0x00c0, 0x4d6a, + 0x6b78, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x037f, 0x017f, + 0x0078, 0x4de4, 0xa186, 0x0001, 0x00c0, 0x4db4, 0x6b78, 0x23a2, + 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, 0x6874, 0x20a2, 0x22a2, + 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, 0x0300, 0x0040, 0x4db3, + 0xd3c4, 0x0040, 0x4d85, 0x687c, 0xa108, 0xd3cc, 0x0040, 0x4d8a, + 0x6874, 0xa108, 0x157e, 0x20a9, 0x000d, 0xad80, 0x0020, 0x201c, + 0x831f, 0x23a2, 0x8000, 0x00f0, 0x4d8f, 0x157f, 0x22a2, 0x22a2, + 0x22a2, 0xa184, 0x0003, 0x0040, 0x4db3, 0x20a1, 0x020b, 0x20e1, + 0x9080, 0x20e1, 0x4000, 0x20a3, 0x0700, 0x6298, 0x22a2, 0x20a3, + 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0898, 0x20a2, 0x1078, 0x4fc0, + 0x22a2, 0x20a3, 0x0000, 0x61c2, 0x037f, 0x017f, 0x1078, 0x4fd1, + 0x007c, 0x20a3, 0x0008, 0x0078, 0x4de2, 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, 0x4fd1, 0x007c, + 0x20a3, 0x0028, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, + 0x60c3, 0x0018, 0x1078, 0x4fd1, 0x007c, 0x20a3, 0x0100, 0x22a2, + 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x22a2, + 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x1078, 0x4fd1, 0x007c, 0x20a3, + 0x0008, 0x0078, 0x4de2, 0x037e, 0x7b10, 0xa384, 0xff00, 0x7812, + 0xa384, 0x00ff, 0x8001, 0x00c0, 0x4e11, 0x22a2, 0x037f, 0x0078, + 0x4de2, 0x20a3, 0x0800, 0x22a2, 0x20a2, 0x037f, 0x0078, 0x4de4, + 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, + 0x2004, 0xd0bc, 0x0040, 0x4e36, 0x0d7e, 0xa0e8, 0x6e00, 0x2d6c, + 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x6d19, + 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x4e3e, 0x20a3, 0x0700, + 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0898, + 0x20a3, 0x0000, 0x1078, 0x4fc0, 0x22a2, 0x20a3, 0x0000, 0x7a08, + 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, + 0x0d7e, 0x157e, 0x137e, 0x147e, 0x017e, 0x037e, 0x7810, 0xa084, + 0x0700, 0x8007, 0x1079, 0x4e63, 0x037f, 0x017f, 0x147f, 0x137f, + 0x157f, 0x0d7f, 0x007c, 0x4e6b, 0x4e6b, 0x4e6d, 0x4e6b, 0x4e6b, + 0x4e6b, 0x4e92, 0x4e6b, 0x1078, 0x12b7, 0x7910, 0xa18c, 0xf8ff, + 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078, + 0x4e9c, 0x0d7e, 0x2069, 0x6d51, 0x6804, 0xd0bc, 0x0040, 0x4e87, + 0x682c, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0078, 0x4e89, 0x20a3, + 0x3f00, 0x0d7f, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x1078, + 0x4fd1, 0x007c, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078, 0x4e9c, + 0x20a3, 0x7f00, 0x0078, 0x4e8a, 0x027e, 0x20e1, 0x9080, 0x20e1, + 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x4eba, + 0x0d7e, 0xa0e8, 0x6e00, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, + 0x6814, 0x20a2, 0x2069, 0x6d19, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, + 0x0078, 0x4ec2, 0x20a3, 0x0100, 0x6298, 0x22a2, 0x20a3, 0x0000, + 0x6230, 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x1078, + 0x4fc0, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, + 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x0c7e, + 0x057e, 0x047e, 0x037e, 0x2061, 0x0100, 0x2071, 0x6d00, 0x6130, + 0x7818, 0x2068, 0x68a0, 0x2028, 0xd0bc, 0x00c0, 0x4eee, 0xa080, + 0x2091, 0x2014, 0xa294, 0x00ff, 0x0078, 0x4ef2, 0x6910, 0x6a14, + 0x7364, 0x7468, 0x781c, 0xa086, 0x0006, 0x0040, 0x4f3d, 0xd5bc, + 0x0040, 0x4f02, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, + 0x0078, 0x4f08, 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, 0x4f31, 0x2011, + 0x0000, 0x629e, 0x6017, 0x0016, 0x1078, 0x4151, 0x037f, 0x047f, + 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x7810, 0x2070, 0x704c, + 0xa084, 0x0003, 0xa086, 0x0002, 0x0040, 0x4f83, 0xd5bc, 0x0040, + 0x4f51, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, + 0x4f57, 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, 0x4f7e, 0x2011, 0x0000, 0x629e, 0x6017, + 0x0012, 0x0078, 0x4f34, 0xd5bc, 0x0040, 0x4f8e, 0xa185, 0x0700, + 0x20a2, 0x6266, 0x636a, 0x646e, 0x0078, 0x4f94, 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, + 0x4fbb, 0x2011, 0x0000, 0x629e, 0x6017, 0x0016, 0x0078, 0x4f34, + 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, + 0x8217, 0x007c, 0x0d7e, 0x2069, 0x6f10, 0x6843, 0x0001, 0x0d7f, + 0x007c, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x1078, + 0x4fdc, 0x1078, 0x4143, 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, 0x414c, + 0x2061, 0x0100, 0x2069, 0x0140, 0x6904, 0xa194, 0x4000, 0x0040, + 0x503a, 0x1078, 0x4fe5, 0x6803, 0x1000, 0x6803, 0x0000, 0x0c7e, + 0x2061, 0x6f10, 0x6128, 0xa192, 0x0002, 0x00c8, 0x5027, 0x8108, + 0x612a, 0x613c, 0x0c7f, 0x81ff, 0x0040, 0x5035, 0x1078, 0x4143, + 0xa188, 0x0007, 0x210c, 0xa18e, 0x0006, 0x00c0, 0x5023, 0x6017, + 0x0012, 0x0078, 0x5035, 0x1078, 0x4fdc, 0x0078, 0x5035, 0x6124, + 0xa1e5, 0x0000, 0x0040, 0x5032, 0x1078, 0x6c76, 0x2009, 0x0014, + 0x1078, 0x5591, 0x0c7f, 0x0078, 0x5035, 0x027f, 0x017f, 0x0d7f, + 0x0c7f, 0x007c, 0x1078, 0x31cb, 0x0078, 0x5035, 0x0c7e, 0x0d7e, + 0x0e7e, 0x017e, 0x027e, 0x1078, 0x415a, 0x2071, 0x6f10, 0x713c, + 0x81ff, 0x0040, 0x5079, 0x2061, 0x0100, 0x2069, 0x0140, 0x6904, + 0x017e, 0x017f, 0xa194, 0x4000, 0x0040, 0x507f, 0x6017, 0x0010, + 0x7144, 0xa192, 0x0002, 0x00c8, 0x5071, 0x8108, 0x7146, 0x1078, + 0x4151, 0x713c, 0xa188, 0x0007, 0x210c, 0xa18e, 0x0006, 0x00c0, + 0x506d, 0x6017, 0x0012, 0x0078, 0x5079, 0x6017, 0x0016, 0x0078, + 0x5079, 0x1078, 0x6c76, 0x2009, 0x004a, 0x1078, 0x5591, 0x0078, + 0x5079, 0x027f, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c, 0x1078, + 0x4151, 0x0078, 0x5079, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x057e, + 0x047e, 0x007e, 0x127e, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0, + 0x2071, 0x6f10, 0x7018, 0x2068, 0x8dff, 0x0040, 0x50af, 0x68a0, + 0xa406, 0x0040, 0x509f, 0x6854, 0x2068, 0x0078, 0x5094, 0x6010, + 0x2060, 0x643c, 0x6540, 0x6644, 0xa6b4, 0x000f, 0x2d60, 0x1078, + 0x3522, 0x0040, 0x50af, 0x1078, 0x5374, 0xa085, 0x0001, 0x127f, + 0x007f, 0x047f, 0x057f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, + 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x4a83, 0x20a3, 0x0f00, + 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, + 0x1078, 0x4fd1, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1, + 0x020b, 0x1078, 0x4afa, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a9, + 0x0006, 0x2011, 0x6d40, 0x2019, 0x6d40, 0x23a6, 0x22a6, 0xa398, + 0x0002, 0xa290, 0x0002, 0x00f0, 0x50dd, 0x20a3, 0x0000, 0x20a3, + 0x0000, 0x60c3, 0x001c, 0x1078, 0x4fd1, 0x147f, 0x157f, 0x007c, + 0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b, 0x1078, 0x4ada, + 0x1078, 0x4af1, 0x7810, 0x007e, 0xa080, 0x0015, 0x2098, 0x7808, + 0xa088, 0x0002, 0x21a8, 0x53a6, 0xa080, 0x0004, 0x8003, 0x60c2, + 0x007f, 0xa080, 0x0001, 0x2004, 0x7812, 0x1078, 0x4fd1, 0x027f, + 0x017f, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, + 0x1078, 0x4a83, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, + 0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x4fd1, 0x147f, 0x157f, + 0x007c, 0x0e7e, 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, + 0x6f10, 0x700c, 0x2060, 0x8cff, 0x0040, 0x513f, 0x600c, 0x007e, + 0x1078, 0x556a, 0x1078, 0x5374, 0x0c7f, 0x0078, 0x5133, 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, + 0x6f10, 0x7024, 0x2060, 0x8cff, 0x0040, 0x5198, 0x1078, 0x4fe5, + 0x68c3, 0x0000, 0x1078, 0x414c, 0x2009, 0x0013, 0x1078, 0x5591, + 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040, 0x517b, 0x6827, 0x0004, + 0x7804, 0xa084, 0x4000, 0x0040, 0x518d, 0x7803, 0x1000, 0x7803, + 0x0000, 0x0078, 0x518d, 0xd084, 0x0040, 0x5182, 0x6827, 0x0001, + 0x0078, 0x5184, 0x00f0, 0x516a, 0x7804, 0xa084, 0x1000, 0x0040, + 0x518d, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x007f, 0x017f, + 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c, + 0x2001, 0x6d00, 0x2004, 0xa096, 0x0001, 0x0040, 0x51d0, 0xa096, + 0x0004, 0x0040, 0x51d0, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, + 0x318e, 0x1078, 0x40d1, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040, + 0x51be, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x51d0, + 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0x51d0, 0xd084, 0x0040, + 0x51c5, 0x6827, 0x0001, 0x0078, 0x51c7, 0x00f0, 0x51ad, 0x7804, + 0xa084, 0x1000, 0x0040, 0x51d0, 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, 0x6f10, 0x703c, 0x2060, 0x8cff, 0x0040, 0x5228, + 0x6817, 0x0010, 0x68cb, 0x0000, 0x68c7, 0x0000, 0x1078, 0x415a, + 0x1078, 0x1a20, 0xa39d, 0x0000, 0x00c0, 0x5202, 0x2009, 0x0049, + 0x1078, 0x5591, 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0040, 0x5215, + 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x5227, 0x7803, + 0x1000, 0x7803, 0x0000, 0x0078, 0x5227, 0xd094, 0x0040, 0x521c, + 0x6827, 0x0002, 0x0078, 0x521e, 0x00f0, 0x5204, 0x7804, 0xa084, + 0x1000, 0x0040, 0x5227, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, + 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, + 0x127f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0x6f10, + 0x6a06, 0x127f, 0x0d7f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, + 0x2069, 0x6f10, 0x6a32, 0x127f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, + 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2071, 0x6f10, 0x7614, 0x2660, + 0x2678, 0x2091, 0x8000, 0x8cff, 0x0040, 0x5286, 0x601c, 0xa206, + 0x00c0, 0x5281, 0x7014, 0xac36, 0x00c0, 0x5260, 0x660c, 0x7616, + 0x7010, 0xac36, 0x00c0, 0x526e, 0x2c00, 0xaf36, 0x0040, 0x526c, + 0x2f00, 0x7012, 0x0078, 0x526e, 0x7013, 0x0000, 0x660c, 0x067e, + 0x2c00, 0xaf06, 0x0040, 0x5277, 0x7e0e, 0x0078, 0x5278, 0x2678, + 0x600f, 0x0000, 0x1078, 0x6283, 0x1078, 0x5374, 0x0c7f, 0x0078, + 0x5253, 0x2c78, 0x600c, 0x2060, 0x0078, 0x5253, 0x127f, 0x007f, + 0x067f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0x157e, 0x147e, 0x20a1, + 0x020b, 0x1078, 0x4c93, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, + 0x20a2, 0x20a2, 0x20a3, 0x4000, 0x0078, 0x52cf, 0x157e, 0x147e, + 0x20a1, 0x020b, 0x1078, 0x4c93, 0x7810, 0x20a2, 0xa006, 0x20a2, + 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, 0x0078, 0x52cf, 0x157e, + 0x147e, 0x20a1, 0x020b, 0x1078, 0x4c93, 0x7810, 0x20a2, 0xa006, + 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, 0x52cf, + 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x4c93, 0x7810, 0x20a2, + 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x1078, + 0x537f, 0x60c3, 0x0020, 0x1078, 0x4fd1, 0x147f, 0x157f, 0x007c, + 0x127e, 0x0c7e, 0x2091, 0x8000, 0x2061, 0x0100, 0x6120, 0xd1b4, + 0x00c0, 0x52e7, 0xd1bc, 0x00c0, 0x5331, 0x0078, 0x5371, 0x2009, + 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, 0x0140, + 0x20a9, 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, 0x0040, + 0x5328, 0x6020, 0xd0b4, 0x0040, 0x5328, 0x6024, 0xd094, 0x00c0, + 0x5328, 0x2104, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x5328, + 0x00f0, 0x52f4, 0x027e, 0x6198, 0xa18c, 0x00ff, 0x8107, 0x6130, + 0xa18c, 0x00ff, 0xa10d, 0x6088, 0x628c, 0x618e, 0x608b, 0xbc91, + 0x6043, 0x0001, 0x6043, 0x0000, 0x608a, 0x628e, 0x6024, 0xd094, + 0x00c0, 0x5327, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x531e, 0x027f, + 0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, 0x0078, + 0x5371, 0x2009, 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, + 0x2069, 0x0140, 0x20a9, 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, + 0x4000, 0x0040, 0x536a, 0x6020, 0xd0bc, 0x0040, 0x536a, 0x2104, + 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x536a, 0x00f0, 0x533e, + 0x027e, 0x6164, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, 0x00ff, + 0xa10d, 0x6088, 0x628c, 0x608b, 0xbc91, 0x618e, 0x6043, 0x0001, + 0x6043, 0x0000, 0x608a, 0x628e, 0x6a04, 0xa294, 0x4000, 0x00c0, + 0x5364, 0x027f, 0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, + 0x0000, 0x0c7f, 0x127f, 0x007c, 0x0e7e, 0x2071, 0x6f10, 0x7020, + 0xa005, 0x0040, 0x537d, 0x8001, 0x7022, 0x0e7f, 0x007c, 0x20a9, + 0x0008, 0x20a2, 0x00f0, 0x5381, 0x20a2, 0x20a2, 0x007c, 0x0f7e, + 0x0e7e, 0x0d7e, 0x0c7e, 0x077e, 0x067e, 0x007e, 0x127e, 0x2091, + 0x8000, 0x2071, 0x6f10, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, + 0x87ff, 0x0040, 0x5417, 0x8cff, 0x0040, 0x5417, 0x601c, 0xa086, + 0x0006, 0x00c0, 0x5412, 0x88ff, 0x0040, 0x53ae, 0x2800, 0xac06, + 0x00c0, 0x5412, 0x2039, 0x0000, 0x0078, 0x53b2, 0x6018, 0xa206, + 0x00c0, 0x5412, 0x7024, 0xac06, 0x00c0, 0x53e0, 0x2069, 0x0100, + 0x68c0, 0xa005, 0x0040, 0x53db, 0x6817, 0x0008, 0x68c3, 0x0000, + 0x1078, 0x54a4, 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, + 0xa384, 0x1000, 0x0040, 0x53d0, 0x6803, 0x0100, 0x6803, 0x0000, + 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x53d8, 0x6827, 0x0001, + 0x037f, 0x0078, 0x53e0, 0x6003, 0x0009, 0x630a, 0x0078, 0x5412, + 0x7014, 0xac36, 0x00c0, 0x53e6, 0x660c, 0x7616, 0x7010, 0xac36, + 0x00c0, 0x53f4, 0x2c00, 0xaf36, 0x0040, 0x53f2, 0x2f00, 0x7012, + 0x0078, 0x53f4, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, + 0x0040, 0x53fd, 0x7e0e, 0x0078, 0x53fe, 0x2678, 0x600f, 0x0000, + 0x6010, 0x2068, 0x1078, 0x6120, 0x0040, 0x5408, 0x1078, 0x6bb3, + 0x1078, 0x6283, 0x1078, 0x5374, 0x88ff, 0x00c0, 0x5421, 0x0c7f, + 0x0078, 0x5398, 0x2c78, 0x600c, 0x2060, 0x0078, 0x5398, 0xa006, + 0x127f, 0x007f, 0x067f, 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, + 0x007c, 0x6017, 0x0000, 0x0c7f, 0xa8c5, 0x0001, 0x0078, 0x5418, + 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x027e, 0x007e, 0x127e, + 0x2091, 0x8000, 0x2071, 0x6f10, 0x7638, 0x2660, 0x2678, 0x8cff, + 0x0040, 0x5493, 0x601c, 0xa086, 0x0006, 0x00c0, 0x548e, 0x88ff, + 0x0040, 0x5448, 0x2800, 0xac06, 0x00c0, 0x548e, 0x0078, 0x544c, + 0x6018, 0xa206, 0x00c0, 0x548e, 0x703c, 0xac06, 0x00c0, 0x545e, + 0x037e, 0x2019, 0x0001, 0x1078, 0x51da, 0x7033, 0x0000, 0x703f, + 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x037f, 0x7038, 0xac36, + 0x00c0, 0x5464, 0x660c, 0x763a, 0x7034, 0xac36, 0x00c0, 0x5472, + 0x2c00, 0xaf36, 0x0040, 0x5470, 0x2f00, 0x7036, 0x0078, 0x5472, + 0x7037, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x547b, + 0x7e0e, 0x0078, 0x547c, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, + 0x1078, 0x6120, 0x0040, 0x5486, 0x1078, 0x6bb3, 0x1078, 0x6283, + 0x88ff, 0x00c0, 0x549d, 0x0c7f, 0x0078, 0x5437, 0x2c78, 0x600c, + 0x2060, 0x0078, 0x5437, 0xa006, 0x127f, 0x007f, 0x027f, 0x067f, + 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x6017, 0x0000, 0x0c7f, + 0xa8c5, 0x0001, 0x0078, 0x5494, 0x0e7e, 0x2071, 0x6f10, 0x2001, + 0x6d00, 0x2004, 0xa086, 0x0002, 0x00c0, 0x54b2, 0x7007, 0x0005, + 0x0078, 0x54b4, 0x7007, 0x0000, 0x0e7f, 0x007c, 0x0f7e, 0x0e7e, + 0x0c7e, 0x067e, 0x027e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, + 0x6f10, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x54f4, + 0x2200, 0xac06, 0x00c0, 0x54ef, 0x7038, 0xac36, 0x00c0, 0x54d2, + 0x660c, 0x763a, 0x7034, 0xac36, 0x00c0, 0x54e0, 0x2c00, 0xaf36, + 0x0040, 0x54de, 0x2f00, 0x7036, 0x0078, 0x54e0, 0x7037, 0x0000, + 0x660c, 0x2c00, 0xaf06, 0x0040, 0x54e8, 0x7e0e, 0x0078, 0x54e9, + 0x2678, 0x600f, 0x0000, 0xa085, 0x0001, 0x0078, 0x54f4, 0x2c78, + 0x600c, 0x2060, 0x0078, 0x54c5, 0x127f, 0x007f, 0x027f, 0x067f, + 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0x2061, 0x7400, 0x2a70, 0x7060, + 0x7046, 0x704b, 0x7400, 0x007c, 0x0e7e, 0x127e, 0x2071, 0x6d00, + 0x2091, 0x8000, 0x7544, 0xa582, 0x0001, 0x0048, 0x5536, 0x7048, + 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, 0x5522, 0xace0, 0x0008, + 0x7054, 0xac02, 0x00c8, 0x551e, 0x0078, 0x5511, 0x2061, 0x7400, + 0x0078, 0x5511, 0x6003, 0x0008, 0x8529, 0x7546, 0xaca8, 0x0008, + 0x7054, 0xa502, 0x00c8, 0x5532, 0x754a, 0xa085, 0x0001, 0x127f, + 0x0e7f, 0x007c, 0x704b, 0x7400, 0x0078, 0x552d, 0xa006, 0x0078, + 0x552f, 0x0e7e, 0x2071, 0x6d00, 0x7544, 0xa582, 0x0001, 0x0048, + 0x5567, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, 0x5554, + 0xace0, 0x0008, 0x7054, 0xac02, 0x00c8, 0x5550, 0x0078, 0x5543, + 0x2061, 0x7400, 0x0078, 0x5543, 0x6003, 0x0008, 0x8529, 0x7546, + 0xaca8, 0x0008, 0x7054, 0xa502, 0x00c8, 0x5563, 0x754a, 0xa085, + 0x0001, 0x0e7f, 0x007c, 0x704b, 0x7400, 0x0078, 0x555f, 0xa006, + 0x0078, 0x5561, 0xac82, 0x7400, 0x1048, 0x12b7, 0x2001, 0x6d15, + 0x2004, 0xac02, 0x10c8, 0x12b7, 0xa006, 0x6006, 0x600a, 0x600e, + 0x6012, 0x6016, 0x601a, 0x601f, 0x0000, 0x6003, 0x0000, 0x2061, + 0x6d00, 0x6044, 0x8000, 0x6046, 0xa086, 0x0001, 0x0040, 0x5589, + 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x476a, 0x127f, 0x0078, + 0x5588, 0x601c, 0xa084, 0x000f, 0x0079, 0x5596, 0x559f, 0x55a7, + 0x55c3, 0x55df, 0x629a, 0x62b6, 0x62d2, 0x559f, 0x55a7, 0xa18e, + 0x0047, 0x00c0, 0x55a6, 0xa016, 0x1078, 0x1532, 0x007c, 0x067e, + 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12b7, 0x1079, 0x55b1, 0x067f, + 0x007c, 0x55c1, 0x5698, 0x5792, 0x55c1, 0x57d7, 0x55c1, 0x55c1, + 0x55c1, 0x5653, 0x5a4d, 0x55c1, 0x55c1, 0x55c1, 0x55c1, 0x55c1, + 0x55c1, 0x1078, 0x12b7, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, + 0x12b7, 0x1079, 0x55cd, 0x067f, 0x007c, 0x55dd, 0x55dd, 0x55dd, + 0x55dd, 0x55dd, 0x55dd, 0x55dd, 0x55dd, 0x5e10, 0x5edd, 0x55dd, + 0x5e29, 0x5e8f, 0x5e29, 0x5e8f, 0x55dd, 0x1078, 0x12b7, 0x067e, + 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12b7, 0x1079, 0x55e9, 0x067f, + 0x007c, 0x55f9, 0x5a96, 0x5b05, 0x5bbb, 0x5cd2, 0x55f9, 0x55f9, + 0x55f9, 0x5a75, 0x5dc6, 0x5dca, 0x55f9, 0x55f9, 0x55f9, 0x55f9, + 0x5df0, 0x1078, 0x12b7, 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, 0x5609, 0x0e7e, 0x6010, 0x2070, + 0x7007, 0x0000, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x556a, 0x007c, + 0x0d7e, 0x037e, 0x7330, 0xa386, 0x0200, 0x00c0, 0x562d, 0x6018, + 0x2068, 0x6813, 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, 0x0040, + 0x5637, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6b32, 0x1078, + 0x556a, 0x037f, 0x0d7f, 0x007c, 0x0d7e, 0x20a9, 0x000e, 0x2e98, + 0x6010, 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x00c0, 0x5650, 0x6018, + 0x2068, 0x7038, 0x680a, 0x703c, 0x680e, 0x6800, 0xc08d, 0x6802, + 0x0d7f, 0x0078, 0x5615, 0x2100, 0xa1b2, 0x0024, 0x10c8, 0x12b7, + 0x0079, 0x565a, 0x5680, 0x568c, 0x5680, 0x5680, 0x5680, 0x5680, + 0x567e, 0x567e, 0x567e, 0x567e, 0x567e, 0x567e, 0x567e, 0x567e, + 0x567e, 0x567e, 0x567e, 0x567e, 0x567e, 0x567e, 0x567e, 0x567e, + 0x567e, 0x567e, 0x567e, 0x567e, 0x567e, 0x567e, 0x567e, 0x567e, + 0x567e, 0x5680, 0x567e, 0x5680, 0x5680, 0x567e, 0x1078, 0x12b7, + 0x6003, 0x0001, 0x6106, 0x1078, 0x4376, 0x127e, 0x2091, 0x8000, + 0x1078, 0x476a, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, + 0x4376, 0x127e, 0x2091, 0x8000, 0x1078, 0x476a, 0x127f, 0x007c, + 0x6004, 0xa0b2, 0x0024, 0x10c8, 0x12b7, 0xa1b6, 0x0013, 0x00c0, + 0x56a4, 0x2008, 0x0079, 0x5706, 0xa1b6, 0x0014, 0x00c0, 0x56fd, + 0x1078, 0x4671, 0x6004, 0xa08e, 0x0000, 0x0040, 0x56fe, 0xa08e, + 0x0002, 0x0040, 0x56c9, 0xa08e, 0x0003, 0x0040, 0x56c9, 0xa08e, + 0x0004, 0x0040, 0x56c9, 0xa08e, 0x001f, 0x0040, 0x56fe, 0xa08e, + 0x0021, 0x0040, 0x5702, 0xa08e, 0x0022, 0x0040, 0x56fe, 0x0078, + 0x56f9, 0x1078, 0x206f, 0x2001, 0x0007, 0x1078, 0x33f3, 0x6018, + 0xa080, 0x0028, 0x200c, 0x1078, 0x5778, 0xa186, 0x007e, 0x00c0, + 0x56df, 0x2001, 0x6d2f, 0x2014, 0xa295, 0x0001, 0x2202, 0x017e, + 0x027e, 0x037e, 0x2110, 0x2019, 0x0028, 0x1078, 0x445c, 0x1078, + 0x43a9, 0x0c7e, 0x6018, 0xa065, 0x0040, 0x56f0, 0x1078, 0x35cf, + 0x0c7f, 0x2c08, 0x1078, 0x6a57, 0x037f, 0x027f, 0x017f, 0x1078, + 0x342f, 0x1078, 0x556a, 0x1078, 0x476a, 0x007c, 0x1078, 0x5778, + 0x0078, 0x56f9, 0x1078, 0x5786, 0x0078, 0x56f9, 0x572c, 0x572e, + 0x5732, 0x5736, 0x573a, 0x573e, 0x572a, 0x572a, 0x572a, 0x572a, + 0x572a, 0x572a, 0x572a, 0x572a, 0x572a, 0x572a, 0x572a, 0x572a, + 0x572a, 0x572a, 0x572a, 0x572a, 0x572a, 0x572a, 0x572a, 0x572a, + 0x572a, 0x572a, 0x572a, 0x572a, 0x5742, 0x5748, 0x572a, 0x5752, + 0x5748, 0x572a, 0x1078, 0x12b7, 0x0078, 0x5748, 0x2001, 0x000b, + 0x0078, 0x575b, 0x2001, 0x0003, 0x0078, 0x575b, 0x2001, 0x0005, + 0x0078, 0x575b, 0x2001, 0x0001, 0x0078, 0x575b, 0x2001, 0x0009, + 0x0078, 0x575b, 0x1078, 0x12b7, 0x0078, 0x575a, 0x1078, 0x33f3, + 0x1078, 0x4671, 0x6003, 0x0002, 0x6017, 0x0028, 0x1078, 0x476a, + 0x0078, 0x575a, 0x1078, 0x4671, 0x6003, 0x0004, 0x6017, 0x0028, + 0x1078, 0x476a, 0x007c, 0x1078, 0x33f3, 0x1078, 0x4671, 0x6003, + 0x0002, 0x037e, 0x2019, 0x6d5c, 0x2304, 0xa084, 0xff00, 0x00c0, + 0x576d, 0x2019, 0x0028, 0x0078, 0x5772, 0x8007, 0x8003, 0x801b, + 0x831b, 0xa318, 0x6316, 0x037f, 0x1078, 0x476a, 0x0078, 0x575a, + 0x0e7e, 0x6010, 0xa005, 0x0040, 0x5784, 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, 0x12b7, 0x6604, 0xa6b6, 0x001f, + 0x00c0, 0x57a6, 0x1078, 0x55fb, 0x0078, 0x57c6, 0x6604, 0xa6b6, + 0x0000, 0x00c0, 0x57af, 0x1078, 0x563c, 0x0078, 0x57c6, 0x6604, + 0xa6b6, 0x0022, 0x00c0, 0x57b8, 0x1078, 0x5620, 0x0078, 0x57c6, + 0xa1b6, 0x0015, 0x00c0, 0x57c0, 0x1079, 0x57cb, 0x0078, 0x57c6, + 0xa1b6, 0x0016, 0x00c0, 0x57c7, 0x1079, 0x58f6, 0x007c, 0x1078, + 0x559f, 0x0078, 0x57c6, 0x57ef, 0x57f2, 0x57ef, 0x5833, 0x57ef, + 0x5892, 0x57ef, 0x57ef, 0x57ef, 0x58ce, 0x57ef, 0x58e4, 0xa1b6, + 0x0048, 0x0040, 0x57e3, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, + 0x1078, 0x1532, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74, 0x7000, + 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x556a, 0x007c, 0x0005, + 0x0005, 0x007c, 0x0e7e, 0x2071, 0x6d00, 0x7078, 0xa086, 0x0074, + 0x00c0, 0x581c, 0x1078, 0x6a2b, 0x00c0, 0x580e, 0x0d7e, 0x6018, + 0x2068, 0x1078, 0x5820, 0x0d7f, 0x2001, 0x0006, 0x1078, 0x33f3, + 0x1078, 0x206f, 0x1078, 0x556a, 0x0078, 0x581e, 0x2001, 0x000a, + 0x1078, 0x33f3, 0x1078, 0x206f, 0x6003, 0x0001, 0x6007, 0x0001, + 0x1078, 0x4376, 0x0078, 0x581e, 0x1078, 0x5889, 0x0e7f, 0x007c, + 0x6800, 0xd084, 0x0040, 0x5832, 0x2001, 0x0000, 0x1078, 0x33df, + 0x2069, 0x6d51, 0x6804, 0xd0a4, 0x0040, 0x5832, 0x2001, 0x0006, + 0x1078, 0x3401, 0x007c, 0x0d7e, 0x2011, 0x6d1e, 0x2204, 0xa086, + 0x0074, 0x00c0, 0x5885, 0x1078, 0x599f, 0x6018, 0x2068, 0xa080, + 0x0028, 0x2014, 0xa286, 0x007e, 0x0040, 0x5850, 0xa286, 0x0080, + 0x00c0, 0x5879, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x0078, 0x586f, + 0x0e7e, 0x0f7e, 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, 0x6d2f, + 0x2e04, 0xa085, 0x0003, 0x2072, 0x2071, 0x7280, 0x2079, 0x0100, + 0x2e04, 0xa084, 0x00ff, 0x2069, 0x6d19, 0x206a, 0x78e6, 0x8e70, + 0x2e04, 0x2069, 0x6d1a, 0x206a, 0x78ea, 0x0f7f, 0x0e7f, 0x2001, + 0x0006, 0x1078, 0x33f3, 0x1078, 0x206f, 0x1078, 0x556a, 0x0078, + 0x5887, 0x2001, 0x0004, 0x1078, 0x33f3, 0x6003, 0x0001, 0x6007, + 0x0003, 0x1078, 0x4376, 0x0078, 0x5887, 0x1078, 0x5889, 0x0d7f, + 0x007c, 0x2001, 0x0007, 0x1078, 0x33f3, 0x1078, 0x206f, 0x1078, + 0x556a, 0x007c, 0x0e7e, 0x2071, 0x6d00, 0x7078, 0xa086, 0x0014, + 0x00c0, 0x58c8, 0x7000, 0xa086, 0x0003, 0x00c0, 0x58a5, 0x6010, + 0xa005, 0x00c0, 0x58a5, 0x1078, 0x2ad1, 0x0d7e, 0x6018, 0x2068, + 0x1078, 0x34ca, 0x1078, 0x5820, 0x0d7f, 0x1078, 0x59a9, 0x00c0, + 0x58c8, 0x2001, 0x0006, 0x1078, 0x33f3, 0x0e7e, 0x6010, 0xa005, + 0x0040, 0x58c1, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, 0x7033, + 0x0200, 0x0e7f, 0x1078, 0x206f, 0x1078, 0x556a, 0x0078, 0x58cc, + 0x1078, 0x5778, 0x1078, 0x5889, 0x0e7f, 0x007c, 0x2011, 0x6d1e, + 0x2204, 0xa086, 0x0014, 0x00c0, 0x58e1, 0x2001, 0x0002, 0x1078, + 0x33f3, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x4376, 0x0078, + 0x58e3, 0x1078, 0x5889, 0x007c, 0x2011, 0x6d1e, 0x2204, 0xa086, + 0x0004, 0x00c0, 0x58f3, 0x2001, 0x0007, 0x1078, 0x33f3, 0x1078, + 0x556a, 0x0078, 0x58f5, 0x1078, 0x5889, 0x007c, 0x57ef, 0x5902, + 0x57ef, 0x5928, 0x57ef, 0x5952, 0x57ef, 0x57ef, 0x57ef, 0x5967, + 0x57ef, 0x597a, 0x0c7e, 0x1078, 0x598d, 0x00c0, 0x5917, 0x2001, + 0x0000, 0x1078, 0x33df, 0x2001, 0x0002, 0x1078, 0x33f3, 0x6003, + 0x0001, 0x6007, 0x0002, 0x1078, 0x4376, 0x0078, 0x5926, 0x2009, + 0x728f, 0x2104, 0xa084, 0xff00, 0xa086, 0x1900, 0x00c0, 0x5924, + 0x1078, 0x556a, 0x0078, 0x5926, 0x1078, 0x5889, 0x0c7f, 0x007c, + 0x1078, 0x599c, 0x00c0, 0x593c, 0x2001, 0x0000, 0x1078, 0x33df, + 0x2001, 0x0002, 0x1078, 0x33f3, 0x6003, 0x0001, 0x6007, 0x0002, + 0x1078, 0x4376, 0x0078, 0x5951, 0x1078, 0x5778, 0x2009, 0x728f, + 0x2104, 0xa084, 0xff00, 0xa086, 0x1900, 0x00c0, 0x594f, 0x2001, + 0x0004, 0x1078, 0x33f3, 0x1078, 0x556a, 0x0078, 0x5951, 0x1078, + 0x5889, 0x007c, 0x1078, 0x599c, 0x00c0, 0x5962, 0x2001, 0x0004, + 0x1078, 0x33f3, 0x6003, 0x0001, 0x6007, 0x0003, 0x1078, 0x4376, + 0x0078, 0x5966, 0x1078, 0x5778, 0x1078, 0x5889, 0x007c, 0x1078, + 0x599c, 0x00c0, 0x5977, 0x2001, 0x0008, 0x1078, 0x33f3, 0x6003, + 0x0001, 0x6007, 0x0005, 0x1078, 0x4376, 0x0078, 0x5979, 0x1078, + 0x5889, 0x007c, 0x1078, 0x599c, 0x00c0, 0x598a, 0x2001, 0x000a, + 0x1078, 0x33f3, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x4376, + 0x0078, 0x598c, 0x1078, 0x5889, 0x007c, 0x2009, 0x728e, 0x2104, + 0xa086, 0x0003, 0x00c0, 0x599b, 0x2009, 0x728f, 0x2104, 0xa084, + 0xff00, 0xa086, 0x2a00, 0x007c, 0xa085, 0x0001, 0x007c, 0x0c7e, + 0x017e, 0xac88, 0x0006, 0x2164, 0x1078, 0x3459, 0x017f, 0x0c7f, + 0x007c, 0x0e7e, 0x2071, 0x728c, 0x7004, 0xa086, 0x0014, 0x00c0, + 0x59cc, 0x7008, 0xa086, 0x0800, 0x00c0, 0x59cc, 0x700c, 0xd0ec, + 0x0040, 0x59ca, 0xa084, 0x0f00, 0xa086, 0x0100, 0x00c0, 0x59ca, + 0x7024, 0xd0a4, 0x0040, 0x59ca, 0xd08c, 0x0040, 0x59ca, 0xa006, + 0x0078, 0x59cc, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x0e7e, 0x0d7e, + 0x0c7e, 0x077e, 0x057e, 0x047e, 0x027e, 0x007e, 0x127e, 0x2091, + 0x8000, 0x2029, 0x6f19, 0x252c, 0x2021, 0x6f1f, 0x2424, 0x2061, + 0x7400, 0x2071, 0x6d00, 0x7244, 0x7060, 0xa202, 0x00c8, 0x5a23, + 0x1078, 0x6c0f, 0x0040, 0x5a1b, 0x671c, 0xa786, 0x0001, 0x0040, + 0x5a1b, 0xa786, 0x0007, 0x0040, 0x5a1b, 0x2500, 0xac06, 0x0040, + 0x5a1b, 0x2400, 0xac06, 0x0040, 0x5a1b, 0x0c7e, 0x6010, 0x2068, + 0x1078, 0x6120, 0x0040, 0x5a11, 0xa786, 0x0003, 0x00c0, 0x5a2d, + 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x36a1, 0x1078, + 0x6276, 0x6000, 0xa086, 0x0004, 0x00c0, 0x5a18, 0x1078, 0x15f2, + 0x1078, 0x6283, 0x0c7f, 0xace0, 0x0008, 0x7054, 0xac02, 0x00c8, + 0x5a23, 0x0078, 0x59e3, 0x127f, 0x007f, 0x027f, 0x047f, 0x057f, + 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0xa786, 0x0006, 0x00c0, + 0x5a08, 0x1078, 0x6bb3, 0x0078, 0x5a11, 0x220c, 0x2304, 0xa106, + 0x00c0, 0x5a40, 0x8210, 0x8318, 0x00f0, 0x5a35, 0xa006, 0x007c, + 0x2304, 0xa102, 0x0048, 0x5a48, 0x2001, 0x0001, 0x0078, 0x5a4a, + 0x2001, 0x0000, 0xa18d, 0x0001, 0x007c, 0x6004, 0xa08a, 0x0024, + 0x10c8, 0x12b7, 0xa08e, 0x0000, 0x0040, 0x5a71, 0xa08e, 0x0002, + 0x0040, 0x5a68, 0xa08e, 0x0003, 0x0040, 0x5a68, 0xa08e, 0x0004, + 0x0040, 0x5a68, 0xa08e, 0x001f, 0x0040, 0x5a71, 0x0078, 0x5a6a, + 0x1078, 0x206f, 0x1078, 0x4671, 0x1078, 0x556a, 0x1078, 0x476a, + 0x007c, 0x1078, 0x5778, 0x0078, 0x5a6a, 0xa182, 0x0040, 0x0079, + 0x5a79, 0x5a88, 0x5a88, 0x5a88, 0x5a88, 0x5a88, 0x5a88, 0x5a88, + 0x5a88, 0x5a88, 0x5a88, 0x5a88, 0x5a8a, 0x5a8a, 0x5a8a, 0x5a8a, + 0x1078, 0x12b7, 0x6003, 0x0001, 0x6106, 0x1078, 0x4327, 0x127e, + 0x2091, 0x8000, 0x1078, 0x476a, 0x127f, 0x007c, 0xa186, 0x0013, + 0x00c0, 0x5a9f, 0x6004, 0xa082, 0x0040, 0x0079, 0x5adf, 0xa186, + 0x0014, 0x10c0, 0x12b7, 0x6004, 0xa082, 0x0040, 0x0079, 0x5aa8, + 0x5ab9, 0x5ab7, 0x5ab7, 0x5ab7, 0x5ab7, 0x5ab7, 0x5ab7, 0x5ab7, + 0x5ab7, 0x5ab7, 0x5ab7, 0x5ad4, 0x5ad4, 0x5ad4, 0x5ad4, 0x1078, + 0x12b7, 0x2001, 0x0007, 0x1078, 0x33f3, 0x1078, 0x4671, 0x0d7e, + 0x6110, 0x2168, 0x1078, 0x6120, 0x0040, 0x5ace, 0x6837, 0x0103, + 0x684b, 0x0028, 0x1078, 0x36a1, 0x1078, 0x6276, 0x0d7f, 0x1078, + 0x556a, 0x1078, 0x476a, 0x007c, 0x2001, 0x0007, 0x1078, 0x33f3, + 0x1078, 0x4671, 0x1078, 0x556a, 0x1078, 0x476a, 0x007c, 0x5af0, + 0x5aee, 0x5aee, 0x5aee, 0x5aee, 0x5aee, 0x5aee, 0x5aee, 0x5aee, + 0x5aee, 0x5aee, 0x5afe, 0x5afe, 0x5afe, 0x5afe, 0x1078, 0x12b7, + 0x1078, 0x4671, 0x6003, 0x0002, 0x1078, 0x476a, 0x6010, 0xa088, + 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x007c, 0x1078, 0x4671, + 0x6003, 0x000f, 0x1078, 0x476a, 0x007c, 0xa182, 0x0040, 0x0079, + 0x5b09, 0x5b18, 0x5b18, 0x5b18, 0x5b18, 0x5b18, 0x5b1a, 0x5b98, + 0x5bb0, 0x5b18, 0x5b18, 0x5b18, 0x5b18, 0x5b18, 0x5b18, 0x5b18, + 0x1078, 0x12b7, 0x0e7e, 0x0d7e, 0x2071, 0x728c, 0x6110, 0x2168, + 0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0040, 0x5b87, 0xa68c, 0x00ff, + 0xa186, 0x0002, 0x0040, 0x5b4c, 0xa186, 0x0028, 0x00c0, 0x5b36, + 0x1078, 0x628a, 0x684b, 0x001c, 0x0078, 0x5b4e, 0xd6dc, 0x0040, + 0x5b41, 0x684b, 0x0015, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, + 0x5b4e, 0xd6d4, 0x0040, 0x5b4c, 0x684b, 0x0007, 0x7318, 0x6b62, + 0x731c, 0x6b5e, 0x0078, 0x5b4e, 0x684b, 0x0000, 0x6837, 0x0103, + 0x6e46, 0xa01e, 0xd6c4, 0x0040, 0x5b61, 0x7328, 0x732c, 0x6b56, + 0x037e, 0x2308, 0x2019, 0x7298, 0xad90, 0x0019, 0x1078, 0x5f4c, + 0x037f, 0xd6cc, 0x0040, 0x5b8c, 0x7124, 0x695a, 0xa192, 0x0021, + 0x00c8, 0x5b75, 0x2071, 0x7298, 0x831c, 0x2300, 0xae18, 0xad90, + 0x001d, 0x1078, 0x5f4c, 0x0078, 0x5b8c, 0x6838, 0xd0fc, 0x0040, + 0x5b7e, 0x2009, 0x0020, 0x695a, 0x0078, 0x5b6a, 0x0f7e, 0x2d78, + 0x1078, 0x5ee4, 0x0f7f, 0x1078, 0x5f39, 0x0078, 0x5b8e, 0x684b, + 0x0000, 0x6837, 0x0103, 0x6e46, 0x1078, 0x36a1, 0x6218, 0x2268, + 0x6a3c, 0x8211, 0x6a3e, 0x0d7f, 0x0e7f, 0x1078, 0x556a, 0x007c, + 0x0f7e, 0x6003, 0x0003, 0x2079, 0x728c, 0x7c04, 0x7b00, 0x7e0c, + 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f, + 0x2c10, 0x1078, 0x17de, 0x1078, 0x4395, 0x1078, 0x4821, 0x007c, + 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, + 0x1078, 0x1532, 0x007c, 0xa182, 0x0040, 0x0079, 0x5bbf, 0x5bce, + 0x5bce, 0x5bce, 0x5bce, 0x5bce, 0x5bd0, 0x5c5e, 0x5bce, 0x5bce, + 0x5c74, 0x5cb4, 0x5bce, 0x5bce, 0x5bce, 0x5bce, 0x1078, 0x12b7, + 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071, 0x728c, 0x6110, 0x2178, + 0x7614, 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, + 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x5c59, 0xa694, + 0xff00, 0xa284, 0x0c00, 0x0040, 0x5bf1, 0x7018, 0x7862, 0x701c, + 0x785e, 0xa284, 0x0300, 0x0040, 0x5c59, 0x1078, 0x130f, 0x1040, + 0x12b7, 0x2d00, 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, + 0x7838, 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, + 0x00ff, 0xa186, 0x0002, 0x0040, 0x5c2b, 0xa186, 0x0028, 0x00c0, + 0x5c15, 0x684b, 0x001c, 0x0078, 0x5c2d, 0xd6dc, 0x0040, 0x5c20, + 0x684b, 0x0015, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x5c2d, + 0xd6d4, 0x0040, 0x5c2b, 0x684b, 0x0007, 0x7318, 0x6b62, 0x731c, + 0x6b5e, 0x0078, 0x5c2d, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, + 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0040, 0x5c42, 0x7328, 0x732c, + 0x6b56, 0x037e, 0x2308, 0x2019, 0x7298, 0xad90, 0x0019, 0x1078, + 0x5f4c, 0x037f, 0xd6cc, 0x0040, 0x5c59, 0x7124, 0x695a, 0xa192, + 0x0021, 0x00c8, 0x5c56, 0x2071, 0x7298, 0x831c, 0x2300, 0xae18, + 0xad90, 0x001d, 0x1078, 0x5f4c, 0x0078, 0x5c59, 0x2d78, 0x1078, + 0x5ee4, 0x0d7f, 0x0e7f, 0x0f7f, 0x077f, 0x007c, 0x0f7e, 0x6003, + 0x0003, 0x2079, 0x728c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, + 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f, 0x2c10, 0x1078, + 0x17de, 0x1078, 0x4fca, 0x007c, 0x0d7e, 0x6003, 0x0002, 0x1078, + 0x4719, 0x1078, 0x4821, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, + 0x5cb2, 0xd1cc, 0x0040, 0x5c8d, 0x6948, 0x017e, 0x1078, 0x1338, + 0x0d7f, 0x1078, 0x5f39, 0x0078, 0x5cb0, 0x6837, 0x0103, 0x6944, + 0xa184, 0x00ff, 0xa186, 0x0002, 0x0040, 0x5cac, 0xa086, 0x0028, + 0x00c0, 0x5c9e, 0x684b, 0x001c, 0x0078, 0x5cae, 0xd1dc, 0x0040, + 0x5ca5, 0x684b, 0x0015, 0x0078, 0x5cae, 0xd1d4, 0x0040, 0x5cac, + 0x684b, 0x0007, 0x0078, 0x5cae, 0x684b, 0x0000, 0x1078, 0x36a1, + 0x1078, 0x556a, 0x0d7f, 0x007c, 0x2001, 0x0007, 0x1078, 0x33f3, + 0x1078, 0x4719, 0x0f7e, 0x0d7e, 0x6110, 0x2178, 0x1078, 0x6120, + 0x0040, 0x5ccb, 0x7837, 0x0103, 0x784b, 0x0028, 0x2f68, 0x1078, + 0x36a1, 0x1078, 0x6276, 0x0d7f, 0x0f7f, 0x1078, 0x556a, 0x1078, + 0x4821, 0x007c, 0xa182, 0x0040, 0x0079, 0x5cd6, 0x5ce5, 0x5ce5, + 0x5ce5, 0x5ce5, 0x5ce5, 0x5ce7, 0x5ce5, 0x5d82, 0x5d8a, 0x5ce5, + 0x5ce5, 0x5ce5, 0x5ce5, 0x5ce5, 0x5ce5, 0x1078, 0x12b7, 0x077e, + 0x0f7e, 0x0e7e, 0x0d7e, 0x2071, 0x728c, 0x6110, 0x2178, 0x7614, + 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, + 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x5d74, 0xa694, 0xff00, + 0xa284, 0x0c00, 0x0040, 0x5d08, 0x7018, 0x7862, 0x701c, 0x785e, + 0xa284, 0x0300, 0x0040, 0x5d71, 0x1078, 0x130f, 0x1040, 0x12b7, + 0x2d00, 0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, + 0x7838, 0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, + 0x00ff, 0xa186, 0x0002, 0x0040, 0x5d43, 0xa186, 0x0028, 0x00c0, + 0x5d2d, 0x684b, 0x001c, 0x0078, 0x5d45, 0xd6dc, 0x0040, 0x5d38, + 0x684b, 0x0015, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x5d45, + 0xd6d4, 0x0040, 0x5d43, 0x684b, 0x0007, 0x7318, 0x6b62, 0x731c, + 0x6b5e, 0x0078, 0x5d45, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, + 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0040, 0x5d5a, 0x7328, 0x732c, + 0x6b56, 0x037e, 0x2308, 0x2019, 0x7298, 0xad90, 0x0019, 0x1078, + 0x5f4c, 0x037f, 0xd6cc, 0x0040, 0x5d71, 0x7124, 0x695a, 0xa192, + 0x0021, 0x00c8, 0x5d6e, 0x2071, 0x7298, 0x831c, 0x2300, 0xae18, + 0xad90, 0x001d, 0x1078, 0x5f4c, 0x0078, 0x5d71, 0x2d78, 0x1078, + 0x5ee4, 0xd6dc, 0x00c0, 0x5d77, 0xa006, 0x0078, 0x5d7b, 0x2001, + 0x0001, 0x7218, 0x731c, 0x1078, 0x156f, 0x0d7f, 0x0e7f, 0x0f7f, + 0x077f, 0x007c, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, + 0x1532, 0x007c, 0x0d7e, 0x6003, 0x0002, 0x6110, 0x2168, 0x694c, + 0xd1e4, 0x0040, 0x5dc4, 0xd1cc, 0x0040, 0x5d9f, 0x6948, 0x017e, + 0x1078, 0x1338, 0x0d7f, 0x1078, 0x5f39, 0x0078, 0x5dc2, 0x6837, + 0x0103, 0x6944, 0xa184, 0x00ff, 0xa186, 0x0002, 0x0040, 0x5dbe, + 0xa086, 0x0028, 0x00c0, 0x5db0, 0x684b, 0x001c, 0x0078, 0x5dc0, + 0xd1dc, 0x0040, 0x5db7, 0x684b, 0x0015, 0x0078, 0x5dc0, 0xd1d4, + 0x0040, 0x5dbe, 0x684b, 0x0007, 0x0078, 0x5dc0, 0x684b, 0x0000, + 0x1078, 0x36a1, 0x1078, 0x556a, 0x0d7f, 0x007c, 0x1078, 0x4671, + 0x0078, 0x5dcc, 0x1078, 0x4719, 0x1078, 0x6120, 0x0040, 0x5de3, + 0x0d7e, 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0x6d0c, 0x210c, + 0xd18c, 0x00c0, 0x5dec, 0xd184, 0x00c0, 0x5de8, 0x6108, 0x694a, + 0x1078, 0x36a1, 0x0d7f, 0x1078, 0x556a, 0x1078, 0x476a, 0x007c, + 0x684b, 0x0004, 0x0078, 0x5de0, 0x684b, 0x0004, 0x0078, 0x5de0, + 0xa182, 0x0040, 0x0079, 0x5df4, 0x5e03, 0x5e03, 0x5e03, 0x5e03, + 0x5e03, 0x5e05, 0x5e03, 0x5e08, 0x5e03, 0x5e03, 0x5e03, 0x5e03, + 0x5e03, 0x5e03, 0x5e03, 0x1078, 0x12b7, 0x1078, 0x556a, 0x007c, + 0x007e, 0x027e, 0xa016, 0x1078, 0x1532, 0x027f, 0x007f, 0x007c, + 0xa182, 0x0025, 0x0079, 0x5e14, 0x5e1d, 0x5e1b, 0x5e1b, 0x5e1b, + 0x5e1b, 0x5e1b, 0x5e1b, 0x1078, 0x12b7, 0x6003, 0x0001, 0x6106, + 0x1078, 0x4327, 0x127e, 0x2091, 0x8000, 0x1078, 0x476a, 0x127f, + 0x007c, 0xa186, 0x0013, 0x00c0, 0x5e33, 0x6004, 0xa082, 0x0025, + 0x2008, 0x0079, 0x5e74, 0xa186, 0x0014, 0x00c0, 0x5e70, 0x1078, + 0x4671, 0x2001, 0x0007, 0x1078, 0x33f3, 0x6018, 0xa080, 0x0028, + 0x200c, 0x017e, 0x027e, 0x037e, 0x2110, 0x2019, 0x0028, 0x1078, + 0x445c, 0x1078, 0x43a9, 0x0c7e, 0x6018, 0xa065, 0x0040, 0x5e52, + 0x1078, 0x35cf, 0x0c7f, 0x2c08, 0x1078, 0x6a57, 0x037f, 0x027f, + 0x017f, 0x1078, 0x342f, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x6120, + 0x0040, 0x5e6a, 0x6837, 0x0103, 0x684b, 0x0006, 0x1078, 0x36a1, + 0x1078, 0x6276, 0x0d7f, 0x1078, 0x556a, 0x1078, 0x476a, 0x007c, + 0x1078, 0x559f, 0x0078, 0x5e6f, 0x5e7d, 0x5e7b, 0x5e7b, 0x5e7b, + 0x5e7b, 0x5e7b, 0x5e86, 0x1078, 0x12b7, 0x1078, 0x4671, 0x6017, + 0x0014, 0x6003, 0x000c, 0x1078, 0x476a, 0x007c, 0x1078, 0x4671, + 0x6017, 0x0014, 0x6003, 0x000e, 0x1078, 0x476a, 0x007c, 0xa182, + 0x002c, 0x00c8, 0x5e99, 0xa182, 0x0025, 0x0048, 0x5e99, 0x0079, + 0x5e9c, 0x1078, 0x559f, 0x007c, 0x5ea3, 0x5ea3, 0x5ea3, 0x5ea3, + 0x5ea5, 0x5ebf, 0x5ea3, 0x1078, 0x12b7, 0x0d7e, 0x1078, 0x6276, + 0x6010, 0x2068, 0x6837, 0x0103, 0x6850, 0xa084, 0x0040, 0x0040, + 0x5eb5, 0x684b, 0x0006, 0x0078, 0x5eb7, 0x684b, 0x0005, 0x6847, + 0x0000, 0x1078, 0x36a1, 0x1078, 0x556a, 0x0d7f, 0x007c, 0x0d7e, + 0x6010, 0x2068, 0x1078, 0x6120, 0x0040, 0x5ed9, 0x6837, 0x0103, + 0x6850, 0xa084, 0x0040, 0x0040, 0x5ed1, 0x684b, 0x0006, 0x0078, + 0x5ed3, 0x684b, 0x0005, 0x6847, 0x0000, 0x1078, 0x36a1, 0x1078, + 0x6276, 0x0d7f, 0x1078, 0x556a, 0x007c, 0x1078, 0x4671, 0x1078, + 0x556a, 0x1078, 0x476a, 0x007c, 0x057e, 0x067e, 0x0d7e, 0x0f7e, + 0x2029, 0x0001, 0xa182, 0x0101, 0x00c8, 0x5ef0, 0x0078, 0x5ef2, + 0x2009, 0x0100, 0x2130, 0x2069, 0x7298, 0x831c, 0x2300, 0xad18, + 0x2009, 0x0020, 0xaf90, 0x001d, 0x1078, 0x5f4c, 0xa6b2, 0x0020, + 0x7804, 0xa06d, 0x0040, 0x5f06, 0x1078, 0x1338, 0x1078, 0x130f, + 0x0040, 0x5f30, 0x8528, 0x6837, 0x0110, 0x683b, 0x0000, 0x2d20, + 0x7c06, 0xa68a, 0x003d, 0x00c8, 0x5f1c, 0x2608, 0xad90, 0x000f, + 0x1078, 0x5f4c, 0x0078, 0x5f30, 0xa6b2, 0x003c, 0x2009, 0x003c, + 0x2d78, 0xad90, 0x000f, 0x1078, 0x5f4c, 0x0078, 0x5f06, 0x0f7f, + 0x852f, 0xa5ad, 0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0078, 0x5f35, + 0x0f7f, 0x852f, 0xa5ad, 0x0003, 0x7d36, 0x0d7f, 0x067f, 0x057f, + 0x007c, 0x0f7e, 0x8dff, 0x0040, 0x5f4a, 0x6804, 0xa07d, 0x0040, + 0x5f48, 0x6807, 0x0000, 0x1078, 0x36a1, 0x2f68, 0x0078, 0x5f3d, + 0x1078, 0x36a1, 0x0f7f, 0x007c, 0x157e, 0xa184, 0x0001, 0x0040, + 0x5f52, 0x8108, 0x810c, 0x21a8, 0x2304, 0x8007, 0x2012, 0x8318, + 0x8210, 0x00f0, 0x5f54, 0x157f, 0x007c, 0x127e, 0x2091, 0x8000, + 0x601c, 0xa084, 0x000f, 0x1079, 0x5f67, 0x127f, 0x007c, 0x5f76, + 0x5f6f, 0x5f71, 0x5f8d, 0x5f6f, 0x5f71, 0x5f71, 0x5f71, 0x1078, + 0x12b7, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0x0d7e, 0x6010, + 0x2068, 0x1078, 0x6120, 0x0040, 0x5f8a, 0xa00e, 0x2001, 0x0005, + 0x1078, 0x372d, 0x1078, 0x36a1, 0x1078, 0x556a, 0xa085, 0x0001, + 0x0d7f, 0x007c, 0xa006, 0x0078, 0x5f88, 0x6000, 0xa08a, 0x0010, + 0x10c8, 0x12b7, 0x1079, 0x5f95, 0x007c, 0x5fa5, 0x5fc4, 0x5fa7, + 0x5fd5, 0x5fc0, 0x5fa5, 0x5f71, 0x5f76, 0x5f76, 0x5f71, 0x5f71, + 0x5f71, 0x5f71, 0x5f71, 0x5f71, 0x5f71, 0x1078, 0x12b7, 0x0d7e, + 0x6010, 0x2068, 0x1078, 0x6120, 0x0040, 0x5fb2, 0x6850, 0xa085, + 0x0005, 0x6852, 0x0d7f, 0x6007, 0x0025, 0x6003, 0x000b, 0x601f, + 0x0002, 0x1078, 0x4327, 0x1078, 0x476a, 0xa085, 0x0001, 0x007c, + 0x1078, 0x15f2, 0x0078, 0x5fa7, 0x0e7e, 0x2071, 0x6f10, 0x7024, + 0xac06, 0x00c0, 0x5fcd, 0x1078, 0x5148, 0x1078, 0x5083, 0x0e7f, + 0x00c0, 0x5fa7, 0x1078, 0x5f71, 0x007c, 0x037e, 0x0e7e, 0x2071, + 0x6f10, 0x703c, 0xac06, 0x00c0, 0x5fe1, 0x2019, 0x0000, 0x1078, + 0x51da, 0x1078, 0x54b6, 0x0e7f, 0x037f, 0x00c0, 0x5fa7, 0x1078, + 0x5f71, 0x007c, 0x0c7e, 0x601c, 0xa084, 0x000f, 0x1079, 0x5ff2, + 0x0c7f, 0x007c, 0x5ffb, 0x605b, 0x60c8, 0x5fff, 0x5ffb, 0x5ffb, + 0x5ffb, 0x556a, 0x605b, 0x007c, 0x6017, 0x0001, 0x007c, 0x6000, + 0xa08a, 0x0010, 0x10c8, 0x12b7, 0x1079, 0x6007, 0x007c, 0x6017, + 0x6019, 0x603a, 0x604d, 0x604d, 0x6017, 0x5ffb, 0x5ffb, 0x5ffb, + 0x604d, 0x604d, 0x6017, 0x6017, 0x6017, 0x6017, 0x6058, 0x1078, + 0x12b7, 0x0e7e, 0x6010, 0x2070, 0x7050, 0xa085, 0x0040, 0x7052, + 0x2071, 0x6f10, 0x7024, 0xac06, 0x0040, 0x6036, 0x1078, 0x5083, + 0x6007, 0x0025, 0x6003, 0x000b, 0x601f, 0x0002, 0x6017, 0x0014, + 0x1078, 0x4327, 0x1078, 0x476a, 0x0e7f, 0x007c, 0x6017, 0x0001, + 0x0078, 0x6034, 0x0d7e, 0x6010, 0x2068, 0x6850, 0xa085, 0x0040, + 0x6852, 0x0d7f, 0x6007, 0x0025, 0x6003, 0x000b, 0x601f, 0x0002, + 0x1078, 0x4327, 0x1078, 0x476a, 0x007c, 0x0d7e, 0x6017, 0x0001, + 0x6010, 0x2068, 0x6850, 0xa085, 0x0040, 0x6852, 0x0d7f, 0x007c, + 0x1078, 0x556a, 0x007c, 0x6000, 0xa08a, 0x0010, 0x10c8, 0x12b7, + 0x1079, 0x6063, 0x007c, 0x6073, 0x5ffc, 0x6075, 0x6073, 0x6075, + 0x6073, 0x6073, 0x6073, 0x5ffb, 0x5ffb, 0x6073, 0x6073, 0x6073, + 0x6073, 0x6073, 0x6073, 0x1078, 0x12b7, 0x0d7e, 0x6018, 0x2068, + 0x6804, 0xa084, 0x00ff, 0x0d7f, 0xa08a, 0x000c, 0x10c8, 0x12b7, + 0x1079, 0x6083, 0x007c, 0x608f, 0x60b1, 0x608f, 0x60b1, 0x608f, + 0x60b1, 0x6091, 0x609a, 0x608f, 0x60b1, 0x608f, 0x60aa, 0x1078, + 0x12b7, 0x6004, 0xa08e, 0x0004, 0x0040, 0x60ac, 0xa08e, 0x0002, + 0x0040, 0x60ac, 0xa08e, 0x0000, 0x0040, 0x60c0, 0xa08e, 0x001f, + 0x0040, 0x60c0, 0xa08e, 0x0021, 0x0040, 0x60c4, 0xa08e, 0x0022, + 0x0040, 0x60c0, 0x1078, 0x2051, 0x1078, 0x5778, 0x1078, 0x556a, + 0x007c, 0x1078, 0x5778, 0x1078, 0x2051, 0x0e7e, 0x127e, 0x2091, + 0x8000, 0x1078, 0x206f, 0x127f, 0x0e7f, 0x1078, 0x556a, 0x007c, + 0x1078, 0x5778, 0x0078, 0x60ac, 0x1078, 0x5786, 0x0078, 0x60ac, + 0x6000, 0xa08a, 0x0010, 0x10c8, 0x12b7, 0x1079, 0x60d0, 0x007c, + 0x60e0, 0x60e0, 0x60e0, 0x60e0, 0x60e0, 0x60e0, 0x60e0, 0x60e0, + 0x60e0, 0x5ffb, 0x60e0, 0x5ffc, 0x60e2, 0x5ffc, 0x60eb, 0x60e0, + 0x1078, 0x12b7, 0x6007, 0x002b, 0x6003, 0x000d, 0x1078, 0x4327, + 0x1078, 0x476a, 0x007c, 0x1078, 0x6276, 0x1078, 0x6120, 0x0040, + 0x6109, 0x1078, 0x2051, 0x0d7e, 0x6010, 0x2068, 0x6837, 0x0103, + 0x684b, 0x0006, 0x1078, 0x36a1, 0x0d7f, 0x601f, 0x0001, 0x6007, + 0x0001, 0x6003, 0x0001, 0x1078, 0x4376, 0x1078, 0x476a, 0x0078, + 0x610b, 0x1078, 0x556a, 0x007c, 0xa284, 0x0007, 0x00c0, 0x611d, + 0xa282, 0x7400, 0x0048, 0x611d, 0x2001, 0x6d15, 0x2004, 0xa202, + 0x00c8, 0x611d, 0xa085, 0x0001, 0x007c, 0xa006, 0x0078, 0x611c, + 0x027e, 0x0e7e, 0x2071, 0x6d00, 0x6210, 0x7058, 0xa202, 0x0048, + 0x6132, 0x705c, 0xa202, 0x00c8, 0x6132, 0xa085, 0x0001, 0x0e7f, + 0x027f, 0x007c, 0xa006, 0x0078, 0x612f, 0x0e7e, 0x0c7e, 0x037e, + 0x007e, 0x127e, 0x2091, 0x8000, 0x2061, 0x7400, 0x2071, 0x6d00, + 0x7344, 0x7060, 0xa302, 0x00c8, 0x6155, 0x601c, 0xa206, 0x00c0, + 0x614d, 0x0c7e, 0x1078, 0x556a, 0x0c7f, 0xace0, 0x0008, 0x7054, + 0xac02, 0x00c8, 0x6155, 0x0078, 0x6140, 0x127f, 0x007f, 0x037f, + 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x0c7e, 0x017e, 0x127e, 0x2091, + 0x8000, 0xa188, 0x6e00, 0x210c, 0x81ff, 0x0040, 0x6182, 0x2061, + 0x7400, 0x2071, 0x6d00, 0x7344, 0x7060, 0xa302, 0x00c8, 0x6182, + 0x6018, 0xa106, 0x00c0, 0x617c, 0x1078, 0x2051, 0x017e, 0x0c7e, + 0x1078, 0x556a, 0x0c7f, 0x017f, 0xace0, 0x0008, 0x7054, 0xac02, + 0x0048, 0x6170, 0x127f, 0x017f, 0x0c7f, 0x0e7f, 0x007c, 0x0c7e, + 0x057e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x5504, 0x057f, + 0x0040, 0x61a0, 0x6612, 0x651a, 0x601f, 0x0003, 0x2009, 0x004b, + 0x1078, 0x5591, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c, + 0xa006, 0x0078, 0x619c, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, + 0x62a0, 0x0c7e, 0x1078, 0x5504, 0x057f, 0x0040, 0x61ca, 0x6013, + 0x0000, 0x651a, 0x601f, 0x0003, 0x0c7e, 0x2560, 0x1078, 0x35cf, + 0x0c7f, 0x1078, 0x445c, 0x1078, 0x43a9, 0x2c08, 0x1078, 0x6a57, + 0x2009, 0x004c, 0x1078, 0x5591, 0xa085, 0x0001, 0x127f, 0x057f, + 0x0c7f, 0x007c, 0xa006, 0x0078, 0x61c6, 0x0c7e, 0x057e, 0x127e, + 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, 0x5504, 0x057f, 0x0040, + 0x61f5, 0x6612, 0x651a, 0x601f, 0x0003, 0x2019, 0x0005, 0x0c7e, + 0x2560, 0x1078, 0x35cf, 0x0c7f, 0x1078, 0x445c, 0x1078, 0x43a9, + 0x2c08, 0x1078, 0x6a57, 0x2009, 0x004d, 0x1078, 0x5591, 0xa085, + 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x61f1, + 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, + 0x5504, 0x057f, 0x0040, 0x6220, 0x6612, 0x651a, 0x601f, 0x0003, + 0x2019, 0x0005, 0x0c7e, 0x2560, 0x1078, 0x35cf, 0x0c7f, 0x1078, + 0x445c, 0x1078, 0x43a9, 0x2c08, 0x1078, 0x6a57, 0x2009, 0x004e, + 0x1078, 0x5591, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c, + 0xa006, 0x0078, 0x621c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, + 0x1078, 0x5504, 0x017f, 0x0040, 0x623c, 0x660a, 0x611a, 0x601f, + 0x0001, 0x2d00, 0x6012, 0x2009, 0x001f, 0x1078, 0x5591, 0xa085, + 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6239, 0x0c7e, + 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x5504, 0x017f, 0x0040, + 0x6258, 0x660a, 0x611a, 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, + 0x0021, 0x1078, 0x5591, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, + 0xa006, 0x0078, 0x6255, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, + 0x1078, 0x5504, 0x017f, 0x0040, 0x6273, 0x611a, 0x601f, 0x0001, + 0x2d00, 0x6012, 0x2009, 0x0000, 0x1078, 0x5591, 0xa085, 0x0001, + 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6270, 0x027e, 0x0d7e, + 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0040, 0x6280, 0x8211, 0x6a3e, + 0x0d7f, 0x027f, 0x007c, 0x6013, 0x0000, 0x601f, 0x0007, 0x6017, + 0x0014, 0x007c, 0x067e, 0x0c7e, 0x2031, 0x6d52, 0x2634, 0xd6e4, + 0x0040, 0x6297, 0x6618, 0x2660, 0x6e44, 0x1078, 0x3507, 0x0c7f, + 0x067f, 0x007c, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12b7, + 0x1079, 0x62a4, 0x067f, 0x007c, 0x62b4, 0x640b, 0x64d4, 0x62b4, + 0x62b4, 0x62b4, 0x62b4, 0x62b4, 0x62ee, 0x6542, 0x62b4, 0x62b4, + 0x62b4, 0x62b4, 0x62b4, 0x62b4, 0x1078, 0x12b7, 0x067e, 0x6000, + 0xa0b2, 0x0010, 0x10c8, 0x12b7, 0x1079, 0x62c0, 0x067f, 0x007c, + 0x62d0, 0x6837, 0x62d0, 0x62d0, 0x62d0, 0x62d0, 0x62d0, 0x62d0, + 0x6812, 0x687d, 0x62d0, 0x62d0, 0x62d0, 0x62d0, 0x62d0, 0x62d0, + 0x1078, 0x12b7, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12b7, + 0x1079, 0x62dc, 0x067f, 0x007c, 0x62ec, 0x668f, 0x66fb, 0x671c, + 0x6769, 0x62ec, 0x62ec, 0x67be, 0x654e, 0x67fa, 0x67fe, 0x62ec, + 0x62ec, 0x62ec, 0x62ec, 0x62ec, 0x1078, 0x12b7, 0xa1b2, 0x0024, + 0x10c8, 0x12b7, 0x2100, 0x0079, 0x62f5, 0x6319, 0x63f5, 0x6319, + 0x6319, 0x6319, 0x6319, 0x6319, 0x6319, 0x6319, 0x6319, 0x6319, + 0x6319, 0x6319, 0x6319, 0x6319, 0x6319, 0x6319, 0x6319, 0x6319, + 0x6319, 0x6319, 0x6319, 0x6319, 0x631b, 0x634a, 0x6354, 0x637c, + 0x6382, 0x63b6, 0x63ee, 0x6319, 0x6319, 0x63fd, 0x6319, 0x6319, + 0x6404, 0x1078, 0x12b7, 0x1078, 0x364d, 0x6618, 0x0c7e, 0x2660, + 0x1078, 0x3459, 0x0c7f, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, + 0xa082, 0x0006, 0x0048, 0x633c, 0x1078, 0x6993, 0x00c0, 0x6376, + 0x1078, 0x6931, 0x00c0, 0x6338, 0x6007, 0x0008, 0x0078, 0x63f0, + 0x6007, 0x0009, 0x0078, 0x63f0, 0x1078, 0x6b02, 0x0040, 0x6346, + 0x1078, 0x6993, 0x0040, 0x6330, 0x0078, 0x6376, 0x6013, 0x1900, + 0x0078, 0x6338, 0x1078, 0x68b7, 0x6007, 0x0006, 0x0078, 0x63f0, + 0x6007, 0x0007, 0x0078, 0x63f0, 0x0d7e, 0x6618, 0x2668, 0x6e04, + 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x6366, 0xa686, + 0x0004, 0x0040, 0x6366, 0x0d7f, 0x0078, 0x6376, 0x1078, 0x69f1, + 0x00c0, 0x6371, 0x1078, 0x34ca, 0x6007, 0x000a, 0x0d7f, 0x0078, + 0x63f0, 0x6007, 0x000b, 0x0d7f, 0x0078, 0x63f0, 0x1078, 0x2051, + 0x6007, 0x0001, 0x0078, 0x63f0, 0x1078, 0x2051, 0x6007, 0x000c, + 0x0078, 0x63f0, 0x1078, 0x364d, 0x6618, 0xa6b0, 0x0001, 0x2634, + 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x63a3, 0xa6b4, 0xff00, + 0x8637, 0xa686, 0x0006, 0x00c0, 0x6376, 0x1078, 0x6a00, 0x00c0, + 0x639d, 0x6007, 0x000e, 0x0078, 0x63f0, 0x1078, 0x2051, 0x6007, + 0x000f, 0x0078, 0x63f0, 0x1078, 0x6b02, 0x0040, 0x63b0, 0xa6b4, + 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x6395, 0x0078, 0x6376, + 0x6013, 0x1900, 0x6007, 0x0009, 0x0078, 0x63f0, 0x1078, 0x364d, + 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, + 0x0048, 0x63db, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x00c0, + 0x6376, 0x1078, 0x6a2b, 0x00c0, 0x63d5, 0x1078, 0x6931, 0x00c0, + 0x63d5, 0x6007, 0x0010, 0x0078, 0x63f0, 0x1078, 0x2051, 0x6007, + 0x0011, 0x0078, 0x63f0, 0x1078, 0x6b02, 0x0040, 0x63e8, 0xa6b4, + 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x63c9, 0x0078, 0x6376, + 0x6013, 0x1900, 0x6007, 0x0009, 0x0078, 0x63f0, 0x6007, 0x0012, + 0x6003, 0x0001, 0x1078, 0x4376, 0x007c, 0x6007, 0x0001, 0x6003, + 0x0001, 0x1078, 0x4376, 0x0078, 0x63f4, 0x6007, 0x0020, 0x6003, + 0x0001, 0x1078, 0x4376, 0x007c, 0x6007, 0x0023, 0x6003, 0x0001, + 0x1078, 0x4376, 0x007c, 0x6004, 0xa0b2, 0x0024, 0x10c8, 0x12b7, + 0xa1b6, 0x0013, 0x00c0, 0x6417, 0x2008, 0x0079, 0x6426, 0xa1b6, + 0x0014, 0x10c0, 0x12b7, 0x2001, 0x0007, 0x1078, 0x3401, 0x1078, + 0x4671, 0x1078, 0x6283, 0x1078, 0x476a, 0x007c, 0x644a, 0x644c, + 0x644a, 0x644a, 0x644a, 0x644c, 0x6454, 0x64af, 0x6472, 0x64af, + 0x6486, 0x64af, 0x6454, 0x64af, 0x64a7, 0x64af, 0x64a7, 0x64af, + 0x64af, 0x644a, 0x644a, 0x644a, 0x644a, 0x644a, 0x644a, 0x644a, + 0x644a, 0x644a, 0x644a, 0x644a, 0x644a, 0x644a, 0x64af, 0x644a, + 0x644a, 0x64af, 0x1078, 0x12b7, 0x1078, 0x4671, 0x6003, 0x0002, + 0x1078, 0x476a, 0x0078, 0x64b5, 0x0f7e, 0x2079, 0x6d51, 0x7804, + 0x0f7f, 0xd0ac, 0x00c0, 0x64af, 0x2001, 0x0000, 0x1078, 0x33df, + 0x2001, 0x0002, 0x1078, 0x33f3, 0x1078, 0x4671, 0x601f, 0x0001, + 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x4376, 0x1078, 0x476a, + 0x0078, 0x64b5, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, + 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x64af, 0xa686, 0x0004, + 0x0040, 0x64af, 0x2001, 0x0004, 0x0078, 0x64ad, 0x2001, 0x6d00, + 0x2004, 0xa086, 0x0003, 0x00c0, 0x648f, 0x1078, 0x2ad1, 0x2001, + 0x0006, 0x1078, 0x64b6, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, + 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x64af, 0x2001, + 0x0006, 0x0078, 0x64ad, 0x2001, 0x0004, 0x0078, 0x64ad, 0x2001, + 0x0006, 0x1078, 0x64b6, 0x0078, 0x64af, 0x1078, 0x3401, 0x1078, + 0x4671, 0x1078, 0x556a, 0x1078, 0x476a, 0x007c, 0x017e, 0x0d7e, + 0x6118, 0x2168, 0x6900, 0xd184, 0x0040, 0x64d1, 0x6104, 0xa18e, + 0x000a, 0x00c0, 0x64c9, 0x699c, 0xd1a4, 0x00c0, 0x64c9, 0x2001, + 0x0007, 0x1078, 0x33f3, 0x2001, 0x0000, 0x1078, 0x33df, 0x1078, + 0x206f, 0x0d7f, 0x017f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, + 0xa084, 0xff00, 0x8007, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x12b7, + 0xa1b6, 0x0015, 0x00c0, 0x64e8, 0x1079, 0x64ef, 0x0078, 0x64ee, + 0xa1b6, 0x0016, 0x10c0, 0x12b7, 0x1079, 0x6527, 0x007c, 0x57ef, + 0x57ef, 0x57ef, 0x57ef, 0x57ef, 0x57ef, 0x57ef, 0x64fb, 0x57ef, + 0x57ef, 0x57ef, 0x57ef, 0x0f7e, 0x2079, 0x6d51, 0x7804, 0x0f7f, + 0xd0ac, 0x00c0, 0x6517, 0x2001, 0x0000, 0x1078, 0x33df, 0x2001, + 0x0002, 0x1078, 0x33f3, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, + 0x0002, 0x1078, 0x4376, 0x1078, 0x476a, 0x0078, 0x6526, 0x2011, + 0x7283, 0x220c, 0x017e, 0x0c7e, 0x1078, 0x3447, 0x00c0, 0x6526, + 0x1078, 0x3256, 0x0c7f, 0x017f, 0x1078, 0x556a, 0x007c, 0x57ef, + 0x57ef, 0x57ef, 0x57ef, 0x57ef, 0x57ef, 0x57ef, 0x6533, 0x57ef, + 0x57ef, 0x57ef, 0x57ef, 0x1078, 0x599c, 0x00c0, 0x653f, 0x6003, + 0x0001, 0x6007, 0x0001, 0x1078, 0x4376, 0x0078, 0x6541, 0x1078, + 0x556a, 0x007c, 0x6004, 0xa08a, 0x0024, 0x10c8, 0x12b7, 0x1078, + 0x4671, 0x1078, 0x6283, 0x1078, 0x476a, 0x007c, 0xa182, 0x0040, + 0x0079, 0x6552, 0x6561, 0x6561, 0x6561, 0x6561, 0x6563, 0x6561, + 0x6561, 0x6561, 0x6561, 0x6561, 0x6561, 0x6561, 0x6561, 0x6561, + 0x6561, 0x1078, 0x12b7, 0x0d7e, 0x0e7e, 0x0f7e, 0x157e, 0x047e, + 0x027e, 0x2071, 0x7280, 0x7444, 0xa4a4, 0xe600, 0x0040, 0x65d4, + 0xa486, 0x2000, 0x0040, 0x6592, 0xa486, 0x0400, 0x0040, 0x6592, + 0x7130, 0xa18c, 0x00ff, 0xa182, 0x0010, 0x00c8, 0x6663, 0x0c7e, + 0x1078, 0x416d, 0x2c68, 0x0c7f, 0x6a00, 0xa284, 0x0001, 0x0040, + 0x6644, 0x1078, 0x420a, 0x0040, 0x666f, 0xa295, 0x0200, 0x6a02, + 0x0078, 0x6598, 0x2009, 0x0001, 0x2011, 0x0200, 0x1078, 0x41f4, + 0x1078, 0x130f, 0x1040, 0x12b7, 0x6003, 0x0007, 0x6106, 0x2d00, + 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, + 0x685e, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0xa18c, 0x00ff, + 0xa10d, 0x6946, 0x684f, 0x0000, 0x6857, 0x0036, 0x1078, 0x36a1, + 0xa486, 0x2000, 0x00c0, 0x65c2, 0x2019, 0x0017, 0x1078, 0x6b8f, + 0x0078, 0x6631, 0xa486, 0x0400, 0x00c0, 0x65cc, 0x2019, 0x0002, + 0x1078, 0x6b8f, 0x0078, 0x6631, 0xa486, 0x0200, 0x00c0, 0x65d2, + 0x1078, 0x6b80, 0x0078, 0x6631, 0x7130, 0xa18c, 0x00ff, 0xa182, + 0x0010, 0x00c8, 0x6687, 0x0c7e, 0x1078, 0x416d, 0x2c68, 0x0c7f, + 0x6a00, 0xa284, 0x0001, 0x0040, 0x668b, 0xa284, 0x0300, 0x00c0, + 0x6683, 0x6804, 0xa005, 0x0040, 0x666f, 0x8001, 0x6806, 0x6003, + 0x0007, 0x6106, 0x1078, 0x12f4, 0x0040, 0x6638, 0x6013, 0x0000, + 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, 0x2c00, 0x684a, + 0x6018, 0x2078, 0x78a0, 0x8007, 0xa10d, 0x6946, 0x6853, 0x003d, + 0x7044, 0xa084, 0x0003, 0xa086, 0x0002, 0x00c0, 0x6613, 0x684f, + 0x0040, 0x0078, 0x661d, 0xa086, 0x0001, 0x00c0, 0x661b, 0x684f, + 0x0080, 0x0078, 0x661d, 0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, + 0x7290, 0xad90, 0x0015, 0x200c, 0x810f, 0x2112, 0x8000, 0x8210, + 0x00f0, 0x6623, 0x200c, 0x6982, 0x8000, 0x200c, 0x697e, 0x1078, + 0x36a1, 0x027f, 0x047f, 0x157f, 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, + 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x4327, + 0x1078, 0x476a, 0x0078, 0x6631, 0x2069, 0x7292, 0x2d04, 0xa084, + 0xff00, 0xa086, 0x1200, 0x00c0, 0x6663, 0x2069, 0x7280, 0x686c, + 0xa084, 0x00ff, 0x017e, 0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, + 0x017f, 0x6003, 0x0001, 0x6007, 0x0043, 0x1078, 0x4327, 0x1078, + 0x476a, 0x0078, 0x6631, 0x6013, 0x0200, 0x6003, 0x0001, 0x6007, + 0x0041, 0x1078, 0x4327, 0x1078, 0x476a, 0x0078, 0x6631, 0xa284, + 0x0004, 0x00c0, 0x6677, 0x6013, 0x0300, 0x0078, 0x6679, 0x6013, + 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x4327, 0x1078, + 0x476a, 0x0078, 0x6631, 0x6013, 0x0500, 0x0078, 0x6679, 0x6013, + 0x0600, 0x0078, 0x6644, 0x6013, 0x0200, 0x0078, 0x6644, 0xa186, + 0x0013, 0x00c0, 0x66a1, 0x6004, 0xa08a, 0x0040, 0x1048, 0x12b7, + 0xa08a, 0x004f, 0x10c8, 0x12b7, 0xa082, 0x0040, 0x2008, 0x0079, + 0x66cd, 0xa186, 0x0047, 0x00c0, 0x66a7, 0x0078, 0x66fb, 0xa186, + 0x0014, 0x10c0, 0x12b7, 0x6004, 0xa082, 0x0040, 0x2008, 0x0079, + 0x66b1, 0x66c0, 0x66c2, 0x66c2, 0x66c0, 0x66c0, 0x66c0, 0x66c0, + 0x66c0, 0x66c0, 0x66c0, 0x66c0, 0x66c0, 0x66c0, 0x66c0, 0x66c0, + 0x1078, 0x12b7, 0x2001, 0x0007, 0x1078, 0x3401, 0x1078, 0x4671, + 0x1078, 0x6283, 0x1078, 0x476a, 0x007c, 0x66dc, 0x66ec, 0x66e5, + 0x66f5, 0x66dc, 0x66dc, 0x66dc, 0x66dc, 0x66dc, 0x66dc, 0x66dc, + 0x66dc, 0x66dc, 0x66dc, 0x66dc, 0x1078, 0x12b7, 0x6010, 0xa088, + 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x1078, 0x4671, 0x6003, + 0x0002, 0x1078, 0x476a, 0x007c, 0x1078, 0x4671, 0x1078, 0x41cd, + 0x1078, 0x556a, 0x1078, 0x476a, 0x007c, 0x1078, 0x4671, 0x2009, + 0x0041, 0x0078, 0x67be, 0xa182, 0x0040, 0x0079, 0x66ff, 0x670e, + 0x6710, 0x670e, 0x670e, 0x670e, 0x670e, 0x670e, 0x6711, 0x670e, + 0x670e, 0x670e, 0x670e, 0x670e, 0x670e, 0x670e, 0x1078, 0x12b7, + 0x007c, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, + 0x2c10, 0x1078, 0x1532, 0x007c, 0xa182, 0x0040, 0x0079, 0x6720, + 0x672f, 0x672f, 0x672f, 0x672f, 0x672f, 0x672f, 0x672f, 0x672f, + 0x672f, 0x6731, 0x6754, 0x672f, 0x672f, 0x672f, 0x672f, 0x1078, + 0x12b7, 0x1078, 0x4719, 0x1078, 0x4821, 0x6010, 0x0d7e, 0x2068, + 0x684c, 0xd0fc, 0x0040, 0x6747, 0xa08c, 0x0003, 0xa18e, 0x0002, + 0x0040, 0x674d, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x67be, 0x6003, + 0x0007, 0x1078, 0x41cd, 0x0d7f, 0x007c, 0x1078, 0x41cd, 0x1078, + 0x556a, 0x0d7f, 0x0078, 0x674c, 0x2001, 0x0007, 0x1078, 0x3401, + 0x1078, 0x4719, 0x1078, 0x4821, 0x6010, 0x0d7e, 0x2068, 0x037e, + 0x2019, 0x0004, 0x1078, 0x6bb3, 0x037f, 0x1078, 0x6283, 0x0d7f, + 0x007c, 0xa186, 0x0013, 0x00c0, 0x6777, 0x6004, 0xa086, 0x0042, + 0x10c0, 0x12b7, 0x1078, 0x4671, 0x1078, 0x476a, 0x007c, 0xa186, + 0x0014, 0x00c0, 0x678b, 0x6004, 0xa086, 0x0042, 0x10c0, 0x12b7, + 0x2001, 0x0007, 0x1078, 0x3401, 0x1078, 0x4671, 0x1078, 0x6283, + 0x1078, 0x476a, 0x007c, 0xa182, 0x0040, 0x0079, 0x678f, 0x679e, + 0x679e, 0x679e, 0x679e, 0x679e, 0x679e, 0x679e, 0x67a0, 0x67ac, + 0x679e, 0x679e, 0x679e, 0x679e, 0x679e, 0x679e, 0x1078, 0x12b7, + 0x037e, 0x047e, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, + 0x1532, 0x047f, 0x037f, 0x007c, 0x6010, 0x0d7e, 0x2068, 0x684c, + 0xd0fc, 0x0040, 0x67b8, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x67be, + 0x6003, 0x0007, 0x1078, 0x41cd, 0x0d7f, 0x007c, 0xa182, 0x0040, + 0x0079, 0x67c2, 0x67d1, 0x67d3, 0x67df, 0x67eb, 0x67d1, 0x67d1, + 0x67d1, 0x67d1, 0x67d1, 0x67d1, 0x67d1, 0x67d1, 0x67d1, 0x67d1, + 0x67d1, 0x1078, 0x12b7, 0x6003, 0x0001, 0x6106, 0x1078, 0x4327, + 0x127e, 0x2091, 0x8000, 0x1078, 0x476a, 0x127f, 0x007c, 0x6003, + 0x0001, 0x6106, 0x1078, 0x4327, 0x127e, 0x2091, 0x8000, 0x1078, + 0x476a, 0x127f, 0x007c, 0x6003, 0x0003, 0x6106, 0x2c10, 0x1078, + 0x17de, 0x127e, 0x2091, 0x8000, 0x1078, 0x4395, 0x1078, 0x4821, + 0x127f, 0x007c, 0x1078, 0x4671, 0x0078, 0x6800, 0x1078, 0x4719, + 0x6110, 0x81ff, 0x0040, 0x680d, 0x0d7e, 0x2168, 0x037e, 0x2019, + 0x0029, 0x1078, 0x6bb3, 0x037f, 0x0d7f, 0x1078, 0x6283, 0x1078, + 0x476a, 0x007c, 0xa182, 0x0025, 0x0079, 0x6816, 0x681d, 0x681d, + 0x681d, 0x681f, 0x681d, 0x681d, 0x681d, 0x1078, 0x12b7, 0x027e, + 0x0e7e, 0x2071, 0x7280, 0x7220, 0x1078, 0x6ad1, 0x0040, 0x682c, + 0x6007, 0x0026, 0x0078, 0x682e, 0x6007, 0x0027, 0x6003, 0x0001, + 0x1078, 0x4327, 0x1078, 0x476a, 0x0e7f, 0x027f, 0x007c, 0xa186, + 0x0013, 0x00c0, 0x6848, 0x6004, 0xa08a, 0x0025, 0x1048, 0x12b7, + 0xa08a, 0x002c, 0x10c8, 0x12b7, 0xa082, 0x0025, 0x0079, 0x6857, + 0xa186, 0x0014, 0x10c0, 0x12b7, 0x2001, 0x0007, 0x1078, 0x3401, + 0x1078, 0x4671, 0x1078, 0x6283, 0x1078, 0x476a, 0x007c, 0x685e, + 0x6860, 0x6860, 0x685e, 0x685e, 0x685e, 0x685e, 0x1078, 0x12b7, + 0x1078, 0x4671, 0x1078, 0x556a, 0x1078, 0x476a, 0x007c, 0xa182, + 0x0025, 0x1048, 0x12b7, 0xa182, 0x002c, 0x10c8, 0x12b7, 0xa182, + 0x0025, 0x0079, 0x6873, 0x687a, 0x687a, 0x687a, 0x687c, 0x687a, + 0x687a, 0x687a, 0x1078, 0x12b7, 0x007c, 0x1078, 0x4671, 0x1078, + 0x6283, 0x1078, 0x476a, 0x007c, 0x127e, 0x037e, 0x087e, 0x2091, + 0x8000, 0x2c40, 0x2019, 0x0002, 0x1078, 0x5387, 0x00c0, 0x68b3, + 0x1078, 0x5428, 0x00c0, 0x68b3, 0x6000, 0xa086, 0x0000, 0x0040, + 0x68b3, 0x601c, 0xa086, 0x0007, 0x0040, 0x68b3, 0x0d7e, 0x6010, + 0x2068, 0x1078, 0x6120, 0x0040, 0x68a7, 0x1078, 0x6bb3, 0x0d7f, + 0x6000, 0xa086, 0x0004, 0x00c0, 0x68af, 0x1078, 0x15f2, 0x6013, + 0x0000, 0x601f, 0x0007, 0x087f, 0x037f, 0x127f, 0x007c, 0x0f7e, + 0x0c7e, 0x037e, 0x157e, 0x2079, 0x7280, 0x7938, 0x783c, 0x1078, + 0x1e1b, 0x00c0, 0x68e8, 0x017e, 0x0c7e, 0x1078, 0x3447, 0x00c0, + 0x68e8, 0x2011, 0x7290, 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, + 0x5a35, 0x00c0, 0x68e8, 0x017f, 0x027f, 0x027e, 0x017e, 0x2019, + 0x0029, 0x1078, 0x445c, 0x1078, 0x43a9, 0x017f, 0x1078, 0x6a57, + 0x1078, 0x35cf, 0x017f, 0x1078, 0x3256, 0xa006, 0x0078, 0x68ea, + 0x0c7f, 0x017f, 0x157f, 0x037f, 0x0c7f, 0x0f7f, 0x007c, 0x0e7e, + 0x0d7e, 0x0c7e, 0x047e, 0x037e, 0x027e, 0x2061, 0x7400, 0x2071, + 0x6d00, 0x7444, 0x7060, 0x8001, 0xa402, 0x00c8, 0x6929, 0x2100, + 0xac06, 0x0040, 0x691b, 0x6000, 0xa086, 0x0000, 0x0040, 0x691b, + 0x6018, 0x2068, 0x68a0, 0xa206, 0x00c0, 0x691b, 0x631c, 0xa386, + 0x0004, 0x0040, 0x6925, 0xa386, 0x0005, 0x0040, 0x6925, 0xa386, + 0x0006, 0x0040, 0x6925, 0xace0, 0x0008, 0x2001, 0x6d15, 0x2004, + 0xac02, 0x00c8, 0x6929, 0x0078, 0x68f7, 0xa085, 0x0001, 0x0078, + 0x692a, 0xa006, 0x027f, 0x037f, 0x047f, 0x0c7f, 0x0d7f, 0x0e7f, + 0x007c, 0x0c7e, 0x0d7e, 0x017e, 0x2009, 0x6d1e, 0x2104, 0xa086, + 0x0074, 0x00c0, 0x6988, 0x2069, 0x728e, 0x690c, 0xa182, 0x0100, + 0x0048, 0x6978, 0x6908, 0xa184, 0x8000, 0x0040, 0x6984, 0xa184, + 0x0800, 0x0040, 0x6984, 0x6910, 0xa18a, 0x0001, 0x0048, 0x697c, + 0x6914, 0x2069, 0x72ae, 0x6904, 0x81ff, 0x00c0, 0x6970, 0x690c, + 0xa182, 0x0100, 0x0048, 0x6978, 0x6908, 0x81ff, 0x00c0, 0x6974, + 0x6910, 0xa18a, 0x0001, 0x0048, 0x697c, 0x6918, 0xa18a, 0x0001, + 0x0048, 0x6984, 0x0078, 0x698e, 0x6013, 0x0100, 0x0078, 0x698a, + 0x6013, 0x0300, 0x0078, 0x698a, 0x6013, 0x0500, 0x0078, 0x698a, + 0x6013, 0x0700, 0x0078, 0x698a, 0x6013, 0x0900, 0x0078, 0x698a, + 0x6013, 0x0b00, 0x0078, 0x698a, 0x6013, 0x0f00, 0x0078, 0x698a, + 0x6013, 0x2d00, 0xa085, 0x0001, 0x0078, 0x698f, 0xa006, 0x017f, + 0x0d7f, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x027e, 0x037e, 0x157e, + 0x6218, 0x2268, 0x6b04, 0xa394, 0x00ff, 0xa286, 0x0006, 0x0040, + 0x69b7, 0xa286, 0x0004, 0x0040, 0x69b7, 0xa394, 0xff00, 0x8217, + 0xa286, 0x0006, 0x0040, 0x69b7, 0xa286, 0x0004, 0x0040, 0x69b7, + 0x0c7e, 0x2d60, 0x1078, 0x3459, 0x0c7f, 0x0078, 0x69ea, 0x2011, + 0x7296, 0xad98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x5a35, 0x00c0, + 0x69eb, 0x2011, 0x729a, 0xad98, 0x0006, 0x20a9, 0x0004, 0x1078, + 0x5a35, 0x00c0, 0x69eb, 0x047e, 0x017e, 0x6aa0, 0xa294, 0x00ff, + 0x8227, 0xa006, 0x2009, 0x6d52, 0x210c, 0xd1a4, 0x0040, 0x69df, + 0x2009, 0x0029, 0x1078, 0x6bf7, 0x6800, 0xc0e5, 0x6802, 0x2019, + 0x0029, 0x1078, 0x445c, 0x1078, 0x43a9, 0x2c08, 0x1078, 0x6a57, + 0x017f, 0x047f, 0xa006, 0x157f, 0x037f, 0x027f, 0x0d7f, 0x0c7f, + 0x007c, 0x0d7e, 0x2069, 0x728e, 0x6800, 0xa086, 0x0800, 0x0040, + 0x69fd, 0x6013, 0x0000, 0x0078, 0x69fe, 0xa006, 0x0d7f, 0x007c, + 0x0c7e, 0x0f7e, 0x017e, 0x027e, 0x037e, 0x157e, 0x2079, 0x728c, + 0x7930, 0x7834, 0x1078, 0x1e1b, 0x00c0, 0x6a24, 0x1078, 0x3447, + 0x00c0, 0x6a24, 0x2011, 0x7290, 0xac98, 0x000a, 0x20a9, 0x0004, + 0x1078, 0x5a35, 0x00c0, 0x6a24, 0x2011, 0x7294, 0xac98, 0x0006, + 0x20a9, 0x0004, 0x1078, 0x5a35, 0x157f, 0x037f, 0x027f, 0x017f, + 0x0f7f, 0x0c7f, 0x007c, 0x0c7e, 0x007e, 0x017e, 0x027e, 0x037e, + 0x157e, 0x2011, 0x7283, 0x2204, 0x8211, 0x220c, 0x1078, 0x1e1b, + 0x00c0, 0x6a50, 0x1078, 0x3447, 0x00c0, 0x6a50, 0x2011, 0x7296, + 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x5a35, 0x00c0, 0x6a50, + 0x2011, 0x729a, 0xac98, 0x0006, 0x20a9, 0x0004, 0x1078, 0x5a35, + 0x157f, 0x037f, 0x027f, 0x017f, 0x007f, 0x0c7f, 0x007c, 0x0e7e, + 0x0c7e, 0x077e, 0x067e, 0x057e, 0x047e, 0x027e, 0x127e, 0x2091, + 0x8000, 0x2029, 0x6f19, 0x252c, 0x2021, 0x6f1f, 0x2424, 0x2061, + 0x7400, 0x2071, 0x6d00, 0x7644, 0x7060, 0x8001, 0xa602, 0x00c8, + 0x6abc, 0x2100, 0xac06, 0x0040, 0x6ab2, 0x1078, 0x6c0f, 0x0040, + 0x6ab2, 0x671c, 0xa786, 0x0001, 0x0040, 0x6ab2, 0xa786, 0x0007, + 0x0040, 0x6ab2, 0x2500, 0xac06, 0x0040, 0x6ab2, 0x2400, 0xac06, + 0x0040, 0x6ab2, 0x6018, 0x2070, 0x70a0, 0xa206, 0x00c0, 0x6ab2, + 0x0d7e, 0x6010, 0x2068, 0x1078, 0x6120, 0x0040, 0x6aa6, 0xa786, + 0x0003, 0x00c0, 0x6ac5, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, + 0x017e, 0x1078, 0x36a1, 0x017f, 0x1078, 0x6276, 0x0d7f, 0x6000, + 0xa086, 0x0004, 0x00c0, 0x6ab0, 0x017e, 0x1078, 0x15f2, 0x017f, + 0x1078, 0x6283, 0xace0, 0x0008, 0x2001, 0x6d15, 0x2004, 0xac02, + 0x00c8, 0x6abc, 0x0078, 0x6a69, 0x127f, 0x027f, 0x047f, 0x057f, + 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x007c, 0xa786, 0x0006, 0x00c0, + 0x6a9b, 0xa386, 0x0005, 0x0040, 0x6ab2, 0x1078, 0x6bb3, 0x0078, + 0x6aa6, 0x0c7e, 0x0e7e, 0x017e, 0x2c08, 0x2170, 0x1078, 0x6bca, + 0x017f, 0x0040, 0x6ae0, 0x601c, 0xa084, 0x000f, 0x1079, 0x6ae3, + 0x0e7f, 0x0c7f, 0x007c, 0x6aeb, 0x6aeb, 0x6aeb, 0x6aeb, 0x6aeb, + 0x6aeb, 0x6aed, 0x6aeb, 0xa006, 0x007c, 0x047e, 0x017e, 0x7018, + 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009, + 0x0020, 0x1078, 0x6bf7, 0x017f, 0x047f, 0x1078, 0x6884, 0xa085, + 0x0001, 0x007c, 0x2001, 0x0001, 0x1078, 0x33df, 0x157e, 0x017e, + 0x027e, 0x037e, 0x20a9, 0x0004, 0x2019, 0x6d05, 0x2011, 0x7296, + 0x1078, 0x5a35, 0x037f, 0x027f, 0x017f, 0x157f, 0xa005, 0x007c, + 0x0f7e, 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x027e, 0x127e, 0x2091, + 0x8000, 0x2061, 0x7400, 0x2079, 0x0001, 0x8fff, 0x0040, 0x6b73, + 0x2071, 0x6d00, 0x7644, 0x7060, 0x8001, 0xa602, 0x00c8, 0x6b73, + 0x88ff, 0x0040, 0x6b39, 0x2800, 0xac06, 0x00c0, 0x6b69, 0x2079, + 0x0000, 0x1078, 0x6c0f, 0x0040, 0x6b69, 0x2400, 0xac06, 0x0040, + 0x6b69, 0x671c, 0xa786, 0x0006, 0x00c0, 0x6b69, 0xa786, 0x0007, + 0x0040, 0x6b69, 0x88ff, 0x00c0, 0x6b51, 0x6018, 0xa206, 0x00c0, + 0x6b69, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x6120, 0x0040, 0x6b5c, + 0x047e, 0x1078, 0x6bb3, 0x047f, 0x0d7f, 0x6000, 0xa086, 0x0004, + 0x00c0, 0x6b64, 0x1078, 0x15f2, 0x1078, 0x6283, 0x88ff, 0x00c0, + 0x6b7c, 0xace0, 0x0008, 0x2001, 0x6d15, 0x2004, 0xac02, 0x00c8, + 0x6b73, 0x0078, 0x6b25, 0xa006, 0x127f, 0x027f, 0x067f, 0x077f, + 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0xa8c5, 0x0001, 0x0078, 0x6b74, + 0x087e, 0x2041, 0x0000, 0x2c20, 0x2019, 0x0002, 0x6218, 0x1078, + 0x5387, 0x1078, 0x5428, 0x1078, 0x6b18, 0x087f, 0x007c, 0x027e, + 0x047e, 0x087e, 0x0c7e, 0x157e, 0x2c20, 0x20a9, 0x007f, 0x2009, + 0x0000, 0x017e, 0x037e, 0x1078, 0x3447, 0x00c0, 0x6ba8, 0x2c10, + 0x2041, 0x0000, 0x1078, 0x5387, 0x1078, 0x5428, 0x1078, 0x6b18, + 0x037f, 0x017f, 0x8108, 0x00f0, 0x6b99, 0x157f, 0x0c7f, 0x087f, + 0x047f, 0x027f, 0x007c, 0x017e, 0x0f7e, 0x8dff, 0x0040, 0x6bc7, + 0x6800, 0xa07d, 0x0040, 0x6bc4, 0x6803, 0x0000, 0x6b52, 0x1078, + 0x36a1, 0x2f68, 0x0078, 0x6bb8, 0x6b52, 0x1078, 0x36a1, 0x0f7f, + 0x017f, 0x007c, 0x0e7e, 0x047e, 0x037e, 0x2061, 0x7400, 0x2071, + 0x6d00, 0x7444, 0x7060, 0x8001, 0xa402, 0x00c8, 0x6bf2, 0x2100, + 0xac06, 0x0040, 0x6be4, 0x6000, 0xa086, 0x0000, 0x0040, 0x6be4, + 0x6008, 0xa206, 0x0040, 0x6bee, 0xace0, 0x0008, 0x2001, 0x6d15, + 0x2004, 0xac02, 0x00c8, 0x6bf2, 0x0078, 0x6bcf, 0xa085, 0x0001, + 0x0078, 0x6bf3, 0xa006, 0x037f, 0x047f, 0x0e7f, 0x007c, 0x0d7e, + 0x007e, 0x1078, 0x130f, 0x007f, 0x1040, 0x12b7, 0x6837, 0x010d, + 0x6803, 0x0000, 0x683b, 0x0000, 0x685b, 0x0000, 0x685e, 0x6956, + 0x6c46, 0x684f, 0x0000, 0x1078, 0x36a1, 0x0d7f, 0x007c, 0x6700, + 0xa786, 0x0000, 0x0040, 0x6c22, 0xa786, 0x0001, 0x0040, 0x6c22, + 0xa786, 0x000a, 0x0040, 0x6c22, 0xa786, 0x0009, 0x0040, 0x6c22, + 0xa085, 0x0001, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, + 0x2071, 0x6d00, 0xd5a4, 0x0040, 0x6c30, 0x7034, 0x8000, 0x7036, + 0xd5b4, 0x0040, 0x6c36, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0040, + 0x6c3d, 0x2071, 0x6d0a, 0x1078, 0x6c6c, 0x0e7f, 0x007f, 0x127f, + 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x6d00, + 0xd5a4, 0x0040, 0x6c4e, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, + 0x6c54, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0040, 0x6c5b, 0x2071, + 0x6d0a, 0x1078, 0x6c6c, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, + 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x6d02, 0x1078, 0x6c6c, + 0x0e7f, 0x007f, 0x127f, 0x007c, 0x2e04, 0x8000, 0x2072, 0x00c8, + 0x6c75, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x007c, 0x0e7e, 0x2071, + 0x6d00, 0x1078, 0x6c6c, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0x6d04, + 0x1078, 0x6c6c, 0x0e7f, 0x007c, 0x0001, 0x0002, 0x0004, 0x0008, + 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, + 0x1000, 0x2000, 0x4000, 0x8000, 0x614c +}; +unsigned short risc_code_length01 = 0x5c95; + 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 Jan 19 02:57:31 1999 +++ linux.ac/drivers/scsi/scsi.c Tue Jan 19 03:09:56 1999 @@ -280,8 +280,6 @@ {"YAMAHA","CDR100","1.00", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ {"YAMAHA","CDR102","1.00", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */ {"iomega","jaz 1GB","J.86", BLIST_NOTQ | BLIST_NOLUN}, -{"IBM","DPES-","*", BLIST_NOTQ | BLIST_NOLUN}, -{"WDIGTL","WDE","*", BLIST_NOTQ | BLIST_NOLUN}, /* * Must be at end of list... */ 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 Sat Jan 9 21:50:44 1999 +++ linux.ac/drivers/scsi/scsi_error.c Sat Jan 30 18:41:18 1999 @@ -1971,6 +1971,7 @@ * trying to unload a module. */ SCSI_LOG_ERROR_RECOVERY(1,printk("Error handler sleeping\n")); + sem.owner_depth = 0; /* Quick fix for now */ down_interruptible (&sem); if (signal_pending(current) ) 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 Jan 19 02:57:31 1999 +++ linux.ac/drivers/scsi/sd.c Tue Jan 26 19:40:49 1999 @@ -708,14 +708,14 @@ */ if (rscsi_disks[dev].sector_size == 1024) if((block & 1) || (SCpnt->request.nr_sectors & 1)) { - printk("sd.c:Bad block number requested"); + printk("sd.c:Bad block number/count requested"); SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); goto repeat; } if (rscsi_disks[dev].sector_size == 2048) if((block & 3) || (SCpnt->request.nr_sectors & 3)) { - printk("sd.c:Bad block number requested"); + printk("sd.c:Bad block number/count requested"); SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors); goto repeat; } @@ -1126,8 +1126,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; /* @@ -1222,16 +1222,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/sd_ioctl.c linux.ac/drivers/scsi/sd_ioctl.c --- linux.vanilla/drivers/scsi/sd_ioctl.c Sun Nov 8 15:07:48 1998 +++ linux.ac/drivers/scsi/sd_ioctl.c Mon Feb 1 00:42:14 1999 @@ -108,6 +108,11 @@ return -EACCES; return revalidate_scsidisk(dev, 1); + case BLKSSZGET: + /* Block size of media */ + return put_user(blksize_size[MAJOR(dev)][MINOR(dev)&0x0F], + (int *)arg); + RO_IOCTLS(dev, arg); default: diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/sr_ioctl.c linux.ac/drivers/scsi/sr_ioctl.c --- linux.vanilla/drivers/scsi/sr_ioctl.c Sun Nov 8 15:07:49 1998 +++ linux.ac/drivers/scsi/sr_ioctl.c Mon Feb 1 10:07:06 1999 @@ -872,6 +872,11 @@ read_ahead[MAJOR(cdi->dev)] = arg; return 0; + case BLKSSZGET: + /* Block size of media */ + return put_user(blksize_size[MAJOR(cdi->dev)][MINOR(cdi->dev)], + (int *)arg); + RO_IOCTLS(cdi->dev,arg); case BLKFLSBUF: 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 Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/scsi/sym53c416.c Sat Jan 16 21:35:28 1999 @@ -0,0 +1,806 @@ +/* + * sym53c416.c + * Low-level SCSI driver for sym53c416 chip. + * Copyright (C) 1998 Lieven Willems (lw_linux@hotmail.com) + * + * LILO command line usage: sym53c416=[,] + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "scsi.h" +#include "hosts.h" +#include "sd.h" +#include "sym53c416.h" + +#define VERSION_STRING "Version 1.0.0" + +#define TC_LOW 0x00 /* Transfer counter low */ +#define TC_MID 0x01 /* Transfer counter mid */ +#define SCSI_FIFO 0x02 /* SCSI FIFO register */ +#define COMMAND_REG 0x03 /* Command Register */ +#define STATUS_REG 0x04 /* Status Register (READ) */ +#define DEST_BUS_ID 0x04 /* Destination Bus ID (WRITE) */ +#define INT_REG 0x05 /* Interrupt Register (READ) */ +#define TOM 0x05 /* Time out multiplier (WRITE) */ +#define STP 0x06 /* Synchronous Transfer period */ +#define SYNC_OFFSET 0x07 /* Synchronous Offset */ +#define CONF_REG_1 0x08 /* Configuration register 1 */ +#define CONF_REG_2 0x0B /* Configuration register 2 */ +#define CONF_REG_3 0x0C /* Configuration register 3 */ +#define CONF_REG_4 0x0D /* Configuration register 4 */ +#define TC_HIGH 0x0E /* Transfer counter high */ +#define PIO_FIFO_1 0x10 /* PIO FIFO register 1 */ +#define PIO_FIFO_2 0x11 /* PIO FIFO register 2 */ +#define PIO_FIFO_3 0x12 /* PIO FIFO register 3 */ +#define PIO_FIFO_4 0x13 /* PIO FIFO register 4 */ +#define PIO_FIFO_CNT 0x14 /* PIO FIFO count */ +#define PIO_INT_REG 0x15 /* PIO interrupt register */ +#define CONF_REG_5 0x16 /* Configuration register 5 */ +#define FEATURE_EN 0x1D /* Feature Enable register */ + +/* Configuration register 1 entries: */ +/* Bits 2-0: SCSI ID of host adapter */ +#define SCM 0x80 /* Slow Cable Mode */ +#define SRID 0x40 /* SCSI Reset Interrupt Disable */ +#define PTM 0x20 /* Parity Test Mode */ +#define EPC 0x10 /* Enable Parity Checking */ +#define CTME 0x08 /* Special Test Mode */ + +/* Configuration register 2 entries: */ +#define FE 0x40 /* Features Enable */ +#define SCSI2 0x08 /* SCSI 2 Enable */ +#define TBPA 0x04 /* Target Bad Parity Abort */ + +/* Configuration register 3 entries: */ +#define IDMRC 0x80 /* ID Message Reserved Check */ +#define QTE 0x40 /* Queue Tag Enable */ +#define CDB10 0x20 /* Command Descriptor Block 10 */ +#define FSCSI 0x10 /* FastSCSI */ +#define FCLK 0x08 /* FastClock */ + +/* Configuration register 4 entries: */ +#define RBS 0x08 /* Register bank select */ +#define EAN 0x04 /* Enable Active Negotiation */ + +/* Configuration register 5 entries: */ +#define LPSR 0x80 /* Lower Power SCSI Reset */ +#define IE 0x20 /* Interrupt Enable */ +#define LPM 0x02 /* Low Power Mode */ +#define WSE0 0x01 /* 0WS Enable */ + +/* Interrupt register entries: */ +#define SRST 0x80 /* SCSI Reset */ +#define ILCMD 0x40 /* Illegal Command */ +#define DIS 0x20 /* Disconnect */ +#define BS 0x10 /* Bus Service */ +#define FC 0x08 /* Function Complete */ +#define RESEL 0x04 /* Reselected */ +#define SI 0x03 /* Selection Interrupt */ + +/* Status Register Entries: */ +#define SCI 0x80 /* SCSI Core Int */ +#define GE 0x40 /* Gross Error */ +#define PE 0x20 /* Parity Error */ +#define TC 0x10 /* Terminal Count */ +#define VGC 0x08 /* Valid Group Code */ +#define PHBITS 0x07 /* Phase bits */ + +/* PIO Interrupt Register Entries: */ +#define SCI 0x80 /* SCSI Core Int */ +#define PFI 0x40 /* PIO FIFO Interrupt */ +#define FULL 0x20 /* PIO FIFO Full */ +#define EMPTY 0x10 /* PIO FIFO Empty */ +#define CE 0x08 /* Collision Error */ +#define OUE 0x04 /* Overflow / Underflow error */ +#define FIE 0x02 /* Full Interrupt Enable */ +#define EIE 0x01 /* Empty Interrupt Enable */ + +/* SYM53C416 SCSI phases (lower 3 bits of SYM53C416_STATUS_REG) */ +#define PHASE_DATA_OUT 0x00 +#define PHASE_DATA_IN 0x01 +#define PHASE_COMMAND 0x02 +#define PHASE_STATUS 0x03 +#define PHASE_RESERVED_1 0x04 +#define PHASE_RESERVED_2 0x05 +#define PHASE_MESSAGE_OUT 0x06 +#define PHASE_MESSAGE_IN 0x07 + +/* SYM53C416 core commands */ +#define NOOP 0x00 +#define FLUSH_FIFO 0x01 +#define RESET_CHIP 0x02 +#define RESET_SCSI_BUS 0x03 +#define DISABLE_SEL_RESEL 0x45 +#define RESEL_SEQ 0x40 +#define SEL_WITHOUT_ATN_SEQ 0x41 +#define SEL_WITH_ATN_SEQ 0x42 +#define SEL_WITH_ATN_AND_STOP_SEQ 0x43 +#define ENABLE_SEL_RESEL 0x44 +#define SEL_WITH_ATN3_SEQ 0x46 +#define RESEL3_SEQ 0x47 +#define SND_MSG 0x20 +#define SND_STAT 0x21 +#define SND_DATA 0x22 +#define DISCONNECT_SEQ 0x23 +#define TERMINATE_SEQ 0x24 +#define TARGET_COMM_COMPLETE_SEQ 0x25 +#define DISCONN 0x27 +#define RECV_MSG_SEQ 0x28 +#define RECV_CMD 0x29 +#define RECV_DATA 0x2A +#define RECV_CMD_SEQ 0x2B +#define TARGET_ABORT_PIO 0x04 +#define TRANSFER_INFORMATION 0x10 +#define INIT_COMM_COMPLETE_SEQ 0x11 +#define MSG_ACCEPTED 0x12 +#define TRANSFER_PAD 0x18 +#define SET_ATN 0x1A +#define RESET_ATN 0x1B +#define ILLEGAL 0xFF + +#define PIO_MODE 0x80 + +#define IO_RANGE 0x20 /* 0x00 - 0x1F */ +#define ID "sym53c416" +#define PIO_SIZE 128 /* Size of PIO fifo is 128 bytes */ + +#define READ_TIMEOUT 150 +#define WRITE_TIMEOUT 150 + +#ifdef MODULE + +#define sym53c416_base sym53c416 +#define sym53c416_base_1 sym53c416_1 +#define sym53c416_base_2 sym53c416_2 +#define sym53c416_base_3 sym53c416_3 + +static unsigned short sym53c416_base = 0; +static unsigned int sym53c416_irq = 0; +static unsigned short sym53c416_base_1 = 0; +static unsigned int sym53c416_irq_1 = 0; +static unsigned short sym53c416_base_2 = 0; +static unsigned int sym53c416_irq_2 = 0; +static unsigned short sym53c416_base_3 = 0; +static unsigned int sym53c416_irq_3 = 0; + +#endif + +/* #define DEBUG */ + +/* Macro for debugging purposes */ + +#ifdef DEBUG +#define DEB(x) x +#else +#define DEB(x) +#endif + +#define MAXHOSTS 4 + +enum phases + { + idle, + data_out, + data_in, + command_ph, + status_ph, + message_out, + message_in + }; + +typedef struct + { + int base; + int irq; + int scsi_id; + } host; + +host hosts[MAXHOSTS] = { + {0, 0, SYM53C416_SCSI_ID}, + {0, 0, SYM53C416_SCSI_ID}, + {0, 0, SYM53C416_SCSI_ID}, + {0, 0, SYM53C416_SCSI_ID} + }; + +static int host_index = 0; + +static char info[120]; + +static Scsi_Cmnd *current_command = NULL; + +struct proc_dir_entry proc_scsi_sym53c416 = {PROC_SCSI_SYM53C416, 7, ID, S_IFDIR | S_IRUGO | S_IXUGO, 2}; + +int fastpio = 1; + +int probeaddrs[] = {0x200, 0x220, 0x240, 0}; + +static void sym53c416_set_transfer_counter(int base, unsigned int len) + { + /* Program Transfer Counter */ + outb(len & 0x0000FF, base + TC_LOW); + outb((len & 0x00FF00) >> 8, base + TC_MID); + outb((len & 0xFF0000) >> 16, base + TC_HIGH); + } + +/* Returns the number of bytes read */ +static __inline__ unsigned int sym53c416_read(int base, unsigned char *buffer, unsigned int len) + { + unsigned int orig_len = len; + unsigned long flags = 0; + unsigned int bytes_left; + int i; + int timeout = READ_TIMEOUT; + + /* Do transfer */ + save_flags(flags); + cli(); + while(len && timeout) + { + bytes_left = inb(base + PIO_FIFO_CNT); /* Number of bytes in the PIO FIFO */ + if(fastpio && bytes_left > 3) + { + insl(base + PIO_FIFO_1, buffer, bytes_left >> 2); + buffer += bytes_left & 0xFC; + len -= bytes_left & 0xFC; + } + else if(bytes_left > 0) + { + len -= bytes_left; + for(; bytes_left > 0; bytes_left--) + *(buffer++) = inb(base + PIO_FIFO_1); + } + else + { + i = jiffies + timeout; + restore_flags(flags); + while(jiffies < i && (inb(base + PIO_INT_REG) & EMPTY) && timeout) + if(inb(base + PIO_INT_REG) & SCI) + timeout = 0; + save_flags(flags); + cli(); + if(inb(base + PIO_INT_REG) & EMPTY) + timeout = 0; + } + } + restore_flags(flags); + return orig_len - len; + } + +/* Returns the number of bytes written */ +static __inline__ unsigned int sym53c416_write(int base, unsigned char *buffer, unsigned int len) + { + unsigned int orig_len = len; + unsigned long flags = 0; + unsigned int bufferfree; + unsigned int i; + unsigned int timeout = WRITE_TIMEOUT; + + /* Do transfer */ + save_flags(flags); + cli(); + while(len && timeout) + { + bufferfree = PIO_SIZE - inb(base + PIO_FIFO_CNT); + if(bufferfree > len) + bufferfree = len; + if(fastpio && bufferfree > 3) + { + outsl(base + PIO_FIFO_1, buffer, bufferfree >> 2); + buffer += bufferfree & 0xFC; + len -= bufferfree & 0xFC; + } + else if(bufferfree > 0) + { + len -= bufferfree; + for(; bufferfree > 0; bufferfree--) + outb(*(buffer++), base + PIO_FIFO_1); + } + else + { + i = jiffies + timeout; + restore_flags(flags); + while(jiffies < i && (inb(base + PIO_INT_REG) & FULL) && timeout) + ; + save_flags(flags); + cli(); + if(inb(base + PIO_INT_REG) & FULL) + timeout = 0; + } + } + restore_flags(flags); + return orig_len - len; + } + +static void sym53c416_intr_handle(int irq, void *dev_id, struct pt_regs *regs) + { + int base = 0; + int i; + unsigned long flags = 0; + unsigned char status_reg, pio_int_reg, int_reg; + struct scatterlist *sglist; + unsigned int sgcount; + unsigned int tot_trans = 0; + + /* We search the base address of the host adapter which caused the interrupt */ + for(i = 0; i < host_index && !base; i++) + if(irq == hosts[i].irq) + base = hosts[i].base; + /* If no adapter found, we cannot handle the interrupt. Leave a message */ + /* and continue. This should never happen... */ + if(!base) + { + printk("sym53c416: No host adapter defined for interrupt %d\n", irq); + return; + } + /* Now we have the base address and we can start handling the interrupt */ + save_flags(flags); + cli(); + status_reg = inb(base + STATUS_REG); + pio_int_reg = inb(base + PIO_INT_REG); + int_reg = inb(base + INT_REG); + restore_flags(flags); + + /* First, we handle error conditions */ + if(int_reg & SCI) /* SCSI Reset */ + { + printk("sym53c416: Warning: Reset received\n"); + current_command->SCp.phase = idle; + current_command->result = DID_RESET << 16; + current_command->scsi_done(current_command); + return; + } + if(int_reg & ILCMD) /* Illegal Command */ + { + printk("sym53c416: Warning: Illegal Command: 0x%02x\n", inb(base + COMMAND_REG)); + current_command->SCp.phase = idle; + current_command->result = DID_ERROR << 16; + current_command->scsi_done(current_command); + return; + } + if(status_reg & GE) /* Gross Error */ + { + printk("sym53c416: Warning: Gross Error\n"); + current_command->SCp.phase = idle; + current_command->result = DID_ERROR << 16; + current_command->scsi_done(current_command); + return; + } + if(status_reg & PE) /* Parity Error */ + { + printk("sym53c416: Warning: Parity Error\n"); + current_command->SCp.phase = idle; + current_command->result = DID_PARITY << 16; + current_command->scsi_done(current_command); + return; + } + if(pio_int_reg & (CE | OUE)) + { + printk("sym53c416: Warning: PIO Interrupt Error\n"); + current_command->SCp.phase = idle; + current_command->result = DID_ERROR << 16; + current_command->scsi_done(current_command); + return; + } + if(int_reg & DIS) /* Disconnect */ + { + if(current_command->SCp.phase != message_in) + current_command->result = DID_NO_CONNECT << 16; + else + current_command->result = (current_command->SCp.Status & 0xFF) | ((current_command->SCp.Message & 0xFF) << 8) | (DID_OK << 16); + current_command->SCp.phase = idle; + current_command->scsi_done(current_command); + return; + } + /* Now we handle SCSI phases */ + switch(status_reg & PHBITS) /* Filter SCSI phase out of status reg */ + { + case PHASE_DATA_OUT: + { + if(int_reg & BS) + { + current_command->SCp.phase = data_out; + outb(FLUSH_FIFO, base + COMMAND_REG); + sym53c416_set_transfer_counter(base, current_command->request_bufflen); + outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG); + if(!current_command->use_sg) + tot_trans = sym53c416_write(base, current_command->request_buffer, current_command->request_bufflen); + else + { + sgcount = current_command->use_sg; + sglist = current_command->request_buffer; + while(sgcount--) + { + tot_trans += sym53c416_write(base, sglist->address, sglist->length); + sglist++; + } + } + if(tot_trans < current_command->underflow) + printk("sym53c416: Warning: underflow, wrote %d bytes, request for %d bytes\n", tot_trans, current_command->underflow); + } + break; + } + case PHASE_DATA_IN: + { + if(int_reg & BS) + { + current_command->SCp.phase = data_in; + outb(FLUSH_FIFO, base + COMMAND_REG); + sym53c416_set_transfer_counter(base, current_command->request_bufflen); + outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG); + if(!current_command->use_sg) + tot_trans = sym53c416_read(base, current_command->request_buffer, current_command->request_bufflen); + else + { + sgcount = current_command->use_sg; + sglist = current_command->request_buffer; + while(sgcount--) + { + tot_trans += sym53c416_read(base, sglist->address, sglist->length); + sglist++; + } + } + if(tot_trans < current_command->underflow) + printk("sym53c416: Warning: underflow, read %d bytes, request for %d bytes\n", tot_trans, current_command->underflow); + } + break; + } + case PHASE_COMMAND: + { + current_command->SCp.phase = command_ph; + printk("sym53c416: Warning: Unknown interrupt in command phase\n"); + break; + } + case PHASE_STATUS: + { + current_command->SCp.phase = status_ph; + outb(FLUSH_FIFO, base + COMMAND_REG); + outb(INIT_COMM_COMPLETE_SEQ, base + COMMAND_REG); + break; + } + case PHASE_RESERVED_1: + case PHASE_RESERVED_2: + { + printk("sym53c416: Warning: Reserved phase\n"); + break; + } + case PHASE_MESSAGE_OUT: + { + current_command->SCp.phase = message_out; + outb(SET_ATN, base + COMMAND_REG); + outb(MSG_ACCEPTED, base + COMMAND_REG); + break; + } + case PHASE_MESSAGE_IN: + { + current_command->SCp.phase = message_in; + current_command->SCp.Status = inb(base + SCSI_FIFO); + current_command->SCp.Message = inb(base + SCSI_FIFO); + if(current_command->SCp.Message == SAVE_POINTERS || current_command->SCp.Message == DISCONNECT) + outb(SET_ATN, base + COMMAND_REG); + outb(MSG_ACCEPTED, base + COMMAND_REG); + break; + } + } + } + +static void sym53c416_init(int base, int scsi_id) + { + outb(RESET_CHIP, base + COMMAND_REG); + outb(NOOP, base + COMMAND_REG); + outb(0x99, base + TOM); /* Time out of 250 ms */ + outb(0x05, base + STP); + outb(0x00, base + SYNC_OFFSET); + outb(EPC | scsi_id, base + CONF_REG_1); + outb(FE | SCSI2 | TBPA, base + CONF_REG_2); + outb(IDMRC | QTE | CDB10 | FSCSI | FCLK, base + CONF_REG_3); + outb(0x83 | EAN, base + CONF_REG_4); + outb(IE | WSE0, base + CONF_REG_5); + outb(0, base + FEATURE_EN); + } + +static int sym53c416_probeirq(int base, int scsi_id) + { + int irq, irqs, i; + + /* Clear interrupt register */ + inb(base + INT_REG); + /* Start probing for irq's */ + irqs = probe_irq_on(); + /* Reinit chip */ + sym53c416_init(base, scsi_id); + /* Cause interrupt */ + outb(NOOP, base + COMMAND_REG); + outb(ILLEGAL, base + COMMAND_REG); + outb(0x07, base + DEST_BUS_ID); + outb(0x00, base + DEST_BUS_ID); + /* Wait for interrupt to occur */ + i = jiffies + 20; + while(i > jiffies && !(inb(base + STATUS_REG) & SCI)) + barrier(); + if(i <= jiffies) /* timed out */ + return 0; + /* Get occurred irq */ + irq = probe_irq_off(irqs); + sym53c416_init(base, scsi_id); + return irq; + } + +/* Setup: sym53c416=base,irq */ +void sym53c416_setup(char *str, int *ints) + { + int i; + + if(host_index >= MAXHOSTS) + { + printk("sym53c416.c: Too many hosts defined\n"); + } + else + { + if(ints[0] < 1 || ints[0] > 2) + { + printk("sym53c416.c: Wrong number of parameters:\n"); + printk("sym53c416.c: usage: sym53c416=[,]\n"); + } + else + { + for(i = 0; i < host_index && i >= 0; i++) + if(hosts[i].base == ints[1]) + i = -2; + if(i >= 0) + { + hosts[host_index].base = ints[1]; + hosts[host_index].irq = (ints[0] == 2)? ints[2] : 0; + host_index++; + } + } + } + } + +static int sym53c416_test(int base) + { + outb(RESET_CHIP, base + COMMAND_REG); + outb(NOOP, base + COMMAND_REG); + if(inb(base + COMMAND_REG) != NOOP) + return 0; + if(!inb(base + TC_HIGH) || inb(base + TC_HIGH) == 0xFF) + return 0; + if((inb(base + PIO_INT_REG) & (FULL | EMPTY | CE | OUE | FIE | EIE)) != EMPTY) + return 0; + return 1; + } + +void sym53c416_probe(void) + { + int *base = probeaddrs; + int ints[2]; + + ints[0] = 1; + for(; *base; base++) + if(!check_region(*base, IO_RANGE) && sym53c416_test(*base)) + { + ints[1] = *base; + sym53c416_setup(NULL, ints); + } + } + +int sym53c416_detect(Scsi_Host_Template *tpnt) + { + unsigned long flags; + struct Scsi_Host * shpnt = NULL; + int i; + int count; + +#ifdef MODULE + int ints[3]; + + ints[0] = 2; + if(sym53c416_base) + { + ints[1] = sym53c416_base; + ints[2] = sym53c416_irq; + sym53c416_setup(NULL, ints); + } + if(sym53c416_base_1) + { + ints[1] = sym53c416_base_1; + ints[2] = sym53c416_irq_1; + sym53c416_setup(NULL, ints); + } + if(sym53c416_base_2) + { + ints[1] = sym53c416_base_2; + ints[2] = sym53c416_irq_2; + sym53c416_setup(NULL, ints); + } + if(sym53c416_base_3) + { + ints[1] = sym53c416_base_3; + ints[2] = sym53c416_irq_3; + sym53c416_setup(NULL, ints); + } +#endif + + printk("sym53c416.c: %s\n", VERSION_STRING); + + sym53c416_probe(); + + /* Now we register and set up each host adapter found... */ + for(count = 0, i = 0; i < host_index; i++) + if(!sym53c416_test(hosts[i].base)) + printk("No sym53c416 found at address 0x%03x\n", hosts[i].base); + else + { + if(hosts[i].irq == 0) + /* We don't have an irq yet, so we should probe for one */ + if((hosts[i].irq = sym53c416_probeirq(hosts[i].base, hosts[i].scsi_id)) == 0) + printk("irq autoprobing failed for sym53c416 at address 0x%03x\n", hosts[i].base); + if(hosts[i].irq && !check_region(hosts[i].base, IO_RANGE)) + { + shpnt = scsi_register(tpnt, 0); + save_flags(flags); + cli(); + /* Request for specified IRQ */ + if(request_irq(hosts[i].irq, sym53c416_intr_handle, 0, ID, NULL)) + { + restore_flags(flags); + printk("Unable to assign IRQ %d\n", hosts[i].irq); + scsi_unregister(shpnt); + } + else + { + /* Inform the kernel of our IO range */ + request_region(hosts[i].base, IO_RANGE, ID); + shpnt->unique_id = hosts[i].base; + shpnt->io_port = hosts[i].base; + shpnt->n_io_port = IO_RANGE; + shpnt->irq = hosts[i].irq; + shpnt->this_id = hosts[i].scsi_id; + sym53c416_init(hosts[i].base, hosts[i].scsi_id); + count++; + restore_flags(flags); + } + } + } + return count; + } + +const char *sym53c416_info(struct Scsi_Host *SChost) + { + int i; + int base = SChost->io_port; + int irq = SChost->irq; + int scsi_id = 0; + int rev = inb(base + TC_HIGH); + + for(i = 0; i < host_index; i++) + if(hosts[i].base == base) + scsi_id = hosts[i].scsi_id; + sprintf(info, "Symbios Logic 53c416 (rev. %d) at 0x%03x, irq %d, SCSI-ID %d, %s pio", rev, base, irq, scsi_id, (fastpio)? "fast" : "slow"); + return info; + } + +int sym53c416_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) + { + int base; + unsigned long flags = 0; + int i; + + /* Store base register as we can have more than one controller in the system */ + base = SCpnt->host->io_port; + current_command = SCpnt; /* set current command */ + current_command->scsi_done = done; /* set ptr to done function */ + current_command->SCp.phase = command_ph; /* currect phase is the command phase */ + current_command->SCp.Status = 0; + current_command->SCp.Message = 0; + + save_flags(flags); + cli(); + outb(SCpnt->target, base + DEST_BUS_ID); /* Set scsi id target */ + outb(FLUSH_FIFO, base + COMMAND_REG); /* Flush SCSI and PIO FIFO's */ + /* Write SCSI command into the SCSI fifo */ + for(i = 0; i < SCpnt->cmd_len; i++) + outb(SCpnt->cmnd[i], base + SCSI_FIFO); + /* Start selection sequence */ + outb(SEL_WITHOUT_ATN_SEQ, base + COMMAND_REG); + /* Now an interrupt will be generated which we will catch in out interrupt routine */ + restore_flags(flags); + return 0; + } + +static void internal_done(Scsi_Cmnd *SCpnt) + { + SCpnt->SCp.Status++; + } + +int sym53c416_command(Scsi_Cmnd *SCpnt) + { + sym53c416_queuecommand(SCpnt, internal_done); + SCpnt->SCp.Status = 0; + while(!SCpnt->SCp.Status) + barrier(); + return SCpnt->result; + } + +int sym53c416_abort(Scsi_Cmnd *SCpnt) + { + printk("sym53c416_abort\n"); + + /* We don't know how to abort for the moment */ + return SCSI_ABORT_SNOOZE; + } + +int sym53c416_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) + { + int base; + int scsi_id = -1; + int i; + + printk("sym53c416_reset\n"); + base = SCpnt->host->io_port; + /* search scsi_id */ + for(i = 0; i < host_index && scsi_id != -1; i++) + if(hosts[i].base == base) + scsi_id = hosts[i].scsi_id; + outb(RESET_CHIP, base + COMMAND_REG); + outb(NOOP | PIO_MODE, base + COMMAND_REG); + outb(RESET_SCSI_BUS, base + COMMAND_REG); + sym53c416_init(base, scsi_id); + return SCSI_RESET_PENDING; + } + +int sym53c416_bios_param(Disk *disk, kdev_t dev, int *ip) + { + int size; + + size = disk->capacity; + ip[0] = 64; /* heads */ + ip[1] = 32; /* sectors */ + if((ip[2] = size >> 11) > 1024) /* cylinders, test for big disk */ + { + ip[0] = 255; /* heads */ + ip[1] = 63; /* sectors */ + ip[2] = size / (255 * 63); /* cylinders */ + } + return 0; + } + +/* Loadable module support */ +#ifdef MODULE + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,26) +MODULE_AUTHOR("Lieven Willems"); +MODULE_PARM(sym53c416, "1-2i"); +MODULE_PARM(sym53c416_1, "1-2i"); +MODULE_PARM(sym53c416_2, "1-2i"); +MODULE_PARM(sym53c416_3, "1-2i"); +#endif + +Scsi_Host_Template driver_template = SYM53C416; + +#include "scsi_module.c" +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/sym53c416.h linux.ac/drivers/scsi/sym53c416.h --- linux.vanilla/drivers/scsi/sym53c416.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/scsi/sym53c416.h Mon Feb 1 00:52:49 1999 @@ -0,0 +1,91 @@ +/* + * sym53c416.h + * + * Copyright (C) 1998 Lieven Willems (lw_linux@hotmail.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + +#ifndef _SYM53C416_H +#define _SYM53C416_H + +#if !defined(LINUX_VERSION_CODE) +#include +#endif + +#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) + +#include +#include + +#define SYM53C416_SCSI_ID 7 + +extern struct proc_dir_entry proc_scsi_sym53c416; + +extern int sym53c416_detect(Scsi_Host_Template *); +extern const char *sym53c416_info(struct Scsi_Host *); +extern int sym53c416_command(Scsi_Cmnd *); +extern int sym53c416_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +extern int sym53c416_abort(Scsi_Cmnd *); +extern int sym53c416_reset(Scsi_Cmnd *, unsigned int); +extern int sym53c416_bios_param(Disk *, kdev_t, int *); +extern void sym53c416_setup(char *str, int *ints); + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,75) + +#define SYM53C416 { \ + proc_dir: &proc_scsi_sym53c416, \ + name: "Symbios Logic 53c416", \ + detect: sym53c416_detect, \ + info: sym53c416_info, \ + command: sym53c416_command, \ + queuecommand: sym53c416_queuecommand, \ + abort: sym53c416_abort, \ + reset: sym53c416_reset, \ + bios_param: sym53c416_bios_param, \ + can_queue: 1, \ + this_id: SYM53C416_SCSI_ID, \ + sg_tablesize: 32, \ + cmd_per_lun: 1, \ + unchecked_isa_dma: 1, \ + use_clustering: ENABLE_CLUSTERING \ + } + +#else + +#define SYM53C416 { \ + NULL, \ + NULL, \ + &proc_scsi_sym53c416, \ + NULL, \ + "Symbios Logic 53c416", \ + sym53c416_detect, \ + NULL, \ + sym53c416_info, \ + sym53c416_command, \ + sym53c416_queuecommand, \ + sym53c416_abort, \ + sym53c416_reset, \ + NULL, \ + sym53c416_bios_param, \ + 1, \ + SYM53C416_SCSI_ID, \ + 32, /* ???? */ \ + 1, \ + 0, \ + 1, \ + ENABLE_CLUSTERING \ + } + +#endif + +#endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/midi_synth.c linux.ac/drivers/sound/midi_synth.c --- linux.vanilla/drivers/sound/midi_synth.c Sun Nov 8 15:08:01 1998 +++ linux.ac/drivers/sound/midi_synth.c Tue Jan 26 23:48:33 1999 @@ -12,6 +12,7 @@ */ /* * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) + * Andrew Veliath : fixed running status in MIDI input state machine */ #include @@ -196,13 +197,19 @@ inc->m_left = len_tab[(data >> 4) - 8]; inc->m_buf[0] = inc->m_prev_status = data; } - } else if (inc->m_prev_status & 0x80) /* Ignore if no previous status (yet) */ - { /* Data byte (use running status) */ - inc->m_state = MST_DATA; + } else if (inc->m_prev_status & 0x80) { + /* Data byte (use running status) */ inc->m_ptr = 2; - inc->m_left = len_tab[(data >> 4) - 8] - 1; - inc->m_buf[0] = inc->m_prev_status; inc->m_buf[1] = data; + inc->m_buf[0] = inc->m_prev_status; + inc->m_left = len_tab[(inc->m_buf[0] >> 4) - 8] - 1; + if (inc->m_left > 0) + inc->m_state = MST_DATA; /* Not done yet */ + else { + inc->m_state = MST_INIT; + do_midi_msg(dev, inc->m_buf, inc->m_ptr); + inc->m_ptr = 0; + } } break; /* MST_INIT */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/sb.h linux.ac/drivers/sound/sb.h --- linux.vanilla/drivers/sound/sb.h Tue Jan 19 02:57:33 1999 +++ linux.ac/drivers/sound/sb.h Sat Jan 30 18:26:08 1999 @@ -48,12 +48,6 @@ #define MDL_ES1868MIDI 14 /* MIDI port of ESS1868 */ #define MDL_AEDSP 15 /* Audio Excel DSP 16 */ -#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_ES1887 0x14 /* Subtype ES1887 for specific handling */ -#define SUBMDL_ES1888 0x14 /* Subtype ES1888 for specific handling */ #define SUBMDL_ALS007 42 /* ALS-007 differs from SB16 only in mixer */ /* register assignment */ #define SUBMDL_ALS100 43 /* ALS-100 allows sampling rates of up */ diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/sb_card.c linux.ac/drivers/sound/sb_card.c --- linux.vanilla/drivers/sound/sb_card.c Thu Jan 28 22:00:14 1999 +++ linux.ac/drivers/sound/sb_card.c Sat Jan 30 18:26:08 1999 @@ -113,7 +113,7 @@ } int sb_be_quiet=0; -int esstype = 0; /* ESS chip type */ +extern int esstype; /* ESS chip type */ #ifdef MODULE @@ -130,13 +130,13 @@ int io = -1; int irq = -1; int dma = -1; -int dma16 = -1; /* Set this for modules that need it */ -int type = 0; /* Can set this to a specific card type */ -int mad16 = 0; /* Set mad16=1 to load this as support for mad16 */ -int trix = 0; /* Set trix=1 to load this as support for trix */ -int pas2 = 0; /* Set pas2=1 to load this as support for pas2 */ +int dma16 = -1; /* Set this for modules that need it */ +int type = 0; /* Can set this to a specific card type */ +int mad16 = 0; /* Set mad16=1 to load this as support for mad16 */ +int trix = 0; /* Set trix=1 to load this as support for trix */ +int pas2 = 0; /* Set pas2=1 to load this as support for pas2 */ int sm_games = 0; /* Mixer - see sb_mixer.c */ -int acer = 0; /* Do acer notebook init */ +int acer = 0; /* Do acer notebook init */ MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); 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 Tue Jan 26 09:44:21 1999 +++ linux.ac/drivers/sound/sb_ess.c Sat Jan 30 18:26:08 1999 @@ -1,9 +1,38 @@ +#undef FKS_LOGGING +#undef FKS_TEST + /* - * Created: 9-Jan-1999 + * tabs should be 4 spaces, in vi(m): set tabstop=4 * * TODO: consistency speed calculations!! + * cleanup! * ????: Did I break MIDI support? * + * History: + * + * Rolf Fokkens (Dec 20 1998): ES188x recording level support on a per + * input basis. + * (Dec 24 1998): Recognition of ES1788, ES1887, ES1888, + * ES1868, ES1869 and ES1878. Could be used for + * specific handling in the future. All except + * ES1887 and ES1888 and ES688 are handled like + * ES1688. + * (Dec 27 1998): RECLEV for all (?) ES1688+ chips. ES188x now + * have the "Dec 20" support + RECLEV + * (Jan 2 1999): Preparation for Full Duplex. This means + * Audio 2 is now used for playback when dma16 + * is specified. The next step would be to use + * Audio 1 and Audio 2 at the same time. + * (Jan 9 1999): Put all ESS stuff into sb_ess.[ch], this + * includes both the ESS stuff that has been in + * sb_*[ch] before I touched it and the ESS suppor + * I added later + * (Jan 23 1998): Full Duplex seems to work. I wrote a small + * test proggy which works OK. Haven't found + * any applications to test it though. So why did + * I bother to create it anyway?? :) Just for + * fun. + * * 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 * file adds features like: @@ -19,27 +48,13 @@ * * ESS detection isn't full proof (yet). If it fails an additional module * parameter esstype can be specified to be one of the following: - * 688, 1688, 1868, 1869, 1788, 1887, 1888 - * - * History: - * - * Rolf Fokkens (Dec 20 1998): ES188x recording level support on a per - * input basis. - * (Dec 24 1998): Recognition of ES1788, ES1887, ES1888, - * ES1868, ES1869 and ES1878. Could be used for - * specific handling in the future. All except - * ES1887 and ES1888 and ES688 are handled like - * ES1688. - * (Dec 27 1998): RECLEV for all (?) ES1688+ chips. ES188x now - * have the "Dec 20" support + RECLEV - * (jan 2 1999): Preparation for Full Duplex. This means - * Audio 2 is now used for playback when dma16 - * is specified. The next step would be to use - * Audio 1 and Audio 2 at the same time. + * -1, 0, 688, 1688, 1868, 1869, 1788, 1887, 1888 + * -1 means: mimic 2.0 behaviour, + * 0 means: auto detect. + * others: explicitly specify chip + * -1 is default, cause auto detect still doesn't work. */ -#undef FKS_LOGGING - /* * About the documentation * @@ -156,13 +171,26 @@ * ES1946 yes This is a PCI chip; not handled by this driver */ +#include +#include + #include "sound_config.h" #include "sb_mixer.h" #include "sb.h" #include "sb_ess.h" -extern int esstype; /* module parameter in sb_card.c */ +#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 */ + +#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_ES1887 0x14 /* Subtype ES1887 for specific handling */ +#define SUBMDL_ES1888 0x15 /* Subtype ES1888 for specific handling */ #ifdef FKS_LOGGING static void ess_show_mixerregs (sb_devc *devc); @@ -370,45 +398,6 @@ } } -#if 0 -static void ess_speed(sb_devc * devc) -{ - int divider; - unsigned char bits = 0; - int speed = devc->speed; - - if (speed < 4000) - speed = 4000; - else if (speed > 48000) - speed = 48000; - - if (speed > 22000) - { - bits = 0x80; - divider = 256 - (795500 + speed / 2) / speed; - } - else - { - divider = 128 - (397700 + speed / 2) / speed; - } - - bits |= (unsigned char) divider; - - ess_write (devc, 0xa1, bits); - - /* - * Set filter divider register - */ - - speed = (speed * 9) / 20; /* Set filter roll-off to 90% of speed/2 */ - divider = 256 - 7160000 / (speed * 82); - - ess_write (devc, 0xa2, divider); - - return; -} -#endif - static int ess_audio_prepare_for_input(int dev, int bsize, int bcount) { sb_devc *devc = audio_devs[dev]->devc; @@ -931,6 +920,29 @@ return ess_common_set_irq_hw (devc); } +#ifdef FKS_TEST + +/* + * FKS_test: + * for ES1887: 00, 18, non wr bits: 0001 1000 + * for ES1868: 00, b8, non wr bits: 1011 1000 + * for ES1888: 00, f8, non wr bits: 1111 1000 + * for ES1688: 00, f8, non wr bits: 1111 1000 + * + ES968 + */ + +static void FKS_test (sb_devc * devc) +{ + int val1, val2; + val1 = ess_getmixer (devc, 0x64); + ess_setmixer (devc, 0x64, ~val1); + val2 = ess_getmixer (devc, 0x64) ^ ~val1; + ess_setmixer (devc, 0x64, val1); + val1 ^= ess_getmixer (devc, 0x64); +printk (KERN_INFO "FKS: FKS_test %02x, %02x\n", (val1 & 0x0ff), (val2 & 0x0ff)); +}; +#endif + static unsigned int ess_identify (sb_devc * devc) { unsigned int val; @@ -1025,42 +1037,55 @@ if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) { char *chip = NULL; + int submodel = -1; - if (esstype) { - int submodel = -1; - - switch (esstype) { - case 688: - submodel = 0x00; - break; - case 1688: - submodel = 0x08; - break; - case 1868: - submodel = SUBMDL_ES1868; - break; - case 1869: - submodel = SUBMDL_ES1869; - break; - case 1788: - submodel = SUBMDL_ES1788; - break; - case 1887: - submodel = SUBMDL_ES1887; - break; - case 1888: - submodel = SUBMDL_ES1888; - break; - }; - if (submodel != -1) { - devc->submodel = submodel; - sprintf (modelname, "ES%d", esstype); - chip = modelname; - }; + switch (esstype) { + case ESSTYPE_DETECT: + case ESSTYPE_LIKE20: + break; + case 688: + submodel = 0x00; + break; + case 1688: + submodel = 0x08; + break; + case 1868: + submodel = SUBMDL_ES1868; + break; + case 1869: + submodel = SUBMDL_ES1869; + break; + case 1788: + submodel = SUBMDL_ES1788; + break; + case 1887: + submodel = SUBMDL_ES1887; + break; + case 1888: + submodel = SUBMDL_ES1888; + break; + default: + printk (KERN_ERR "Invalid esstype=%d specified\n", esstype); + return 0; + }; + if (submodel != -1) { + devc->submodel = submodel; + sprintf (modelname, "ES%d", esstype); + chip = modelname; }; if (chip == NULL && (ess_minor & 0x0f) < 8) { chip = "ES688"; }; +#ifdef FKS_TEST +FKS_test (devc); +#endif + /* + * If Nothing detected yet, and we want 2.0 behaviour... + * Then let's assume it's ES1688. + */ + if (chip == NULL && esstype == ESSTYPE_LIKE20) { + chip = "ES1688"; + }; if (chip == NULL) { int type; @@ -1080,6 +1105,10 @@ chip = "ES1878"; devc->submodel = SUBMDL_ES1878; break; + default: + if ((type & 0x00ff) != ((type >> 8) & 0x00ff)) { + printk ("ess_init: Unrecognized %04x\n", type); + } }; }; #if 0 diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/sys_timer.c linux.ac/drivers/sound/sys_timer.c --- linux.vanilla/drivers/sound/sys_timer.c Sun Nov 8 15:08:02 1998 +++ linux.ac/drivers/sound/sys_timer.c Tue Jan 26 23:48:33 1999 @@ -13,6 +13,7 @@ */ /* * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) + * Andrew Veliath : adapted tmr2ticks from level 1 sequencer (avoid overflow) */ #include @@ -39,11 +40,17 @@ tmr2ticks(int tmr_value) { /* - * Convert system timer ticks (HZ) to MIDI ticks - * (divide # of MIDI ticks/minute by # of system ticks/minute). + * Convert timer ticks to MIDI ticks */ - return ((tmr_value * curr_tempo * curr_timebase) + (30 * 100)) / (60 * HZ); + unsigned long tmp; + unsigned long scale; + + /* tmr_value (ticks per sec) * + 1000000 (usecs per sec) / HZ (ticks per sec) -=> usecs */ + tmp = tmr_value * (1000000 / HZ); + scale = (60 * 1000000) / (curr_tempo * curr_timebase); /* usecs per MIDI tick */ + return (tmp + scale / 2) / scale; } static void 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 Sun Jan 24 19:55:36 1999 +++ linux.ac/drivers/video/Config.in Sun Jan 24 20:28:50 1999 @@ -37,7 +37,7 @@ fi if [ "$CONFIG_ATARI" = "y" ]; then bool 'Atari native chipset support' CONFIG_FB_ATARI - bool 'ATI Mach64 display support' CONFIG_FB_ATY + bool 'ATI Mach64 display support' CONFIG_FB_ATARI_ATY fi if [ "$CONFIG_PPC" = "y" ]; then bool 'Open Firmware frame buffer device support' CONFIG_FB_OF @@ -45,7 +45,7 @@ bool 'Apple "control" display support' CONFIG_FB_CONTROL bool 'Apple "platinum" display support' CONFIG_FB_PLATINUM bool 'Apple "valkyrie" display support' CONFIG_FB_VALKYRIE - bool 'ATI Mach64 display support' CONFIG_FB_ATY + bool 'ATI Mach64 display support' CONFIG_FB_OF_ATY bool 'IMS Twin Turbo display support' CONFIG_FB_IMSTT bool 'Chips 65550 display support' CONFIG_FB_CT65550 bool 'S3 Trio display support' CONFIG_FB_S3TRIO @@ -73,7 +73,7 @@ bool ' G100/G200 support' CONFIG_FB_MATROX_G100 bool ' Multihead support' CONFIG_FB_MATROX_MULTIHEAD fi - bool 'ATI Mach64 display support' CONFIG_FB_ATY + bool 'ATI Mach64 display support' CONFIG_FB_PCI_ATY fi fi if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then @@ -104,11 +104,27 @@ if [ "$CONFIG_PCI" != "n" ]; then bool 'PCI framebuffers' CONFIG_FB_PCI if [ "$CONFIG_FB_PCI" != "n" ]; then - bool ' ATI Mach64 display support' CONFIG_FB_ATY + bool ' ATI Mach64 display support' CONFIG_FB_SPARC64_PCI_ATY fi fi fi tristate 'Virtual Frame Buffer support (ONLY FOR TESTING!)' CONFIG_FB_VIRTUAL + + if [ "$CONFIG_FB_ATARI_ATY" = "y" \ + -o "$CONFIG_FB_OF_ATY" = "y" \ + -o "$CONFIG_FB_PCI_ATY" = "y" \ + -o "$CONFIG_FB_SPARC64_PCI_ATY" = "y" ]; then + define_bool CONFIG_FB_ATY y + else + if [ "$CONFIG_FB_ATARI_ATY" = "m" \ + -o "$CONFIG_FB_OF_ATY" = "m" \ + -o "$CONFIG_FB_PCI_ATY" = "m" \ + -o "$CONFIG_FB_SPARC64_PCI_ATY" = "m" ]; then + define_bool CONFIG_FB_ATY m + else + define_bool CONFIG_FB_ATY n + fi + fi bool 'Advanced low level driver options' CONFIG_FBCON_ADVANCED if [ "$CONFIG_FBCON_ADVANCED" = "y" ]; then diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/Makefile linux.ac/drivers/video/Makefile --- linux.vanilla/drivers/video/Makefile Sun Jan 24 19:55:36 1999 +++ linux.ac/drivers/video/Makefile Tue Jan 26 23:43:49 1999 @@ -128,6 +128,14 @@ endif endif +ifeq ($(CONFIG_FB_CYBER2000),y) +L_OBJS += cyber2000fb.o +else + ifeq ($(CONFIG_FB_CYBER2000),m) + M_OBJS += cyber2000fb.o + endif +endif + ifeq ($(CONFIG_FB_MAC),y) L_OBJS += macfb.o endif diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/cgsixfb.c linux.ac/drivers/video/cgsixfb.c --- linux.vanilla/drivers/video/cgsixfb.c Tue Dec 22 23:19:55 1998 +++ linux.ac/drivers/video/cgsixfb.c Wed Jan 27 18:58:06 1999 @@ -352,8 +352,8 @@ do { i = fbc->s; } while (i & 0x10000000); - fbc->fg = attr_fgcol(p,*s); - fbc->bg = attr_bgcol(p,*s); + fbc->fg = attr_fgcol(p, scr_readw(s)); + fbc->bg = attr_bgcol(p, scr_readw(s)); fbc->mode = 0x140000; fbc->alu = 0xe880fc30; fbc->pixelm = ~(0); @@ -379,15 +379,15 @@ fbc->x1 = (x += 4 * fontwidth(p)) - 1; fbc->y0 = y; if (fontheightlog(p)) { - fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); - fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); - fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); - fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); + fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); + fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); + fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); + fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); } else { - fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); - fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); - fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); - fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); + fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); + fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); + fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); + fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); } if (fontwidth(p) == 8) { for (i = 0; i < fontheight(p); i++) @@ -408,11 +408,11 @@ fbc->x1 = (x += 2 * fontwidth(p)) - 1; fbc->y0 = y; if (fontheightlog(p)) { - fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1)); - fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1)); + fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); + fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); } else { - fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1); - fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1); + fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); + fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); } for (i = 0; i < fontheight(p); i++) { fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p)); @@ -428,9 +428,9 @@ fbc->x1 = (x += fontwidth(p)) - 1; fbc->y0 = y; if (fontheightlog(p)) - i = ((*s++ & p->charmask) << fontheightlog(p)); + i = ((scr_readw(s++) & p->charmask) << fontheightlog(p)); else - i = ((*s++ & p->charmask) * fontheight(p)); + i = ((scr_readw(s++) & p->charmask) * fontheight(p)); if (fontwidth(p) <= 8) { fd1 = p->fontdata + i; for (i = 0; i < fontheight(p); i++) diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/clgenfb.c linux.ac/drivers/video/clgenfb.c --- linux.vanilla/drivers/video/clgenfb.c Sun Jan 24 19:55:37 1999 +++ linux.ac/drivers/video/clgenfb.c Wed Jan 27 18:59:21 1999 @@ -204,8 +204,8 @@ struct fb_info_gen *info); static int clgen_blank(int blank_mode, struct fb_info_gen *info); -static void clgen_set_dispsw(const void *par, struct display *disp, - struct fb_info_gen *info); +static void clgen_set_disp(const void *par, struct display *disp, + struct fb_info_gen *info); /* function table of the above functions */ static struct fbgen_hwswitch clgen_hwswitch = @@ -220,7 +220,7 @@ clgen_setcolreg, clgen_pan_display, clgen_blank, - clgen_set_dispsw + clgen_set_disp }; /* Text console acceleration */ @@ -1372,13 +1372,14 @@ } } -static void clgen_set_dispsw(const void *par, struct display *disp, - struct fb_info_gen *info) +static void clgen_set_disp(const void *par, struct display *disp, + struct fb_info_gen *info) { struct clgenfb_par *_par = (struct clgenfb_par*) par; struct clgenfb_info *info2 = (struct clgenfb_info *)info; - printk("clgen_get_dispsw(): "); + printk("clgen_set_disp(): "); + disp->screen_base = info2->fbmem; switch (_par->var.bits_per_pixel) { #ifdef FBCON_HAS_MFB @@ -1670,7 +1671,7 @@ int init_module(void) { printk("init_module()\n"); - clgenfb_init(0); + clgenfb_init(); return 0; } diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/creatorfb.c linux.ac/drivers/video/creatorfb.c --- linux.vanilla/drivers/video/creatorfb.c Sun Jan 24 19:55:38 1999 +++ linux.ac/drivers/video/creatorfb.c Wed Jan 27 18:58:06 1999 @@ -433,8 +433,8 @@ FFBWait(fbc); FFBFifo(fbc, 2); - fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,*s)]; - fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,*s)]; + fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,scr_readw(s))]; + fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,scr_readw(s))]; xy = fb->s.ffb.xy_margin; if (fontwidthlog(p)) xy += (xx << fontwidthlog(p)); @@ -452,15 +452,15 @@ fbc->fontinc = 0x10000; fbc->fontxy = xy; if (fontheightlog(p)) { - fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); - fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); - fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); - fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); + fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); + fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); + fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); + fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); } else { - fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); - fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); - fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); - fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); + fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); + fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); + fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); + fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); } FFBFifo(fbc, fontheight(p)); if (fontwidth(p) == 8) { @@ -483,11 +483,11 @@ fbc->fontinc = 0x10000; fbc->fontxy = xy; if (fontheightlog(p)) { - fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1)); - fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1)); + fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); + fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); } else { - fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1); - fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1); + fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); + fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); } FFBFifo(fbc, fontheight(p)); for (i = 0; i < fontheight(p); i++) { @@ -504,9 +504,9 @@ fbc->fontinc = 0x10000; fbc->fontxy = xy; if (fontheightlog(p)) - i = ((*s++ & p->charmask) << fontheightlog(p)); + i = ((scr_readw(s++) & p->charmask) << fontheightlog(p)); else - i = ((*s++ & p->charmask) * fontheight(p)); + i = ((scr_readw(s++) & p->charmask) * fontheight(p)); FFBFifo(fbc, fontheight(p)); if (fontwidth(p) <= 8) { fd1 = p->fontdata + i; diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/cyber2000fb.c linux.ac/drivers/video/cyber2000fb.c --- linux.vanilla/drivers/video/cyber2000fb.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/video/cyber2000fb.c Tue Jan 26 23:43:49 1999 @@ -0,0 +1,1125 @@ +/* + * linux/drivers/video/cyber2000.c + * + * Integraphics Cyber2000 frame buffer device + * + * Based on cyberfb.c + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include